5.19 综合案例2.0-智能风扇(仅支持2.2以上版本)

最新案例教程点击下方链接跳转,CSDN已停止更新

点击跳转HaaS506官方最新案例







简介

日常生活中,我们经常需要一些通过风扇降温的场景,比如说机房,电脑主机等等。人为的去打开或者关闭风扇,调节档位,操作起来不是很方便。本案例通过一个温度传感器实时的采集当前温度,然后依据温度值,动态调节风扇速度。
本案例通过一个温度传感器实时采集当前温度,然后依据温度值,动态的调节风扇的转速和开关,同时我们可以通过手机app实时的控制风扇转速所对应的温度档位,实现对风扇的远程控制,既能方便我们控制风扇,也能有效的节能,绿色环保。

AHT10温湿度传感器

  • 模块说明
产品型号AHT10
供电电压1.8-3.6V(DC)
测量范围(湿度)0~99.9%RH
测量范围(温度)-40~+85℃
湿度精度±2%RH(25℃)
温度精度±0.3℃
分辨率温度:0.1℃,湿度:0.1%RH
输出信号I2C信号

在这里插入图片描述
在这里插入图片描述

电机模块

这类模块集成了驱动芯片,我们不必分开购买马达、扇叶和L9110模块。通过PWM脉冲宽度来调节电机转速。
在这里插入图片描述
电机上有四个接口:

  • VCC:电源正极,接树莓派的 5V 接口。

  • GND:电源负极,接树莓派任意一个 GND 口。

  • INA 和 INB :两个控制口。驱动的核心就落在两个输入引脚上。

     INA 为高电平,INB 为低电平时——正转;
     INA 为低电平,INB 为高电平时——反转。
     单独只接其中一个接口也能控制
    

准备

本案例需要的硬件

器材数量
HaaS506开发板1
AHT10温湿度传感器1
电机模块1
SIM卡1
杜邦线若干

硬件连接图

在这里插入图片描述

代码流程

1、连接阿里云平台。
2、开机上传一次内置的温度阈值,并持续读取并上传当前温湿度传感器读取的温度数值
3、设置云端回调,接收来自云端的数据,更改程序中的判断数值

功能实现

1、物联网平台开发

第一次使用物联网平台的读者,需要开通实例后使用物联网平台功能。也可以使用免费的公共实例进行开发,在阿里云物联网平台中,左上角选择‘华东2-上海’,点击‘公共实例’,即可开通。

1、平台产品创建可参考haas506 2.0开发教程-aliyunIoT
2、创建产品属性(添加物模型)

  • 选择产品功能定义编辑草稿
    在这里插入图片描述
  • 添加自定义功能
  • 添加标识符数据类型(标识符要与代码一致)
  • 点击发布上线
    在这里插入图片描述
  • 点击确定
    在这里插入图片描述

2、设备端开发

  • 第一次使用开发板的读者可以按照haas5062.0开发教程-导学篇搭建开发环境。

  • 搭建完后复制以下代码到Visual Studio Code,复制产品证书到代码相应位置。
    在这里插入图片描述

  • 2.2版本获取IMEI号接口有更新,需要更改以下内容(Ctrl+F 查找modem)

# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.info.getDevImei()
...

  • main.py
# coding=utf-8
from ahtx0 import AHT10
from driver import PWM
import network
import ujson
import utime as time
import modem
from  aliyunIoT import Device
import kv


# 警报开关以及时间段控制
gear1_temp = 22
gear2_temp = 27
gear3_temp = 32
FLAG_CUR_TEMP = "temp"
FLAG_GEAR1 = "gear1"
FLAG_GEAR2 = "gear2"
FLAG_GEAR3 = "gear3"
cur_gear = 0


#当iot设备连接到物联网平台的时候触发'connect' 事件
def on_connect(data):
    global module_name,default_ver,productKey,deviceName,deviceSecret,on_trigger,on_download,on_verify,on_upgrade
    print('***** connect lp succeed****')
    data_handle = {}
    data_handle['device_handle'] = device.getDeviceHandle()


#当连接断开时,触发'disconnect'事件
def on_disconnect():
    print('linkkit is disconnected')


#当iot云端下发属性设置时,触发'props'事件
def on_props(request):
    global FLAG_GEAR1, FLAG_GEAR2, FLAG_GEAR3,FLAG_CUR_TEMP,gear1_temp, gear2_temp, gear3_temp,temp
    params=request['params']
    data_all=eval(params)
    if FLAG_GEAR1 in data_all :
        gear1_temp = data_all[FLAG_GEAR1]
        value_gears()
    if FLAG_GEAR2 in data_all :
        gear2_temp = data_all[FLAG_GEAR2]
        value_gears()  
    if FLAG_GEAR3 in data_all :
        gear3_temp = data_all[FLAG_GEAR3]
        value_gears()            
    if FLAG_CUR_TEMP in data_all:
        temp = data_all[FLAG_CUR_TEMP]
        upload_temp()

#当iot云端调用设备service时,触发'service'事件
def on_service(id,request):
    print('clound req id  is {} , req is {}'.format(id,request))
#当设备跟iot平台通信过程中遇到错误时,触发'error'事件
def on_error(err):
    print('err msg is {} '.format(err))

#网络连接的回调函数
def on_4g_cb(args):
     global g_connect_status
     pdp = args[0]
     netwk_sta = args[1]
     if netwk_sta == 1:
         g_connect_status = True
     else:
         g_connect_status = False

#网络连接
def connect_network():
     global net,on_4g_cb,g_connect_status
     #NetWorkClient该类是一个单例类,实现网络管理相关的功能,包括初始化,联网,状态信息等.
     net = network.NetWorkClient()
     g_register_network = False
     if net._stagecode is not None and net._stagecode == 3 and net._subcode == 1:
         g_register_network = True
     else:
         g_register_network = False
     if g_register_network:
    #注册网络连接的回调函数on(self,id,func);  1代表连接,func 回调函数  ;return 0 成功
         net.on(1,on_4g_cb)    
         net.connect(None)
     else:
         print('网络注册失败')
     while True:
         if g_connect_status:
             print('网络连接成功')
             break
         time.sleep_ms(20)

#动态注册回调函数
def on_dynreg_cb(data):
     global deviceSecret,device_dyn_resigter_succed
     deviceSecret = data
     device_dyn_resigter_succed = True


 # 连接物联网平台
def dyn_register_device(productKey,productSecret,deviceName):
    global on_dynreg_cb,device,deviceSecret,device_dyn_resigter_succed
    key = '_amp_customer_devicesecret'
    deviceSecretdict = kv.get(key)
    print("deviceSecretdict:",deviceSecretdict)
    if isinstance(deviceSecretdict,str):    
        deviceSecret = deviceSecretdict 

    if deviceSecretdict is None or deviceSecret is None:
        key_info = {
            'productKey': productKey  ,
            'productSecret': productSecret ,
            'deviceName': deviceName
            }
        # 动态注册一个设备,获取设备的deviceSecret
        #下面的if防止多次注册,当前若是注册过一次了,重启设备再次注册就会卡住,
        if not device_dyn_resigter_succed:
            device.register(key_info,on_dynreg_cb)   

def upload_date(key_value):
    data_str=ujson.dumps(key_value)
    data={
        'params':data_str
        }      
    device.postProps(data)
    value_data.clear()


value_data = {}
def upload_temp():
    global value_data,temp,FLAG_CUR_TEMP
    value_data[FLAG_CUR_TEMP]=temp
    upload_date(value_data)
    
def value_gears():
    global FLAG_GEAR1,FLAG_GEAR2,FLAG_GEAR3,gear1_temp, gear2_temp, gear3_temp,value_data
    value_data[FLAG_GEAR1]=gear1_temp
    upload_date(value_data)
    value_data[FLAG_GEAR2]=gear2_temp
    upload_date(value_data)
    value_data[FLAG_GEAR3]=gear3_temp
    upload_date(value_data)

#电机控制
def control(gear):
    if not isinstance(gear,int):
        raise ValueError("gear is not an int object")
    if not gear in range(4):
        raise ValueError("gear must be in range 0-3")
    if gear == 0:
        duty= 0
    if gear == 1:
        duty= 33
    if gear == 2:
        duty= 66
    if gear == 3:
        duty= 99
    param = {'freq':3000, 'duty': duty }
    pwm_pwm.setOption(param)


if __name__ == '__main__':
    ICCID=None
    g_connect_status = False
    net = None
    device = None
    deviceSecret = None
    deviceName = None
    #替换下列产品信息
    ###################################    
    productKey = "a1A9j0EmrQr"
    productSecret = "21ATZN5PR2iuv08w"
    ###################################
    device_dyn_resigter_succed = False

    # 连接网络
    connect_network()
     # 获取设备的IMEI 作为deviceName 进行动态注册
    #2.2版本改为
    #deviceName = modem.info.getDevImei()
    deviceName = modem.getDevImei()
    #获取设备的ICCID
    ICCID=modem.sim.getIccid()
    #初始化物联网平台Device类,获取device实例
    device = Device()
    if deviceName is not None and len(deviceName) > 0 :
     #动态注册一个设备
        dyn_register_device(productKey,productSecret,deviceName)
    else:
        print("获取设备IMEI失败,无法进行动态注册")
    while deviceSecret is None:
        time.sleep(0.2)
    print('动态注册成功:' + deviceSecret)

    key_info = {
        'region' : 'cn-shanghai' ,
        'productKey': productKey ,
        'deviceName': deviceName ,
        'deviceSecret': deviceSecret ,
        'keepaliveSec': 60,
        }
    #打印设备信息
    print(key_info)

    #device.ON_CONNECT 是事件,on_connect是事件处理函数/回调函数
    device.on(device.ON_CONNECT,on_connect)
    device.on(device.ON_DISCONNECT,on_disconnect)
    device.on(device.ON_PROPS,on_props)
    device.on(device.ON_SERVICE,on_service)
    device.on(device.ON_ERROR,on_error)
    device.connect(key_info)

    #主程序
    time.sleep(2)
    value_gears()
    print('start work')
    #初始化温度传感器
    a=AHT10()
    #set mode(℃ or F)
    a.set_mode(0)
    #初始化电机模块
    pwm_pwm = PWM()
    pwm_pwm.open("pwm_pwm")
    while True:
        time.sleep_ms(200)
        temp =  a.temperature()  #获取温度信息
        print('cur temp is {}'.format(temp))
        upload_temp()
        if temp <= gear1_temp and cur_gear != 0:
            cur_gear = 0
            control(cur_gear)
            print('fan change to gear {}'.format(cur_gear))
        elif temp > gear1_temp and temp <= gear2_temp and cur_gear != 1:
            cur_gear = 1
            control(cur_gear)
            print('fan change to gear {}'.format(cur_gear))
        elif temp > gear2_temp and temp <= gear3_temp and cur_gear != 2:
            cur_gear = 2
            control(cur_gear)
            print('fan change to gear {}'.format(cur_gear))
        elif temp > gear3_temp and cur_gear != 3:
            cur_gear = 3
            control(cur_gear)
            print('fan change to gear {}'.format(cur_gear))



ahtx0.py

import utime as time
from driver import I2C

#CONSTANTS
AHT10_ADDRESS = 0x38     # 0111000 (7bit address)
AHT10_READ_DELAY_MS = 75 # Time it takes for AHT to collect data
AHT_TEMPERATURE_CONST = 200
AHT_TEMPERATURE_OFFSET = 50
KILOBYTE_CONST = 1048576
CMD_INITIALIZE = bytearray([0xE1, 0x08, 0x00])
CMD_MEASURE = bytearray([0xAC, 0x33, 0x00])
FARENHEIT_MULTIPLIER = 9/5
FARENHEIT_OFFSET = 32

class AHT10:
    def __init__(self,  mode=0, address=AHT10_ADDRESS):
        self.i2c = I2C()
        self.i2c.open('aht10')

        self.address = address
        writeBuf=bytearray(4)
        writeBuf[0]=self.address
        writeBuf[1]=CMD_INITIALIZE[0]
        writeBuf[2]=CMD_INITIALIZE[1]
        writeBuf[3]=CMD_INITIALIZE[2]
        self.i2c.write(writeBuf)

        self.readings_raw = bytearray(8)
        self.results_parsed = [0, 0]
        self.mode = mode      # 0 for Celsius(摄氏度), 1 for Farenheit(华氏度)

    def read_raw(self):
        writeBuf=bytearray(4)
        writeBuf[0]=self.address
        writeBuf[1]=CMD_MEASURE[0]
        writeBuf[2]=CMD_MEASURE[1]
        writeBuf[3]=CMD_MEASURE[2]
        self.i2c.write(writeBuf)

        time.sleep_ms(AHT10_READ_DELAY_MS)
        readBuf=bytearray(6)
        readBuf[0]=AHT10_ADDRESS
        self.i2c.read(readBuf)
        self.readings_raw[0]=readBuf[0]
        self.readings_raw[1]=readBuf[1]
        self.readings_raw[2]=readBuf[2]
        self.readings_raw[3]=readBuf[3]
        self.readings_raw[4]=readBuf[4]
        self.readings_raw[5]=readBuf[5]

        self.results_parsed[0] = self.readings_raw[1] << 12 | self.readings_raw[2] << 4 | self.readings_raw[3] >> 4
        self.results_parsed[1] = (self.readings_raw[3] & 0x0F) << 16 | self.readings_raw[4] << 8 | self.readings_raw[5]

    def humidity(self):
        self.read_raw()
        return (self.results_parsed[0] / KILOBYTE_CONST) * 100 

    def temperature(self):
        self.read_raw()
        if self.mode is 0:
            return (self.results_parsed[1] / KILOBYTE_CONST) * AHT_TEMPERATURE_CONST - AHT_TEMPERATURE_OFFSET
        else:
            return ((self.results_parsed[1] / KILOBYTE_CONST) * AHT_TEMPERATURE_CONST - AHT_TEMPERATURE_OFFSET) * FARENHEIT_MULTIPLIER + FARENHEIT_OFFSET

    def set_mode(self, mode):
        if mode==0 or mode==1:
            self.mode = mode
        else:    
            raise ValueError('Mode must be either 0 for Celsius or 1 Farenheit')

  • board.json
{
  "name": "haas506",
  "version": "1.0.0",
  "io": {
    "ADC0": {
      "type": "ADC",
      "port": 0,
      "sampling": 12000000
    },
    "ADC1": {
      "type": "ADC",
      "port": 1,
      "sampling": 12000000
    },
    "pwm_pwm": {
      "type": "PWM",
      "port": 39
      },
    "pwm_lpg": {
      "type": "PWM",
      "port": 3
      },
    "aht10": {
      "type": "I2C",
      "port": 1,
      "addrWidth": 7,
      "freq": 400000,
      "mode": "master",
      "devAddr": 56
    },      
    "serial1": {
      "type": "UART",
      "port": 0,
      "dataWidth": 8,
      "baudRate": 115200,
      "stopBits": 1,
      "flowControl": "disable",
      "parity": "none",
      "timeout": 1000
    },
    "serial2": {
      "type": "UART",
      "port": 1,
      "dataWidth": 8,
      "baudRate": 9600,
      "stopBits": 1,
      "flowControl": "disable",
      "parity": "none",
      "timeout": 1000
    },
    "serial3": {
      "type": "UART",
      "port": 2,
      "dataWidth": 8,
      "baudRate": 115200,
      "stopBits": 1,
      "flowControl": "disable",
      "parity": "none",
      "timeout": 1000
    }
  },
  "debugLevel": "ERROR",
  "repl": "enable",
  "replPort": 0
}


调试

1、串口调试工具log,网络连接成功动态注册成功重复打印当前温度,模式更改时打印更改的模式
在这里插入图片描述
2、云端有数据传入,打开实时刷新,显示数据会自动更新。
在这里插入图片描述

3、物联网应用开发

以下是物联网应用开发流程,接下来按以下流程介绍移动端应用的开发。

3.1新建‘普通项目’

  • 使用阿里云IoTStudio创建项目。
  • 在项目管理新建空白项目
    在这里插入图片描述
    在这里插入图片描述

3.2关联产品和设备

在这里插入图片描述
在这里插入图片描述

3.3新建‘移动应用’

在这里插入图片描述
在这里插入图片描述
点击上图红框中的‘组件’,就可以看到可用的组件列表。各组件的使用说明请参考组件说明

3.4页面设计

按顺序将组件从上到下拖到中间画布区
在这里插入图片描述
文本组件设置
在这里插入图片描述

开关组件设置

  • 配置数据源
    在这里插入图片描述
    在这里插入图片描述
  • 配置交互
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    同样的方法,配置其他两个数字框
    在这里插入图片描述
    在这里插入图片描述
  • 数字框三
    在这里插入图片描述
    在这里插入图片描述
    实时曲线组件设置
    在这里插入图片描述
    在这里插入图片描述

3.5预览和发布上线

在页面‘’保存‘’并点击‘预览’进行预览。
在这里插入图片描述
手机扫描二维码,可以在手机进行设置并查看实时温度数据。
在这里插入图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值