话不多说先上视频,一看就懂

另外可参考这里:https://www.cnblogs.com/dehai/p/4285749.html ,这个近6年前的帖子

程序结构

程序分成上位机(PC端)与下位机(单片机):

PC端,使用的是WinForm ,声音识别采用微软的System.Speech.dll(这个也有很多坑后面会每坑说明)

程序由 :指令库,任务库,Http服务3部分组成

指令库:
系统会选择加载目录下XH.Cmd.xxxx.dll文件,并加载XHCmd开头的类型,类型需要做XHCmdAttribute标注,并且继承XHCommandBasic类

任务库:
系统会选择加载目录下XH.Task.xxxx.dll文件,并且加载XHTask开头的定义且继承XHTaskBasic的类,这可以用来提醒下班,自动关灯,关空调

定期检查机房服务器状态等等。。。。可以做很多扩展。

可以在在配置文件AppSetting节中ExcludeCmd与ExcludeTask,排除不需要加载的类型,另外下班提醒时间,开灯开空调提醒域值也在配置文件中

 下面是PC端需要注意的问题---各种坑点

1.操作系统用的是Win7 64位完整版,很多Ghost版不带语音模块,程序能编译但一运行就会出错

2.电脑的麦克风跟杨声器最好是2个设备并且分开一段距离防

3.无法把程序改成Windows服务的形式,必需是可视化的Windows Form形式, 远程桌面连接或计划任务启动的都无法使用语音识别功能

  如果要长期处于监听状态,只能将程序执行文件的快捷方式拖进Windows的 “启动”目录下,并且取消windows的登陆界面

4.为保证程序稳定运行,建议在计划任务里设置每天凌晨重启PC、

5.当然为了保证一定的安全,PC机专用,开启防火墙(但要开放TCP ,9495端口),另外可以在网关设备或核心交换机处禁止PC访问外网或被外网访问。

6.提供的代码里定义PC的IP是10.2.8.188,端口是9495, 使用时务必修改成实际的IP地址

7.app.Config中的DefaultClientIP用来区分多个单片机用的,目前只涉及一个单片机的情况下设置成服务器IP:Port形式,如果要支持多个单片机,需要自己调整程序,框架是支持的。

  具体原理是,单片机每个http请求会在QueryString携带传感器读数,并且带上自己的标识(也就是TagIP), 而PC会将下发的指令(指开灯,开空调等)通过这个请求的Response 返回给

 指定tagIp的单片机,下发指令存放在一个以tagIp作为key的字典中。收到http请求后,在生成Response时会查看对应Key的字典中有无要携带回去的指令,有的话就会在Response中体现。每个单片机每隔2-3秒左右发送一次请求,也就是系统延迟在2-3秒左右。

8.执行目录下的data下面可以放mp3,语音指令是”播放音乐“,程序会随机选择一个mp3文件播放。

单片机是arduino uno 配合网络板扩展,采用的是有线网络,硬件模块也是近6年前的老物件

单片上连了红外头用来控制空调,光敏电阻采集网照强度可以在昏暗时提醒开灯,用温湿传感器DHT11--这个也比较坑,用电流传感器--用来确定空调是否打开,还有控制灯的继电器

完整的单片机代码入下,注意接口

#define DHT11_PIN 0   ---dht11 连的是arduino的A0 口
#define CurrentIndexPin A3   --- 电流传感器连A3口
#define IlluminationPin A2     --热敏电阻连A2口
#define relayAPin 8             ---继电器连 8号口
#define RebootPin 5           --这个是5号口连的是三级管的基级,用来物理重启单片机用的,这样你的系统可以非常非常强壮

/*
Web client This sketch connects to a website (http://www.google.com)
using an Arduino Wiznet Ethernet shield. Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13 created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe, based on work by Adrian McEwen */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
//#include <avr/wdt.h> #define DHT11_PIN 0
#define CurrentIndexPin A3
#define IlluminationPin A2
#define relayAPin 8
#define RebootPin 5
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAA, 0xBE, 0xEF, 0xFF, 0xE2 };
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "10.2.8.188"; // name address for Google (using DNS) // Set the static IP address to use if the DHCP fails to assign
IPAddress ip(10,2,8,198);
IPAddress gateway(10,2,8,1);
IPAddress dns_server(60,191,134,196);
IPAddress subnet(255,255,255,0);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client; // Media Control RAW Code
IRsend irsend;
//open_cool_20_strong
const unsigned int PowerOn[] PROGMEM={
4610,4152,742,1395,740,354,737,1398,724,1438,718,350,714,380,709,1439,688,408,665,
405,641,1522,628,442,621,472,618,1518,612,1550,607,469,591,1567,586,1555,574,522,566,
1573,555,1608,554,1608,547,1589,543,1619,540,1595,546,547,544,1592,545,548,546,522,
541,553,548,519,544,550,542,525,544,550,545,522,544,1617,545,524,542,551,543,524,543,
524,543,551,548,1587,545,1617,543,524,570,1591,542,1619,547,1589,545,1616,546,1590,
543,5188,4375,4380,544,1590,548,545,546,1590,541,1621,545,522,544,550,545,1590,546,
547,546,521,542,1620,544,522,544,550,543,1592,543,1619,549,519,543,1618,541,1621,545,
521,546,1617,544,1592,546,1616,546,1589,543,1619,546,1615,545,524,541,1620,542,524,
543,551,545,523,543,524,542,551,545,523,543,549,548,520,539,1622,541,527,546,547,543,
523,542,551,544,524,540,1622,541,1594,546,548,543,1592,545,1616,543,1593,545,1616,
548,1614,540
}; //共有199条数据 //close
const unsigned int PowerOff[] PROGMEM={
4589,4171,734,1402,725,369,717,1419,715,1447,711,361,700,404,673,1466,653,443,634,
435,626,1535,624,445,620,474,614,1522,610,1552,601,468,597,1567,590,490,569,1590,567,
1574,553,1609,549,1612,549,519,541,1620,551,1586,542,1620,545,522,546,548,544,523,
546,548,546,1589,533,561,535,532,534,1628,535,1601,537,1624,541,527,545,547,543,526,
546,547,544,523,545,549,547,522,537,529,573,1589,543,1619,544,1592,555,1605,551,1584,
548,5184,4376,4377,542,1594,544,549,544,1592,544,1618,548,519,543,552,546,1589,544,
550,543,523,547,1616,546,521,544,549,546,1589,546,1616,544,523,545,1618,543,523,571,
1592,546,1615,549,1587,546,1616,549,518,546,1616,543,1593,545,1616,542,550,545,523,
545,522,544,549,546,1590,546,547,546,520,549,1615,544,1617,545,1590,546,548,545,521,
548,520,544,547,545,524,545,549,544,524,544,550,544,1592,542,1618,546,1590,543,1619,
546,1615,540
}; //共有199条数据 byte relayAStatus=0;
int il=0;
int ci=0;
int errCount=0; void setup() { pinMode(relayAPin,OUTPUT);
digitalWrite(relayAPin, relayAStatus);
pinMode(RebootPin,OUTPUT);
digitalWrite(RebootPin,LOW); //wdt_enable(WDTO_8S); DDRC|=_BV(DHT11_PIN);
PORTC|=_BV(DHT11_PIN);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
} // start the Ethernet connection:
// give the Ethernet shield a second to initialize: if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
Ethernet.begin(mac, ip,dns_server,gateway,subnet);
} delay(2000);
Serial.println("Ready");
} void loop()
{ double t=0;
double h=0;
bool isOK=false; isOK=readDHT11Data(t,h);
httpRequest(t,h);
if(relayAStatus==1){
digitalWrite(relayAPin, HIGH);
}else{
digitalWrite(relayAPin,LOW) ;
}
il=analogRead(IlluminationPin);
ci=getMaxValue();
Serial.println(il);
Serial.println(ci); delay(1000); }
//================DHT11 Code================== //================DT11 Code 1=======================
bool readDHT11Data(double &t,double &h){
t=-888;
h=-888; byte dht11_dat[5];
byte dht11_in;
byte i;
PORTC &= ~_BV(DHT11_PIN);
delay(18);
PORTC|=_BV(DHT11_PIN);
delayMicroseconds(40);
DDRC &= ~_BV(DHT11_PIN);
delayMicroseconds(40);
dht11_in = PINC & _BV(DHT11_PIN);
if(dht11_in)
{
Serial.println("dht11 start condition 1 not met");
return false;
} delayMicroseconds(80);
dht11_in=PINC & _BV(DHT11_PIN);
if(!dht11_in) {
Serial.println("dht11 start condition 2 not met");
return false;
} delayMicroseconds(80);
for(i=0;i<5;i++)
dht11_dat[i]=read_dht11_dat();
DDRC|=_BV(DHT11_PIN);
PORTC|=_BV(DHT11_PIN);
byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
if(dht11_dat[4]!=dht11_check_sum)
{
Serial.println("DHT11 checksum error");
return false;
} t= dht11_dat[2] + (double)dht11_dat[3]/100;
h=dht11_dat[0] + (double)dht11_dat[1] /100; Serial.print("temperature = ");
Serial.print(t,DEC);
Serial.print("C");
Serial.print("Current humdity= ");
Serial.print(String(h));
Serial.println("%"); return true;
}
byte read_dht11_dat()
{
byte i = 0;
byte result = 0;
for(i=0;i<8;i++)
{
while(!(PINC&_BV(DHT11_PIN)));
delayMicroseconds(30);
if(PINC&_BV(DHT11_PIN))
result|=(1<<(7-i));
while((PINC&_BV(DHT11_PIN)));
}
return result;
} //================End DHT11 Code================== //================Http Request Code========================
void httpRequest(double t,double h){
// if you get a connection, report back via serial: if(!client.connected()){
Serial.println("disconnecting.");
client.stop();
if (client.connect(server, 9495)) {
Serial.println("connected");
}else{
// kf you didn't get a connection to the server:
Serial.println("connection failed");
errCount++;
if(errCount>=3){
digitalWrite(RebootPin,HIGH);
delay(1000);
}
}
} else{ // Make a HTTP request:
client.println("GET /?m=c&mil=" + String(millis()) + "&t="+String(t)+"&h="+String(h)+ "&ra=" +String(relayAStatus)+"&i="+String(il) +"&ci=" +String(ci) +" HTTP/1.1");
client.println("Host:10.2.8.188");
//client.println("Connection: close"); client.println();
delay(10);
String reply="";
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
reply+=c; }
//Serial.print(reply);
if(reply.indexOf("\"Model\":\"OPENA\"")>=0){
Serial.println("OPEN");
powerOnA();
}
if(reply.indexOf("\"Model\":\"CLOSEA\"")>=0){
Serial.println("CLOSE");
powerOffA();
}
if(reply.indexOf("\"Model\":\"OPENL\"")>=0){
Serial.println("OPENL");
powerOnL();
}
if(reply.indexOf("\"Model\":\"CLOSEL\"")>=0){
Serial.println("CLOSEL");
powerOffL();
}
errCount=0;
//wdt_reset();
} }
//================End Http Request Code=============== //================AirConditioner && Light Control===========
void powerOffA(){ unsigned int t[199];
for(int i=0;i<199;i++){
t[i] = pgm_read_word_near(PowerOff+i); }
irsend.sendRaw2(t,199,38);
delay(3000);
}
void powerOnA(){ unsigned int t[199];
for(int i=0;i<199;i++){
t[i] = pgm_read_word_near(PowerOn+i); } irsend.sendRaw2(t,199,38);
delay(3000);
}
void powerOffL(){
relayAStatus=0;
}
void powerOnL(){
relayAStatus=1; } //================CurrentIndex Read Max Value=================
int getMaxValue()
{
int sensorValue; //value read from the sensor
int sensorMax = 0;
uint32_t start_time = millis();
while((millis()-start_time) < 1000)//sample for 1000ms
{
sensorValue = analogRead(CurrentIndexPin);
if (sensorValue > sensorMax)
{
/*record the maximum sensor value*/
sensorMax = sensorValue;
}
}
return sensorMax;
} //================End CurrentIndex ReadMax Value============= //================End AirConditioner Control===================

 单片机端注意的事项

1.DHT11 正负极一定不能接反,数据线要检测下是否导通的,话说折腾了几个小时发现是陈年的数据线时通时不通导致的。。。

如果单片机用mega2560那么使用DHT11库比较方便.

2.红外发射头针对Uno 使用的是3号脚,而针对mega2560使用的是9号脚,另外红外头必需足够靠近空调。同时务必注意连线接触要
好。

3.继电器,刚开始用的机械的,然后是光藕隔离机械的,但是由于负载是LED(220AC,70W)结果经常一吸合上就跳不开了。

所以如果也是LED等带交流转直流的务必采用固态继电器,这里使用的是5V高电平触发,220V AC 2A 的固态继电器,可自己

上某宝或某东找去。

4.电流传感器,这个是检测空调是否启动的,某宝上能找到的是最大支持5A电流,用来检测空调有点问题(空调最大16A),所以要改动空调电源线的火线(L线)

,在主空调火线上旁路一条细线分流,

线径是主线的1/5,电流传感器(感应式的)就装旁线上,理论上可将电流降低1/6,就能符合传感器的规格了。

5.最后是三极管(S8050),基极过1K电阻连5号口,集电极过270欧电阻连Vcc,同时集电极连单片机RESET口,发射极连GND,单片机

代码里检测到连续3次错误后会给5号口高电平,这样就可以重启单片机,5号口默认是数字输出LOW.

完整代码下载:点这里

------------------------------------------------------------------------------------------------------------------

5年前接触的arduino,做为一个.net程序员15年了,儿子也11岁了

马上奔4了,15年前是程序员,现在仍旧是程序员,只是年纪大了,身体差了,毛病多了,亲人朋友也有离世。。。。

园子里的程序员门,你们还好吗,多珍重。。。。。

何须问

C#+Arduino Uno 实现声控系统完全实施手册的更多相关文章

  1. 基于Proteus仿真的Arduino学习(1)——Arduino Uno最小系统及LED的简单使用

    一.前言:  A.Arduino简介 Arduino是由一个欧洲开发团队于2005年冬季开发.其成员包括Massimo Banzi.David Cuartielles.Tom Igoe.Gianluc ...

  2. Arduino UNO仿真开发环境设置和仿真运行

    一. Proteus仿真平台简介 Proteus软件是英国Labcenter electronics公司出版的EDA工具软件(该软件中国总代理为广州风标电子技术有限公司).它不仅具有其它EDA工具软件 ...

  3. 详解Arduino Uno开发板的引脚分配图及定义(重要且基础)

    首先开发板实物图如下: 在本篇文章中,我们将详细介绍Arduino开发板的硬件电路部分,具体来说,就是介绍Arduino Uno开发板的引脚分配图及定义.Arduino Uno微控制器采用的是Atme ...

  4. Arduino + RFID 读取 IC 卡 Arduino uno中获得RFID的UID 并通过串口转发RFID卡号

    RFID简介:射频识别即RFID(Radio Frequency IDentification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需识别系统与特定 ...

  5. Arduino Uno微控制器采用的是Atmel的ATmega328

    参考:https://www.yiboard.com/thread-831-1-1.html 在本篇文章中,我们将详细介绍Arduino开发板的硬件电路部分,具体来说,就是介绍Arduino Uno开 ...

  6. Arduino uno R3 ISP刷Rootloader for arduino pro mini

    找了好久才发现的,好东西.介绍怎么使用uno对mini 刷Rootloader **SOLUTION** Reinstall the Arduino Pro Mini Bootloader using ...

  7. [Arduino] Arduino Uno R3 中文介绍

    Arduino UNO是Arduino USB接口系列的最新版本,作为Arduino平台的参考标准模板.UNO的处理器核心是ATmega328,同时具有14路数字输入/输出口(其中6路可作为PWM输出 ...

  8. Arduino UNO的原理图

    Arduino UNO的原理图是开源的,所以可以从arduino网站上下载它: https://www.arduino.cc/en/Main/ArduinoBoardUno 原理图PDF: https ...

  9. 2.6 基于ARDUINO UNO+MC20的路径显示功能

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

随机推荐

  1. Centos-检查文件系统并尝试修复-fsck

    fsck 检查文件系统并尝试修改错误,修复对象为设备,本质上是调用 /sbin/fsck.filesystemName 命令, filesystemName是指定设备的文件系统类型,如图分区中有文件丢 ...

  2. CentOS7的下载及虚拟机的创建

    一.CentOS的安装 1,首先打开开源镜像网站:www.mirrors.163.com(网易开源镜像网站),www.mirrors.aliyun.com(阿里云开源镜像网站) 以网易为例 2.点击进 ...

  3. GAN在seq2seq中的应用 Application to Sequence Generation

    Improving Supervised Seq-to-seq Model 有监督的 seq2seq ,比如机器翻译.聊天机器人.语音辨识之类的 . 而 generator 其实就是典型的 seq2s ...

  4. C面向对象: 升级版本实现:同步逻辑、少量连续失败则增补、多次连续失败则拉长同步周期

    // C语言之 面向对象+虚事务的抽象 /*********** 进阶练习: (对虚的事物的抽象) 完善部门职责 ***********************/ #include <stdio ...

  5. 001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学

    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学 welcome to Java World 欢迎来到Java世界 一起领略Java编程世界的奥秘与奥妙 ...

  6. 【题解】hdu4757 【TJOI2018】异或

    题目链接 题目大意:有一颗树,有点权,每次询问:一条路径\(x->y\)中与\(z\)异或的最大值,或是以\(x\)为根的子树中与\(y\)异或的最大值. 树剖--还是算了. 观察到,子树的\( ...

  7. HashMap 、ConcurrentHashMap知识点全解析

    散列表 在了解hashmap之前,要先知道什么是散列表,因为hashmap就是在散列表结构基础上改造而成的.散列表,也叫哈希表,是根据关键码值(key value)而直接进行访问的数据结构.也就是说, ...

  8. 小白使用Hystrix

    Hystrix是什么东西?百度一下: 没错,hystrix是豪猪的意思,作为SpringCloud微服务系统中保持服务稳定的重要组件,正如它的名字一样,它对整个系统起到了保护的作用. 在许多文章当中把 ...

  9. Apache Hudi与Apache Flink集成

    感谢王祥虎@wangxianghu 投稿 Apache Hudi是由Uber开发并开源的数据湖框架,它于2019年1月进入Apache孵化器孵化,次年5月份顺利毕业晋升为Apache顶级项目.是当前最 ...

  10. C#数据结构-栈

    栈的定义不需要多说,相信大家都非常熟悉,但是,在实际应用中栈的应用我们很少想到会去用栈结构,先上代码看下用法: Stack st = new Stack(); st.Push('A'); st.Pus ...