9873|3

232

帖子

5

TA的资源

一粒金砂(高级)

楼主
 

一起玩树莓派3+体验物联网云服务 [复制链接]

本帖最后由 x1816 于 2016-11-12 10:38 编辑 Raspberry Pi 3拥有一组GPIO接口,上面有SPI、I2C等常用的总线接口,还集成了蓝牙功能,可以比较方便地连接各种传感器件,另外其无线网络可以很轻松的连接到各大云平台。
通过本文可以搭建的系统结构图:
之前的分享一直把Raspberry Pi作为一个小服务器使用,对用户提供服务。而这篇分享会把Raspberry Pi用作一个物联网接入的网关,并利用GPIO,衔接传感器和物联网平台。 接入外部传感器 与其精挑细选,犹豫再三,不如立即行动。手边正好有个传感器模块,看看能不能接到Raspberry Pi上。 名称是BH1750数字环境光强度传感器
模块通过3.3V供电,使用I2C总线通信,连接到Raspberry Pi上的供电口和I2C接口就可以了(ADDR是地址线,这里接地)。 用i2cdetect –y 1看一下,确认已经连上:
看到那个23,说明接线都正确了,接下来就要写程序读取传感器数据了。 一种方法是读datasheet,慢慢调试。但是bh1750不是特别新的传感器,已经有热心网友写好了类库,我找了一个python版本的(bh1750.py)。
  1. https://gist.github.com/oskar456/95c66d564c58361ecf9f
复制代码
  1. #!/usr/bin/python2
  2. # vim: expandtab ts=4 sw=4
  3. # Inspired by http://www.raspberrypi-spy.co.uk/2015/03/bh1750fvi-i2c-digital-light-intensity-sensor/
  4. import smbus
  5. import time
  6. class BH1750():
  7. """ Implement BH1750 communication. """
  8. # Define some constants from the datasheet
  9. POWER_DOWN = 0x00 # No active state
  10. POWER_ON = 0x01 # Power on
  11. RESET = 0x07 # Reset data register value
  12. # Start measurement at 4lx resolution. Time typically 16ms.
  13. CONTINUOUS_LOW_RES_MODE = 0x13
  14. # Start measurement at 1lx resolution. Time typically 120ms
  15. CONTINUOUS_HIGH_RES_MODE_1 = 0x10
  16. # Start measurement at 0.5lx resolution. Time typically 120ms
  17. CONTINUOUS_HIGH_RES_MODE_2 = 0x11
  18. # Start measurement at 1lx resolution. Time typically 120ms
  19. # Device is automatically set to Power Down after measurement.
  20. ONE_TIME_HIGH_RES_MODE_1 = 0x20
  21. # Start measurement at 0.5lx resolution. Time typically 120ms
  22. # Device is automatically set to Power Down after measurement.
  23. ONE_TIME_HIGH_RES_MODE_2 = 0x21
  24. # Start measurement at 1lx resolution. Time typically 120ms
  25. # Device is automatically set to Power Down after measurement.
  26. ONE_TIME_LOW_RES_MODE = 0x23
  27. def __init__(self, bus, addr=0x23):
  28. self.bus = bus
  29. self.addr = addr
  30. self.power_down()
  31. self.set_sensitivity()
  32. def _set_mode(self, mode):
  33. self.mode = mode
  34. self.bus.write_byte(self.addr, self.mode)
  35. def power_down(self):
  36. self._set_mode(self.POWER_DOWN)
  37. def power_on(self):
  38. self._set_mode(self.POWER_ON)
  39. def reset(self):
  40. self.power_on() #It has to be powered on before resetting
  41. self._set_mode(self.RESET)
  42. def cont_low_res(self):
  43. self._set_mode(self.CONTINUOUS_LOW_RES_MODE)
  44. def cont_high_res(self):
  45. self._set_mode(self.CONTINUOUS_HIGH_RES_MODE_1)
  46. def cont_high_res2(self):
  47. self._set_mode(self.CONTINUOUS_HIGH_RES_MODE_2)
  48. def oneshot_low_res(self):
  49. self._set_mode(self.ONE_TIME_LOW_RES_MODE)
  50. def oneshot_high_res(self):
  51. self._set_mode(self.ONE_TIME_HIGH_RES_MODE_1)
  52. def oneshot_high_res2(self):
  53. self._set_mode(self.ONE_TIME_HIGH_RES_MODE_2)
  54. def set_sensitivity(self, sensitivity=69):
  55. """ Set the sensor sensitivity.
  56. Valid values are 31 (lowest) to 254 (highest), default is 69.
  57. """
  58. if sensitivity < 31:
  59. self.mtreg = 31
  60. elif sensitivity > 254:
  61. self.mtreg = 254
  62. else:
  63. self.mtreg = sensitivity
  64. self.power_on()
  65. self._set_mode(0x40 | (self.mtreg >> 5))
  66. self._set_mode(0x60 | (self.mtreg & 0x1f))
  67. self.power_down()
  68. def get_result(self):
  69. """ Return current measurement result in lx. """
  70. data = self.bus.read_word_data(self.addr, self.mode)
  71. count = data >> 8 | (data&0xff)<<8
  72. mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1
  73. ratio = 1/(1.2 * (self.mtreg/69.0) * mode2coeff)
  74. return ratio*count
  75. def wait_for_result(self, additional=0):
  76. basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128
  77. time.sleep(basetime * (self.mtreg/69.0) + additional)
  78. def do_measurement(self, mode, additional_delay=0):
  79. """
  80. Perform complete measurement using command
  81. specified by parameter mode with additional
  82. delay specified in parameter additional_delay.
  83. Return output value in Lx.
  84. """
  85. self.reset()
  86. self._set_mode(mode)
  87. self.wait_for_result(additional=additional_delay)
  88. return self.get_result()
  89. def measure_low_res(self, additional_delay=0):
  90. return self.do_measurement(self.ONE_TIME_LOW_RES_MODE, additional_delay)
  91. def measure_high_res(self, additional_delay=0):
  92. return self.do_measurement(self.ONE_TIME_HIGH_RES_MODE_1, additional_delay)
  93. def measure_high_res2(self, additional_delay=0):
  94. return self.do_measurement(self.ONE_TIME_HIGH_RES_MODE_2, additional_delay)
  95. def main():
  96. #bus = smbus.SMBus(0) # Rev 1 Pi uses 0
  97. bus = smbus.SMBus(1) # Rev 2 Pi uses 1
  98. sensor = BH1750(bus)
  99. while True:
  100. print "Sensitivity: {:d}".format(sensor.mtreg)
  101. for measurefunc, name in [(sensor.measure_low_res, "Low Res "),
  102. (sensor.measure_high_res, "HighRes "),
  103. (sensor.measure_high_res2, "HighRes2")]:
  104. print "{} Light Level : {:3.2f} lx".format(name, measurefunc())
  105. print "--------"
  106. sensor.set_sensitivity((sensor.mtreg + 10) % 255)
  107. time.sleep(1)
  108. if __name__=="__main__":
  109. main()
复制代码
写一个bh1750_test.py简单测试一下:
  1. # -*- coding: utf-8 -*-
  2. from bh1750 import BH1750
  3. import smbus
  4. bus = smbus.SMBus(1) # Rev 2 Pi uses 1
  5. bhsensor = BH1750(bus)
  6. bhsensor.set_sensitivity(254)
  7. result = bhsensor.measure_high_res()
  8. print int(result)
复制代码
工作正常,可以读取光照值。 另外加个CPU温度的监控吧: Raspberry Pi的CPU温度可以通过如下代码获得:
  1. # -*- coding: utf-8 -*-
  2. # 打开文件
  3. file = open("/sys/class/thermal/thermal_zone0/temp")
  4. # 读取结果,并转换为浮点数
  5. temp = float(file.read()) / 1000
  6. # 关闭文件
  7. file.close()
  8. # 向控制台打印
  9. print "temp : %.1f" %temp
复制代码
本质上就是读取一个文件,结果如下(有小风扇吹着,温度不高):
接入云平台服务 接下来该推送到云端,先找个云平台注册。 我使用的是中国移动物联网开放平台OneNET:
  1. http://open.iot.10086.cn
复制代码
网站上有详细的教程,说明如何接入,这里就不重复说明了。 主要流程是创建一个产品,产品下面接入设备,每个设备可以设置多个数据流。 这里创建2个数据流:
  1. bh1750
  2. cputemp
复制代码
用来接收上述2个传感器的数据。 注意创建后,记下设备ID,是7位数字,还有APIkey,相当于接入密钥。 然后在Raspberry Pi上编写访问云平台的代码(文件名iot10086.py)
  1. # -*- coding: utf-8 -*-
  2. import requests
  3. import json
  4. #接入类:中国移动物联网开放平台http://open.iot.10086.cn/
  5. class Iot10086(object):
  6. #api-key
  7. apikey =''
  8. #apiurl只能精确到项目----设备,设备下的datastream在set_data时指定
  9. apiurl=''
  10. def __init__(self,apikey,apiurl):
  11. self.apikey = apikey
  12. self.apiurl = apiurl
  13. self.apiheaders={'api-key':apikey}
  14. #设置传感器
  15. def set_data(self,datastream,value):
  16. apiurl_set = self.apiurl + '?type=3' #上传用的url要加上type3
  17. payload={datastream:str(value)}
  18. r=requests.post(apiurl_set, headers=self.apiheaders, data=json.dumps(payload), timeout=30)
  19. return r.status_code
  20. #获取传感器数值(返回dict)
  21. def get_data(self,datastream):
  22. apiurl_get = self.apiurl + '?datastream_id=' + datastream
  23. r=requests.get(apiurl_get, headers=self.apiheaders, timeout=20)
  24. if r.status_code == 200:
  25. return json.loads(r.text)
  26. else:
  27. return r.status_code
复制代码
通过HTTP接入,只需要构造合适的HTTP请求就可以了。 最后编写主程序,把获取传感器数据,推送到云端等流程写好(主程序名称:main_iot10086.py):
  1. # -*- coding: utf-8 -*-
  2. from iot10086 import Iot10086
  3. import datetime
  4. from bh1750 import BH1750
  5. import smbus
  6. apikey ='xxxxxxxxxxxxxxxxxxxxxxxxxxxx' #这里要输入默认APIKEY,默认关联本产品所有设备
  7. apiurl='http://api.heclouds.com/devices/xxxxxxx/datapoints'#这个apiurl里的设备ID是云平台上可以查到。
  8. iot = Iot10086(apikey,apiurl)
  9. ################################################################
  10. #处理bh1750数据
  11. ################################################################
  12. #获取时间戳
  13. timestamp = datetime.datetime.now().isoformat()[0:19] #获取ISO8601格式时间,如2016-12-30T11:00:00
  14. print timestamp
  15. #获取BH1750传感器数据
  16. bus = smbus.SMBus(1)
  17. bhsensor = BH1750(bus)
  18. bhsensor.set_sensitivity(254)
  19. bh1750_result = '%.1f'%bhsensor.measure_high_res()
  20. print 'bh1750_result = ' + bh1750_result
  21. #上传到iot10086
  22. iot_post_status =iot.set_data('bh1750', bh1750_result)
  23. print iot_post_status
  24. #读回iot10086记录
  25. #iot_result = iot.get_data('bh1750')
  26. #print 'iot_result = ',iot_result
  27. ################################################################
  28. #处理CPU Temperature数据
  29. ################################################################
  30. #获取时间戳
  31. timestamp = datetime.datetime.now().isoformat()[0:19] #获取ISO8601格式时间,如2016-12-30T11:00:00
  32. print timestamp
  33. #获取CPU temperature 数据
  34. #打开文件
  35. file = open("/sys/class/thermal/thermal_zone0/temp")
  36. # 读取结果,并转换为浮点数
  37. cputemp_result = '%.1f'%(float(file.read()) / 1000)
  38. # 关闭文件
  39. file.close()
  40. print 'cputemp_result = ', cputemp_result
  41. #上传到iot10086
  42. iot_post_status =iot.set_data('cputemp', cputemp_result)
  43. print iot_post_status
复制代码
测试一下程序,如果iot_post_status返回200,就成功了,在云平台的数据查看页面上应该也能实时看到推送的数据。 定时执行 上面的程序执行一次只能推送当前时间点的一次数据,并不具备周期性执行的功能。 要定时执行这个程序,可以用Linux的计划任务cron程序。 Raspberry Pi上的cron程序默认已经开启,我们只需要编写需要执行的内容就可以了。 执行:
  1. crontab –l
复制代码
注意不用加sudo,我们的程序以pi用户运行就可以了。 首次运行需要选择一个编辑器打开,在末尾加上一行:
  1. */1 * * * * /usr/bin/python /home/pi/IOTpy/main_iot10086.py >/dev/null 2>&1

复制代码
表示每分钟运行1次,注意程序要写完整路径。最后的>/dev/null 2>&1是输出重定向,程序是后台运行,把输出丢弃。 查看结果 运行一段时间后,云平台上应该已经收到不少数据了。用云平台的应用管理功能,在线创建一个简单的应用,方便查看数据:

最新回复

谢谢分享  详情 回复 发表于 2018-1-26 13:32

赞赏

1

查看全部赞赏

点赞 关注(1)

回复
举报

1059

帖子

1

TA的资源

版主

沙发
 
很好,不错,谢谢分享
 
 

回复

6107

帖子

4

TA的资源

版主

板凳
 
谢谢分享,看看那个云平台去!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
谢谢分享
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表