|
楼主 |
发表于 2016-10-18 10:50:38
|
显示全部楼层
本帖最后由 gongqingkui 于 2016-10-18 11:00 编辑
Arduino的LED、servo和LCD1602
这个系统可以识别三种指令:二值型、整数型和字符串型。
LED开关、闪烁显然是二值型的指令控制的。命令首字母为b,为b0或者b1,标示二值型的关和开。这里以控制Arduino板子上的LED为例:只用一句话digitalWrite(13, HIGH);或者digitalWrite(13, LOW);。这个LED的引脚接在13脚上,所以控制它高低电平就可以实现闪烁或者亮灭的功能。同理,如果不接Arduino板上的LED而另外接诸如继电器之类的元件,就可以实现控制外围高压电路的功能。
数值型指令发送一个整数,命令首字母为d,为 dIntNUM。这里用伺服器作为实例。伺服器根据收到的0-180的数据进行角度调整。语句也很简单。引入并且实例化Servo:
#include <Servo.h>
Servo servo1;
在setup()函数中servo1.attach(10);设定伺服器1的数据引脚接到10脚上。
在程序loop中进行接收和处理指令,之后发送角度到伺服器1:servo1.write(ans);
字符型的指令发送一条字符串给Arduino主机,命令首字母为s,为sString。这里用1602液晶屏做例子,把收到的字符串显示到液晶屏上。语句基本是:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
初始化setup时:lcd.begin(16, 2);在随便输出点什么看看:lcd.print("SmartHome");。接收到相关字符串后,先设定显示位置lcd.setCursor(0, 0);然后输出数据lcd.print(data + 1);
以上,实现了接收指令后解析,发送到相应的设备或者控制外围硬件做出反应的功能。下面说明如何给Arduino发送指令。
串口
这个小系统Arduino的串口接收消息并解析、控制硬件。接收的三种消息分别用不同字母开头,Arduino判断首字母并解析出相应数据,发送控制命令给硬件。
在setup中打开和初始化串口。 Serial.begin(9600);
Serial.flush();
在loop中接收串口发来的消息,存进buffer中,并调用splitString函数处理数据,再调用setLED完成对硬件发送控制指令的操作。
在测试时,可以使用Arduino自带的串口监视器,自己手动发送以b、d、s开头的测试信号。下面再连到Cubieboard上去。
Cubieboard串口链接
在这个小系统的设计中,Arduino负责硬件控制,接受解析指令。而另外一台Cubieboard2负责构建IOT服务器。这个服务器现在主要完成web接口和发送指令给Arduino的功能,未来还要完成自动控制和智能控制的功能。之所以不直接用Arduino做中心,也是考虑为未来自动和智能控制的留空间。
首先Cubieboard最简单先要和Arduino用串口连起来。插上USB转串口线之后,进到/dev/中ls下,可以看到以ttyUSB开头的设备,例如ttyUSB0,就表示串口线的名字。然后把TX和RX脚连到Arduino的0和1脚上。
用minicom软件测试下连上Arduino没有。首先下载安装sudo apt-get install minicom然后再配置下sudo minicom –s主要是把串口设置中的名字修改为USB串口线名字,关闭硬件流控制功能。然后就可以打开minicom测试了。直接输入相应的控制指令并且回车,就会将指令发送到Arduino中,如果有错的话,可以试下把串口线rx和tx对调。
Python串口
Minicom串口测试正常之后,就可以写Python程序通过串口发送指令了。写好串口收发程序也是为了下一步web封装和与在线物联网服务连接。
发送程序serialPortModule.py比较简单:- import serial
- def serialSend(str):
- t = serial.Serial('/dev/ttyUSB1',9600)
- with t:
- n = t.write(str)
- t.close()
- return n
复制代码 引入serial包后,新建一个发送函数serialSend,以待发送指令作为参数。语句很简单,返回发送的指令长度。这里唯一需要注意的是ttyUSB的编号,要在/dev/里查询得到。那么接收的程序serialRead.py是这样的:- import serial
- def serialRead():
- t = serial.Serial('/dev/ttyUSB1',9600)
- print t.isOpen()
- with t:
- while(1):
- s = t.readline()
- print s
- #todo save to DB or web
- if __name__ == '__main__':
- serialRead()
复制代码 程序自动接收串口发送的字符串指令,解析后可以完成转发到在线服务器或者存储到数据库的操作。
Pythonweb封装
编写好串口发送函数后,可在命令行下进行简单测试。测试无误后,可以编写web程序,在web程序中,根据用户点击,来调用串口发送函数,进行指令的传递。Web服务器这里用的是python的web库。代码如下:
web_manual.py程序导入相应的包后,首先用render指明模板所在目录templates/,然后指定URL访问列表情况,最后根据URL中制定名字,编写相应的控制器。控制器中的GET和POST分别指代两种访问方法,用render.具体模板名来传值到相应模板。Db类和sqldb类用来访问本地sqlite3数据库。经过以上程序,在服务器中打开python web.py 1234,然后访问localhost:1234既可以访问到这个简单的网站,实现局域网内查看和控制设备的能力。- # encoding: utf-8
- import web
- import os
- import sqlite3
- import time
- import serial
- from actuatorModule import execute
- from web import form
- # templete floder
- render = web.template.render('templates/')
- # url tables
- urls = ('/', 'index',
- '/manualcontroller', 'manualcontroller',
- '/temperature', 'temperature',
- '/humidity', 'humidity'
- )
- class index:
- def GET(self):
- return render.index()
- class temperature:
- def GET(self):
- db1 = db()
- rs = db1.execute('select * from temperature order by id desc limit 20')
- return render.temperature(rs)
- class humidity:
- def GET(self):
- db1 = db()
- rs = db1.execute('select * from humidity order by id desc limit 20')
- return render.humidity(rs)
- class manualcontroller:
- def GET(self):
- return web.seeother('/')
- def POST(self):
- i = web.input()
- print i.switcher1, i.servor1, i.led1
- if i.servor1 != "":
- if int(i.servor1)>=0 and int(i.servor1) <=180:
- execute("d",i.servor1)
- elif i.led1 != "":
- if i.led1 !="":
- execute("s",i.led1)
- elif i.switcher1 != "":
- if i.switcher1 == "1" or i.switcher1 == "0" :
- execute("b",i.switcher1)
- return web.seeother('/')
- class db:
- def __init__(self):
- self.db = sqldb()
- def insert(self,table,values):
- return
- def delete(self,table,index):
- return
- def update(self,table,index,values):
- return
- def select(self,table,index):
- i = (table,index)
- sql = 'select * from %s where id = %d'%(table,index)
- self.db.cu.execute(sql)
- rs = self.db.cu.fetchall()
- self.db.conn.commit()
- return rs
- def execute(self,sql):
- self.db.cu.execute(sql)
- rs = self.db.cu.fetchall()
- self.db.conn.commit()
- return rs
-
-
- class sqldb:
- def __init__(self):
- self.db = 'db.db'
- if os.path.exists(self.db):
- self.conn = sqlite3.connect(self.db)
- self.cu = self.conn.cursor()
- else:
- self.conn = sqlite3.connect(self.db)
- self.cu = self.conn.cursor()
- self.cu.execute(
- 'create table sensors(id integer primary key autoincrement,date text,value text)')
- self.cu.execute(
- 'insert into sensors values(null,\'2016-1-1 12:00:00\',\'32\')')
- self.cu.execute(
- 'create table actuators(id integer primary key autoincrement,date text,value text)')
- self.cu.execute(
- 'insert into actuators values(null,\'2016-1-1 12:00:02\',\'open AC ato 26\')')
- self.conn.commit()
- if __name__ == '__main__':
- app = web.application(urls, globals())
- app.run()
复制代码 采用上诉方法开启服务器之后,智能内网访问web服务,为了达到外网操作的能力,需要使用花生壳的动态IP的映射的服务。
花生棒
一般家庭使用的网络均是动态变更IP地址的,外网访问不方便。这里使用花生棒来保证外网访问内网的能力。需要在oray注册账号,并购买花生棒,绑定账号,指定内网IP和Port对外共享,之后就可以在外网使用内网服务了。
DHT11
系统目前还只具备接受和解析指令控制外围设备的功能,不能从周围环境探测信号。现在我们增加个简单的温湿度探测器,连接到Arduino上,然后将接受的数据通过串口传递到cb上。
DHT引脚如图所示**,自左至右分别是+5V,data,nc,Gnd。连线比较简单,电源接好后,data线连接到Arduino的引脚9上就行了。需要添加的程序如下。- #include <dht11.h>
- dht11 DHT11;
- #define DHT11PIN 9
- float humidity = 0.0;
- float temperature = 0.0;
- 主程序中:
- int chk = DHT11.read(DHT11PIN);
- switch (chk)
- {
- case DHTLIB_OK:
- break;
- case DHTLIB_ERROR_CHECKSUM:
- break;
- case DHTLIB_ERROR_TIMEOUT:
- break;
- default:
- break;
- }
- humidity = (float)DHT11.humidity;
- temperature = (float)DHT11.temperature;
复制代码 |
|