本文的開發項目由開發者發布在CSDN博客(F l e)分享,該設計采用esp8266燒寫機智云固件。并且esp8266與stm32進行通信,則stm32可以通過esp8266與機智云服務器進行數據交互,而機智云服務器可以和機智云app進行數據交互。為此,實現stm32通過esp8266可以與機智云app進行數據交互。
stm32作為MCU與傳感器進行數據交互,得到傳感器采集的數值,所以完成的是傳感器和app的數據交互。由于本次實驗增加了對光照強度的采集,所以又增加了一個三色RGB燈外設。通過機智云app可以調節RGB燈的光強,以此來模擬光照強度的變化。整個設計的傳感器數據流向如下圖所示:
另外,對于用機智云app調節RGB燈的光強的數據流向如下圖:
01
傳感器的測試
本次設計利用STM32CubeMX進行開發,代碼設計過程分模塊進行,分別編寫測試用例驗證各模塊的功能,包括oled模塊、按鍵模塊、dht11模塊、光敏電阻模塊、rgb模塊。1、oled模塊① 接線:
②代碼編寫:
本次設計中oled采用硬件SPI2驅動,STM32CubeMX的設計如下圖:
利用STM32CubeMX生成的SPI主要代碼如上所示。在生成的SPI代碼上進一步編寫oled.c和oled.h文件。
oled.c封裝了以下的函數:
測試函數:
int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); OLED_Init(); OLED_ShowString(0, 0, "wait for set esp8266,press key1 to set esp8266 with AIRLINK_MODE");}
③測試用例實驗結果:
由上圖可知,oled模塊的顯示函數能夠正確顯示。
2、按鍵模塊
①接線:
KEY_R0接地,KEY_L0和KEY_L1可以用于檢測按鍵狀態。對應的引腳為:
②代碼編寫:
STM32CubeMX設計如下:
PC11設置為輸出模式,PC10和PB5設置為輸入模式。
Key.c封裝了以下函數:
void key_init(void){ HAL_GPIO_WritePin(KEY_COM_GND_GPIO_Port,KEY_COM_GND_Pin,GPIO_PIN_RESET);}
void Test_key(void){ if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==GPIO_PIN_SET) { OLED_ShowString(0,0,"key1_up"); } else { OLED_ShowString(0,0,"key1_down"); } if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin)==GPIO_PIN_SET) { OLED_ShowString(0,10,"key2_up"); } else { OLED_ShowString(0,10,"key2_down"); } OLED_Refresh_Gram();}
測試用例:
int main(void){ MX_GPIO_Init(); key_init(); while(1) { Test_key(); }}
③測試用例實驗結果:
由圖中可以看出,按鍵一被按下時顯示key1_down和key2_up,與理論相符。
3、dht11模塊
①接線:
②代碼編寫:
由于dht11的數據引腳有時需要作為輸入,有時需要作為輸出,所以不在STM32CubeMX設置。
Dht11.c主要封裝了以下函數:
這里的us延時并沒有使用定時器來產生,而是用系統時鐘來實現:
void delay_us(uint32_t us){ uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us); while (delay--) { ; }}
測試用例:
int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); OLED_Init(); while(1) { Test_dht11(); }
void Test_dht11(void){ char txt[16]; while(1) { DHT11_Read_Data(&humidity_integer,&humidity_decimal,&temperature_integer,&temperature_decimal); sprintf(txt, "temp:%d.%d", temperature_integer,temperature_decimal); OLED_ShowString(0,0,txt); sprintf(txt, "humi:%d.%d", humidity_integer,humidity_decimal); OLED_ShowString(0,10,txt); OLED_Refresh_Gram(); }}
③測試用例實驗結果:
由上圖可以看出,溫度為23.3℃,濕度為53.0%,濕度的小數為0,與理論相符。
4、光敏電阻模塊
①接線:
②代碼編寫:
STM32CubeMX設置ADC1的IN0如下:
Stm32Rct6的ADC是12位的,這里沒有更改的選項,則ADC讀取的最大值是2^12=4096。
這里采樣時間Sampling Time選擇1.5個周期。ADC采樣時間 = (采樣周期+12.5周期)* 1/ADC時鐘頻率,這里ADC采樣時間=(1.5+12.5)*1/12 = 1.167us。light_check5506.c主要封裝以下函數:
void light_check5506_init(void){ HAL_ADCEx_Calibration_Start(&hadc1); HAL_Delay(200);}
uint32_t light_check5506_getinitvalue(void){ HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1,50);//?Tê±50ms return HAL_ADC_GetValue(&hadc1);}
uint32_t light_check5506_get0to100value(void){ //°μ-->áá£o0~100 uint32_t value; value=light_check5506_getinitvalue(); value=4096-value;//?ê?êy?Yê???°μêy?Y??′ó value=(value*100/4096);//?ˉ?a0~100μ?êy,±?D??è3?ò?100?ù3y£?òò?aè?2?ê???êy return value;}
void Test_5506(void){ uint32_t value; char txt[16]; while(1) { value=light_check5506_get0to100value(); sprintf(txt, "light(0-100):%d", value); OLED_ShowString(0,0,txt); OLED_Refresh_Gram(); }}
測試用例:
main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); MX_ADC1_Init(); OLED_Init(); light_check5506_init(); while(1)` { Test_5506(); }}
③測試用例實驗結果:
將ADC讀取的值歸一化到0~100后光照強度的數值為18。
5、rgb模塊
①接線:
②代碼編寫:
STM32CubeMX設置TIM8的三個通道如下:
計數周期Counter Period設置為255,這是為了便于查找RGB顏色表進行顏色設置,占空比Pulse設置為50%Rgb.c封裝了以下函數:
void rgb_init(void){ HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);}void Test_rgb(void){ rgb_setpwm(10.0,100.0,200.0);}void rgb_setpwm(uint8_t pwm_r,uint8_t pwm_g,uint8_t pwm_b){ __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1,pwm_r); __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2,pwm_g); __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3,pwm_b);}
測試用例:
main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); MX_TIM8_Init(); rgb_init(); OLED_Init(); while(1)` { Test_rgb(); }}
③測試用例實驗結果:
由上圖可知RGB燈被點亮。
02
通過esp8266實現數據上傳和數據回傳
在進行數據上傳與數據回傳之前,首先進行用于打印數據的串口1的設置和用于stm32與esp8266通信的串口2。串口1:
串口1設置PA9和PA10分別作為TX和RX,波特率為115200,不使能中斷。
串口2:
串口2設置PA2和PA3分別作為TX和RX,波特率為9600,使能中斷。
1、數據上傳:溫濕度數據、關照強度數據
①主要代碼
void userHandle(void){ DHT11_Read_Data( & humidity_integer, & humidity_decimal, & temperature_integer, & temperature_decimal); currentDataPoint.valuehumidity = humidity_integer; currentDataPoint.valueLight_intensity = light_check5506_get0to100value(); currentDataPoint.valueDHT11 = temperature_integer + 0.1 * temperature_decimal; }
在userHandle(void)中添加溫濕度數據的采集以及光照強度的讀取。userHandle()是main函數中while循環的內容。
由上圖可以看出,userHandle對于用戶來說是最頂層的,數據在userHandle中采集,依次經過gizCheckReport判斷是否上報當前狀態的數據、gizDataPoints2ReportData完成用戶區數據到上報型數據的轉換、gizReportData將轉換后的上報數據通過串口發送給 WiFi 模塊。
②設計結果:
首先確保esp8266和手機都已經連接到同一個網絡,這里用電腦作為這個網絡。
由上圖可知手機和esp8266已經連接上了電腦。機智云app連接上esp8266后得到上傳來的數據:
Oled上的數據是stm32收集的,上圖的數據是機智云app通過esp8266收到的,兩者一致,說明數據交互是正確的。2、數據回傳:RGB三數值
①主要代碼
int8_t gizwitsEventProcess(eventInfo_t * info, uint8_t * gizdata, uint32_t len){ uint8_t i = 0; dataPoint_t * dataPointPtr = (dataPoint_t *)gizdata; moduleStatusInfo_t * wifiData = (moduleStatusInfo_t *)gizdata; protocolTime_t * ptime = (protocolTime_t *) gizdata; # if MODULE_TYPE gprsInfo_t * gprsInfoData = (gprsInfo_t *)gizdata; # else moduleInfo_t * ptModuleInfo = (moduleInfo_t *) gizdata; # endif if ((NULL == info) || (NULL == gizdata)) { return -1; } for (i=0; i < info->num; i++) { switch(info->event[i]) { case EVENT_LED_R: currentDataPoint.valueLED_R = dataPointPtr->valueLED_R; GIZWITS_LOG("Evt:EVENT_LED_R %d\n", currentDataPoint.valueLED_R); rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B); break; case EVENT_LED_G: currentDataPoint.valueLED_G = dataPointPtr->valueLED_G; GIZWITS_LOG("Evt:EVENT_LED_G %d\n", currentDataPoint.valueLED_G); rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B); break; case EVENT_LED_B: currentDataPoint.valueLED_B = dataPointPtr->valueLED_B; GIZWITS_LOG("Evt:EVENT_LED_B %d\n", currentDataPoint.valueLED_B); rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B); break; } }}
在gizwitsEventProcess中的EVENT_LED_R、EVENT_LED_G、EVENT_LED_B分別添加對對RGB三個PWM的賦值,賦值之后使其立即生效。
protocolIssuedProcess被 gizwitsHandle 調用,接收來自云端或 app端下發的相關協議數據。ACTION_CONTROL_DEVICE進行“控制型協議”的相關處理,gizDataPoint2Event根據協議生成“控制型事件”,并進行相應數據類型的轉化轉換,gizwitsEventProcess是位于數據回傳過程中的最底層,根據已生成的“控制型事件”進行相應處理。
②設計結果:
首先確保esp8266和手機都已經連接到同一個網絡,這里用電腦作為這個網絡。
由上圖可知手機和esp8266已經連接上了電腦。機智云app設置RGB三個PWM數值,得到oled上的數據為:
由上圖可知,右圖為機智云app設置的三個PWM數值,左圖再oled上為同樣的數值,說明數據交互正確。
03
總 結
①通過這次設計接觸了STM32CubeMX這個軟件,相比與之前的標準庫,STM32CubeMX生成的Hal庫不僅封裝度更高,而且更有利于開發者進行快速開發,而且在本次實驗中機智云生成的代碼也是基于Hal庫的,這說明以后對于stm32來說,會越來越趨向于Hal開發。②官網永遠是對解決問題的最好地方,機智云的官方文檔給了我極大幫助。
③esp8266的燒錄對于供電要求十分苛刻,導致多次燒錄都失敗了,所以在制pcb的時候加上了esp8266的燒錄接口,以及GPIO的接地開關,還有復位電路。PCB擴展板圖如下:
④stmRct6板的供電十分差,由于剛開始只是接了ST-LINK進行供電,導致dht11和oled一起使用時dht11的VCC口只有2.6V,進而使得dht11通信一直不成功,這也說明了一切先從電源管理開始,確保供電沒問題再查找軟件問題。
-
傳感器
+關注
關注
2550文章
51046瀏覽量
753140 -
數據
+關注
關注
8文章
7006瀏覽量
88955 -
物聯網
+關注
關注
2909文章
44578瀏覽量
372881 -
STM32
+關注
關注
2270文章
10896瀏覽量
355778 -
機智云
+關注
關注
2文章
589瀏覽量
26393
發布評論請先 登錄
相關推薦
評論