一个有点物联网感觉的作品。原理是使用温度传感器(模拟输出)得到当前温度,网络上传,网络显示。
因为是模拟输出,raspberry pi不能直接使用。简单起见,直接用Arudino作为ADC,和raspberry pi串口通信。
网络上传是raspberry pi的强项。再加上我给raspberry pi装了无线USB网卡,更加方便,直接电源输入即可。
网络显示依赖于网络上传,本次使用的是yeelink的服务。提供类似温度记录的功能。直接拿来使用了。
温度收集部分,为了调试,增加了LCD用于显示当前温度。
raspberry pi部分。使用绿灯表示上传成功,红灯表示上传失败。实际运行没一次失败……
串口通信其实很简单,把USB相连即可。通讯上采用raspberry pi发一次请求,Arduino回应一次的被动方式。
raspberry pi的代码
import serial
import RPi.GPIO as GPIO
import datetime
from time import sleep
import httplib
PIN_LED_PASSED=22
PIN_LED_FAILED=23
API_KEY='API_KEY_HERE'
HOST='api.yeelink.net'
URI='/v1.0/device/15530/sensor/26740/datapoints'
def loop(s):
s.writelines(['G']) # send serial command to get current temperature
c = s.readline().strip()
if not c:
return
now = datetime.datetime.now().isoformat()
print '[INFO]', now, c
if send_sensor_data(now, c):
GPIO.output(PIN_LED_PASSED, GPIO.HIGH)
else:
GPIO.output(PIN_LED_FAILED, GPIO.HIGH)
sleep(1)
GPIO.output(PIN_LED_PASSED, GPIO.LOW)
GPIO.output(PIN_LED_FAILED, GPIO.LOW)
sleep(10) # sleep 10 seconds for yeelink limit(> 10s after previous request)
def send_sensor_data(timestamp, value):
payload = '{"timestamp":"' + timestamp + '","value":' + value + '}'
headers = {'U-ApiKey': API_KEY}
conn = httplib.HTTPConnection(HOST)
conn.request('POST', URI, payload, headers)
resp = conn.getresponse()
conn.close()
if resp.status == 200:
return True
else:
print '[WARN] failed to send sensor data,', resp.reason
return False
if __name__ == '__main__':
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_LED_PASSED, GPIO.OUT)
GPIO.setup(PIN_LED_FAILED, GPIO.OUT)
s = serial.Serial('/dev/ttyACM0', 9600, timeout = 1)
s.open()
print '[INFO] sensor data collector start'
try:
while True:
loop(s)
except KeyboardInterrupt:
s.close()
GPIO.cleanup()
Arduino的代码
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// TMP sensor connect to A0
#define PIN_TMP 0
int analogValue = 0;
float voltage = 0;
float celsius = 0;
int serialCmd;
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
Serial.begin(9600);
lcd.init();
// lcd.backlight();
lcd.print("ALL CLEAR!");
}
void loop() {
analogValue = analogRead(PIN_TMP);
voltage = analogValue * 5000.0 / 1024;
celsius = (voltage - 500) / 10;
// show temperature on LCD
lcd.clear();
lcd.print(celsius);
// send to serial if necessary
if(Serial.available() && Serial.read() == 71 /* G */) {
Serial.println(celsius);
}
delay(1000);
}


