引言
本项目使用PSoC 6 RTT积木式开发套件(开发板PSoC 62 with CAPSENSE evaluation kit),基于RT-Thread实现基于NB-IOT通信的设备上云,将设备的数据上传到阿里云物联网平台上,可以进行数据观测。
功能
- 采集电容触摸数据,且转换成范围在0~100。
- 采集光照传感器的 数据,判断设备现在所处是白天还是黑夜。
- 将采集的数据通过NB-IOT传输到阿里云的物联网平台上。
前期准备
软件
- RT-Thread Studio
- 阿里云服务器
- 串口调试助手
硬件
- PSoC 6 RTT积木式开发套件
- 光照传感器
- BC26
项目开发
硬件开发
- 将PSoC 6 RTT积木式开发套件通过USB Type-A to USB Type-C线连接到PC电脑。
- 将光照传感器的5V和GND连接到开发板,且将DO引脚连接到开发板的P5_0。
- 将BC26的串口连接到开发板的串口五,引脚为P11_0和P11_1。
软件开发
- 修改uart5引脚
在uart_config.h文件中找到串口五的位置,然后进行修改,修改内容如下:
#if defined(BSP_USING_UART5)复制代码
- #ifndef UART5_CONFIG
- #define UART5_CONFIG \
- { \
- .name = "uart5", \
- .tx_pin = P11_1, \
- .rx_pin = P11_0, \
- .usart_x = SCB5, \
- .intrSrc = scb_5_interrupt_IRQn, \
- .userIsr = uart_isr_callback(uart5), \
- .UART_SCB_IRQ_cfg = &UART5_SCB_IRQ_cfg, \
- }
- void uart5_isr_callback(void);
- #endif /* UART5_CONFIG */
- #endif /* BSP_USING_UART5 */
- #ifndef UART5_CONFIG
- 编写NB-IOT模块的驱动文件
- 创建一个定时器,用以实现发送命令之后等待回馈的接收的毫秒延时。
void delay_ms(rt_uint32_t ms)复制代码
- {
- delay_sem=rt_sem_create("delay_sem", 0, RT_IPC_FLAG_FIFO);
- if(delay_sem==RT_NULL)
- {
- LOG_E("Failed to create semaphore.");
- return ;
- }
- //初始化定时器
- delay_timer=rt_timer_create("delay_timer", delay_timer_timeout, RT_NULL, ms, RT_TIMER_FLAG_ONE_SHOT);
- if(delay_timer==RT_NULL)
- {
- LOG_E("Failed to create delay_timer.");
- rt_sem_delete(delay_sem);
- return ;
- }
- //启动定时器
- rt_timer_start(delay_timer);
- //等待信号量
- rt_sem_take(delay_sem, RT_WAITING_FOREVER);
- //删除信号量和定时器
- rt_sem_delete(delay_sem);
- rt_timer_delete(delay_timer);
- }
- {
- 创建一个线程用于接收NB-IOT模块发来的数据。
rt_err_t bc260y_recv_callback(rt_device_t dev,rt_size_t size)复制代码
- {
- if((size)&&(bc260y_rx_sem))
- rt_sem_release(bc260y_rx_sem);
- return RT_EOK;
- }
- static void bc260y_parse_cmd(uint8_t *p_data)
- {
- if(p_data == NULL)
- {
- LOG_E("%s %d data cannot be empty", __FILE__, __LINE__);
- return;
- }
- uint8_t ch = *p_data;
- while(rt_device_read(bc260y_dev, 0, &ch, 1)==1)
- {
- if(RxCounter>=500)
- RxCounter=0;
- RxBuffer[RxCounter++]=ch;
- }
- }
- static void bc260y_parse_thread_entry(void *para)
- {
- uint32_t res;
- uint8_t ch=0;
- while(1)
- {
- if(bc260y_rx_sem)
- {
- res=rt_sem_take(bc260y_rx_sem, RT_WAITING_FOREVER);
- if(res==RT_EOK)
- {
- bc260y_parse_cmd(&ch);
- }
- }
- }
- }
- {
- 编写对NB-IOT的指令程序。
void Clear_Buffer(void)//清空缓存复制代码
- {
- memset(RxBuffer,0,RxBuffer_Size);
- RxCounter=0;
- }
- void BC260Y_Init(void)
- {
- bc260y_sendStr("AT\r\n");
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"OK");//返回OK
- Clear_Buffer();
- while(strx==NULL)
- {
- Clear_Buffer();
- bc260y_sendStr("AT\r\n");
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"OK");//返回OK
- }
- bc260y_sendStr("AT+QMTDISC=0\r\n");
- delay_ms(300);
- bc260y_sendStr("AT+CFUN=1\r\n");//获取卡号,类似是否存在卡的意思,比较重要。
- delay_ms(300);
- bc260y_sendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"460");//返460,表明识别到卡了
- Clear_Buffer();
- while(strx==NULL)
- {
- Clear_Buffer();
- bc260y_sendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"460");//返回OK,说明卡是存在的
- }
- bc260y_sendStr("AT+CGATT=1\r\n");//激活网络,PDP
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"OK");//返OK
- Clear_Buffer();
- bc260y_sendStr("AT+CGATT?\r\n");//查询激活状态
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"+CGATT: 1");//返1
- Clear_Buffer();
- while(strx==NULL)
- {
- Clear_Buffer();
- bc260y_sendStr("AT+CGATT?\r\n");//获取激活状态
- delay_ms(300);
- strx=strstr((const char*)RxBuffer,(const char*)"+CGATT: 1");//返回1,表明注网成功
- }
- bc260y_sendStr("AT+CSQ\r\n");//查看获取CSQ值
- delay_ms(300);
- Clear_Buffer();
- bc260y_sendStr("AT+QSCLK=0\r\n");//获取激活状态
- delay_ms(300);
- Clear_Buffer();
- bc260y_sendStr("AT+QMTCLOSE=0\r\n");//获取激活状态
- delay_ms(300);
- Clear_Buffer();
- }
- {
- 编写触摸数据采集程序,将采集到的数据转化为百分比数据。
static void capsense_isr(void)复制代码
- {
- /* enter interrupt */
- rt_interrupt_enter();
- Cy_CapSense_InterruptHandler(CYBSP_CSD_HW, &cy_capsense_context);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- void capsense_callback(cy_stc_active_scan_sns_t *ptrActiveScan)
- {
- rt_sem_release(trans_done_semphr);
- }
- static uint32_t initialize_capsense(void)
- {
- uint32_t status = CYRET_SUCCESS;
- /* CapSense interrupt configuration parameters */
- static const cy_stc_sysint_t capSense_intr_config =
- {
- .intrSrc = csd_interrupt_IRQn,
- .intrPriority = CAPSENSE_INTR_PRIORITY,
- };
- /* Capture the CSD HW block and initialize it to the default state. */
- status = Cy_CapSense_Init(&cy_capsense_context);
- if (CYRET_SUCCESS != status)
- {
- return status;
- }
- /* Initialize CapSense interrupt */
- cyhal_system_set_isr(csd_interrupt_IRQn, csd_interrupt_IRQn, CAPSENSE_INTR_PRIORITY, &capsense_isr);
- NVIC_ClearPendingIRQ(capSense_intr_config.intrSrc);
- NVIC_EnableIRQ(capSense_intr_config.intrSrc);
- /* Initialize the CapSense firmware modules. */
- status = Cy_CapSense_Enable(&cy_capsense_context);
- if (CYRET_SUCCESS != status)
- {
- return status;
- }
- status = Cy_CapSense_RegisterCallback(CY_CAPSENSE_END_OF_SCAN_E,
- capsense_callback, &cy_capsense_context);
- if (CYRET_SUCCESS != status)
- {
- return status;
- }
- return status;
- }
- void Slider_Init(void)
- {
- cy_rslt_t result;
- result = initialize_capsense();
- if (CYRET_SUCCESS != result)
- {
- /* Halt the CPU if CapSense initialization failed */
- RT_ASSERT(0);
- }
- /* Initiate first scan */
- Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
- trans_done_semphr = rt_sem_create("slider_sem", 0, RT_IPC_FLAG_PRIO);
- if (trans_done_semphr == RT_NULL)
- {
- rt_kprintf("create transform done semphr failed.\n");
- RT_ASSERT(0);
- return;
- }
- }
- static void process_touch(void)
- {
- cy_stc_capsense_touch_t *slider_touch_info;
- uint16_t slider_pos;
- uint8_t slider_touch_status;
- static uint16_t slider_pos_prev;
- /* Get slider status */
- slider_touch_info = Cy_CapSense_GetTouchInfo(
- CY_CAPSENSE_LINEARSLIDER0_WDGT_ID, &cy_capsense_context);
- slider_touch_status = slider_touch_info->numPosition;
- slider_pos = slider_touch_info->ptrPosition->x;
- /* Detect the new touch on slider */
- if ((RT_NULL != slider_touch_status) &&
- (slider_pos != slider_pos_prev))
- {
- slider_buf=slider_pos/3;
- }
- slider_pos_prev = slider_pos;
- }
- static void Slider_thread_entry(void *parameter)
- {
- Slider_Init();
- for (;;)
- {
- rt_sem_take(trans_done_semphr, RT_WAITING_FOREVER);
- /* Process all widgets */
- Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);
- /* Process touch input */
- process_touch();
- /* Establishes synchronized operation between the CapSense
- * middleware and the CapSense Tuner tool.
- */
- Cy_CapSense_RunTuner(&cy_capsense_context);
- /* Initiate next scan */
- Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
- rt_thread_mdelay(50);
- }
- }
- int Slider_ctrl_init(void)
- {
- rt_err_t ret = RT_EOK;
- sld_thread = rt_thread_create("slider_th",
- Slider_thread_entry,
- RT_NULL,
- 1024,
- 25,
- 10);
- if (sld_thread != RT_NULL)
- {
- rt_thread_startup(sld_thread);
- }
- else
- {
- ret = -RT_ERROR;
- }
- return ret;
- }
- #endif
- {
- 在阿里云物联网平台上创建产品 、设备和功能。
将mqtt的三要素,产品名、设备名和设备密钥填写到程序中。
功能演示
- 设备状态
- 获取数据
- 数据上云
- 改变状态
- 获取数据
- 数据上云