6585| 0
|
[项目] 【Gokit2&ZigBee&STM32】之无线工业粉尘监测仪 |
手机也可实时监控无线工业粉尘,还能实现太阳能供电!!!! 原创申明:如转载请注明来源:http://club.gizwits.com/thread-3242-1-1.html · 作品说明及使用场景 远程无线工业粉尘监测仪采用高精度激光粉尘传感器对工厂内的空气粉尘浓度进行监测,特别适合应用于汽车轮毂厂、铝镁打磨厂、抛光车间、电镀车间、面粉厂等易发生粉尘爆Zha的地方。粉尘监测仪采用STM32控制粉尘传感器并将数据通过串口传输到ZigBee终端设备,ZigBee终端设备通过ZigBee网络传输到ZigBee协调器,ZigBee协调器通过串口传输到Gokit2,Gokit2连接到路由器最终通过以太网连接到云服务器。做为公司的管理层能够通过手机远程实时的对工厂粉尘浓度进行监管,同时工厂管理室放置的ZigBee协调器连接着语音报警系统,现场便能通知粉尘超标报警信息。除此之外,作品还扩展了对温湿度监测的功能、太阳能充电及供电系统。 · 作品展示 代码下载: 无线工业粉尘监测仪代码.rar (11.13 MB, 下载次数: 69) 请各位小伙伴们多多指教 更多详情代码,原理图,教程,请移步到原帖:http://club.gizwits.com/thread-3242-1-1.html 项目硬件设计 首先规划一下作品设计思路,下面便画张鱼骨图来展示一下作品的总体规划,如果1所示。 图1 无线工业粉尘监测仪鱼骨图 有了鱼骨图就有了设计的方向,先从鱼尾开始做起吧!首当其冲便是采集传感器数据,攀藤G1粉尘传感器采用STM32驱动并用串口接收传感器采集的数据。 图2 攀藤G1激光粉尘传感器 传感数据无线传输依赖于ZigBee无线传感网络,因此搭建ZigBee网络是项目的核心之一。ZigBee组成网状网络,使数据能够绕过障碍物进行无线传输,能够在复杂的工厂环境中畅通无阻的将数据传输到控制室。 图3 ZigBee三大金刚 数据传输到ZigBee协调器之后我们的Gokit2终于亮相了。ZigBee协调器通过串口与Gokit2连接,将ZigBee网络内收集到的数据传递给Gokit2,Gokit2再将数据传输到机智云,这时候就可以通过手机以及电脑获取实时的粉尘浓度信息了。由于Gokit2的设计对于我这种强迫症来说使用起来有点麻烦,于是稍微改装了一下,如图4图5所示。 图4 Gokit2下载开关改装 图5 Gokit2串口跳线改装 改装完之后将ZigBee协调器通过杜邦线与Gokit2以及语音合成模块连接,连接完成之后将它们一下用螺母锁在亚克力板上。如图6图7图8所示。 图6 ZigBee协调器 图7 连接语音合成模块 图8 连接Gokit2 前端的传感数据采集发送是项目的重中之重,花了好长时间才搭好这个平台。内含粉尘传感器一枚(采集粉尘浓度)、STM32开发板一块(粉尘传感器数据处理)、ZigBee终端节点一块(数据无线传输)、太阳能电源系统(供电)。各种跳线实在凌乱T T,太阳能电池板电源接反烧了一块ZigBee开发板。。。用亚克力板做了个外壳,能把东西塞进去就行,外观神马的因为手残也就只能这样了。。。 图9 前端内景-1 图10 前端内景-2 图11 前端上表面 图12 前端下表面 图13 无线工业粉尘监测仪全家福 项目软件设计 开发环境: IAR For 8051 8.10.1(ZigBee-CC2530开发使用)、Keil V4 For ARM(Gokit2及STM32使用) 代码依旧流程图编写 [mw_shl_code=applescript,true]/*STM32main函数代码*/ #include "stm32f10x.h" #include "usart1.h" #include "Time_test.h" #include "LCD12864.h" volatile u32 time,time_LCD; // ms 计时变量 u8 PM_save[11]; /* * 函数名:main * 描述 :主函数 * 输入 :无 * 输出 :无 */ int main(void) { /* USART1 config 115200 8-N-1 */ u8 i,LCD_PM1[6]={"PM1.0:"},LCD_PM25[6]={"PM2.5:"},LCD_PM10[5]={"PM10:"}; u8 LCD_PM1_DATA[5],LCD_PM25_DATA[5],LCD_PM10_DATA[5]; u16 LCD_PM1_SAVE,LCD_PM25_SAVE,LCD_PM10_SAVE; SystemInit(); TIM2_NVIC_Configuration(); TIM2_Configuration(); USART1_Config();//串口初始化 lcdinit();//12864初始化 NVIC_Configuration(); write_com(0x03); delay(50); write_com(0x81); lcd_display(LCD_PM1); write_com(0x91); lcd_display(LCD_PM25); write_com(0x89); lcd_display(LCD_PM10); delay(50); write_com(0x01);//清屏 START_TIME;//启动定时器 while(1) { /* 每1000MS更新一次数据 */ if(time_LCD > 1000) { LCD_PM1_SAVE = PM_save[4]*256 + PM_save[5]; LCD_PM1_DATA[0] = LCD_PM1_SAVE/1000+'0'; LCD_PM1_DATA[1] = LCD_PM1_SAVE/100%10+'0'; LCD_PM1_DATA[2] = LCD_PM1_SAVE%100/10+'0'; LCD_PM1_DATA[3] = LCD_PM1_SAVE%10+'0'; LCD_PM1_DATA[4] = 0; LCD_PM25_SAVE = PM_save[6]*256 + PM_save[7]; LCD_PM25_DATA[0] = LCD_PM25_SAVE/1000+'0'; LCD_PM25_DATA[1] = LCD_PM25_SAVE/100%10+'0'; LCD_PM25_DATA[2] = LCD_PM25_SAVE%100/10+'0'; LCD_PM25_DATA[3] = LCD_PM25_SAVE%10+'0'; LCD_PM25_DATA[4] = 0; LCD_PM10_SAVE = PM_save[8]*256 + PM_save[9]; LCD_PM10_DATA[0] = LCD_PM10_SAVE/1000+'0'; LCD_PM10_DATA[1] = LCD_PM10_SAVE/100%10+'0'; LCD_PM10_DATA[2] = LCD_PM10_SAVE%100/10+'0'; LCD_PM10_DATA[3] = LCD_PM10_SAVE%10+'0'; LCD_PM25_DATA[4] = 0; write_com(0x84); lcd_display(LCD_PM1_DATA); write_com(0x94); lcd_display(LCD_PM25_DATA); write_com(0x8c); lcd_display(LCD_PM10_DATA); time_LCD =0; } /* 每5000MS将数据通过串口传输到ZigBee终端节点 */ if(time>5000) { for(i=0;i<11;i++) { USART_SendData(USART2,PM_save);//发送数据 while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); } time = 0; } } } [/mw_shl_code] [mw_shl_code=applescript,true]/*ZigBee用户函数代码*/ #include "OSAL.h" #include "ZGlobals.h" #include "AF.h" #include "aps_groups.h" #include "ZDApp.h" #include "SampleApp.h" #include "SampleAppHw.h" #include "OnBoard.h" /* HAL */ #include "hal_lcd.h" #include "hal_led.h" #include "hal_key.h" #include "MT_UART.h" #include "MT.h"//消息命令ID定义头文件 #include "string.h" #include "hal_voice.h" const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] = { SAMPLEAPP_PERIODIC_CLUSTERID,//广播簇ID SAMPLEAPP_FLASH_CLUSTERID }; const SimpleDescriptionFormat_t SampleApp_SimpleDesc = { SAMPLEAPP_ENDPOINT, // int Endpoint; SAMPLEAPP_PROFID, // uint16 AppProfId[2]; SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; SAMPLEAPP_FLAGS, // int AppFlags:4; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList // uint8 *pAppInClusterList; }; endPointDesc_t SampleApp_epDesc; uint8 SampleApp_TaskID; // Task ID for internal task/event processing // This variable will be received when // SampleApp_Init() is called. devStates_t SampleApp_NwkState; uint8 SampleApp_TransID; // This is the unique message ID (counter) afAddrType_t SampleApp_Periodic_DstAddr;//广播afAddrType_t类型数据 afAddrType_t SampleApp_Flash_DstAddr; afAddrType_t Point_To_Point_DstAddr; aps_Group_t SampleApp_Group; uint8 SampleAppPeriodicCounter = 0; uint8 SampleAppFlashCounter = 0; /********************************************** * LOCAL FUNCTIONS */ void SampleApp_HandleKeys( uint8 shift, uint8 keys ); void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt ); void SampleApp_SendPointToPointMessage( uint8 *dat ) ;//点对点传播 void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg);//数据接收处理 /********************************************** * NETWORK LAYER CALLBACKS */ /********************************************** * PUBLIC FUNCTIONS */ /********************************************** * @fn SampleApp_Init * * @brief Initialization function for the Generic App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notificaiton ... ). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void SampleApp_Init( uint8 task_id ) { SampleApp_TaskID = task_id; SampleApp_NwkState = DEV_INIT; SampleApp_TransID = 0; /********串口初始化************/ MT_UartInit(); MT_UartRegisterTaskID(SampleApp_TaskID); HalUARTWrite(0,"uart init success\n" ,18); /**************************/ // uint8 vol[11]={0xfd,0x00,0x08,0x01,0x01,0x5b,0x76,0x30,0x31,0x5d,0x84}; // HalUARTWrite(1,vol,11);//减小音量 #if defined ( BUILD_ALL_DEVICES ) // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered // together - if they are - we will start up a coordinator. Otherwise, // the device will start as a router. if ( readCoordinatorJumper() ) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; else zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; #endif // BUILD_ALL_DEVICES #if defined ( HOLD_AUTO_START ) // HOLD_AUTO_START is a compile option that will surpress ZDApp // from starting the device and wait for the application to // start the device. ZDOInitDevice(0); #endif //Setup for the Point To Point destination address Point_To_Point_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//点对点短地址 Point_To_Point_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; Point_To_Point_DstAddr.addr.shortAddr = 0x0000; //协调器地址 // Fill out the endpoint description. SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_epDesc.task_id = &SampleApp_TaskID; SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SampleApp_epDesc ); uint8 test[]={"欢迎使用无线工业粉尘监测仪"},len=0; len = sizeof(test); voice_input(test,len); } /********************************************** * @fn SampleApp_ProcessEvent * * @brief Generic Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { case CMD_SERIAL_MSG: //串口收到数据后由 MT_UART 层传递过来的 SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt); break; case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break; // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } return 0; } /*对接收到的串口数据进行处理*/ void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg) { uint8 *str=NULL; //len 有用数据长度 str=cmdMsg->msg; //指向数据开头 if( (*(str+1) ==0x42) && (*(str+2) ==0x4D) ) SampleApp_SendPointToPointMessage(str);//将数据通过广播发送 } void SampleApp_HandleKeys( uint8 shift, uint8 keys ) { } /*协调器对接收到的数据进行处理*/ void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint8 PM[10],WS[10]; switch ( pkt->clusterId ) { case SAMPLEAPP_POINT_TO_POINT_CLUSTERID: if(pkt->cmd.Data[1] == 0X42 && pkt->cmd.Data[2] == 0X4d)//判断粉尘数据是否符合协议 { /*协调器接收到终端节点的数据后对数据进行剪切*/ uint16 PM1_0,PM2_5,PM10; PM[0] = pkt->cmd.Data[1]; PM[1] = pkt->cmd.Data[2]; PM[2] = pkt->cmd.Data[5]; PM[3] = pkt->cmd.Data[6]; PM[4] = pkt->cmd.Data[7]; PM[5] = pkt->cmd.Data[8]; PM[6] = pkt->cmd.Data[9]; PM[7] = pkt->cmd.Data[10]; PM[8] = 0xdd; PM[9] = 0xff; PM1_0 = (PM[2]*256) + PM[3]; PM2_5 = (PM[4]*256) + PM[5]; PM10 = (PM[6]*256) + PM[7]; if( (PM1_0 < PM2_5 < PM10) && (PM1_0<2000) &&(PM2_5<2000) && (PM10<2000))//判断粉尘浓度是否超过设定阈值 { HalUARTWrite(0,PM,10); if(( PM1_0>1000) | (PM2_5>1000)| (PM10>1000) ) { uint8 test[]={"警告警告粉尘浓度超标"},len=0;//发送报警信息到语音合成模块 len = sizeof(test); voice_input(test,len); } } } if(pkt->cmd.Data[1] == 0xaa && pkt->cmd.Data[2] == 0xbb)//判断温湿度数据是否符合协议 { WS[0] = pkt->cmd.Data[1]; WS[1] = pkt->cmd.Data[2]; WS[2] = pkt->cmd.Data[3]; WS[3] = pkt->cmd.Data[4]; WS[4] = pkt->cmd.Data[5]; WS[5] = pkt->cmd.Data[6]; WS[6] = pkt->cmd.Data[7]; WS[7] = pkt->cmd.Data[8]; WS[8] = 0xdd; WS[9] = 0xff; HalUARTWrite(0,WS,10); if(WS[2]>0x30 )//判断温度是否超过设定阈值 { uint8 test[]={"警告警告温度过高"},len=0;//发送报警信息到语音合成模块 len = sizeof(test); voice_input(test,len); } if(WS[3]>0x40 )////判断湿度浓度是否超过设定阈值 { uint8 test[]={"警告警告湿度过高"},len=0;//发送报警信息到语音合成模块 len = sizeof(test); voice_input(test,len); } break; } } } /*点对点传输函数,终端节点用来发送点对点消息到协调器*/ void SampleApp_SendPointToPointMessage( uint8 *dat ) { if ( AF_DataRequest( &Point_To_Point_DstAddr, &SampleApp_epDesc, SAMPLEAPP_POINT_TO_POINT_CLUSTERID, *dat,//(byte)osal_strlen(dat), dat, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } } /********************************************** **********************************************/[/mw_shl_code] [mw_shl_code=applescript,true]/*Gokit2代码*/ #include "gokit.h" /*Global Variable*/ uint32_t ReportTimeCount = 0; uint8_t gaterSensorFlag = 0; uint8_t Set_LedStatus = 0; uint8_t NetConfigureFlag = 0; uint8_t curTem = 0, curHum = 0; uint8_t lastTem = 0,lastHum = 0; extern RingBuffer u_ring_buff; uint8_t p0Flag = 0; WirteTypeDef_t WirteTypeDef; ReadTypeDef_t ReadTypeDef; uint8_t Rx_sensor[10]={0};//´«¸ÐÆ÷Êý¾Ý extern uint8_t zb_count; uint8_t Switch_LEDStatus = 0,Switch_WaterStatus = 0,Switch_AirStatus = 0,Switch_WaringStatus = 0; /** * @brief Main program. * @param None * @retval None */ int main(void) { uint8_t p0_control_buf[MAX_P0_LEN]; SystemInit(); HW_Init(); SW_Init(); while(1) { KEY_Handle(); GizWits_MessageHandle(p0_control_buf, sizeof(WirteTypeDef_t)); if(gaterSensorFlag != 0) { gaterSensorFlag = 0; Zigbee_sensorData();//获取ZigBee串口传输的数据 GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);//上传数据到机智云服务器 } } } /** @addtogroup GizWits_HW_Init * @{ */ void HW_Init(void) { Delay_Init(72); UARTx_Init(); RGB_KEY_GPIO_Init(); RGB_LED_Init(); LED_GPIO_Init(); KEY_GPIO_Init(); TIM3_Int_Init(7199,9); //ms interrupt Motor_Init(); DHT11_Init(); IR_Init(); } /** @addtogroup GizWits_SW_Init * @{ */ void SW_Init() { ReadTypeDef.PM1_0_H =0; ReadTypeDef.PM1_0_L =0; ReadTypeDef.PM2_5_H = 0; ReadTypeDef.PM2_5_L = 0; ReadTypeDef.PM10_H = 0; ReadTypeDef.PM10_L = 0; GizWits_init(sizeof(ReadTypeDef_t)); printf("hello world\r\n"); printf("Gokit Init Ok ...\r\n"); } /** @addtogroup Printf_SystemRccClocks * @{ */ void Printf_SystemRccClocks(void) { uint8_t SYSCLKSource; RCC_ClocksTypeDef SystemRCC_Clocks; printf("System start...\r\n"); SYSCLKSource = RCC_GetSYSCLKSource(); if(SYSCLKSource==0x04) printf("SYSCLKSource is HSE\r\n"); else if(SYSCLKSource==0x00) printf("SYSCLKSource is HSI\r\n"); else if(SYSCLKSource==0x08) printf("SYSCLKSource is PL!\r\n"); RCC_GetClocksFreq(&SystemRCC_Clocks); printf("SYS clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.SYSCLK_Frequency/1000000); printf("HCLK clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.HCLK_Frequency/1000000); printf("PCLK1 clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.PCLK1_Frequency/1000000); printf("PCLK2_clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.PCLK2_Frequency/1000000); printf("SADCCLK_Frequencyclock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.ADCCLK_Frequency/1000000); } /*Gokit2获取到ZigBee协调器传输的数据进行处理*/ void Zigbee_sensorData(void) { uint8_t i; if( (Rx_sensor[0] == 0x42) && (Rx_sensor[9] == 0xFF) )//判断数据是否符合协议 { ReadTypeDef.PM1_0_H = Rx_sensor[2];//保存数据到结构体中 ReadTypeDef.PM1_0_L = Rx_sensor[3];//保存数据到结构体中 ReadTypeDef.PM2_5_H = Rx_sensor[4];//保存数据到结构体中 ReadTypeDef.PM2_5_L = Rx_sensor[5];//保存数据到结构体中 ReadTypeDef.PM10_H = Rx_sensor[6];//保存数据到结构体中 ReadTypeDef.PM10_L = Rx_sensor[7];//保存数据到结构体中 printf("%s",Rx_sensor);//打印数据,方便调试 for(i=0;i<10;i++) { Rx_sensor = 0;//清除数组为下一次数据保存 } zb_count =0; } } /***************************************************** * Function Name : KEY_Handle * Description : Key processing function * Input : None * Output : None * Return : None * Attention : None *****************************************************/ void KEY_Handle(void) { uint8_t Key_return =0; Key_return = ReadKeyValue(); if(Key_return & KEY_UP) { if(Key_return & PRESS_KEY1) { #ifdef PROTOCOL_DEBUG printf("KEY1 PRESS\r\n"); #endif } if(Key_return & PRESS_KEY2) { #ifdef PROTOCOL_DEBUG printf("KEY2 PRESS ,Soft AP mode\r\n"); #endif //Soft AP mode, RGB red LED_RGB_Control(255, 0, 0); GizWits_D2WConfigCmd(SoftAp_Mode); NetConfigureFlag = 1; } } if(Key_return & KEY_LONG) { if(Key_return & PRESS_KEY1) { #ifdef PROTOCOL_DEBUG printf("KEY1 PRESS LONG ,Wifi Reset\r\n"); #endif GizWits_D2WResetCmd(); } if(Key_return & PRESS_KEY2) { //AirLink mode, RGB Green #ifdef PROTOCOL_DEBUG printf("KEY2 PRESS LONG ,AirLink mode\r\n"); #endif LED_RGB_Control(0, 128, 0); GizWits_D2WConfigCmd(AirLink_Mode); NetConfigureFlag = 1; } } } /***************************************************** * Function Name : GizWits_WiFiStatueHandle * Description : Callback function , Judge Wifi statue * Input : None * Output : None * Return : Bit , Attr_Flags * Attention : *****************************************************/ void GizWits_WiFiStatueHandle(uint16_t wifiStatue) { if(((wifiStatue & Wifi_ConnClouds) == Wifi_ConnClouds) && (NetConfigureFlag == 1)) { printf("W2M->Wifi_ConnClouds\r\n"); NetConfigureFlag = 0; LED_RGB_Control(0,0,0); } } /************* (C) COPYRIGHT 2011 STMicroelectronics ****END OF FILE***/[/mw_shl_code] |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed