Exercise #2: connect to Wifi AP + send TCP request
- This exercise and the previous one are quite simple because the sketch is mainly an assembly of protion of code already written, coming from the course or libraries examples.
- The single "problem" is to decompose the pressure into 4 digits because the provided tm1637 library is not able to display directly the value of an number.
NB: the readLine() function is a bit modified compared to the course. Here, we use the fact that the WiFiClient class inherits from the Stream class, providing methods like read(). thus, instead of directly using the client within readLine(), it takes a Stream object as a parameter. It allows to read lines on every kind of stream, like files, serial, ...
#include <BME280I2C.h>
#include <Wire.h>
#include <WiFi.h>
#include "TM1637.h"
// defines for LCD display
#define CLK 32
#define DIO 33
TM1637 tm1637(CLK,DIO);
// defines for bme280
#define BME280_SDA_PIN 18
#define BME280_SCL_PIN 23
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
float temperature(NAN);
float humidity(NAN);
float pressure(NAN);
// credentials of the wifi AP
const char *ssid = "testingiot"; // the ssid of the AP
const char *password = "testingiot"; // the password of the AP
// the wifi client to connect to TCP server
WiFiClient client;
byte connState;
char ipServ[20] = "192.168.0.2"; // setup default address
int portServ = 12345; // setup default port
String idClient;
#define SERIAL_BAUD 115200
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3 /* Time ESP32 will go to sleep (in seconds) */
RTC_DATA_ATTR int bootCount = 0;
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason) {
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
// function to read a line on any stream (NB: which includes WiFiClient)
String readLine(Stream& stream) {
char buffer[4096]; // read lines upto 4095 characters (the last must be always \0)
memset(buffer,0,4096); // reset buffer
int index = 0;
char c;
while ((index < 4095) && (stream.available())) {
c = stream.read();
if (c == '\n') return String(buffer); // end-of-line reached => return
buffer[index++] = c; // store the char
}
// if end of buffer/file is reached return the buffer
return String(buffer);
}
void setupWifi() {
int ret = 0;
// uncomment 2 following lines if needed
//WiFi.setAutoConnect(false); // see comments
//WiFi.setSleepMode(WIFI_NONE_SLEEP); // always active => big consumption
ret = WiFi.mode (WIFI_STA); // setup as a wifi client
Serial.println("setting Wifi mode: "+String(ret));
ret = WiFi.begin(ssid,password); // try to connect
Serial.println("begin connection to AP: "+String(ret));
while (WiFi.status() != WL_CONNECTED) { // check connection
delay(500);
Serial.print(".");
}
// debug messages
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
}
bool setupServerConnection() {
if (client.connect(ipServ, portServ)) {
connState = 1;
Serial.println("connected to server");
// disable buffering small mesg
client.setNoDelay(true);
// receive my id from the server
idClient = readLine(client);
Serial.println("my id is "+idClient);
return true;
}
else {
connState = 0;
Serial.println("connection failed");
return false;
}
}
void readBME280Data() {
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pressure, temperature, humidity, tempUnit, presUnit);
}
void sendRequest() {
String data = String(temperature)+" "+String(humidity)+" "+String(pressure);
String req = "1 "+idClient+" "+data;
Serial.println("sending request: "+req);
client.println(req);
String answer = readLine(client);
Serial.println("servers answers: "+answer);
}
void displayPressure() {
// decompose pressure into 4 digits
// d0 is the digit of thousands
// d1 for hundreds
// d2 for tenth
// d3 for units
int pres = (int)pressure;
int d0 = pres/1000;
if (d0 == 0) {
tm1637.display(0,0x7f); // set to no light
}
else {
tm1637.display(0,d0);
}
int d1 = (pres%1000)/100;
int d2 = ((pres%1000)%100)/10;
int d3 = ((pres%1000)%100)%10;
tm1637.display(1,d1);
tm1637.display(2,d2);
tm1637.display(3,d3);
}
void setup() {
Serial.begin(SERIAL_BAUD);
while(!Serial) {} // Wait for serial to be ready
// manage wake-up from deep-sleep
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
// initialize display
tm1637.init();
tm1637.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST =
// initialize I2C
Wire.begin(BME280_SDA_PIN, BME280_SCL_PIN);
// initialize BME280
while(!bme.begin()) {
Serial.println("Could not find BME280 sensor!");
delay(1000);
}
// try to detect BME280 sensor
switch(bme.chipModel()) {
case BME280::ChipModel_BME280:
Serial.println("Found BME280 sensor! Success.");
break;
case BME280::ChipModel_BMP280:
Serial.println("Found BMP280 sensor! No Humidity available.");
break;
default:
Serial.println("Found UNKNOWN sensor! Error!");
}
// setup wifi
setupWifi();
delay(100);
}
void loop() {
// if not connected, do ti
if (connState == 0) {
if (! setupServerConnection()) { delay(1000); }
}
else if (connState == 1) {
readBME280Data();
displayPressure();
sendRequest();
// go into deep-sleep for 5s
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
}