一个有点物联网感觉的作品。原理是使用温度传感器(模拟输出)得到当前温度,网络上传,网络显示。
因为是模拟输出,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); }