Linux Quick Start Guide

In this section are instructions for installing firmware available for download on the official website of the MicroPython Foundation for any supported board of STMicroelectronics. The main target of the examples and tutorials available on this site remains the NUCLEO-WB55 board.

Tools required to install MicroPython: It is necessary to use a Windows computer with a Linux virtual machine installed or a computer running Linux.

To obtain a virtual machine: You will find a «Polytech» virtual machine by following this link. Go to the category «Ressources pour programmer le STM32 sur un ordinateur personnel», then click on “Avec VirtualBox”.

Installing MicroPython on a ST microcontroller board using a Linux computer

From the Linux desktop, open a terminal by doing Right click, then “Open a terminal here”. Then enter the following commands, one by one, to install the required software.

sudo apt-get install git
sudo apt-get install make
sudo apt-get install gcc
sudo apt-get install gcc-arm-none-eabi

Enter your password when prompted. Press the “y” (or “o” if the language is french) key to accept the installation when prompted. Once the pre-requisite software is installed, it is necessary to retrieve the MicroPython project from the Git tool by writing to a terminal the following commands (open from a folder where the MicroPython utility will be placed):

git clone https://github.com/micropython/micropython
cd ~/micropython
git submodule update --init
cd mpy-cross
make
cd ../ports/stm32

You can now perform the following command:

make BOARD={your-board-model}

It is necessary to replace {your-board-model} with the name of the STM32 board that is being used. For example, if you are using a NUCLEO F446RE, you will need to write the command:

make BOARD=NUCLEO_F446RE

A list of MicroPython compatible STMicroelectronics boards is available here.

  • It is possible that the make command does not work as intended, in this case you must add:
PYTHON=python2 pour obtenir la commande suivante :
make BOARD={your-board-model} PYTHON=python3
  • You have successfully completed this step if the terminal displays:

make-board.png

The previous commands have generated a folder called build-{your– board–model} available in /micropython/ports/stm32 (the micropython folder is located in the folder in which you opened the terminal).

Open the file explorer to retrieve this folder. It contains a file with an extension .hex;that’s the MicroPython engine that we will be flashing in the STM32.

For this, we will use STM32CubeProgrammer, downloadable here, and choose STM32CubePrg-Lin for Linux or STM32CubePrg-W64 for Windows(64Bits). You will need to create a myST account.

  • 1 - Installation on a Linux environment:

Open a terminal and enter the following commands:

sudo apt-get install libusb-1.0.0-dev

Extract the downloaded archive, then run SetupSTM32CubeProgrammer-x.y.z. linux (x,y,z vary by version) Let the installer guide you.

Then enter the following command in a terminal:

sudo cp ~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/Drivers/rules/*.* /etc/udev/rules.d
  • 2 - Installation on a Windows environment:

Copy the .hex file to a USB key and then switch to a Windows environment. Extract the downloaded archive, then run SetupSTM32CubeProgrammer-x.y.z. linux (x,y,z vary by version) Let the installer guide you.

`STM32CubeProgrammer’ is now installed.

Open the .hex" (1) file in STM32CubeProgrammer and connect the Nucleo board to the computer. On the software, click connect (2) then download (3) and finally verify` (3). If you encounter an error while connecting, try reconnecting the cable or changing the USB port.

cube-programmer.png

The code is flashed on the card if a successful verification message is observed. You have thus managed to install MicroPython on a STM32 board.

First codes in MicroPython

Open a serial terminal like gtkterm or PuTTY. Choose the serial port corresponding to your STM32 board, with a speed of 115200 (device manager > ports(COM and LPT) > STMicroelectronics, the port is in brackets on Windows and /dev/ttyACM0 on Linux). You should then see a similar message after pressing the black RESET button:

reset-button.png

You can then use the terminal as a Python shell, this is the MicroPython interactive interpreter named REPL. Now enter the following lines to test the Python language :

print(« Hello World »)
for i in range (10) :

You will notice that the >> entries became ... after the second command, this is to be expected because the notion of indentation is very important in the Python language, unlike other languages (like C for example). Then type print(i) and press the Enter key three times and you will see:

print-i.png

We created a variable called i that we incremented to 9. Enter help() to learn some commands specific to the MicroPython language.

Using the Geany software to read a MicroPython program

Now that we know how to program in MicroPython on a STM32 from a serial terminal, it’s time to switch gears. The serial terminal method can become tiring in the case of a program consisting of several tens of lines because you would be compelled to write line after line all the while taking into account the indentation of the Python language. That’s why we will «automate» the Geany development tool in order to «compile» a program written in MicroPython.

First, it is necessary to install the Geany software:

  • On a Linux environment, enter this command on a terminal:
sudo apt-get install geany
  • On a Windows environment, download the software here.

Then retrieve the pyboard.py. It is in the downloaded micropython/tools/' folder. This file contains a program written in Python language and designed to to "send" MicroPython programs to the STM32 board. Create a directory on your computer and drop the pyboard.py file into it. You must then configure the Geany software. After opening the app, go to the Build > Set Build Commands menu to add a new button named MicroPython in the Run Commands` section. In the following field, write:

python pyboard.py --device '/dev/ttyACM0' "%f"** for Linux
python pyboard.py --device COMx "%f"

for Windows, replace x with the number that you can find under Device Manager > ports(COM and LPT) > STMicroelectronics, the number is between brackets. Note: the port can vary according to the used board and the USB port.

You should get this :

geany-compilateur.png

You can now create a file with the name of your choice with a .py'extension (create a text document and manually add .py) and place it in the directory you just created. Open it with Geany and then run this program with Build > MicroPython.

This tutorial is finished, you should now be able to write a script and run it from Geany!

Practical exercises with MicroPython

At first we will see how to turn on an LED. To do this, write the code below directly on a serial emulator or on the Geany IDE:

from pyb import LED
led = LED(1)
led.on()

This code is used to turn on the user LED of your microcontroller, this LED is usually green-colored.

  • It is very important to start a MicroPython program for STM32 by importing the pyb library or one of these components (LED, Pin, ExtInt, Timer .Etc). Add at the beginning (first line) of your program:
import pyb

Introduction to Input/Output:

from pyb import Pin

p_out = Pin('PA5', Pin.OUT_PP) # Green LED corresponding to LED(1)
p_out.high() # p_out.low() for turning off the LED

p_in = Pin('PC13', Pin.IN, Pin.PULL_UP)
p_in.value() # takes the value 0 or 1

The user LED should light up here too. The p_in.value() function must return and display a bit with a value of 0 or 1 depending on the status of PC13 (usually the user push button).

We have learned how to turn on an output pin and read the value of an input pin, we’ll move on now to see how to generate a PWM. Pulse Width Modulation (PWM) is used when we want to generate a pseudo-analog signal from a digital source. PWM signals have the following characteristics:

  • A frequency, which refers to the speed at which the signal has completed a full cycle (10Hz→10 cycles per second).
  • A Duty Cycle that corresponds to the duration at high state over the signal period.

duty-cycle-examples.png

Before generating a PWM, it is imperative to know if the STM32 pin we want to use is compatible with this modulation. We should also know the number of the timer (as well as its channel) that is used for the modulation. For example, the PA5 pin - which is usually connected to the user LED on a majority of Nucleo boards- can be connected electrically to the 2-channel Timer 1 on some STM32F4.

In this case, the code to flash this LED with a 1Hz frequency PWM and a 50% Duty Cycle will be:

from pyb import Pin, Timer
LED = Pin('PA5') # PA5 --> TIM2, CH1
tim = Timer(2, freq=1)
ch = tim.channel(1, Timer.PWM, pin=LED)
ch.pulse_width_percent(50) # 50% DutyCycle

The Duty Cycle ratio is 0.5 on a 1Hz PWM frequency, so the LED is on for 500 milliseconds and off for 500 milliseconds as well.

A list of MicroPython code tips is available here.

Attention: Some codes are yet to be compatible with STM32 microcontrollers, they are intended for the pyboard card (an experiment card that is natively programmable in MicroPython).).

_For the NUCLEO-WB55 card that is our main target and for the firmware distributed on this site, the list of available PWM pins and the associated Timers / Channels for the distributed firmware is as follows:

  • A3 : TIM2_CH1
  • A2 : TIM2_CH2
  • D0 : TIM2_CH4
  • D1 : TIM2_CH3
  • D3 : TIM1_CH3
  • D5 : TIM2_CH1
  • D6 : TIM1_CH1
  • D9 : TIM1_CH2
  • D11 : TIM17_CH1
  • D12 : TIM16_CH1
  • D13 : TIM2_CH1
  • D14 : TIM17_CH1
  • D15 : TIM16_CH1

Here is an example of a suitable code implementing the PWM for the NUCLEO-WB55 board and as always _for the firmware distributed on this site _:

# Script object :
# The intensity of the LED ceases to vary after a first press of the sw1 button
# It starts to vary again after a second press on sw1.
# Use external interruptions to manage the button.
# Hardware (in addition to the NUCLEO-WB55 board): one LED connected to D6 and GND

from pyb import Pin, Timer, ExtInt
import time

# SW1 Button Initialization
sw1 = pyb.Pin( 'SW1' , pyb.Pin.IN)
sw1.init(pyb.Pin.IN, pyb.Pin.PULL_UP, af=-1)

# button interruption management
button_pressed = False

def callback(line):
#    print("line =", line)
    global button_pressed
    button_pressed = not button_pressed

ext = ExtInt(Pin('SW1'), ExtInt.IRQ_RISING, Pin.PULL_UP, callback)

# PWM Initialization
p = Pin('D6')
ti = 1
ch = 1
tim = Timer(ti, freq=1000)
ch = tim.channel(ch, Timer.PWM, pin=p)
i=0

while True:
    if button_pressed :
        while i < 101: # increases the intensity of the LED in steps of 1%
            ch.pulse_width_percent(i)
            i=i+1
            time.sleep_ms(10) # 10 ms pause

        while i > 0: # reduces LED intensity by steps of 1%
            ch.pulse_width_percent(i)
            i=i-1
            time.sleep_ms(10) # 10 ms pause

References