MicroPython

5 minute read

Where I investigate using MicroPython on the HUZZAH32.

Background

I have spent quite a few years using Python to develop applications. I like the language, however I believed it wasn’t a good candidate for microcontrollers. Given the strong development behind both CircuitPython and MicroPython, I though it would be a good idea to test it and determine via testing and not assumptions.

Sources

Getting Started

I followed the steps Wolf Paulus provides on his website and had no problems. I am using macOS Big Sur with the Apple native USB drivers. Which means I’m using /dev/tty.usbserial-01F4D567 and not /dev/tty.SLAB_USBtoUART. I haven’t had any problems…yet.

Initial Step

To confirm I was able to communicate with the HUZZAH32 (I use the application Serial):

# press reset on HUZZAH32
MicroPython v1.15 on 2021-04-18; ESP32 module with ESP32
Type "help()" for more information.
>>> help()
Welcome to MicroPython on the ESP32!

For generic online docs please visit http://docs.micropython.org/

For access to the hardware use the 'machine' module:

import machine
pin12 = machine.Pin(12, machine.Pin.OUT)
pin12.value(1)
pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
print(pin13.value())
i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))
i2c.scan()
i2c.writeto(addr, b'1234')
i2c.readfrom(addr, 4)

Basic WiFi configuration:

import network
sta_if = network.WLAN(network.STA_IF); sta_if.active(True)
sta_if.scan()                             # Scan for available access points
sta_if.connect("<AP_name>", "<password>") # Connect to an AP
sta_if.isconnected()                      # Check for successful connection

Control commands:
  CTRL-A        -- on a blank line, enter raw REPL mode
  CTRL-B        -- on a blank line, enter normal REPL mode
  CTRL-C        -- interrupt a running program
  CTRL-D        -- on a blank line, do a soft reset of the board
  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)
For a list of available modules, type help('modules')
# manual blink...ON/OFF/ON
>>> import machine
>>> pin13 = machine.Pin(13, machine.Pin.OUT)
>>> pin13.value(1)
>>> pin13.value(0)
>>> pin13.value(1)

OK, everything looks to be working. Let’s write some code.

Code Process

Phillip van Allen has a nice writeup as to the process of writing MicroPython code.

His process works, however, one can quickly see why the WebREPL is a superior solution. The requirement to close your serial connection is a PIA.

I have a different process: Have two applications open, I use Serial (macOS app) for my serial communications with the HUZZAH32 and Sublime Text as my editor.

  1. To get code, in text editor:
    • CMD-A for select All
    • CMD-C for Copy
  1. To paste code, in Serial:
    • CTRL-C to stop running
    • CTRL-E to start Copy/Paste Mode
    • CMD-V to Paste
    • CTRL-D end Mode and run program.

The above process works so well for me, its hard to complain about the time it takes. :)

Side Note as to Forth

The REPL process works, its not perfect, however it is much better than the C++/Arduino Compile/Load/Run paradigm. Forth has a REPL and it is extensible, which means (roughly) one can write the language using the language. There remains a need to be able to create and store files, however, its less critical in the testing phase.

As an example of the simple blink code above, I could define a word in Forth to do those same things using “the REPL” and that code would continue to exist. In most versions of Forth it would be stored in Flash, so it would remain after reset or a power cycle.

Redo ManPinTest and TestPin in MicroPython

The first step is to re-write the two programs from the Arduino framework in MicroPython.

ManPinTest

I simplified ManPinTest as printing is far more simple and I don’t need Hex and Binary equivalents of the pin.

# ManPinTest.py - blink a defined pin at 5Hz
# identify the pin to be tested
# either by pin i.e; 27 or pins_arduino.h address A10
# also identifies bit position by binary or hex
import machine
import time
pin = machine.Pin(13, machine.Pin.OUT)

print(pin, "will have a 5Hz digital signal.")

# with a delay of 100, the pin will have a 5Hz frequency
while 1 == 1:
    pin.value(1)
    time.sleep_ms(100)
    pin.value(0)
    time.sleep_ms(100)

PinTest (loaded as main.py)

Wow, developing in MicroPython is much easier and more fun than Arduino C++. I really like it! I’m going to continue to use MicroPython on the ESP32 for it is such a nice development environment.

# PinTest.py - interactive app to test pins on a board
import machine
import time


minTest = 0
maxTest = 3

# Pins 34-39 are input only on ESP32
maxPins = 33


def getPin():
    pin = int(input("Enter pin to test: "))
    if (pin > maxPins):
        print("Error, pin requested > number of output pins: ", pin)
        pin = -1
    elif (pin < 0):
        print("Error, pin requested < 0: ", pin)
        pin = -1
    else:
        print(pin, " enabled as Output")
    return(pin)


def getTest():
    test = int(input("Enter test to run: "))
    if test > maxTest:
        print("Error, test requested > tests allowed ", test)
        test = -1
    elif test < minTest:
        print("Error, test requested < 0", test)
        test = -1
    else:
        print("Run test", test)
    return(test)


def blink(pin):
    pin.value(1)  # sets the digital pinN on
    time.sleep_ms(500)            # waits for a second
    pin.value(0)  # sets the digital pinN on
    time.sleep_ms(500)            # waits for a second


def runTest_1(pin):
    pin.value(1)
    print(pin, " is now High")


def runTest_2(pin):
    pin.value(0)
    print(pin, " is now LOW")


def runTest_3(pin):
    print(pin, " will blink once")
    blink(pin)


def PinTest():
    startState = True
    testState = True
    print("Running Pin Test")
    print("""Tests: 0=> new pin 1=> High 2=> Low  3=> Blink once""")

    while startState:
        pin = getPin()
        if pin > 0:
            startState = False
            pinT = machine.Pin(pin, machine.Pin.OUT)

    while testState:
        test = getTest()
        if test >= 0:
            if test == 0:
                startState = True
                testState = False

            elif test == 1:  # 1 - set pin HIGH
                runTest_1(pinT)
                testState = True

            elif test == 2:  # 1 - set pin LOW
                runTest_2(pinT)
                testState = True

            elif test == 3:  # 1 - set pin to BLINK
                runTest_3(pinT)
                testState = True

            else:  # print error, not a valid test number
                print(test, "entered. Must be 0, 1, 2, or 3")
                testState = True


if __name__ == '__main__':
    while 1 == 1:
        PinTest()

Comments powered by Talkyard.