基于STM32+华为云IOT设计的智慧路灯

发布者:RadiantSerenity最新更新时间:2024-03-25 来源: elecfans关键字:STM32  智慧路灯 手机看文章 扫描二维码
随时随地手机看文章


随着工业和城市的快速发展,道路照明系统的产业也在迅速发展,并趋于复杂化,为了更经济地控制和维护复杂的路灯系统,市面上各大科技公司开发了各种路灯控制系统,并且路灯都连上物联网云端,连上了政府网络,可以远程了解路灯的工作情况,运行情况。
为了方便了解物联网平台,学习物联网开发,了解智慧路灯的开发,本文就采用华为云IOT物联网平台,选择STM32作为主控芯片,再配合相关的传感器完成智慧路灯开发。

2. 具体实现的功能以及相关的硬件

当前设计的智慧路灯采用NBIOT模块-BC20连接华为云物联网服务器,上传路灯的各种参数信息:环境光强度、太阳能充电板电压、锂电池电量等信息。设计了一款手机APP,可以通过华为云物联网平台的应用侧提供的开发接口,获取路灯上传的参数信息,并且可以在手机APP上远程手动控制路灯开关,设置路灯的开启和关闭时间等。 智慧路灯的的主控芯片采用STM32F103C8T6、NBIOT联网模块采用BC20,BC20内置了MQTT协议,可以通过AT指令连接物联网平台实现通信。智慧路灯采用锂电池供电,并且配有太阳能充电板,可以使用太阳进行充电补偿电量。使用了功率监控器,电池电量检测芯片,可以检测充电效率、电流、电压、电池电量等信息。BC20带了GPS功能,可以上报路灯的GPS位置到云端服务器,手机APP获取之后,可以调用百度地图显示出路灯的位置。

image.png


image.png


image.png

3. 硬件选型

3.1 STM32F103C8T6

image.png


image.png

3.2 太阳能板

image.png

3.3 锂电池充电模块

image.png

3.4 功率检测模块

image.png

3.5 BH1750光敏传感器

image.png

3.6 LED灯

image.png

3.7 BC20-NBIOT模块

型号: BC20+BD+GPS

品牌: 创思

产地: 中国大陆

接口类型: TTL

适用场景: NBIOT

尺寸: 40x40x12mm

工作电流: 0.5A

支持TCP/IP协议: 

支持传输速率: 115200Kbps

工作电压: 5V

是否支持语音电话: 否

模块类型: 其他

是否支持短信: 否

支持制式标准: GSM/GPRS(2G)

是否支持电话簿: 否


image.png

4. 创建产品与设备

4.1 创建产品

地址:https://www.huaweicloud.com/?locale=zh-cn

image.png


image.png


image.png


image.png

4.2 自定义模型

地址: https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-dev/all-product/7211833377cf435c8c0580de390eedbe/product-detail/6276134223aaf461a0f6e515

image.png


image.png


image.png


image.png


image.png


image.png


image.png


image.png


image.png

4.3 创建设备

image.png


image.png

{
    'device_id': '6276134223aaf461a0f6e515_1126626497',
    'secret': '12345678'
}

4.4 MQTT密匙生成

创建完产品、设备之后,接下来就需要知道如何通过MQTT协议登陆华为云服务器。
官方的详细介绍在这里:
https://support.huaweicloud.com/devg-iothub/iot_01_2127.html#ZH-CN_TOPIC_0240834853__zh-cn_topic_0251997880_li365284516112

属性上报格式:
https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html

image.pngimage.png

MQTT设备登陆密匙生成地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

image.png


image.png

DeviceId      	6276134223aaf461a0f6e515_1126626497
DeviceSecret 	12345678
ClientId  		6276134223aaf461a0f6e515_1126626497_0_0_2022050706
Username  		6276134223aaf461a0f6e515_1126626497
Password  		73ebe0779dbd5b2e2fd3db8ab8f642b78d7a532576f2e14d2799d4f78d37bcc8

华为云物联网平台的域名是:161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
华为云物联网平台的IP地址是:121.36.42.100
在软件里参数填充正确之后,就看到设备已经连接成功了。
接下来打开设备页面,可以看到设备已经在线了。

image.png


image.png

4.5 主题订阅与发布

//订阅主题: 平台下发消息给设备
$oc/devices/6276134223aaf461a0f6e515_1126626497/sys/messages/down
//设备上报数据
$oc/devices/6276134223aaf461a0f6e515_1126626497/sys/properties/report
//上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
{'services': [{'service_id': 'led','properties':{'GPS':'lat:12.345,lng:45.678'}}]}

通过MQTT客户端软件模拟上报测试:

image.png


image.png

4.6 应用侧开发

为了更方便的展示设备数据,与设备完成交互,还需要开发一个配套的上位机,官方提供了应用侧开发的API接口、SDK接口,为了方便通用一点,我这里采用了API接口完成数据交互,上位机软件采用QT开发。

帮助文档地址: ttps://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html

设备属性就是设备上传的传感器状态数据信息,应用侧提供了API接口,可以主动向设备端下发请求指令;设备端收到指令之后需要按照约定的数据格式上报数据;所以,要实现应用层与设备端的数据交互,需要应用层与设备端配合才能完成。

image.png


image.png

5. STM32程序设计

STM32连接华为云IOT的工程案例: https://download.csdn.net/download/xiaolong1126626497/81993720

image.png

5.1 BC20连接华为云物联网服务器-调试

image.png

连接MQTT服务器

AT+QMTOPEN=0,'a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com',1883


OK


+QMTOPEN: 0,0



登录MQTT服务器

命令格式: AT+QMTCONN=,,,

AT+QMTCONN=0,'6210e8acde9933029be8facf_dev1_0_0_2022021913','6210e8acde9933029be8facf_dev1','6cea55404b463e666cd7a6060daba745bbaa17fe7078dfef45f8151cdf19673d'


OK


+QMTCONN: 0,0,0



订阅主题

命令格式: AT+QMTSUB=,,'”,[,'”,…]


AT+QMTSUB=0,1,'$oc/devices/6210e8acde9933029be8facf_dev1/sys/messages/down',2


OK


+QMTSUB: 0,1,0,2



发布主题

命令格式:AT+QMTPUB=,,,,'',''


先发送指令: 

AT+QMTPUB=0,0,0,0,'$oc/devices/6210e8acde9933029be8facf_dev1/sys/properties/repor'


等待返回 '>' 

接着发送数据.不需要加回车。

'{'services': [{'service_id': 'gps','properties':{'longitude':12.345,'latitude':33.345}}]}'

数据发送完毕,再发送结束符。 十六进制的值--0x1a  。某些串口调试助手可以适应ctrl+z 快捷键输入0xA

等待模块返回'OK',到此数据发送完成。    

OK


+QMTPUB: 0,0,0

5.2 测试模块

第一步接上之后,串口调试助手选择波特率为115200,勾选软件上的发送新行选项。发送

AT

过去,正常模块会返回

OK


查询模块是否正常

AT


OK



获取卡号,查询卡是否插好

AT+CIMI


460041052911195


OK



激活网络

AT+CGATT=1


OK



获取网络激活状态

AT+CGATT?


+CGATT: 1


OK



查询网络质量

AT+CSQ


+CSQ: 26,0


OK

    

AT+CEREG=? //检查网络状态

+CEREG: 0,1 //找网成功

OK


5.3 keil工程代码

image.png


image.png


image.png

5.4 功率检测

#include 'INA226.h'

#include 'delay.h'

// 接线说明:

// 模拟IIC:

//IIC_SCL -- 时钟线PB6(推挽、开漏输出)

//IIC_SDA -- 双向数据线PB7

INA226 ina226_data;

//初始化INA226

void INA226_Init(void)

{


IIC_Init();

INA226_SendData(INA226_ADDR1,CFG_REG,0x8000); //重新启动

INA226_SendData(INA226_ADDR1,CFG_REG,0x484f); //设置转换时间204us,求平均值次数128,采样时间为204*128,设置模式为分流和总线连续模式

INA226_SendData(INA226_ADDR1,CAL_REG,CAL); //设置分辨率

//INA226_SendData(INA226_ADDR1,CAL_REG,0x0012);//设置分流电压转电流转换参数

INA226_Get_ID(INA226_ADDR1); //获取ina226的id

}


//设置寄存器指针

void INA226_SetRegPointer(u8 addr,u8 reg)

{

IIC_Start();


IIC_Send_Byte(addr);

IIC_Wait_Ack();


IIC_Send_Byte(reg);

IIC_Wait_Ack();


IIC_Stop();

}


//发送,写入数据

void INA226_SendData(u8 addr,u8 reg,u16 data)

{

u8 temp=0;

IIC_Start();


IIC_Send_Byte(addr);

IIC_Wait_Ack();


IIC_Send_Byte(reg);

IIC_Wait_Ack();

temp = (u8)(data>>8);

IIC_Send_Byte(temp);

IIC_Wait_Ack();


temp = (u8)(data&0x00FF);

IIC_Send_Byte(temp);

IIC_Wait_Ack();

IIC_Stop();

}


//读取数据

u16 INA226_ReadData(u8 addr)

{

u16 temp=0;

IIC_Start();


IIC_Send_Byte(addr+1);

IIC_Wait_Ack();

temp = IIC_Read_Byte(1);

temp<<=8;

temp |= IIC_Read_Byte(0);

IIC_Stop();

return temp;

}

//1mA/bit

u16 INA226_GetShunt_Current(u8 addr)

{

u16 temp=0;

INA226_SetRegPointer(addr,CUR_REG);

temp = INA226_ReadData(addr);

if(temp&0x8000) temp = ~(temp - 1);

return temp;

}


//获取id

void INA226_Get_ID(u8 addr)

{

u32 temp=0;

INA226_SetRegPointer(addr,INA226_GET_ADDR);

temp = INA226_ReadData(addr);

ina226_data.ina226_id = temp;

}


//获取校准值

u16 INA226_GET_CAL_REG(u8 addr)

{

u32 temp=0;

INA226_SetRegPointer(addr,CAL_REG);

temp = INA226_ReadData(addr);

return (u16)temp;

}


//1.25mV/bit

u16 INA226_GetVoltage(u8 addr)

{

u32 temp = 0;

INA226_SetRegPointer(addr,BV_REG);

temp = INA226_ReadData(addr);

return (u16)temp;

}


//2.5uV/bit

u16 INA226_GetShuntVoltage(u8 addr)

{

int16_t temp = 0;

INA226_SetRegPointer(addr,SV_REG);

temp = INA226_ReadData(addr);

if(temp&0x8000) temp = ~(temp - 1);

return (u16)temp;

}


//获取电压

void GetVoltage(float *Voltage)//mV

{

*Voltage = INA226_GetVoltage(INA226_ADDR1)*Voltage_LSB;

}


//获取分流电压

void Get_Shunt_voltage(float *Voltage)//uV

{

*Voltage = (INA226_GetShuntVoltage(INA226_ADDR1)*INA226_VAL_LSB);//如需矫正电流分流参数请将这里改为2.5

}


//获取电流

void Get_Shunt_Current(float *Current)//mA

{

*Current = (INA226_GetShunt_Current(INA226_ADDR1)* CURRENT_LSB);

}


//获取功率= 总线电压 * 电流

void get_power()//W

{

GetVoltage(&ina226_data.voltageVal); //mV

Get_Shunt_voltage(&ina226_data.Shunt_voltage); //uV

Get_Shunt_Current(&ina226_data.Shunt_Current); //mA

Get_Power(&ina226_data.Power);

ina226_data.Power_Val = ina226_data.voltageVal*0.001f * ina226_data.Shunt_Current*0.001f; //mV*mA

}


//获取功率装载值,ina226内部计算的的功率,由于未经校准,故不采用


u16 INA226_Get_Power(u8 addr)

{

int16_t temp=0;

INA226_SetRegPointer(addr,PWR_REG);

temp = INA226_ReadData(addr);

return (u16)temp;

}


//获取功率,ina226内部计算,不准确,不采用

void Get_Power(float *Power)//W

{

*Power = (INA226_Get_Power(INA226_ADDR1)*POWER_LSB);

}


//不设置报警,舍弃

/*

u8 INA226_AlertAddr()

{

u8 temp;

IIC_Start();


IIC_Send_Byte(INA226_GETALADDR);

IIC_Wait_Ack();

temp = IIC_Read_Byte(1);

IIC_Stop();

return temp;

}

*/


5.5 BH1750环境光强度

#include 'bh1750.h'

float Read_BH1750_Data()

{

    unsigned char t0;

    unsigned char t1;

    float t;

    u8 r_s=0;

    IIC_Start(); //发送起始信号

    IIC_WriteOneByteData(0x46);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:1rn');

    IIC_WriteOneByteData(0x01);

    r_s=IIC_GetACK();//获取应答

     if(r_s)printf('error:2rn');

    IIC_Stop(); //停止信号 

    

    IIC_Start(); //发送起始信号

    IIC_WriteOneByteData(0x46);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:3rn');

    IIC_WriteOneByteData(0x01);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:4rn');

    IIC_Stop(); //停止信号 

    

    IIC_Start(); //发送起始信号

    IIC_WriteOneByteData(0x46);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:5rn');

    IIC_WriteOneByteData(0x10);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:6rn');

    IIC_Stop(); //停止信号 

    

    DelayMs(100); //等待

    

    IIC_Start(); //发送起始信号

    IIC_WriteOneByteData(0x47);

    r_s=IIC_GetACK();//获取应答

    if(r_s)printf('error:7rn');

    

    t0=IIC_ReadOneByteData(); //接收数据

    IIC_SendACK(0); //发送应答信号

    t1=IIC_ReadOneByteData(); //接收数据

    IIC_SendACK(1); //发送非应答信号

    IIC_Stop(); //停止信号

    

     t=(((t0<<8)|t1)/1.2);

     return t;  

}

关键字:STM32  智慧路灯 引用地址:基于STM32+华为云IOT设计的智慧路灯

上一篇:STM32CubeMX之定时器PWM输出
下一篇:基于STM32+华为云IOT设计智能称重系统

推荐阅读最新更新时间:2024-11-17 16:17

在Linux下搭建STM32开发环境攻略
Linux发行版是64bit的Fedora19,方案选择为:Eclipse+CodeSourcery+OpenOCD+STLINKv2。 NO1.准备STM32的开发板,购买仿真器STLINKv2。 NO2.安装 CodeSourcery 如果是64bit机器,首先确认它能够运行32bit的软件。CodeSourcery可以在官网https://sourcery.mentor.com下载,名称为arm-2013.05-23-arm-none-eabi.bin,安装它。 CodeSourcery是编译好的二进制GCC程序包。 NO3.安装 OpenOCD 实际上,使用下面这个命令就可以: yum ins
[单片机]
图说CRC原理应用及STM32硬件CRC外设
在嵌入式产品应用中,常常需要应对系统数据在存储或者传输过程中的完整性问题。 所谓完整性是指数据在其生命周期中的准确性和一致性。这些数据可能存储在EEPROM/FLASH里,或者基于通信协议进行传输,它们有可能因为外界干扰或者程序错误,甚至系统入侵而导致被破坏。如果这些数据在使用前不做校验,产品功能可能失效。在一些特定领域,严重时可能会危及用户财产甚至生命安全。 本文就来聊聊使用较为广泛的循环冗余校验技术,以及在STM32中的一些具体使用体会。 所谓循环冗余校验(CRC:Cyclic Redundancy Check)是一种错误检测算法,通常在通信协议中或存储设备中用于检测原始数据的意外变动。可以简单理解成对有用数据按照一定
[单片机]
图说CRC原理应用及<font color='red'>STM32</font>硬件CRC外设
学习STM32,你不得不了解的五大嵌入式操作系统
基于STM平台且满足实时控制要求操作系统,有以下5种可供移植选择。分别为μClinux、μC/OS-II、eCos、FreeRTOS和rt-thread。下面分别介绍这五种嵌入式操作系统的特点及不足,通过对比,读者可以根据自己的应用需求选择合适的平台。 TOP1:μClinux μClinux是一种优秀的嵌入式Linux版本,其全称为micro-control Linux,从字面意思看是指微控制Linux。同标准的Linux相比,μClinux的内核非常小,但是它仍然继承了Linux操作系统的主要特性,包括良好的稳定性和移植性、强大的网络功能、出色的文件系统支持、标准丰富的API,以及TCP/IP网络协议等。因为没有MMU
[嵌入式]
STM32高级定时器用于普通定时,定时周期变长
最近在用stm32定时器控制步进电机,由于普通定时器不够用,只能把TIM1当普通定时器用,我随手就把普通定时器的代码搬过去。 void cs_Timer_Init(void) //TIM1 us级 { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 1000; TIM_TimeBaseStructure.TIM_Prescaler = 71;
[单片机]
STM32—IIC通信(软件实现底层函数)
使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:IIC #ifndef __BSP_IIC_H #define __BSP_IIC_H #include stm32f10x.h #define SCL_PORT GPIOA #define SCL_PIN GPIO_Pin_2 #define SCL_MOOD GPIO_Mode_Out_OD #define SCL_SPEED GPIO_Speed_50MHz #define SDA_PORT GPIOA #define SDA_PIN GPIO_Pin_3 #defi
[单片机]
STM32开发 -- 打开网址测试脚本编写
一、CURL软件 1、CURL简介 CURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。 cURL支持的通信协议有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。 curl还支持SSL认证、HTTP POST、HTTP PUT、FTP上传, HTTP form based upload、proxies、HTTP/2、cookies、用户名+密码认证
[单片机]
<font color='red'>STM32</font>开发 -- 打开网址测试脚本编写
STM32之ADC单通道单次例程
#include stm32f10x.h /* RCC时钟配置 */ void RCC_config(void) { ErrorStatus HSEStartUpStatus; /* RCC寄存器设置为默认配置 */ RCC_DeInit(); /* 打开外部高速时钟 */ RCC_HSEConfig(RCC_HSE_ON); /* 等待外部高速时钟稳定 */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* 设置HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYS
[单片机]
ARM学习《五》——关于STM32串口下载
经过两天的努力终于把刚做的STM32最小系统版调试好了,做了两件事:一,把串口调通了,可以往PC机上发送数据。二,可以进行串口下载了。今天把串口下载的步骤记录下来 当然要进行串口下载首先要将232电路调通,保证可用,就是无障碍的和PC通讯。然后将写好编译好的HEX文件载入下载即可,这里STM32的识别hex文件的,这点比LM3S系列的ARM 强。首先要到网上下载Flash_Loader_Demonstrator_V2.1.0_Setup这个串口下载的上位机软件,是安装版的,网上到处都是,去ST官方网站去下载也可以。 串口下载程序软件: 官方: http://www.st.co
[单片机]
ARM学习《五》——关于<font color='red'>STM32</font>串口下载
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved