ESP8266篇
esp8266作为一个智能家居,物联网最基本的平台,可以说是家喻户晓了。无论是产品还是自己做一些简单的小项目,用这个都还是比较合适的。8266主要可以用AT指令控制,也可以用自带的SDK开发,官方已经把开发环境做好了,上手起来还是比较方便的。能用SDK当然就不建议玩AT了,关于SDK方面的学习,我自己就不班门弄斧了,各位可以参考下面的链接,博主也是这样学过来的。
https://www.cnblogs.com/imliubo/p/10090798.html
然后博主是基于机智云来做的,作为不会写app的小伙伴,这种官方提供好的平台还是很有用处,根据自己需求配置,一些小项目还是足够了。
机智云教程请参考如下链接。
https://blog.csdn.net/weixin_43353164/article/details/82961659
步入正题,之前把zigbee部分都做完了,现在来做esp8266的,这方面很简单,搭好基础矿建后,根据需求改代码就行了。
首先我定义了两个结构体,分别用来存放我两个zigbee发送过来的数据。
typedef struct {
bool led;
bool fan;
uint32_t temp;
uint32_t humid;
uint32_t light;
uint32_t fan_start;
uint32_t led_start;
}ZigBee;
ZigBee Place_A =
{
.led = 0,
.fan = 0,
.temp = 0,
.humid = 0,
.light = 0,
.fan_start = 0,
.led_start = 0,
};
ZigBee Place_B =
{
.led = 0,
.fan = 0,
.temp = 0,
.humid = 0,
.light = 0,
.fan_start = 0,
.led_start = 0,
};
进入userHandle函数,在此我们将zigbee发过来的数据存入机智云当前显示的变量中。
void ICACHE_FLASH_ATTR userHandle(void)
{
static uint8 ledtime = 0;
ledtime++;
if (LED_TIMEOUT < ledtime)
{
ledtime = 0;
currentDataPoint.valueA_LED = Place_A.led;
currentDataPoint.valueA_FAN = Place_A.fan;
currentDataPoint.valueA_temp = Place_A.temp;
currentDataPoint.valueA_humid = Place_A.humid;
currentDataPoint.valueA_light = Place_A.light;
currentDataPoint.valueA_fan_start = Place_A.fan_start;
currentDataPoint.valueA_led_start = Place_A.led_start;
currentDataPoint.valueB_LED = Place_B.led;
currentDataPoint.valueB_FAN = Place_B.fan;
currentDataPoint.valueB_temp = Place_B.temp;
currentDataPoint.valueB_humid = Place_B.humid;
currentDataPoint.valueB_light = Place_B.light;
currentDataPoint.valueB_fan_start = Place_B.fan_start;
currentDataPoint.valueB_led_start = Place_B.led_start;
}
system_os_post(USER_TASK_PRIO_2, SIG_UPGRADE_DATA, 0);
}
进入gizwitsEventProcess函数,通过8266控制zigbee的部分都在此完成,这里只贴了基本的代码,剩下的变量以此类推完成。
case EVENT_LED :
currentDataPoint.valueLED = dataPointPtr->valueLED;
GIZWITS_LOG("Evt: EVENT_LED %d \n", currentDataPoint.valueLED);
if(0x01 == currentDataPoint.valueLED)
{
uart0_sendStr("manual");
}
else
{
uart0_sendStr("auto");
}
break;
case EVENT_A_LED :
currentDataPoint.valueA_LED = dataPointPtr->valueA_LED;
GIZWITS_LOG("Evt: EVENT_A_LED %d \n", currentDataPoint.valueA_LED);
if(0x01 == currentDataPoint.valueA_LED)
{
uart0_sendStr(A_LED_ON);
Place_A.led = 1;
}
else
{
uart0_sendStr(A_LED_OFF);
Place_A.led = 0;
}
break;
case EVENT_A_fan_start:
currentDataPoint.valueA_fan_start= dataPointPtr->valueA_fan_start;
GIZWITS_LOG("Evt:EVENT_A_fan_start %d\n",currentDataPoint.valueA_fan_start);
Place_A.fan_start = currentDataPoint.valueA_fan_start;
os_sprintf(buf, "A_FAN_START:%d", currentDataPoint.valueA_fan_start);
uart0_sendStr(buf);
break;
接下来我们做接收数据并处理的部分。
首先8266的串口先要做一些处理,让串口一用作系统默认的打印信息,而串口0用于和zigbee通信。
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
{
/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); //demo with a task to process the uart data
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
#if UART_BUFF_EN
pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE);
pRxBuffer = Uart_Buf_Init(UART_RX_BUFFER_SIZE);
#endif
#if UART_SELFTEST&UART_BUFF_EN
os_timer_disarm(&buff_timer_t);
os_timer_setfn(&buff_timer_t, uart_test_rx , NULL); //a demo to process the data in uart rx buffer
os_timer_arm(&buff_timer_t,10,1);
#endif
}
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen);
这个函数是创建一个任务,就是用如处理串口0的接收数据的,
uart_config(UART0);
这就是配置串口寄存器,在这个里面有设置了串口的回调函数
关于串口不明白的直接看下面链接,讲8266串口接收的。
https://blog.csdn.net/chen244798611/article/details/51470630/
然后在user_init里加上
uart_init(115200,115200);
UART_SetPrintPort(1);
然后我们就进入回调函数中处理数据。
LOCAL ICACHE_FLASH_ATTR ///
uart_recvTask(os_event_t *events)
{
uint8 BUF[100];
uint8 buf[10];
uint8 j = 0;
uint8 i = 3;
if(events->sig == 0){
#if UART_BUFF_EN
Uart_rx_buff_enq();
#else
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
uint8 d_tmp = 0;
uint8 idx=0;
for(idx=0;idx<fifo_len;idx++) {
d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
BUF[j++] = d_tmp;
//uart_tx_one_char(UART0, d_tmp);
}
//uart0_sendStr(BUF);
if (BUF[0] == '@')
{
if (BUF[1] == 'A')
{
Place_A.led = BUF[2];
Place_A.fan = BUF[3];
Place_A.temp = data_conver(&i, BUF);
Place_A.humid = data_conver(&i, BUF);
Place_A.light = data_conver(&i, BUF);
Place_A.fan_start = data_conver(&i, BUF);
Place_A.led_start = data_conver(&i, BUF);
}
else if (BUF[1] == 'B')
{
Place_B.led = BUF[2];
Place_B.fan = BUF[3];
Place_B.temp = data_conver(&i, BUF);
Place_B.humid = data_conver(&i, BUF);
Place_B.light = data_conver(&i, BUF);
Place_B.fan_start = data_conver(&i, BUF);
Place_B.led_start = data_conver(&i, BUF);
}
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
uart_rx_intr_enable(UART0);
#endif
}else if(events->sig == 1){
#if UART_BUFF_EN
//already move uart buffer output to uart empty interrupt
//tx_start_uart_buffer(UART0);
#else
#endif
}
}
```c
data_conver(&i, BUF)是一个数据处理函数,根据用户自定义的数据格式来解析数据。
ICACHE_FLASH_ATTR
int abc(int data, int n)
{
int x = data;
if (n == 0)
{
return 1;
}
while(--n)
{
data *= x;
}
return data;
}
ICACHE_FLASH_ATTR
uint32 data_conver(uint8 *i, uint8 buf[])
{
uint32 data = 0;
uint8 temp = *i;
uint8 j;
while(buf[++(*i)] != '#');
for (j = *i-temp-1; j > 0; j--)
{
data += (buf[++temp] - '0') * abc(10, j-1);
}
return data;
}
这样ESP8266方面就全部做完了,是不是很简单。
接下来我们来看一下效果。
因为之前玩坏了一块,所以就用一块来试验的,效果是还不错的,也可以远程控制,不过我只用LED测试了一下,继电器什么的都还没有装。
总结
zigbee和esp8266做智能家居和物联网这些实在是不错,自己买来玩一玩也可以做个小东西。博主也面试过几个做物联网和智能家居的,不过公司的话涉及的会更底层,而不是这么简单的应用,如果有意向往这方面发展的小伙伴还是可以考虑深入学习一下。