|
| 1 | +# LVGL in less than 10 minutes with Tasmota |
| 2 | + |
| 3 | +Tasmota is a widely used open-source firmware for ESP8266 and EPS32 based devices. It supports a wide variety of devices, sensors and integrations to Home Automation and Cloud services. Tasmota firmware is downloaded more than 200,000 times each month, and has an active and growing community. |
| 4 | + |
| 5 | +In 2021, Tasmota added full support of LVGL for ESP32 based devices. It also introduced the [Berry scripting language](https://github.com/berry-lang/berry/wiki/Reference), a small-footprint language similar to Python and fully integrated in Tasmota. A comprehensive mapping of LVGL in Berry language is available, similar to the mapping of Micropython. |
| 6 | + |
| 7 | +The tutorial below illustrates how to install Tasmota on M5Stack devices (based on ESP32) and run your first LVGL application in Berry - all in less than 10 minutes. |
| 8 | + |
| 9 | +We will use nice [M5Stack](https://m5stack.com/) devices that integrate ESP32 and a 320x240 display, with touchscreen or physical buttons depending on the device. |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +## Flash Tasmota-lvgl on the device |
| 14 | + |
| 15 | +We have packaged an easy to use Web Flasher for ESP32. |
| 16 | + |
| 17 | +_If this method fails or if you prefer local client method, have a look at [Getting Started](https://tasmota.github.io/docs/Getting-Started/) on Tasmota documentation._ |
| 18 | + |
| 19 | + |
| 20 | +- Connect your M5Stack device via a USB Cable. |
| 21 | + |
| 22 | +- Connect to the [Tasmota Web Installer](https://arendst.github.io/Tasmota-firmware/) |
| 23 | + |
| 24 | + |
| 25 | + |
| 26 | +- Scroll down in `Development` section and select `Tasmota32 LVGL` |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +- Click `Connect` and select the appropriate Serial Port. It should connect in a couple of second. |
| 31 | + |
| 32 | + |
| 33 | + |
| 34 | +- Click `Install Development Tasmota32 Lvgl (English)` |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | +- Check `Erase Device` if it's the first time you install Tasmota, or you may experience unwanted behavior. Click `Next` |
| 39 | + |
| 40 | + |
| 41 | + |
| 42 | +- Click `Install` |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +- It should take a little more to Erase and Flash |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +You can now close the Web Flasher and proceed to the Wifi configuration |
| 51 | + |
| 52 | +## Configure Tasmota Wifi |
| 53 | + |
| 54 | +The next step can be done with a phone or a computer. |
| 55 | + |
| 56 | +- Connect to temporary the wifi access point with a name starting with `tasmota-...` |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +- You should be automatically brought to the Wifi configuration page. If not, try connecting to `192.168.4.1` |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +- Select your wifi network (yes, my wifi is named `Tasmota`...), enter the password and hit `Save`. If all goes well, you should see the IP address of Tasmota and be redirected to it. |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +- You should now see the Tasmota main screen. |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +## Configure Tasmota for M5Stack |
| 73 | + |
| 74 | +Tasmota is based on general purpose firmwares, you now need to configure specifically for your M5Stack device. We provide two templates, one for `M5Stack Basic/Gray/GO/Fire` and one for `M5Stack Core2`. |
| 75 | + |
| 76 | +- Go to Tasmota main screen and click on `Configuration` |
| 77 | + |
| 78 | + |
| 79 | + |
| 80 | +- Then click on `Auto-configuration`. You are now on the Auto-configuration page. Select `M5Stack Fire` or `M5Stack Core2`. Then click on `Apply configuration`. |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | +The device restarts and you should be back to Tasmota main page. The screen should have been configured (you should see a short flash on the screen). |
| 85 | + |
| 86 | + |
| 87 | + |
| 88 | +## Try a LVGL demo app |
| 89 | + |
| 90 | +In this last step, we will try to run a small LVGL application written in Berry. |
| 91 | + |
| 92 | +- Go to Tasmota Main Screen and click `Consoles` then `Manage File System` |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +- Click on `Create and edit new file`, enter the filename `autoexec.be` and copy the following code in the text pane: |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | +``` python |
| 101 | +#- start LVGL and init environment -# |
| 102 | +lv.start() |
| 103 | + |
| 104 | +tasmota.cmd("DisplayDimmer 50") |
| 105 | + |
| 106 | +hres = lv.get_hor_res() # should be 320 |
| 107 | +vres = lv.get_ver_res() # should be 240 |
| 108 | + |
| 109 | +scr = lv.scr_act() # default screean object |
| 110 | +f20 = lv.montserrat_font(20) # load embedded Montserrat 20 |
| 111 | + |
| 112 | +#- Background with a gradient from black #000000 (bottom) to dark blue #0000A0 (top) -# |
| 113 | +scr.set_style_bg_color(lv.color(0x0000A0), lv.PART_MAIN | lv.STATE_DEFAULT) |
| 114 | +scr.set_style_bg_grad_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT) |
| 115 | +scr.set_style_bg_grad_dir(lv.GRAD_DIR_VER, lv.PART_MAIN | lv.STATE_DEFAULT) |
| 116 | + |
| 117 | +#- Upper state line -# |
| 118 | +stat_line = lv.label(scr) |
| 119 | +if f20 != nil stat_line.set_style_text_font(f20, lv.PART_MAIN | lv.STATE_DEFAULT) end |
| 120 | +stat_line.set_long_mode(lv.LABEL_LONG_SCROLL) # auto scrolling if text does not fit |
| 121 | +stat_line.set_width(hres) |
| 122 | +stat_line.set_align(lv.TEXT_ALIGN_LEFT) # align text left |
| 123 | +stat_line.set_style_bg_color(lv.color(0xD00000), lv.PART_MAIN | lv.STATE_DEFAULT) # background #000088 |
| 124 | +stat_line.set_style_bg_opa(lv.OPA_COVER, lv.PART_MAIN | lv.STATE_DEFAULT) # 100% background opacity |
| 125 | +stat_line.set_style_text_color(lv.color(0xFFFFFF), lv.PART_MAIN | lv.STATE_DEFAULT) # text color #FFFFFF |
| 126 | +stat_line.set_text("Tasmota") |
| 127 | +stat_line.refr_size() # new in LVGL8 |
| 128 | +stat_line.refr_pos() # new in LVGL8 |
| 129 | + |
| 130 | +#- display wifi strength indicator icon (for professionals ;) -# |
| 131 | +wifi_icon = lv_wifi_arcs_icon(stat_line) # the widget takes care of positioning and driver stuff |
| 132 | +clock_icon = lv_clock_icon(stat_line) |
| 133 | + |
| 134 | +#- create a style for the buttons -# |
| 135 | +btn_style = lv.style() |
| 136 | +btn_style.set_radius(10) # radius of rounded corners |
| 137 | +btn_style.set_bg_opa(lv.OPA_COVER) # 100% backgrond opacity |
| 138 | +if f20 != nil btn_style.set_text_font(f20) end # set font to Montserrat 20 |
| 139 | +btn_style.set_bg_color(lv.color(0x1fa3ec)) # background color #1FA3EC (Tasmota Blue) |
| 140 | +btn_style.set_border_color(lv.color(0x0000FF)) # border color #0000FF |
| 141 | +btn_style.set_text_color(lv.color(0xFFFFFF)) # text color white #FFFFFF |
| 142 | + |
| 143 | +#- create buttons -# |
| 144 | +prev_btn = lv.btn(scr) # create button with main screen as parent |
| 145 | +prev_btn.set_pos(20,vres-40) # position of button |
| 146 | +prev_btn.set_size(80, 30) # size of button |
| 147 | +prev_btn.add_style(btn_style, lv.PART_MAIN | lv.STATE_DEFAULT) # style of button |
| 148 | +prev_label = lv.label(prev_btn) # create a label as sub-object |
| 149 | +prev_label.set_text("<") # set label text |
| 150 | +prev_label.center() |
| 151 | + |
| 152 | +next_btn = lv.btn(scr) # right button |
| 153 | +next_btn.set_pos(220,vres-40) |
| 154 | +next_btn.set_size(80, 30) |
| 155 | +next_btn.add_style(btn_style, lv.PART_MAIN | lv.STATE_DEFAULT) |
| 156 | +next_label = lv.label(next_btn) |
| 157 | +next_label.set_text(">") |
| 158 | +next_label.center() |
| 159 | + |
| 160 | +home_btn = lv.btn(scr) # center button |
| 161 | +home_btn.set_pos(120,vres-40) |
| 162 | +home_btn.set_size(80, 30) |
| 163 | +home_btn.add_style(btn_style, lv.PART_MAIN | lv.STATE_DEFAULT) |
| 164 | +home_label = lv.label(home_btn) |
| 165 | +home_label.set_text(lv.SYMBOL_OK) # set text as Home icon |
| 166 | +home_label.center() |
| 167 | + |
| 168 | +#- callback function when a button is pressed, react to EVENT_CLICKED event -# |
| 169 | + |
| 170 | +def btn_clicked_cb(obj, event) |
| 171 | + var btn = "Unknown" |
| 172 | + if obj == prev_btn btn = "Prev" |
| 173 | + elif obj == next_btn btn = "Next" |
| 174 | + elif obj == home_btn btn = "Home" |
| 175 | + end |
| 176 | + print(btn, "button pressed") |
| 177 | +end |
| 178 | + |
| 179 | +prev_btn.add_event_cb(btn_clicked_cb, lv.EVENT_CLICKED, 0) |
| 180 | +next_btn.add_event_cb(btn_clicked_cb, lv.EVENT_CLICKED, 0) |
| 181 | +home_btn.add_event_cb(btn_clicked_cb, lv.EVENT_CLICKED, 0) |
| 182 | +``` |
| 183 | + |
| 184 | +- Click `Save` and restart the device. You should now see this on the M5Stack screen: |
| 185 | + |
| 186 | + |
| 187 | + |
| 188 | +You will find more information on [LVGL-Tasmota-Berry mapping](https://tasmota.github.io/docs/LVGL/). |
0 commit comments