This post was last edited by sonicfirr on 2022-9-5 07:45
The previous two reviews, this case is based on these two:
【Beetle ESP32-C3】VI. OLED, AHT10 and TCP (Arduino)
【Beetle ESP32-C3】VII. Network timing and weather request (Arduino)
On Sunday, I integrated the first two evaluation cases and made a "big job". The functions are as follows:
1) OLED can display two screens (called PAGE in the code), "clock + AHT10 temperature and humidity" and "weather icon + temperature".
2) Button (connected to IO7) is used to control the OLED screen change.
This article first gives the complete code, and then plans to write a review description. Code logic - I have been working on it for a day, and I really don’t have the energy to explain the logic.
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <Adafruit_AHTX0.h>
//-----SSID & password
const char *ssid = "yourssid"; //WIFI AP ssid
const char *password = "yourpsw"; //WIFI AP password
//-----NTP server & timezone offset
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 14400; //3600*4 for UTC+8
const int daylightOffset_sec = 14400;
struct tm t; //time struct
void printLocalTime(void);
//-----timer HW per second
hw_timer_t *timer = NULL; //timer variable
volatile SemaphoreHandle_t timersem; //timer fire sem
void IRAM_ATTR onTimer(void); //callback func
void initTimer(void);
//-----weather server URL & instance for json parsing
DynamicJsonDocument doc(1024); //json doc instance
const char *url = "https://api.thinkpage.cn/v3/weather/now.json?key=your_apikey&location=tianjin&language=en&unit=c";
void getWeather(void); //request now weather func
int code = 0; //weather code
int degree = 0; //weather temperature
//-----u8g2 instance & functions
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
void drawLocalTimePage(void);
void drawNowWeatherPage(int code, int temp);
//-----input key
#define KEY 7
//-----show page enum
typedef enum {
TIMEPAGE = 0,
WEATHERPAGE,
} AITA_PAGE_INDEX;
//-----global variable of page No
int pagestate = TIMEPAGE;
//-----AHT10 instance & sensor variables
Adafruit_AHTX0 aht; //aht instance
sensors_event_t aht_humi, aht_temp; //sensor variables
void getAHT10(void); //read aht10 sensor
void setup() {
//-----initialize BSP
Serial.begin(115200);
pinMode(KEY, INPUT_PULLUP);
//-----initialize u8g2
u8g2.begin();
u8g2.setFontPosTop();
u8g2.enableUTF8Print();
//-----initialize AHT10
if(!aht.begin()) {
Serial.println("Could not find AHT");
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_osb18_tf);
u8g2.drawStr(5,10,"no AHT");
u8g2.sendBuffer();
while(1) delay(10);
}
Serial.println("AHT10 or AHT20 found");
getAHT10();
//-----connect AP
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
//-----print IP address
Serial.println(" CONNECTED");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//-----initialize and get the time then initialize timer(per sec)
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
if(!getLocalTime(&t)){
Serial.println("Failed to obtain time");
return;
} else {
Serial.println(&t, "%A, %B %d %Y %H:%M:%S");
initTimer();
getWeather();
}
}
void loop() {
//-----update time state per second
if(xSemaphoreTake(timersem, 0) == pdTRUE) {
getLocalTime(&t);
}
//-----refresh screen
if(pagestate == TIMEPAGE)
drawLocalTimePage();
else if(pagestate == WEATHERPAGE)
drawNowWeatherPage(code, degree);
//-----update weather info per 5 minutes
if(t.tm_min%5==0 && t.tm_sec==0) {
getAHT10();
if(WiFi.status() == WL_CONNECTED) {
getWeather();
}
}
//-----read KEY
if(digitalRead(KEY) == 0) {
delay(30);
if(digitalRead(KEY) == 0) {
if(pagestate == WEATHERPAGE) pagestate = TIMEPAGE;
else pagestate++;
}
}
}
//-----second timer callback function
void IRAM_ATTR onTimer() {
xSemaphoreGiveFromISR(timersem, NULL);
}
//-----intialize timer function
void initTimer() {
timersem = xSemaphoreCreateBinary();
//ESP32 sysclk is 80MHz.
//frequency division factor to 80,
//then timer clock is 1MHz.
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true); //1000000us timer
timerAlarmEnable(timer);
}
//-----print local time function
void printLocalTime(void) {
if(!getLocalTime(&t)) {
Serial.println("Failed to obtain time");
return;
}
Serial.println(&t, "%F %T %A");
}
//-----read AHT10 sensor function
void getAHT10(void) {
aht.getEvent(&aht_humi, &aht_temp);
}
//-----draw local time function
void drawLocalTimePage(void) {
char str[6] = {0};
u8g2.clearBuffer();
//line1. set time & weekday
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.setCursor(0, 0);
u8g2.print(&t, "%H:%M:%S %a");
u8g2.setCursor(24, 18);
//line2. set date
u8g2.setFont(u8g2_font_8x13_mf);
u8g2.print(&t, "%Y-%m-%d");
//line3. set aht10 humidity
u8g2.drawStr(0, 32, "Humi: ");
memset(str, 0, 6);
dtostrf(aht_humi.relative_humidity, 6, 2, str);
u8g2.drawStr(48, 32, str);
u8g2.drawStr(96,32, "% rH");
//line4. set aht10 temperature
u8g2.drawStr(0, 48, "Temp: ");
memset(str, 0, 6);
dtostrf(aht_temp.temperature, 6, 2, str);
u8g2.drawStr(48, 48, str);
u8g2.setCursor(96, 48);
u8g2.print("° C");
//draw screen
u8g2.sendBuffer();
}
//-----set weather icon function
void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol) {
if(symbol>=0 && symbol<4) { //Sun
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 69);
} else if(symbol>=4 && symbol<9) { //Cloudy
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 65);
} else if(symbol==9) { //Overcast
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 64);
} else if(symbol>=10 && symbol<13) {//Thunder
u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t);
u8g2.drawGlyph(x, y, 67);
} else if(symbol>=13 && symbol<21) {//Rain
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 67);
} else { //Others show star
u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);
u8g2.drawGlyph(x, y, 68);
}
}
//-----set weather temperature degree function
void drawWeatherDegree(uint8_t symbol, int degree) {
drawWeatherSymbol(0, 0, symbol);
u8g2.setFont(u8g2_font_logisoso32_tf);
u8g2.setCursor(48+6, 10);
u8g2.print(degree);
u8g2.print("°C"); //requires enableUTF8Print()
}
//-----draw now weather function
void drawNowWeatherPage(int code, int temp) {
u8g2.clearBuffer();
drawWeatherDegree(code, temp);
u8g2.setCursor(32, 48);
u8g2.setFont(u8g2_font_8x13_mf);
u8g2.print("Tianjin");
u8g2.sendBuffer();
}
//-----request now weather function
void getWeather() {
if((WiFi.status() == WL_CONNECTED)) {
HTTPClient http; //create HTTPClient instance
http.begin(url); //begin HTTP request
int httpCode = http.GET(); //get response code - normal:200
if(httpCode > 0) {
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
//parse response string to DynamicJsonDocument instance
deserializeJson(doc, payload);
//get top level Json-Object
JsonObject obj = doc.as<JsonObject>();
//get "results" property then parse the value to Json-Array
JsonVariant resultsvar = obj["results"];
JsonArray resultsarr = resultsvar.as<JsonArray>();
//get array index 0 which is now weather info
JsonVariant resultselementvar = resultsarr[0];
JsonObject resultselementobj = resultselementvar.as<JsonObject>();
/* get values of city, temp, code, update */
//get city
JsonVariant namevar = resultselementobj["location"]["name"];
String namestr = namevar.as<String>();
Serial.println(namestr);
//get temperature
JsonVariant temperaturevar = resultselementobj["now"]["temperature"];
String temperaturestr = temperaturevar.as<String>();
degree = temperaturevar.as<int>();
Serial.println(temperaturestr);
//get weather code
JsonVariant codevar = resultselementobj["now"]["code"];
code = codevar.as<int>();
Serial.println(code);
//get last_update time
JsonVariant last_updatevar = resultselementobj["last_update"];
String last_updatestr = last_updatevar.as<String>();
Serial.println(last_updatestr);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n",
http.errorToString(httpCode).c_str());
}
http.end(); //end http connectiong
}
}
Figure 8-1 Example OLED display effect