World Clock& Weather Monitoring Design With LGVL/SqureLine

by Lan_Makerfabs in Circuits > Arduino

1000 Views, 2 Favorites, 0 Comments

World Clock& Weather Monitoring Design With LGVL/SqureLine

IMG_20231111_163346.jpg
IMG_20231113_101942.jpg

In this article, I'm going to make a screen that displays real-time time and weather conditions in some capital cities, using Squareline_studio and MaTouch ESP32-S3 Parallel TFT with Touch 7"

Hello everyone! Do you know, it snowed in north lately, and there are many videos online about playing in the snow, which make me eager to go to on a trip there. But what bothers me is that I am located in the south, where the weather is still extremely hot, with a huge temperature difference from the north. If I want to travel to the north, I need to keep an eye on the weather there.

So, I created this screen that can display real-time and weather information, it can get the time and weather information of website or server by connecting wifi.

Supplies

{B434F6CC-043C-4c81-A6F1-28DDEB8C1904}.png

This display module support Wifi & Bluetooth 5.0.

  • Software support: Arduino, SquareLine

SquareLine Design

QQ截图20231110084517.png
QQ截图20231109175645.png
时钟黑 1.png
  • Create a new product

Choose the Arduino and enter in parameters. According to the features of MaTouch ESP32-S3 Parallel TFT with Touch 7" ,the resolution is 1024*600, the shape is rectangle, and the color depth is 16-bit.

  • Design the screen

Add the clock and weather images to assets, and then it allows you to select them and widget components to design the scenes. After, clicking the widget of the list on the Hierarchy panel, you can modify the parameters of the select widget on the Inspector panel, all is determined by your preference.

And this is Basic usage of Squareline with MaTouch 2.1 . Except for the SquareLine page design and code part, all the other operations are almost the same.

Firmware of Clock Screen

  • The MaTouch ESP32-S3 Parallel TFT with Touch 7"  is not compatible with the TFT_eSPI library, so I use the GFX_Library_of_Arduino library instead of the driver.

Since I did not use the TFT_eSPI library, it is needed to delete or comment all the codes related to the TFT_eSPI library.

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();

tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */

When I use the GFX library, it is needed to define the GFX Library For the Arduino Interface pin.

Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
    GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
    40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
    45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
    5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
    8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);


Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
    bus,
    SCREEN_W /* width */, 1 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 128 /* hsync_back_porch */,
    SCREEN_H /* height */, 1 /* vsync_polarity */, 13 /* vsync_front_porch */, 3 /* vsync_pulse_width */, 45 /* vsync_back_porch */,
    1 /* pclk_active_neg */, 16000000 /* prefer_speed */, true /* auto_flush */);

  • LVGL is a user interface library primarily focused on display functionality, but it lacks user interaction capabilities. So, I need something to help me touch or interact with the screen.

Modify the touchpad function according to the pre-set functions in touch.h, and pass the state of the touchpad to the LVGL graphics library.

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
    if (touch_has_signal())
    {
        if (touch_touched())
        {
            data->state = LV_INDEV_STATE_PR;


            /*Set the coordinates*/
            data->point.x = touch_last_x;
            data->point.y = touch_last_y;
        }
        else if (touch_released())
        {
            data->state = LV_INDEV_STATE_REL;
        }
    }
    else
    {
        data->state = LV_INDEV_STATE_REL;
    }
}

  • Connecting wifi and getting NTP.
#define SSID "Makerfabs"
#define PWD "20160704"

// NTP
const char *ntpServer = "120.25.108.11";

void wifi_init()
{
    WiFi.begin(SSID, PWD);


    int connect_count = 0;
    while (WiFi.status() != WL_CONNECTED)
    {
        vTaskDelay(500);
        USBSerial.print(".");
        connect_count++;
    }


    USBSerial.println("Wifi connect");
    configTime((const long)(8 * 3600), 0, ntpServer);


    net_flag = 1;
}
  • Adjust the angle of the hour, minute and second hands according to the acquisition time.
void display_time()
{
    struct tm timeinfo;


    if (!getLocalTime(&timeinfo))
    {
        USBSerial.println("Failed to obtain time");
        return;
    }
    else
    {
        int year = timeinfo.tm_year + 1900;
        int month = timeinfo.tm_mon + 1;
        int day = timeinfo.tm_mday;
        int hour = timeinfo.tm_hour;
        int min = timeinfo.tm_min;
        int sec = timeinfo.tm_sec;


        int sec_angle = 3600 * sec / 60;
        int min_angle = 3600 * min / 60 + 60 * sec / 60;
        int hour_angle = 3600 * (hour % 12) / 12 + 300 * min / 60;


        lv_img_set_angle(ui_Image2, hour_angle);
        lv_img_set_angle(ui_Image3, min_angle);
        lv_img_set_angle(ui_Image4, sec_angle);


        lv_img_set_angle(ui_Image7, hour_angle);
        lv_img_set_angle(ui_Image8, min_angle);
        lv_img_set_angle(ui_Image9, sec_angle);
    }
}

The raw code.

Firmware of Weather Screen

  • The MaTouch ESP32-S3 Parallel TFT with Touch 7"  is not compatible with the TFT_eSPI library, so I use the GFX_Library_of_Arduino library instead of the driver.

Since I did not use the TFT_eSPI library, it is needed to delete or comment all the codes related to the TFT_eSPI library.

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();

tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */

When I use the GFX library, it is needed to define the GFX Library For the Arduino Interface pin.

Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
    GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
    40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
    45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
    5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
    8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);


Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
    bus,
    SCREEN_W /* width */, 1 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 128 /* hsync_back_porch */,
    SCREEN_H /* height */, 1 /* vsync_polarity */, 13 /* vsync_front_porch */, 3 /* vsync_pulse_width */, 45 /* vsync_back_porch */,
    1 /* pclk_active_neg */, 16000000 /* prefer_speed */, true /* auto_flush */);

  • LVGL is a user interface library primarily focused on display functionality, but it lacks user interaction capabilities. So, I need something to help me touch or interact with the screen.

Modify the touchpad function according to the pre-set functions in touch.h, and pass the state of the touchpad to the LVGL graphics library.

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
    if (touch_has_signal())
    {
        if (touch_touched())
        {
            data->state = LV_INDEV_STATE_PR;


            /*Set the coordinates*/
            data->point.x = touch_last_x;
            data->point.y = touch_last_y;
        }
        else if (touch_released())
        {
            data->state = LV_INDEV_STATE_REL;
        }
    }
    else
    {
        data->state = LV_INDEV_STATE_REL;
    }
}

  • Connecting wifi
#define SSID "Makerfabs"
#define PWD "20160704"

void wifi_init()
{
    WiFi.begin(SSID, PWD);


    int connect_count = 0;
    while (WiFi.status() != WL_CONNECTED)
    {
        vTaskDelay(500);
        USBSerial.print(".");
        connect_count++;
    }


    USBSerial.println("Wifi connect");
    configTime((const long)(8 * 3600), 0, ntpServer);


    net_flag = 1;
}
  • Getting the weather information of the cities.
String city_list[CITY_COUNT] =
    {
        "Beijing",    // china
        "Tokyo",      // japan
        "Washington", // usa
        "London",     // england
        "Paris",      // france
        "Canberra",   // Australia
        "Brazil",     // Brazil
        "Berlin"      // german
};

void weather_request(int country_num)
{
    HTTPClient http;


    USBSerial.print("[HTTP] begin...\n");


    String url = "http://api.weatherapi.com/v1/current.json?key=271578bfbe12438085782536232404&q=" + city_list[country_num] + "&aqi=no";


    http.begin(url);


    USBSerial.print("[HTTP] GET...\n");
    // start connection and send HTTP header
    int httpCode = http.GET();


    // httpCode will be negative on error
    if (httpCode > 0)
    {
        // HTTP header has been send and Server response header has been handled
        USBSerial.printf("[HTTP] GET... code: %d\n", httpCode);


        // file found at server
        if (httpCode == HTTP_CODE_OK)
        {
            String payload = http.getString();
            USBSerial.println(payload);


            // JSON
            DynamicJsonDocument doc(1024);
            deserializeJson(doc, payload);
            JsonObject obj = doc.as<JsonObject>();


            String city = doc["location"]["name"];
            String last_update = doc["current"]["last_updated"];
            String cond_txt = doc["current"]["condition"]["text"];
            float tmp = doc["current"]["temp_c"];
            float hum = doc["current"]["humidity"];
            float pressure = doc["current"]["pressure_mb"];
            float uv = doc["current"]["uv"];


            String text = city + " " + cond_txt + " " + last_update;


            USBSerial.println(text);
            USBSerial.println(tmp);
            USBSerial.println(hum);
            USBSerial.println(pressure);
            USBSerial.println(uv);


            lv_label_set_text(ui_Label1, text.c_str());


            char c[10];
            sprintf(c, "%.1f C", tmp);
            lv_label_set_text(ui_LabelTemp, c);
            sprintf(c, "%.1f %%", hum);
            lv_label_set_text(ui_LabelHumi, c);
            sprintf(c, "%.1f kPa", pressure / 10);
            lv_label_set_text(ui_LabelPress, c);
            sprintf(c, "%.1f", uv);
            lv_label_set_text(ui_LabelUV, c);


            lv_arc_set_value(ui_ArcTemp, tmp);
            lv_arc_set_value(ui_ArcHumi, hum);
            lv_arc_set_value(ui_ArcPress, pressure);
            lv_arc_set_value(ui_ArcUV, uv);
        }
    }
    else
    {
        USBSerial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }


    http.end();
}

The raw code.

Result

video_20231113_101404.gif
video_20231111_162911_edit.gif

In the clock display example, we can see the clock hands change with real-time. In the weather display example,when I click the button in the upper right corner, I can change the city which I want to get weather information.