[Digi-Key Follow me Issue 2] Air quality sensor and network controlled LED display demonstration
[Copy link]
This post was last edited by Lucheni on 2023-11-14 16:43
This post is the final submission of the second phase of Follow me. A total of two projects were completed
①Air quality sensor
②RGB LED control system based on onboard buttons and web buttons
For specific project demonstration, please refer to the video: https://training.eeworld.com.cn/video/38390?md5__2280=eqRxy7GQeiu49DBqDTClYOi%3Dq0Qweq%2Bex&alichlgref=http%3A%2F%2Ftraining.eeworld.com.cn%2Fcourse%2F68227
Air quality sensor project introduction and key code description:
This project uses the Adafruit ESP32-S3 TFT Feather board to connect the SGP40 and SCD41 sensors. These two sensors can measure voc, temperature, humidity and real carbon dioxide values respectively. The development board has an iic interface and a TFT color screen, which is very suitable for sensor connection and data display. Therefore, this project builds a demo of the air quality sensor based on these three parts.
The code is written in Arduino. I encapsulate the initialization of each module, data reading and display refresh as functions, which are directly called in the setup and loop functions. I think the readability is still very high.
The following is the sensor data reading function. It should be noted that when sgp40 calculates voc internally, it needs to pass the temperature and humidity data obtained by scd41 into
void ScdRead(uint16_t &co2, float &temperature, float &humidity){
bool isDataReady = false;
uint16_t error;
error = scd4x.getDataReadyFlag(isDataReady);
if (isDataReady) {
delay(10);
error = scd4x.readMeasurement(co2, temperature, humidity);
if (error) {
Serial.print("Error trying to execute readMeasurement(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else if (co2 == 0) {
Serial.println("Invalid sample detected, skipping.");
}
}
}
void SgpRead(uint16_t &sraw, int32_t &voc_index, float &temperature, float &humidity){
sraw = sgp.measureRaw(temperature, humidity);
voc_index = sgp.measureVocIndex(temperature, humidity);
}
The following is the tft refresh function, each time only the data part of the display block is refreshed locally
void TftRefresh() {
// tft print function!
tft.fillRect(60, 0, 60, 135, ST77XX_BLACK);
tft.setCursor(60, 10);
tft.setTextColor(ST77XX_RED);
tft.setTextSize(2);
tft.println(temperature);
tft.setCursor(60, 35);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.println(humidity);
tft.setCursor(60, 60);
tft.setTextColor(ST77XX_GREEN);
tft.setTextSize(2);
tft.println("null");
tft.setCursor(60, 85);
tft.setTextColor(ST77XX_BLUE);
tft.setTextSize(2);
tft.println(co2);
tft.setCursor(60, 110);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.println(voc_index);
}
The data on the tft side is displayed in Chinese. This code converts Chinese characters into bitmaps and calls the drawbitmap function for processing (the processing method can be seen in the previous quick pass tutorial https://en.eeworld.com/bbs/thread-1254565-1-1.html ):
const uint8_t PROGMEM str1[]= {0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00};/*"温",1*/
const uint8_t PROGMEM str2[]= {0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E};/*"度",1*/
const uint8_t PROGMEM str3[]= {0x00,0x00,0x27,0xF8,0x14,0x08,0x14,0x08,0x87,0xF8,0x44,0x08,0x44,0x08,0x17,0xF8,0x11,0x20,0x21,0x20,0xE9,0x24,0x25,0x28,0x23,0x30,0x21,0x20,0x2F,0xFE,0x00,0x00};/*"湿",0*/
const uint8_t PROGMEM str4[]= {0x10,0x00,0x10,0x00,0x3F,0xFC,0x20,0x00,0x4F,0xF0,0x80,0x00,0x3F,0xF0,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0A,0x00,0x0A,0x00,0x06,0x00,0x02};/*"气",0*/
const uint8_t PROGMEM str5[]= {0x00,0x00,0x3F,0xFE,0x20,0x00,0x20,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x2F,0xFC,0x20,0x80,0x20,0x80,0x20,0x90,0x20,0x88,0x20,0x88,0x40,0x80,0x5F,0xFE,0x80,0x00};/*"压",1*/
This project actually completed the task 1 to display Chinese on the screen
Introduction to the RGB LED control system based on onboard buttons and web buttons and key code description:
This project realizes the effect of onboard buttons controlling the color change of onboard LEDs and web page buttons controlling the display content of external LED arrays.
The loop function polls whether the button is pressed. If it is pressed, the onboard LED starts to change color (this can be optimized to a key interrupt, but the current project polling is also OK without modification)
if (!digitalRead(0)) {
TB.setColor(TB.Wheel(j++));
}
At the same time, the loop function polls whether the button in the web page generated by esp32 is pressed, and if it is pressed, the flag bit is modified
WiFiClient client = server.available();
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> to move LED.<br>");
client.print("Click <a href=\"/L\">here</a> to stop LED.<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
go=1; // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
go=0; // GET /L turns the LED off
}
}
Finally, determine whether to slide the content displayed on the external LED array based on the flag and the current time.
if ((((t=millis()%65536)-ledprevtime)>SHIFTDELAY)&&(go==1)){
matrix.fillScreen(0);
matrix.setCursor(x, 5);
for (byte i = 0; i < strlen(adafruit); i++) {
// set the color
matrix.setTextColor(adaColors[i]);
// write the letter
matrix.print(adafruit[i]);
}
if (--x < -50) {
x = matrix.width();
}
matrix.show();
ledprevtime = millis()%65536;
}
This project actually completed Task 2, Task 3, and Task 4, and realized four small projects: generating web pages and controlling them through wifi, using onboard buttons, using onboard RGB LEDs, and using an external 6*12 LED array.
The above project code can be found here: https://download.eeworld.com.cn/detail/Lucheni/629865
Summarize:
This activity studied wifi control, LED control, sensor data reading and Chinese display based on esp32s3, and I gained a lot. Of course, my personal favorite is the development board of this activity. It has a tft color screen on the compact feather version, an onboard power meter, and reserved welding interfaces for temperature and humidity sensors. It has a double-sided layout, which is very delicate for a development board. I look forward to playing with more and better boards in future activities!
|