环境安全卫士固件开发
Posted 三明治开发社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了环境安全卫士固件开发相关的知识,希望对你有一定的参考价值。
固件开发
开发环境是在Linux下进行开发的,环境搭建和SDK的拉取可以在涂鸦github上的仓库上进行学习。
该代码是基于1.0.2版本的 SDK 进行开发的,第一次接触soc开发的同学,可以在涂鸦github上的仓库拉取代码进行学习和开发。该代码中的 apps/template-demo 比较简单,可在该代码的基础上进行学习或开发。
本 demo可在github上下载源代码,下载完成源代码后,将代码放入SDK里面的APPS文件夹下。进行编译下载就可以了。编译后的产物中会出现QIO,UA,UG文件其中QIO是生产固件,UA是用户去固件,UG是升级固件。
本 demo主要是通过3种方式进行获取传感器信息的,分别是串口,adc,检测引脚高低电平。下面将以这三种方式进行简单的介绍。
1.串口类传感器:甲醛,pm2.5
通过阅读甲醛传感器的资料我们可以发现,传感器数据上传格式和计算方法如下:
/***********************************************************
* Function: get_ch2o_sensor_value
* Input: none
* Output: none
* Return: none
* Notice: 得到并上传甲醛的数据
***********************************************************/
static VOID get_ch2o_sensor_value(VOID)
{
UINT_T buff_ret, find_head_index = 0;
//甲醛数据高位,低位
UCHAR_T ch2o_data_high, ch2o_data_low;
//校验和
UCHAR_T check_sums = 0x00;
//串口数据缓存区
UCHAR_T ch2o_receive_buffer[CH2O_BUFFER_SIZE];
//指向甲醛数据头部
UCHAR_T *p_ch2o_value = NULL;
memset(ch2o_receive_buffer, 0, sizeof(ch2o_receive_buffer));
//读取串口数据
bk_uart_recv(CH2O_SENSOR_UART, ch2o_receive_buffer, CH2O_BUFFER_SIZE, 0xFFFF);
// for (find_head_index = 0; find_head_index<CH2O_BUFFER_SIZE; find_head_index++) {
// PR_NOTICE("ch2o_receive_buffer[%d] = %02x", find_head_index, ch2o_receive_buffer[find_head_index]);
// }
//寻找 ch2o 传感器发送过来的头部
for (find_head_index = 0; find_head_index<CH2O_BUFFER_SIZE; find_head_index++) {
if (ch2o_receive_buffer[find_head_index] == 0xff && \\
ch2o_receive_buffer[find_head_index+1] == 0x17 && \\
ch2o_receive_buffer[find_head_index+2] == 0x04){
//PR_NOTICE("find head is %d", find_head_index);
break;
}
}
//本次采集数据不完整
if (find_head_index > 11) {
PR_ERR("ch2o get uart data no complete!");
return;
}
//将指针指向 ch2o 数据中的头部
p_ch2o_value = ch2o_receive_buffer + find_head_index;
//检验和,确认读取的数据的准确性
check_sums = ch2o_check_sum(p_ch2o_value, 9);
if (check_sums != *(p_ch2o_value + 8)) {
PR_ERR("ch2o check_sums error");
return;
}
ch2o_data_high = *(p_ch2o_value+4);
ch2o_data_low = *(p_ch2o_value+5);
gs_air_box.ch2o_value = ch2o_data_high * 256 + ch2o_data_low;
//PR_NOTICE("ch2o value is : %d .", gs_air_box.ch2o_value);
//上传 ch2o 数据到涂鸦云
updata_dp_single(gs_air_box.dp_ch2o_value, PROP_VALUE, gs_air_box.ch2o_value);
return;
}
校验和的计算方式为:
/***********************************************************
* Function: ch2o_check_sum
* Input: none
* Output: none
* Return: none
* Notice: 甲醛数据校验和
***********************************************************/
static UCHAR_T ch2o_check_sum(UCHAR_T *data, UCHAR_T len)
{
UCHAR_T i, tempq = 0;
data += 1; //指向data[1]
for(i=0; i<(len-2); i++)
{
tempq += *data;
data++;
}
tempq = (~tempq) + 1;
return (tempq);
}
PM2.5的获取方法和甲醛的很相似,这里不再过多介绍。
2.ADC类传感器:燃气传感器,烟雾传感器
相关资料
由于在WB3S上只要一个ADC,所以我们这里用RS2255 芯片进行复用,引脚选择如下:
A(PWM0/GPIOA_6) | B(PWM1/GPIOA_7) | ON CHANNEL(S) |
---|---|---|
0 | 0 | A0 |
0 | 1 | A1 |
1 | 0 | A2 |
1 | 1 | A3 |
ADC初始化:
/* ADC */
#define ADC_DATA_LEN 4
static tuya_adc_dev_t tuya_adc;
static VOID adc_init(VOID)
{
tuya_adc.priv.pData = Malloc(ADC_DATA_LEN * sizeof(USHORT_T)); //这里一直使用tuya_adc,所有后面就没有释放该空间
memset(tuya_adc.priv.pData, 0, ADC_DATA_LEN*sizeof(USHORT_T));
tuya_adc.priv.data_buff_size = ADC_DATA_LEN; //设置数据缓存个数
}
ADC采集:
/***********************************************************
* Function: get_adc_value
* Input: none
* Output: adc_value : 采集到的 adc 值
* Return: none
* Notice: 得到 adc 采集的电压值
***********************************************************/
VOID get_adc_value(OUT USHORT_T* adc_value)
{
INT_T ret;
if (adc_value == NULL) {
PR_ERR("pm25_adc_value is NULL");
return;
}
memset(tuya_adc.priv.pData, 0, ADC_DATA_LEN*sizeof(USHORT_T));
ret = tuya_hal_adc_init(&tuya_adc);
if (ret != OPRT_OK) {
PR_ERR("ADC init error : %d ", ret);
return;
}
ret = ret = tuya_hal_adc_value_get(ADC_DATA_LEN, adc_value);
if (ret != OPRT_OK) {
PR_ERR("ADC get value error : %d ", ret);
}
tuya_hal_adc_finalize(&tuya_adc);
return;
}
烟雾传感器,数据获取:
/* 烟雾传感器 */
#define SMOKE_ALARM_LIM 1.0
/***********************************************************
* Function: get_smoke_sensor_value
* Input: none
* Output: none
* Return: none
* Notice: 得到并上传烟雾的数据,A1
***********************************************************/
static VOID get_smoke_sensor_value(VOID)
{
USHORT_T smoke_adc_value;
FLOAT_T smoke_volt;
//复用 adc 到 A1
tuya_gpio_write(RS2255_A, FALSE);
tuya_gpio_write(RS2255_B, TRUE);
tuya_hal_system_sleep(500);
//得到烟雾传感器 ad 值
get_adc_value(&smoke_adc_value);
//PR_NOTICE("smoke_adc_value : %d ", smoke_adc_value);
//计算实际电压值
smoke_volt = (smoke_adc_value / 4095.0) * 2.4 * 2;
//PR_NOTICE("smoke_volt : %lf ", smoke_volt);
//判断是否到报警门限值
if (smoke_volt >= SMOKE_ALARM_LIM) {
gs_air_box.smoke_state = ALARM;
} else {
gs_air_box.smoke_state = NORMAL;
}
//上传数据
updata_dp_single(gs_air_box.dp_smoke_state, PROP_ENUM, gs_air_box.smoke_state);
//PR_NOTICE("get smoke value, updata...");
return;
}
燃气传感器和烟雾相似,这里就不再过多介绍。
3.检测引脚高低电平获取状态:火焰传感器
火焰传感器,检测到火焰后断开220v电源,重启后220v通电,防止发生意外情况。
/***********************************************************
* Function: get_smoke_sensor_value
* Input: none
* Output: none
* Return: none
* Notice: 得到并上传火焰的数据
***********************************************************/
static VOID get_flame_sensor_value(VOID)
{
if (FALSE == tuya_gpio_read(FLAME_SENSOR_PIN)) {
gs_air_box.flame_state = ALARM;
/* 检测到火焰,拉低220V控制引脚,断电 */
tuya_gpio_write(POWER_OFF_220V_PIN, FALSE);
} else {
gs_air_box.flame_state = NORMAL;
}
updata_dp_single(gs_air_box.dp_flame_state, PROP_ENUM, gs_air_box.flame_state);
return;
}
4.设备初始化:
启动时,先对环境安全卫士相关的外设和引脚进行初始化设置,创建信号量,传感器预热,预热完成后释放信号量,开始采集。
/***********************************************************
* Function: air_box_device_init
* Input: none
* Output: none
* Return: none
* Notice: 环境安全卫士设备初始化
***********************************************************/
VOID air_box_device_init(VOID)
{
INT_T opRet = OPRT_OK;
/* 火焰传感器相关外设初始化 */
tuya_gpio_inout_set(FLAME_SENSOR_PIN, TRUE);
tuya_gpio_inout_set(POWER_OFF_220V_PIN, FALSE);
/* 启动时,拉高220V控制引脚,通电 */
tuya_gpio_write(POWER_OFF_220V_PIN, TRUE);
/* ADC 复用,相关引脚初始化 */
tuya_gpio_inout_set(RS2255_A, FALSE);
tuya_gpio_inout_set(RS2255_B, FALSE);
adc_init();
/* 甲醛传感器使用 uart2 接收数据,在函数 app_init() 里面已经修改完成波特率 */
/* pm2.5 传感器 串口 初始化 */
ty_uart_init(PM25_SENSOR_UART, TYU_RATE_9600, TYWL_8B, TYP_NONE, TYS_STOPBIT1, (PM25_BUFFER_SIZE * SIZEOF(UCHAR_T)), TRUE);
/* 创建信号量 */
opRet = tuya_hal_semaphore_create_init(&preheat_semaphore, 0, 1);
if (opRet != OPRT_OK) {
PR_ERR("creat preheat semaphore error : %d", opRet);
}
/* 预热 60s 后释放信号量,开始采集传感器数据 */
opSocSWTimerStart(preheat_timer, SENSOR_PREHEAT_TIME, preheat_semaphore_post_task);
tuya_hal_thread_create(NULL, "acquire sensor data", 512*4, TRD_PRIO_2, acquire_data_task, NULL);
}
预热完成释放信号量:
VOID preheat_semaphore_post_task(VOID)
{
//预热完成,释放信号量
tuya_hal_semaphore_post(preheat_semaphore);
//关闭预热软件定时器
opSocSWTimerStop(preheat_timer);
//预热完成,上传预热完成数据到涂鸦云
gs_air_box.preheat_state = false;
updata_dp_single(gs_air_box.dp_preheat, PROP_BOOL, gs_air_box.preheat_state);
}
传感器采集数据任务轮询函数:
/***********************************************************
* Function: acquire_data_task
* Input: none
* Output: none
* Return: none
* Notice: 获取传感器数据任务
***********************************************************/
VOID acquire_data_task(VOID)
{
//等待预热完成
tuya_hal_semaphore_wait(preheat_semaphore);
while (1) {
get_ch2o_sensor_value();
get_flame_sensor_value();
get_gas_sensor_value();
get_pm25_sensor_value();
get_smoke_sensor_value();
tuya_hal_system_sleep(500);
}
}
整机演示
1.实时显示当前空气状况
烧录授权完成后,设备就可以正常配网了。连接WiFi,打开蓝牙,按照配网流程成功配网后,即可使用app控制设备。已经配网成功的设备,可长按按键再次进入配网模式。
环境安全卫士APP显示界面:
2.报警
当烟雾,燃气或者火焰三者中有一种的浓度大于设定值,则app会显示报警状态,并且断开220V电压。
至此,我们已经成功完成多功能环境安全卫士的开发。
以上是关于环境安全卫士固件开发的主要内容,如果未能解决你的问题,请参考以下文章