| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,26 +11,27 @@ ESP32S3-7814 is no longer a stand-alone WiFi access point. Because of the additi | |||
| 11 | 11 | ||
| 12 | 12 | This is the web page a fully functioning ESP32-S3 developer board presents now. | |
| 13 | 13 | ||
| 14 | -  | ||
| 14 | +  | ||
| 15 | 15 | ||
| 16 | 16 | The view the web page presents is dynamic. Here's what that means: | |
| 17 | 17 | 1. If the OLED display isn't present, then the `Toggle OLED` button is not shown. | |
| 18 | - 2. If the ESP32-S3 fails to connect with the MQTT broker then the `MQTT5 Test` button is not shown. | ||
| 18 | + 2. If the ESP32-S3 fails to connect with the MQTT broker then the `MQTT Report` button is not shown. | ||
| 19 | 19 | 3. If the ESP32-S3 developer board does not have a configured `vfs2` FLASH section, then the text at the bottom showing `vfs2 size` is not shown. | |
| 20 | 20 | ||
| 21 | 21 | ## Startup Output | |
| 22 | 22 | This startup output is captured from Thonny's REPL window. | |
| 23 | 23 | ``` | |
| 24 | 24 | Boot: START | |
| 25 | - Memory: 8,297,184 bytes | ||
| 25 | + Memory: 8,172,048 bytes | ||
| 26 | 26 | Flash: 33,554,432 bytes | |
| 27 | 27 | Platform: MicroPython 1.26.0 preview xtensa IDFv5.4.1 with newlib4.3.0 | |
| 28 | 28 | Unique ID: 68B6B33D7814 | |
| 29 | 29 | SSID: ESP32S3-7814 | |
| 30 | 30 | CPU Clock: 160,000,000 Hz | |
| 31 | 31 | I2C: SoftI2C(scl=2, sda=1, freq=500000) | |
| 32 | - I2C: Devices found: ['0x3d'] | ||
| 33 | - I2C: SSD1306 OLED Found | ||
| 32 | + I2C: Devices found: ['0x3d', '0x70', '0x71'] | ||
| 33 | + I2C: SSD1306 OLED Initialized | ||
| 34 | + I2C: HT16K33 LEDs Initialized | ||
| 34 | 35 | Boot: END | |
| 35 | 36 | Main: START | |
| 36 | 37 | LED: COLORS | |
@@ -41,14 +42,13 @@ This startup output is captured from Thonny's REPL window. | |||
| 41 | 42 | WIFI: 192.168.0.174 | |
| 42 | 43 | WIFI: NTP Connection Attempt #1 | |
| 43 | 44 | WIFI: NTP Connection Successful | |
| 44 | - DATE: 8:28 AM Friday 27 June 2025 | ||
| 45 | + DATE: 8:19 AM Monday 7 July 2025 | ||
| 45 | 46 | MQTT: Broker connection start from ESP32S3-7814 to 192.168.0.210 | |
| 46 | 47 | MQTT: Set callback | |
| 47 | 48 | MQTT: Connect | |
| 48 | 49 | MQTT: Subscribe to topic b'esp32-mqtt5/test' | |
| 49 | - MQTT: Init ping timer: Timer(3, mode=PERIODIC, period=60000) | ||
| 50 | + MQTT: Init ping timer: Timer(3, mode=PERIODIC, period=120000) | ||
| 50 | 51 | MQTT: Broker connection successful to 192.168.0.210 | |
| 51 | - | ||
| 52 | 52 | ``` | |
| 53 | 53 | If the board fails to connect to the MQTT broker, this is the last part of the output: | |
| 54 | 54 | ``` | |
@@ -73,7 +73,7 @@ Install the latest MicroPython release to the ESP32-S3 development board. It can | |||
| 73 | 73 | ||
| 74 | 74 | Once the firmware is operational on the ESP32-S3 developer board, then upload all the Python files, and only the Python files, to the developer board. | |
| 75 | 75 | ||
| 76 | - You will need to create `settings.py` file that contains the two lines: | ||
| 76 | + You will need to create `settings.py` file that contains the following two lines: | ||
| 77 | 77 | 1. `AP_SSID = "your-wifi-SSID"` and | |
| 78 | 78 | 2. `AP_PASSWORD = "your-wifi-password"`, | |
| 79 | 79 | ||
@@ -86,7 +86,12 @@ Install Mosquitto via `apt`: | |||
| 86 | 86 | ```bash | |
| 87 | 87 | $ sudo apt install mosquitto mosquitto-clients -y | |
| 88 | 88 | ``` | |
| 89 | - Once installed make sure that the Mosquitto broker is up and running: | ||
| 89 | + Once installed, add the following lines (at a minimum) to `/etc/mosquitto/conf.d/default.conf`: | ||
| 90 | + ``` | ||
| 91 | + allow_anonymous true | ||
| 92 | + listener 1883 0.0.0.0 | ||
| 93 | + ``` | ||
| 94 | + Once installed make check if the Mosquitto broker is up and running: | ||
| 90 | 95 | ```bash | |
| 91 | 96 | $ systemctl status mosquitto | |
| 92 | 97 | ● mosquitto.service - Mosquitto MQTT Broker | |
@@ -107,7 +112,7 @@ Jun 10 22:01:46 pi05-01 systemd[1]: Started mosquitto.service - Mosquitto MQTT B | |||
| 107 | 112 | Jun 14 00:50:10 pi05-01 systemd[1]: Reloading mosquitto.service - Mosquitto MQTT Broker... | |
| 108 | 113 | Jun 14 00:50:10 pi05-01 systemd[1]: Reloaded mosquitto.service - Mosquitto MQTT Broker. | |
| 109 | 114 | ``` | |
| 110 | - In the example above Mosquitto is loaded and active (running). If it's not, then type `sudo systemctl start mosquitto` at the prompt and check the status again. | ||
| 115 | + In the example above Mosquitto is loaded and active (running). If it is and you've edited the `default.conf` file, then type `sudo systemctl stop mosquitto` followed by `sudo systemctl start mosquitto` to read the configuration file. `systemctl` has a `restart` command, but I prefer a hard stop then a start to make sure everything is properly initialized. | ||
| 111 | 116 | #### Development and Testing | |
| 112 | 117 | Once the broker is up, open a terminal and type the following: | |
| 113 | 118 | ```bash | |
@@ -119,30 +124,36 @@ The application on the ESP32-S3 connects to the broker via the Mosquitto subscri | |||
| 119 | 124 | ||
| 120 | 125 | All ESP32-S3 minified JSON messages: | |
| 121 | 126 | ``` | |
| 122 | - {"PWRON":"ESP32S3-7814","DATE":"2025-06-27T20:22:53.004Z"} | ||
| 123 | - {"PING":"ESP32S3-7814","DATE":"2025-06-27T20:23:53.004Z"} | ||
| 124 | - {"LED":"ESP32S3-7814","COLOR":"RED","STATE":"ON","DATE":"2025-06-27T20:24:01.004Z"} | ||
| 125 | - {"LED":"ESP32S3-7814","COLOR":"RED","STATE":"OFF","DATE":"2025-06-27T20:24:06.004Z"} | ||
| 126 | - {"LED":"ESP32S3-7814","COLOR":"GREEN","STATE":"ON","DATE":"2025-06-27T20:24:08.004Z"} | ||
| 127 | - {"LED":"ESP32S3-7814","COLOR":"GREEN","STATE":"OFF","DATE":"2025-06-27T20:24:10.004Z"} | ||
| 128 | - {"LED":"ESP32S3-7814","COLOR":"BLUE","STATE":"ON","DATE":"2025-06-27T20:24:12.004Z"} | ||
| 129 | - {"LED":"ESP32S3-7814","COLOR":"BLUE","STATE":"OFF","DATE":"2025-06-27T20:24:14.004Z"} | ||
| 130 | - {"TEST":"ESP32S3-7814","VERSION":"MicroPython 1.26.0 preview","COMPILER":"IDFv5.4.1","BUILD_DATE":"2025-06-26","DATE":"2025-06-27T20:24:17.004Z"} | ||
| 131 | - | ||
| 127 | + {"PWRON":"ESP32S3-7814","DATE":"2025-07-08T18:54:56.001Z"} | ||
| 128 | + {"NEOP":"ESP32S3-7814","COLOR":"RED","STATE":"ON","DATE":"2025-07-08T18:55:05.001Z"} | ||
| 129 | + {"NEOP":"ESP32S3-7814","COLOR":"RED","STATE":"OFF","DATE":"2025-07-08T18:55:07.001Z"} | ||
| 130 | + {"NEOP":"ESP32S3-7814","COLOR":"GREEN","STATE":"ON","DATE":"2025-07-08T18:55:08.001Z"} | ||
| 131 | + {"NEOP":"ESP32S3-7814","COLOR":"GREEN","STATE":"OFF","DATE":"2025-07-08T18:55:09.001Z"} | ||
| 132 | + {"NEOP":"ESP32S3-7814","COLOR":"BLUE","STATE":"ON","DATE":"2025-07-08T18:55:11.001Z"} | ||
| 133 | + {"NEOP":"ESP32S3-7814","COLOR":"BLUE","STATE":"OFF","DATE":"2025-07-08T18:55:12.001Z"} | ||
| 134 | + {"REPORT":"ESP32S3-7814","OLED":"Enabled","ANLED":"Enabled","VERSION":"MicroPython 1.26.0 preview","COMPILER":"IDFv5.4.2","BUILD_DATE":"2025-07-07","DATE":"2025-07-08T18:55:15.001Z"} | ||
| 135 | + {"PING":"ESP32S3-7814","DATE":"2025-07-08T18:56:56.001Z"} | ||
| 132 | 136 | ``` | |
| 133 | 137 | The `PWRON` message is sent every time the board successfully starts up and immediately after opening a connection to the MQTT broker. | |
| 134 | 138 | ||
| 135 | - The `PING` message is sent every 60 seconds. | ||
| 139 | + The `PING` message is sent every 120 seconds/two minutes. | ||
| 136 | 140 | ||
| 137 | - The `LED` messages are generated from the web page buttons toggling the color LED. They tell which LED color is chosen and if the LED is on or off. | ||
| 141 | + The `NEOP` messages are generated from the web page buttons toggling the color NeoPixel. They tell which color is chosen and if it's state is on or off. | ||
| 138 | 142 | ||
| 139 | - The `TEST` message is sent via the `MQTT5 Test` web page button. It sends the MicroPython version, the version of the ESP-IDF toolset that was used to build that MicroPython version and the date it was last built. | ||
| 143 | + The `REPORT` message is sent via the `MQTT Report` web page button. It sends if the OLED (`OLED`) display was found and enabled (None if not), if the alphanumeric (`ANLED`) 14-segment LEDs were found and enabled (None if not), MicroPython version, the version of the ESP-IDF toolset that was used to build that MicroPython version and the date it was last built. | ||
| 140 | 144 | ||
| 141 | 145 | Every message contains the SSID that sent the message. | |
| 142 | 146 | ||
| 143 | - Every message time stamp is in ISO 8601 format, UTC. | ||
| 147 | + Every message time stamp is ISO 8601 UTC. | ||
| 144 | 148 | ||
| 145 | 149 | ## Changes and Updates | |
| 150 | + #### _8 July 2025_ | ||
| 151 | + | ||
| 152 | + * Stepped up to ESP-IDF 5.4.2 to build the latest MicroPython sources. | ||
| 153 | + * Added drivers and hardware for HT16K33/YT16K33 14-segment LED displays. The LEDs display a 24 hour clock. | ||
| 154 | + The drivers are from **HT16K33 Drivers 4.2.0** (https://github.com/smittytone/HT16K33-Python) and are in the `lib` folder. | ||
| 155 | + * Cleaned up the code and web page to better align everything. | ||
| 156 | + | ||
| 146 | 157 | #### _26 June 2025_ | |
| 147 | 158 | ||
| 148 | 159 | After re-reading a specific MicroPython check-in, I re-ran `idf.py fullclean`, then `idf.py set-target esp32s3 menuconfig` to set the maximum amount of flash to 32 GiB. The latest checkins fixed the bug with the ESP32-S3 boards with more than 8 GiB of FLASH; those boards will now report the correct amount of FLASH. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,6 +22,7 @@ | |||
| 22 | 22 | import machine | |
| 23 | 23 | import ssd1306 | |
| 24 | 24 | import display_tools | |
| 25 | + import ht16k33_tools as htools | ||
| 25 | 26 | ||
| 26 | 27 | print( " Boot: START") | |
| 27 | 28 | print(f" Memory: {gc.mem_free():,} bytes") | |
@@ -56,12 +57,16 @@ | |||
| 56 | 57 | # Check if there is an SSD1306 display attached. | |
| 57 | 58 | # | |
| 58 | 59 | if ssd1306.OLED_ADDR in i2c_scanned: | |
| 59 | - print(" I2C: SSD1306 OLED Found") | ||
| 60 | 60 | # | |
| 61 | 61 | # Create instance of SSD1306 class to control the | |
| 62 | 62 | # display. Initialize it by clearing everything. | |
| 63 | 63 | # | |
| 64 | 64 | DISPLAY = ssd1306.SSD1306_I2C(ssd1306.OLED_WIDTH, ssd1306.OLED_HEIGHT, SOFT_I2C) | |
| 65 | 65 | DISPLAY.fill(0) | |
| 66 | + print(" I2C: SSD1306 OLED Initialized") | ||
| 67 | + | ||
| 68 | + if htools.LED1_ADDR in i2c_scanned and htools.LED2_ADDR in i2c_scanned: | ||
| 69 | + htools.init(SOFT_I2C) | ||
| 70 | + print(" I2C: HT16K33 LEDs Initialized") | ||
| 66 | 71 | ||
| 67 | 72 | print(" Boot: END") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,16 +19,16 @@ | |||
| 19 | 19 | import time | |
| 20 | 20 | import mqtt_tools as mqtt | |
| 21 | 21 | ||
| 22 | - _display = None | ||
| 23 | - _ssid = None | ||
| 24 | - _ip = None | ||
| 22 | + display = None | ||
| 23 | + ssid = None | ||
| 24 | + ip = None | ||
| 25 | 25 | ||
| 26 | - def do_graphics(display, SSID, ip): | ||
| 27 | - global _display, _ssid, _ip | ||
| 26 | + def do_graphics(_display, _ssid, _ip): | ||
| 27 | + global display, ssid, ip | ||
| 28 | 28 | ||
| 29 | - _display = display | ||
| 30 | - _ssid = SSID | ||
| 31 | - _ip = ip | ||
| 29 | + display = _display | ||
| 30 | + ssid = _ssid | ||
| 31 | + ip = _ip | ||
| 32 | 32 | # | |
| 33 | 33 | # Display the official MicroPython logo | |
| 34 | 34 | # | |
@@ -45,7 +45,7 @@ def do_graphics(display, SSID, ip): | |||
| 45 | 45 | display.text(platform.platform().split('-')[1], 72, 0, 1) | |
| 46 | 46 | if mqtt.mqttClient is not None: | |
| 47 | 47 | display.text(f"MQTT {mqtt.mqtt_msg_count}", 40, 10, 1) | |
| 48 | - display.text(SSID, 0, 36, 1) | ||
| 48 | + display.text(ssid, 0, 36, 1) | ||
| 49 | 49 | display.text(str(ip), 0, 46, 1) | |
| 50 | 50 | now = time.localtime(time.time() + (-4 * 3600)) | |
| 51 | 51 | year = now[0] | |
@@ -59,26 +59,26 @@ def do_graphics(display, SSID, ip): | |||
| 59 | 59 | _show_display = True | |
| 60 | 60 | ||
| 61 | 61 | def timer_callback(t): | |
| 62 | - global _display, _show_display | ||
| 62 | + global display, _show_display | ||
| 63 | 63 | _show_display = False | |
| 64 | - _display.fill(0) | ||
| 65 | - _display.show() | ||
| 64 | + display.fill(0) | ||
| 65 | + display.show() | ||
| 66 | 66 | ||
| 67 | 67 | def setup_display_blank_timer(): | |
| 68 | 68 | timer = Timer(2) | |
| 69 | 69 | timer.init(period=60000, mode=Timer.ONE_SHOT, callback=timer_callback) | |
| 70 | 70 | ||
| 71 | 71 | def toggle_display_on_off(): | |
| 72 | - global _display, _ssid, _ip, _show_display | ||
| 72 | + global display, ssid, ip, _show_display | ||
| 73 | 73 | ||
| 74 | - if _display is None: | ||
| 74 | + if display is None: | ||
| 75 | 75 | return | |
| 76 | 76 | ||
| 77 | 77 | _show_display = not _show_display | |
| 78 | 78 | ||
| 79 | 79 | if _show_display: | |
| 80 | - do_graphics(_display, _ssid, _ip) | ||
| 80 | + do_graphics(display, ssid, ip) | ||
| 81 | 81 | setup_display_blank_timer() | |
| 82 | 82 | else: | |
| 83 | - _display.fill(0) | ||
| 84 | - _display.show() | ||
| 83 | + display.fill(0) | ||
| 84 | + display.show() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,77 @@ | |||
| 1 | + """ | ||
| 2 | + Copyright 2025 William H. Beebe, Jr. | ||
| 3 | + | ||
| 4 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + you may not use this file except in compliance with the License. | ||
| 6 | + You may obtain a copy of the License at | ||
| 7 | + | ||
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + | ||
| 10 | + Unless required by applicable law or agreed to in writing, software | ||
| 11 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + See the License for the specific language governing permissions and | ||
| 14 | + limitations under the License. | ||
| 15 | + """ | ||
| 16 | + | ||
| 17 | + from machine import Timer | ||
| 18 | + import time | ||
| 19 | + from ht16k33 import HT16K33Segment14 | ||
| 20 | + | ||
| 21 | + LED1_ADDR = const(0x70) | ||
| 22 | + LED2_ADDR = const(0x71) | ||
| 23 | + LED3_ADDR = const(0x72) | ||
| 24 | + LED4_ADDR = const(0x73) | ||
| 25 | + | ||
| 26 | + i2c = None | ||
| 27 | + led1 = None | ||
| 28 | + led2 = None | ||
| 29 | + # Make sure to uncomment the next three lines if you choose | ||
| 30 | + # to use the 12 hour clock. | ||
| 31 | + # 11111111112222 | ||
| 32 | + # 012345678901234567890123 | ||
| 33 | + #am_pm_str = "AAAAAAAAAAAAPPPPPPPPPPPP" | ||
| 34 | + | ||
| 35 | + def clock_display_callback(timer_object): | ||
| 36 | + # Time calculation is hard-coded for EST/EDT (New York America). | ||
| 37 | + now = time.localtime(time.time() + (-4 * 3600)) | ||
| 38 | + hours = now[3] | ||
| 39 | + minutes = now[4] | ||
| 40 | + seconds = now[5] | ||
| 41 | + atime = f"{hours:2d}{minutes:02d}{seconds:02d}" | ||
| 42 | + led1.set_character(atime[0], 0).set_character(atime[1], 1).set_glyph(0x0009, 2).set_character(atime[2], 3).draw() | ||
| 43 | + led2.set_character(atime[3], 0).set_glyph(0x0009, 1).set_character(atime[4], 2).set_character(atime[5], 3).draw() | ||
| 44 | + """ | ||
| 45 | + This code will produce a 12 hour clock with AM and PM indicator. | ||
| 46 | + I can't decide if I prefer the 12 hour display or the 24 hour display, | ||
| 47 | + so I have left (commented below) code in for both. | ||
| 48 | + am_pm = am_pm_str[hours] | ||
| 49 | + | ||
| 50 | + if hours < 12: | ||
| 51 | + if hours == 0: | ||
| 52 | + hours = 12 | ||
| 53 | + else: | ||
| 54 | + if hours > 12: | ||
| 55 | + hours -= 12 | ||
| 56 | + | ||
| 57 | + atime = f"{hours:2d}{minutes:02d}" | ||
| 58 | + led1.set_character(atime[0], 0).set_character(atime[1], 1).set_glyph(0x0009, 2).set_character(atime[2], 3).draw() | ||
| 59 | + led2.set_character(atime[3], 0).set_character(' ', 1).set_character(am_pm, 2).set_character('M', 3).draw() | ||
| 60 | + """ | ||
| 61 | + | ||
| 62 | + def init(_i2c): | ||
| 63 | + global i2c, led1, led2 | ||
| 64 | + i2c = _i2c | ||
| 65 | + led1 = HT16K33Segment14(i2c, board=HT16K33Segment14.ECBUYING_054) | ||
| 66 | + led1.set_brightness(2) | ||
| 67 | + led1.clear().draw() | ||
| 68 | + led2 = HT16K33Segment14(i2c, i2c_address=0x71, board=HT16K33Segment14.ECBUYING_054) | ||
| 69 | + led2.set_brightness(2) | ||
| 70 | + led2.clear().draw() | ||
| 71 | + | ||
| 72 | + def start_clock(): | ||
| 73 | + if i2c is None: | ||
| 74 | + return | ||
| 75 | + | ||
| 76 | + timer = Timer(1) | ||
| 77 | + timer.init(period=1000, mode=Timer.PERIODIC, callback=clock_display_callback) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,16 @@ | |||
| 1 | + __author__ = 'Tony Smith' | ||
| 2 | + __credits__ = ['Tony Smith', 'Ubi de Feo', 'akbiocca'] | ||
| 3 | + __license__ = "MIT" | ||
| 4 | + __version__ = "4.2.0" | ||
| 5 | + __maintainer__ = "Tony Smith" | ||
| 6 | + | ||
| 7 | + from .ht16k33 import * | ||
| 8 | + from .ht16k33bar import * | ||
| 9 | + from .ht16k33matrix import * | ||
| 10 | + from .ht16k33matrixcolour import * | ||
| 11 | + from .ht16k33matrixfeatherwing import * | ||
| 12 | + from .ht16k33matrixmulti import * | ||
| 13 | + from .ht16k33segment import * | ||
| 14 | + from .ht16k33segment14 import * | ||
| 15 | + from .ht16k33segmentbig import * | ||
| 16 | + from .ht16k33segmentgen import * | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments