Search code examples
pythonmicrocontrolleresp8266micropython

Unstable Micropython on ESP8266


I take my first steps in Micropythone on ESP8266. I uploaded the latest version 1.13 and when I try to run wifi in AP mode - strange things happen. Once every few wifi runs will work, but most often there is no response (I can't see wifi network from my computer). That's my code:

boot.py

# Libraries
import uos, machine, ujson
import gc

# Changing CPU from 80MHz to 160MHz
machine.freq(160000000)

# Load and check the config file
print('BOOT: Loading database.json...')

data = open('database.json', 'r')
config = ujson.load(data)
data.close()

# Config is corrupted
if config['Device']['Manufacture'] != 'ACME' or config['Checksum'] != '18caE':

  print('BOOT: database.json is corrupted! Uploading from backup.')

  # Copy clean from backup
  dataBackup = open('database-backup.json', 'r')
  configBackup = ujson.load(dataBackup)
  dataBackup.close()

  if configBackup:
    data = open('database.json', 'w')
    ujson.dump(configBackup, data)
    data.close()

    print('BOOT: Uploading from backup completed! Rebooting system...')

  # Reboot OS
  machine.reset()

# Config is correct
else:

  print('BOOT: database.json loading completed!')

  # Clean memory
  gc.collect()

main.py

# Libraries
import network, servers

print('MAIN: Loading module...')

servers.py

import network

print('SERVER: Loading module...')

# Setup Wi-Fi card
# As Access Point
if config['Configuration']['WiFiMode'] == 'Access Point':

  print('SERVER: Setup as Access Point')

  wifi = network.WLAN(network.AP_IF)
  wifi.active(True)
  wifi.config(essid = config['Device']['Name'] + ' ' + config['Device']['SerialNumber'], password = config['Configuration']['WiFiAPPassword'])
  wifi.ifconfig(('192.168.0.1','255.255.255.0','192.168.0.1','192.168.0.1'))

# As Wi-Fi client
elif config['Configuration']['WiFiMode'] == 'Client':

  print('SERVER: Setup as client ' + config['Configuration']['WiFiClientSSID'] + ' with password ' + config['Configuration']['WiFiClientPassword'])

else:
  machine.reset()

database.json

{
    "Device": {
        "Manufacture": "ACME",
        "Name": "My device",
        "SerialNumber": "M0J4"
    },
    "Configuration": {
        "WiFiAPPassword": "test1test",
        "WiFiAPIP": "192.168.0.1",
        "WiFiAPMask": "255.255.255.0",

        "WiFiClientSSID": "Network name",
        "WiFiClientPassword": "Network password",

        "WiFiMode": "Access Point",
    },
    "Checksum": "18caE"
}

Sometimes this code starts, but usually stops after boot.py. I'm broken down because I wrote a lot of code without ESP8266 and from 12 hours I'm tired of the very beginning...


Solution

  • A "global" variable is only global within a module. Your config variable is visible within main.py, boot.py, and the REPL because those all execute within the same context (the implicit __main__ module), but it won't be visible in other modules.

    One solution is to move your config handling code into another module. E.g., create config.py with:

    import gc
    import json
    import machine
    
    config = {}
    
    
    def load_config():
        global config
    
        # Load and check the config file
        print("BOOT: Loading database.json...")
    
        try:
            with open("database.json", "r") as fd:
                config = json.load(fd)
        except OSError:
            # failed to open file (maybe it didn't exist)
            config = {}
    
        # Config is corrupted
        if (
            config.get("Device", {}).get("Manufacture") != "ACME"
            or config.get("Checksum") != "18caE"
        ):
    
            print("BOOT: database.json is corrupted! Uploading from backup.")
    
            # Copy clean from backup
            with open('database-backup.json', 'r') as fd:
                configBackup = json.load(fd)
    
            with open('database.json', 'w') as fd:
                json.dump(configBackup, fd)
    
            print("BOOT: Uploading from backup completed! Rebooting system...")
    
            # Reboot OS
            machine.reset()
        # Config is correct
        else:
    
            print("BOOT: database.json loading completed!")
    
            # Clean memory
            gc.collect()
    

    Then your boot.py becomes:

    import machine
    import gc
    
    # Changing CPU from 80MHz to 160MHz
    machine.freq(160000000)
    
    gc.collect()
    

    And servers.py looks like:

    import config
    import machine
    import network
    
    print("SERVER: Loading module...")
    
    
    config.load_config()
    
    # Setup Wi-Fi card
    # As Access Point
    if config.config["Configuration"]["WiFiMode"] == "Access Point":
    
        print("SERVER: Setup as Access Point")
    
        wifi = network.WLAN(network.AP_IF)
        wifi.active(True)
        wifi.config(
            essid="{} {}".format(
                config.config["Device"]["Name"],
                config.config["Device"]["SerialNumber"],
            ),
            password=config.config["Configuration"]["WiFiAPPassword"],
        )
        wifi.ifconfig(("192.168.0.1", "255.255.255.0", "192.168.0.1", "192.168.0.1"))
    
    # As Wi-Fi client
    elif config.config["Configuration"]["WiFiMode"] == "Client":
    
        print(
            "SERVER: Setup as client {} with password {}".format(
                config["Configuration"]["WiFiClientSSID"],
                config["Configuration"]["WiFiClientPassword"],
            )
        )
    
    else:
        machine.reset()