3. 虚谷号和Arduino的自定义通讯¶
3.1. 原理简介¶
虚谷号和板载Arduino的通讯,是通过串口来实现的。xugu库也是基于Firmata协议开发,跑在串口协议上。
3.2. 应用场景¶
xugu库支持的传感器主要分为两类,一是开关量(也称数字)传感器,返回高低电平;二是模拟传感器,返回0-5V之间的电压。
除了这两类的传感器,还有数字型传感器,如DH11温湿度传感器,DS18B20温度传感器。这些传感器无法使用xugu库,如果项目中用到这类传感器,就需要另写代码,自定义通讯协议。
3.3. 范例:DH11传感器实验¶
Arduino接DH11传感器,将数据通过串口发送给虚谷号。虚谷号使用Python代码,将串口信息打印出来。
1.Arduino代码
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain
#include "DHT.h"
#define DHTPIN 13 // what pin we're connected to
// Uncomment whatever type you're using!
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
}
void loop() {
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
//String cmd=serial_command();
String cmd="";
while(1){
if(Serial.available()){
cmd+=char(Serial.read());
delay(2);
}else{break;}
}
cmd.replace("\n","");
cmd.replace("\0","");
if(cmd=="PING"){
Serial.print("OK");
}
//delay(2000);
float h = dht.readHumidity();
float t = dht.readTemperature();
//lcd.clear();
// check if returns are valid, if they are NaN (not a number) then something went wrong!
if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
} else {
Serial.print(h);
Serial.print(t);
}
delay(150);
}
2.Python代码
import serial
import time
import subprocess
import os
arduino_serial=serial.Serial('/dev/ttyS1',115200)
arduino_serial.close()
time.sleep(0.5)
arduino_serial.open()
time.sleep(0.5)
def arduino_burn():
"""
:return:
"""
subprocess.call("arduino_burn.sh /home/scope/Desktop/DHT11/DHT11.ino /home/scope/software/log/arduino_burn_log.txt", shell=True)
def serial_send(msg):
global arduino_serial
msg=msg.encode("utf-8")
arduino_serial.write(msg)
time.sleep(0.01)
def serial_receive(pin_num = '1'):
global arduino_serial
receiver=arduino_serial.read_all()
if receiver:
if b'\0' not in receiver:
receiver=receiver.decode("utf-8")
if '\r\n' in receiver:
receiver = receiver.replace('\r\n', '')
return receiver
else:
return -1
def check_protocol():
serial_send("PING")
time.sleep(1)
receiver=serial_receive()
if("OK" not in str(receiver)):
print("not found firmata protocol, burn it.")
arduino_burn()
print("burn complete")
def getTempandHum():
"""
读取温度和湿度
"""
value = serial_receive()
if value != -1:
humi = value[:5]
Temp = value[-5:]
print("温度:%s 湿度:%s%%"%(Temp,humi))
check_protocol()
while True: #创建一个循环
getTempandHum()
time.sleep(1)
3.4. 高级技巧¶
在Python代码中自动检测Arduino,并调用烧写工具。
3.5. 参考范例:灯带控制¶
import serial
import time
import subprocess
import os
arduino_serial=serial.Serial('/dev/ttyS1',9600)
arduino_serial.close()
time.sleep(0.5)
arduino_serial.open()
time.sleep(0.5)
def arduino_burn():
"""
:return:
"""
path=os.getcwd()
subprocess.call("arduino_burn.sh /home/scope/Desktop/Neo_xugu_test/Arduino_NeoPixel/Arduino_NeoPixel.ino /home/scope/software/log/arduino_burn_log.txt", shell=True)
def serial_send(msg):
global arduino_serial
msg=msg.encode("utf-8")
print(msg)
arduino_serial.write(msg)
def serial_receive():
global arduino_serial
receiver=arduino_serial.read_all()
receiver=receiver.decode("utf-8")
return receiver
def check_protocol():
serial_send("PING")
time.sleep(1)
receiver=serial_receive()
if(receiver!="OK"):
print("not found firmata protocol, burn it.")
arduino_burn()
print("burn complete")
def set_pixel(index,r,g,b):
index=str(index)
r=str(r)
g=str(g)
b=str(b)
cmd="N"+index+"R"+r+"G"+g+"B"+b+";"
serial_send(cmd)
check_protocol()
while True:
a=0
while a <8:
for i in range(8):
if i==a:
set_pixel(i,200,200,0)
else:
set_pixel(i,0,0,0,)
time.sleep(1)
a+=1
if(__name__=="__main__"):
print("please import this file to python program")