peterhinch / micropython-micro-gui

A lightweight MicroPython GUI library for display drivers based on framebuf, allows input via pushbuttons. See also micropython-touch.
MIT License
247 stars 37 forks source link

Trouble Connecting with Wifi #41

Closed ectotoplogist closed 8 months ago

ectotoplogist commented 9 months ago

I'm having a problem trying to use micro-gui with WiFi.

So, after importing hardware_setup.py, widgets, and the rest that I need, I tried to make my ESP32 (board here) connect to WiFi. The screen is ST7735 1.8" 128 x 160, so I guess there's nothing out of the ordinary. The REPL (in Thonny) keeps saying RuntimeError: Wifi Unknown Error 0x0101, seemingly a memory allocation issue thing. Anyway, here goes the imports:

import hardware_setup
from gui.core.ugui import Screen, ssd

from gui.widgets import Label, Button, CloseButton, Menu
from gui.core.writer import CWriter

import gui.fonts.font10 as font10
from gui.core.colors import *

import utime
import uasyncio
import network

from machine import Pin, UART

station = network.WLAN(network.STA_IF)

followed by the rest of the code, which works without the import network and station = network.WLAN(network.STA_IF). Importing network before hardware_setup leads to the screen not initialising.

The hardware_setup.py can be found below. (I took it from you and simply changed the pins.)

from machine import Pin, SPI, freq
import gc
from drivers.st7735r.st7735r_4bit import ST7735R as SSD
freq(240_000_000) 
# Create and export an SSD instance
prst = Pin(5, Pin.OUT, value=1)
pcs = Pin(4, Pin.OUT, value=1)
pdc = Pin(13, Pin.OUT, value=0)  # Arbitrary pins
#busy = Pin(15, Pin.IN)
# Datasheet allows 10MHz
spi = SPI(2, sck=Pin(19), mosi=Pin(23), miso=Pin(18), baudrate=10_000_000)
gc.collect()  # Precaution before instantiating framebuf

# Using normal socket connection default args apply
# ssd = SSD()
ssd = SSD(spi, pcs, pdc, prst)
gc.collect()
from gui.core.ugui import Display, quiet
# quiet()
# Create and export a Display instance
# Define control buttons
nxt = Pin(26, Pin.IN, Pin.PULL_UP)  # Move to next control
sel = Pin(27, Pin.IN, Pin.PULL_UP)  # Operate current control
prev = None  # Move to previous control
increase = None  # Increase control's value
decrease = None  # Decrease control's value
# display = Display(ssd, nxt, sel, prev)  # 3-button mode
display = Display(ssd, nxt, sel)  # 5-button mode

I don't know what to experiment further. Assistance is appreciated.

But I can't appreciate this micro-gui enough. It saved me from weeks of headache (not hyperbole). My project works beautifully because of this. It's just the Internet connection that's the problem.

peterhinch commented 9 months ago

Try doing a garbage collect here:

import utime
import uasyncio
from machine import Pin, UART
import gc
gc.collect()
import network
station = network.WLAN(network.STA_IF)

It's possible that RAM has become fragmented, which this might help with. The display buffer only uses 10KB so there should be plenty of RAM. Usually if MicroPython runs out of memory you get a memory error.

If that doesn't help, try running without Thonny, using a terminal emulator to get the REPL. I've never used Thonny, but there have been reported problems with it.

If all that fails, let me know and I will try to run this on an ESP32.

ectotoplogist commented 9 months ago

Indeed, nothing seems to help. I tried the following:

Thank you for the suggestions, though! I appreciate them.

peterhinch commented 9 months ago

I attempted to replicate this without success: I doubt this is a memory problem.

I used the original ESP32 reference board running V1.20. This uses the ESP-WROOM-32 as per your board. I installed current MicroGui code and hardware_setup.py copied from your post. I pasted the code in your original post with no errors, then ran the following (the first line is the outcome from the paste):

Using 2 switches.
>>> import gc
>>> gc.collect()
>>> gc.mem_free()
47312
>>> 

The free RAM after a reboot is 109616 bytes, so the pasted code is using 62304 bytes. This is not excessive.

You have done everything I would have tried. Importing before hardware_setup.py is expected to produce memory errors because hardware_setup requires a contiguous 10K bytes which is only achievable if imported very early. This is not an indicator of problems.

I assume you've verified that WiFi works normally with your board. [EDIT] I still think the fact that you get a WiFi error on import is trying to tell us something: at that stage you haven't initialised the WiFi interface. Have you checked main.py and boot.py to ensure that WiFi hasn't been set up before you get the REPL?

Aside from that I'm out of ideas, sorry.

ectotoplogist commented 8 months ago

Okay, I checked the boot.py and main.py files, and they don't initialise the WiFi interface. In fact, boot.py is empty.

You have been very helpful, and I appreciate that. I feel like I have bothered you too much already, so I will close this issue. The fact that the replication isn't successful gives me some hope. I will keep trying.

peterhinch commented 8 months ago

If you find a solution please tell. I'm very puzzled by this.

ectotoplogist commented 8 months ago

After a bit more experimentation (and trimming main.py), I got it connected to WiFi. I decided to connect to the Internet and call GC on boot, then import hardware_setup later. I don't know why, but it works.

I think the cause is the main code after those imports aren't trim enough.