Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: HTS221 LIS3MDL LPS22HB LSM303AGR LSM6DSL VL53L0X picojson
Fork of HelloWorld_ST_Sensors by
main.cpp
00001 /*------------------------------------------------------------------------------ 00002 Home Environment Monitoring with STM32 Discovery IOT Node 00003 Disco_HomeEnv 00004 Features: 00005 - Monitor temperature, relative humidity and air pressure 00006 - Connects to a local TSDB server (over http) to log this data 00007 - Display the data on a Nextion smart display with 30s autosleep and proximity 00008 or touch detection wake up 00009 Next: 00010 - add RTC sync and time display --> done 00011 - add light sensor to monitor illuminance --> low priority 00012 - improve reading by either: reduce power on time of WiFi module (batch logging) 00013 or by compensating for board own temperature --> WiP 00014 - use a local toolchain to compile mbed projects (with trueStudio) --> WiP 00015 - add option to choose location from a list and update location tag 00016 - incrementally convert the project to electric energy monitoring: 00017 - read 2x simultaneous adc channels using DMA 00018 - save daily power readings to QSP mem for batch logging and recovey? 00019 - add screen to display current power drawing, daily and monthly cumulatives 00020 ------------------------------------------------------------------------------*/ 00021 00022 #include "main.h" 00023 00024 /* ---------- SETUP ------------- */ 00025 void setup() 00026 { 00027 printf("\n***************************************************************\n"); 00028 printf("*** Home Env on STM32 IoT Discovery ***\n"); 00029 printf("***************************************************************\n"); 00030 00031 printf("> Initializing sensors and WiFi... \n"); 00032 00033 int range_status; 00034 00035 /* Init all sensors with default params */ 00036 hum_temp.init(NULL); 00037 press_temp.init(NULL); 00038 magnetometer.init(NULL); 00039 acc_gyro.init(NULL); 00040 range_status = range.init_sensor(VL53L0X_DEFAULT_ADDRESS); 00041 00042 /* enable sensors */ 00043 hum_temp.enable(); 00044 press_temp.enable(); 00045 // acc_gyro.enable_x(); 00046 // acc_gyro.enable_g(); 00047 00048 uint8_t id; 00049 hum_temp.read_id(&id); 00050 printf("HTS221 humidity & temperature id = 0x%X\r\n", id); 00051 press_temp.read_id(&id); 00052 printf("LPS22HB pressure & temperature id = 0x%X\r\n", id); 00053 magnetometer.read_id(&id); 00054 printf("LIS3MDL magnetometer id = 0x%X\r\n", id); 00055 acc_gyro.read_id(&id); 00056 printf("LSM6DSL accelerometer&gyroscope id = 0x%X\r\n", id); 00057 printf("VL53L0x status = %d \r\n", range_status); 00058 00059 sense_enabled = true; 00060 00061 /* Setup display */ 00062 WAKE_UP_DISPLAY; 00063 WIFI_ICON_OFF; 00064 UPLOAD_ICON_OFF; 00065 NO_WAKEUP_ON_SERIALIN;// no wakeup on serial in 00066 SLEEP_ON_NOTOUCH_30S;// sleep after 30sec no touch 00067 WAKEUP_ON_TOUCH;// wake up on touch 00068 00069 00070 /*Initialize WIFI module */ 00071 WiFi_on = connectWiFi(); 00072 if (WiFi_on) { 00073 led3 = 1; 00074 //WiFi_led_ticker.attach(&toggle_led3_cb, 0.25); 00075 rtc_synced = sync_rtc(); 00076 // enter power save mode 00077 /*if (WIFI_SetPowerSaveMode(1, (UPLOAD_PERIOD_S - 1)*1000) == WIFI_STATUS_OK) { 00078 printf("> es-wifi entered power save mode\n"); 00079 } else { 00080 printf("> ERROR: es-wifi did not enter power save mode\n"); 00081 }*/ 00082 } 00083 00084 // start event tickers 00085 getMeasurementsTicker.attach(&time_to_sense_cb, SENSE_PERIOD_S); 00086 sendMeasurementsTicker.attach(&time_to_send_cb, UPLOAD_PERIOD_S); 00087 checkProximityTicker.attach(&time_to_check_distance_cb, CHECK_PROXIMITY_PERIOD_S); 00088 00089 } // Setup 00090 00091 00092 /* ---------- LOOP ------------- */ 00093 void loop() { 00094 time_t rawtime; 00095 tm *pTime; 00096 00097 if (take_measurements) { 00098 // Environment data 00099 hum_temp.get_temperature(&tempC_val); 00100 tempF_val = tempC_val*(9.0/5.0) + 32; 00101 hum_temp.get_humidity(&RH_val); 00102 00103 press_temp.get_pressure(&Patm_val); 00104 press_temp.get_temperature(&tempC_val2); 00105 00106 00107 // Inertial data 00108 /* 00109 magnetometer.get_m_axes(axes); 00110 printf("LIS3MDL [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00111 00112 acc_gyro.get_x_axes(axes); 00113 printf("LSM6DSL [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00114 00115 acc_gyro.get_g_axes(axes); 00116 printf("LSM6DSL [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); 00117 */ 00118 00119 // print results to terminal 00120 /* 00121 printf("HTS221: temp= %.2f C, hum= %.2f%%\r\n", tempC_val, RH_val); 00122 printf(" temp= %.2f F\n", tempF_val); 00123 printf("LPS22HB: patm= %.2f mbar, temp= %.2f C\r\n", Patm_val, tempC_val2); 00124 printf("VL53L0X [mm] = %6ld\r\n", distance_val); 00125 */ 00126 // refresh screen with updated measurements 00127 nextion.printf("valC.txt=\"%.1f\"\xff\xff\xff", tempC_val); 00128 nextion.printf("valF.txt=\"%.1f\"\xff\xff\xff", tempF_val); 00129 nextion.printf("valRH.txt=\"%.1f\"\xff\xff\xff", RH_val); 00130 nextion.printf("valAtm.val=%.0f\xff\xff\xff", Patm_val); 00131 nextion.printf("valRange.val=%d\xff\xff\xff", distance_val); 00132 00133 take_measurements = false; 00134 } 00135 00136 if (send_measurements) { 00137 00138 printf("HTS221: temp= %.2f C, hum= %.2f%%\r\n", tempC_val, RH_val); 00139 00140 // body of the request 00141 char request_body[256]; 00142 char *InfluxServerUrl = INFLUX_SERVER_URL; 00143 sprintf(request_body, "disco_iot,loc=%s temperature=%.2f,humidity=%.1f,pressure=%.1f \n","playroom", tempC_val, RH_val, Patm_val); 00144 00145 // build header of the request 00146 sprintf((char *)http_request, "POST %s HTTP/1.1\r\nHost: %s \r\n", INFLUX_WRITE_EP, InfluxServerUrl); 00147 strcat((char *)http_request, "Accept: */*\r\n"); 00148 strcat((char *)http_request, "User-agent: ES-WIFI TcpClient\r\n"); 00149 strcat((char *)http_request, "Connection: Close\r\n"); //"Connection: Keep-Alive\r\n" 00150 char buffer[64]; 00151 sprintf(buffer, "Content-Length: %d \r\n\r\n", strlen(request_body)); 00152 strcat((char *)http_request, buffer); 00153 00154 // append body to the header of the request 00155 strcat((char *)http_request, request_body); 00156 reqLen = strlen((char *)http_request); 00157 00158 // Establish a connection to DB server 00159 uint8_t socketid = 1; 00160 if (checkWiFi()) { 00161 led3 = 1; 00162 if (connectToServer(INFLUX_SERVER_URL, INFLUX_SERVER_PORT, socketid)) { 00163 ledhttp =1; 00164 // submit POST request 00165 // printf("> Sending a POST request with length=%d including a body length=%d\n", reqLen, strlen(request_body)); 00166 // printf((char *)http_request); 00167 uint16_t dataLen; 00168 if (WIFI_SendData(socketid, http_request, reqLen, &dataLen, WIFI_WRITE_TIMEOUT) != WIFI_STATUS_OK) { 00169 printf("> ERROR: Could not send request to %s", InfluxServerUrl); 00170 UPLOAD_ICON_OFF; 00171 } else { 00172 request_sent++; 00173 UPLOAD_ICON_ON; 00174 } 00175 // get server response 00176 // memset(&http_resp[0], 0, sizeof(http_resp)); 00177 WIFI_ReceiveData(socketid, http_resp, sizeof(http_resp), &dataLen, WIFI_READ_TIMEOUT); 00178 if(dataLen > 0) { 00179 /* 00180 printf("> Server response:\n"); 00181 printf((char *)http_resp); 00182 printf("\n> Response length: %d \n", dataLen); 00183 */ 00184 memset(&buffer[0], 0, sizeof(buffer)); 00185 // get the first line of the response 00186 strcpy(buffer, strtok((char *)http_resp, "\r\n")); 00187 // extract the response code 00188 int response_code = 0; 00189 sscanf(buffer, "HTTP/1.1 %d", &response_code); 00190 // printf("> Response code: %d \n", response_code); 00191 /* common response codes from InfluxDB API: 00192 HTTP/1.1 204 No Content 00193 HTTP/1.1 400 Bad Request 00194 HTTP/1.1 404 Not Found 00195 HTTP/1.1 500 Internal Server Error 00196 */ 00197 if (response_code == 204) request_acked++; 00198 } else { 00199 UPLOAD_ICON_OFF; 00200 printf("> Error: No response from the server %s.\n", InfluxServerUrl); 00201 } 00202 printf("> Requests sent: %d, ack'ed: %d\n", request_sent, request_acked); 00203 ledhttp = 0; 00204 WIFI_CloseClientConnection(socketid); 00205 } else { 00206 printf("> ERROR: Could not open connection to %s \n", InfluxServerUrl); 00207 } 00208 00209 // enter power save mode for UPLOAD_PERIOD_S - 1 sec, beacon interval = 100ms 00210 if (WIFI_SetPowerSaveMode(1, (UPLOAD_PERIOD_S - 1)*1000) == WIFI_STATUS_OK) { 00211 printf("> es-wifi entered power save mode\n"); 00212 } else { 00213 printf("> ERROR: es-wifi did not enter power save mode\n"); 00214 } 00215 00216 } else { 00217 printf("> ERROR: Could not connect to WiFi \n"); 00218 led3 = 0; 00219 } 00220 00221 if (rtc_synced) { 00222 time(&rawtime); 00223 pTime = localtime(&rawtime); 00224 // printf ("Current local time and date: %s", asctime(pTime)); 00225 // printf("> %d:%d:%d\n", pTime->tm_hour, pTime->tm_min, pTime->tm_sec); 00226 } else { 00227 rtc_synced = sync_rtc(); 00228 } 00229 00230 send_measurements = false; 00231 } 00232 00233 if (check_proximity) { 00234 // make sure display is awake when somebody get close to the screen 00235 // Proximity value 00236 uint32_t dist_val = 0; 00237 int status = range.get_distance(&dist_val); 00238 if (status == VL53L0X_ERROR_NONE) { 00239 if (dist_val < 500) { 00240 nextion.printf("sleep=0\xff\xff\xff");// send wake up command 00241 } 00242 distance_val = dist_val; 00243 } else { 00244 distance_val = 9999; 00245 } 00246 00247 // since this is a 1-sec period ticker, we do clock display refresh in here too 00248 // get a formatted local time to be displayed 00249 if (rtc_synced) { 00250 time(&rawtime); 00251 pTime = localtime(&rawtime); 00252 nextion.printf("hour.txt=\"%02d\"\xff\xff\xff", pTime->tm_hour); 00253 nextion.printf("minute.txt=\"%02d\"\xff\xff\xff", pTime->tm_min); 00254 nextion.printf("vis sec,1\xff\xff\xff"); 00255 //nextion.printf("vis sec,%d\xff\xff\xff", pTime->tm_sec % 2 == 0 ? 1 : 0); 00256 } 00257 00258 check_proximity = false; 00259 } 00260 } // Loop 00261 00262 00263 int main() { 00264 setup(); 00265 while(1) { 00266 loop(); 00267 } 00268 } 00269 00270 00271 /* */ 00272 /* Interrupts servicing callback functions */ 00273 /* */ 00274 00275 // ISR for flashing WiFi LED 00276 /* 00277 void toggle_led3_cb() 00278 { 00279 led3 = !led3; 00280 }*/ 00281 00282 // ISR to enable taking measurements (and refresh display) 00283 void time_to_sense_cb(void) 00284 { 00285 if (sense_enabled) { 00286 take_measurements = true; 00287 } 00288 } 00289 00290 // ISR to enable handling sending data 00291 void time_to_send_cb(void) 00292 { 00293 if (sense_enabled) { 00294 send_measurements = true; 00295 } 00296 } 00297 00298 // ISR to enable checking distance 00299 void time_to_check_distance_cb(void) 00300 { 00301 check_proximity = true; 00302 } 00303 00304 /** 00305 * @brief Connect to the WiFi network with credentials in mbed_app.json 00306 * @param None 00307 * @retval True for WiFi connected, False if there was an error 00308 */ 00309 bool connectWiFi(void) 00310 { 00311 uint8_t IP_Addr[4]; 00312 uint8_t MAC_Addr[6]; 00313 00314 if(WIFI_Init() == WIFI_STATUS_OK) { 00315 // printf("> WiFi module initialized.\n"); 00316 char fwVer[32]; 00317 if(WIFI_GetModuleFwRevision(fwVer) == WIFI_STATUS_OK) { 00318 printf("> Firmware version: %s\n", fwVer); 00319 } 00320 /* 00321 if(WIFI_GetMAC_Address(MAC_Addr) == WIFI_STATUS_OK) { 00322 printf("> WiFi module MAC Address : %X:%X:%X:%X:%X:%X\n", 00323 MAC_Addr[0], 00324 MAC_Addr[1], 00325 MAC_Addr[2], 00326 MAC_Addr[3], 00327 MAC_Addr[4], 00328 MAC_Addr[5]); 00329 } else { 00330 printf("> ERROR : CANNOT get MAC address\n"); 00331 }*/ 00332 00333 if( WIFI_Connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, WIFI_ECN_WPA2_PSK) == WIFI_STATUS_OK) { 00334 if(WIFI_GetIP_Address(IP_Addr) == WIFI_STATUS_OK) { 00335 printf("> IP Address : %d.%d.%d.%d\n", 00336 IP_Addr[0], 00337 IP_Addr[1], 00338 IP_Addr[2], 00339 IP_Addr[3]); 00340 WIFI_ICON_ON; 00341 UPLOAD_ICON_OFF; // reset db sync status if (re-)connect happened 00342 return true; 00343 } else { 00344 printf("> ERROR : es-wifi module CANNOT get IP address\n"); 00345 } 00346 } else { 00347 printf("> ERROR : es-wifi module NOT connected\n"); 00348 } 00349 } else { 00350 printf("> ERROR : WIFI Module cannot be initialized.\n"); 00351 } 00352 WIFI_ICON_OFF; 00353 UPLOAD_ICON_OFF; 00354 return false; 00355 } 00356 00357 00358 /** 00359 * @brief check WiFi connection status, retry once if it's offline 00360 * @param None 00361 * @retval True for WiFi (re)connected, False if reconnection failed 00362 */ 00363 00364 bool checkWiFi(void) 00365 { 00366 uint8_t ip_addr[4]; 00367 if(WIFI_GetIP_Address(ip_addr) == WIFI_STATUS_OK) { 00368 WIFI_ICON_ON; 00369 return true; 00370 } else { 00371 return connectWiFi(); 00372 } 00373 } 00374 00375 /** 00376 * @brief create a TCP session on a server 00377 * @param serverUrl : TCP server URL 00378 * @param serverPort : port TCP server is listening on 00379 * @retval true if connection established 00380 */ 00381 bool connectToServer(char *serverUrl, uint16_t serverPort, uint8_t socket_id) 00382 { 00383 uint8_t serverIP[] = {0, 0, 0, 0}; 00384 uint16_t trials = CONNECTION_TRIAL_MAX; 00385 00386 while (trials--) { 00387 // get the server IP through a (local) DNS resolve 00388 if (WIFI_GetHostAddress(serverUrl, serverIP) == WIFI_STATUS_OK) { 00389 00390 printf("> %s resolved to: %d.%d.%d.%d\n", serverUrl, 00391 serverIP[0], 00392 serverIP[1], 00393 serverIP[2], 00394 serverIP[3]); 00395 // establish TCP connection to server 00396 if( WIFI_OpenClientConnection(socket_id, WIFI_TCP_PROTOCOL, "TCP_Client", serverIP, serverPort, 0) == WIFI_STATUS_OK) { 00397 printf("> Connected to %s .\n", serverUrl); 00398 return true; 00399 } 00400 } else { 00401 printf("> ERROR : Cannot resolve URL: %s\n", serverUrl); 00402 printf("> Trials left: %d\n", trials); 00403 } 00404 } 00405 00406 if(!trials) { 00407 printf("> ERROR : Cannot establish connection\n"); 00408 } 00409 return false; 00410 } 00411 00412 00413 /** 00414 * @brief get current unix timestamp and use it to sync rtc 00415 * @retval True if successful, False if failed 00416 */ 00417 bool sync_rtc() { 00418 // 1- establish connection to time server (socket 2) 00419 uint8_t socketid = 2; 00420 uint16_t dataLen; 00421 if (checkWiFi()) { 00422 if (connectToServer(TIME_SERVER_URL, TIME_SERVER_PORT, socketid)) { 00423 sprintf((char *)http_request, "GET %s HTTP/1.1\r\nHost: %s \r\n", TIME_SERVER_EP, TIME_SERVER_URL); 00424 strcat((char *)http_request, "Connection: Close\r\n\r\n"); 00425 reqLen = strlen((char *)http_request); 00426 if (WIFI_SendData(socketid, http_request, reqLen, &dataLen, WIFI_WRITE_TIMEOUT) != WIFI_STATUS_OK) { 00427 printf("> ERROR: Could not send request to %s\n", TIME_SERVER_URL); 00428 } else { 00429 printf("> TS: Sent %d bytes\n", dataLen); 00430 } 00431 00432 // 2- get server response and parse the json 00433 WIFI_ReceiveData(socketid, http_resp, sizeof(http_resp), &dataLen, WIFI_READ_TIMEOUT); 00434 if(dataLen > 0) { 00435 printf("> TS: Received %d bytes\n", dataLen); 00436 // extract the body (json payload) from the response 00437 char *resp_body = strstr((char *)http_resp, "\r\n\r\n"); // get the body + "OK" 00438 resp_body = strtok(resp_body, "\r\n"); // get rid of 'OK' 00439 picojson::value json_val; 00440 string err = picojson::parse(json_val, resp_body, resp_body + strlen(resp_body)); 00441 if(err.empty()) { 00442 00443 // 3- convert timestamp to local time and sync rtc 00444 uint32_t timestamp_val = (unsigned)json_val.get("timestamp").get<double>(); 00445 printf("> utc_ts = %u \n",timestamp_val); // print utc 00446 timestamp_val -= 3600*5; // EST: utc - 5h 00447 set_time(timestamp_val); 00448 WIFI_CloseClientConnection(socketid); // close socket on success 00449 return true; 00450 } else { 00451 printf("> ERROR: TS json parsing\n"); 00452 } 00453 } else { 00454 printf("> ERROR: Did not receive data from TS server\n"); 00455 } 00456 WIFI_CloseClientConnection(socketid); // close socket on failure to retrieve time 00457 } else { 00458 printf("> ERROR: Cannot establish connection to %s \n", TIME_SERVER_URL); 00459 } 00460 } 00461 return false; 00462 } 00463
Generated on Thu Jul 28 2022 00:59:16 by
1.7.2
