DEV Community

Cover image for MicroPython 101 IoT Basics
Philip John Basile
Philip John Basile Subscriber

Posted on • Edited on

MicroPython 101 IoT Basics

MicroPython is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library. It's optimized to run on microcontrollers, which are small, low-power computers on a single integrated circuit.

MicroPython offers a complete implementation of Python 3.4 and includes significant aspects of Python 3.5. However, it doesn't incorporate every feature introduced from Python 3.5 onwards. That said, it does adopt some fresh syntax from Python 3.6 and specific features from subsequent versions like 3.8 (assignment expressions) and 3.9. It also encompasses a selection of the standard library.

Here are some of the key features:

Interactive Prompt: MicroPython runs an interactive prompt (REPL) when a board is connected and powered.

Extensive libraries: These include hardware-specific modules like machine, network, etc., that allows you to control GPIO pins, connect to WiFi, and much more.

Python Syntax: It uses Python syntax which makes it easy to learn and use.

Efficiency: MicroPython is designed to be efficient both in terms of memory usage and speed.

Installation:

To get started, you need to install MicroPython firmware onto your microcontroller. This process differs from device to device, but usually, it involves downloading the firmware and then using a tool to flash it onto the board.

Hello World with MicroPython:

Let's look at a basic example of blinking an LED (a "Hello, World!" equivalent in the hardware world).

from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)

while True:
    led.on()
    sleep(0.5)
    led.off()
    sleep(0.5)
Enter fullscreen mode Exit fullscreen mode

This script does the following:

  • It imports the Pin class from the machine module and the sleep function from the time module.
  • It defines led to be pin number 2 and sets it as an output.
  • In an infinite loop, it turns the LED on, waits for half a second, turns the LED off, and then waits for another half a second before repeating.

Interacting with the REPL:

After you've flashed MicroPython onto your board, you can connect to it to start programming. You typically do this via a serial connection over USB. Once connected, you'll see the Python prompt >>>, where you can type commands and see their output immediately.

Using Digital Inputs

MicroPython allows you to read the state of buttons, switches, or any digital input. For example, if you have a push-button switch connected to pin 5, you could read its state as follows:

from machine import Pin

button = Pin(5, Pin.IN)

while True:
    print(button.value())
Enter fullscreen mode Exit fullscreen mode

This script continuously prints the state of the button.

Using Analog Inputs

Microcontrollers often have pins that can read analog values, like varying voltages. You can use MicroPython's ADC (Analog-to-Digital Converter) class for this:

from machine import Pin, ADC
from time import sleep

adc = ADC(Pin(32))  # assuming an analog sensor is connected to pin 32

while True:
    print(adc.read())
    sleep(1)
Enter fullscreen mode Exit fullscreen mode

This script will read and print the analog value every second.

Networking with MicroPython

One of the big advantages of MicroPython (especially on network-capable hardware like the ESP8266 or ESP32) is its networking capabilities. Here's a simple example of connecting to a Wi-Fi network:

import network

station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("<your ssid>", "<your password>")

# Wait for the module to connect to the wifi
while station.isconnected() == False:
    pass

print('Connection successful')
print(station.ifconfig())
Enter fullscreen mode Exit fullscreen mode

This script attempts to connect to the given SSID with the provided password, then it waits until a connection is established. Once connected, it prints the network configuration which includes the assigned IP address.

Pulse Width Modulation (PWM):

PWM is a technique for getting analog results with digital means. It is commonly used to control servos, LEDs, and other devices that need a varying amount of power. Here is an example of using PWM to control the brightness of an LED:

from machine import Pin, PWM
from time import sleep

pwm = PWM(Pin(5))  # create PWM object from a pin
pwm.freq(500)      # set frequency
pwm.duty(512)      # set duty cycle

while True:
    for duty in range(0, 1024, 10):
        pwm.duty(duty)
        sleep(0.005)
Enter fullscreen mode Exit fullscreen mode

This will cause the LED to fade in and out smoothly.

Timers and Interrupts:

MicroPython can also handle hardware interrupts and timers. These can be used for time-sensitive operations or tasks that need to occur at regular intervals:

from machine import Pin, Timer

led = Pin(5, Pin.OUT)
timer = Timer()

def toggle_led(timer):
    led.value(not led.value())

timer.init(period=500, mode=Timer.PERIODIC, callback=toggle_led)
Enter fullscreen mode Exit fullscreen mode

This script will toggle the state of the LED every 500 milliseconds.

Working with Files:

MicroPython also provides a pyb module that includes functions for file I/O operations. Here's how you could write to a file:

with open('myfile.txt', 'w') as f:
    f.write('Hello, MicroPython!')
Enter fullscreen mode Exit fullscreen mode

And here's how you could read from a file:

with open('myfile.txt', 'r') as f:
    print(f.read())
Enter fullscreen mode Exit fullscreen mode

Web Server:

MicroPython even allows you to create a simple web server to control or monitor your device over the internet:

import socket
from machine import Pin

led = Pin(2, Pin.OUT)

def web_page():
    if led.value():
        gpio_state="ON"
    else:
        gpio_state="OFF"

    html = """
    <html>
    <body>
    <p>GPIO state: <strong>""" + gpio_state + """</strong></p>
    </body>
    </html>
    """
    return html

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)

while True:
    conn, addr = s.accept()
    request = conn.recv(1024)
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()
Enter fullscreen mode Exit fullscreen mode

This server responds with a simple web page showing the current state of the LED.

Built-in Libraries

MicroPython includes a selection of Python standard libraries, along with some MicroPython-specific modules for hardware access:

machine Module: This module contains functions related to the hardware and peripherals like pins, ADC, PWM, I2C, SPI, etc.

network Module: As seen in previous examples, this module allows you to connect your MicroPython device to a network.

ujson Module: Similar to Python's json module, it allows you to work with JSON data.

usocket Module: Provides a subset of Python's socket module for networking.

utime Module: This module provides functions for time access and conversions.

uos Module: Provides functions for file and directory access, similar to Python's os module.

Some Useful Tools for MicroPython

Mu Editor: A simple Python editor that works with MicroPython. It can connect directly to a microcontroller board and provides a built-in REPL.

uPyCraft: A dedicated IDE designed specifically for MicroPython. It supports flashing firmware onto devices, has a built-in file manager for managing the filesystem on your microcontroller, and provides a built-in REPL.

rshell: A remote shell for MicroPython that allows file transfer and running scripts on the microcontroller.

mpfshell: A simple shell-based file explorer for MicroPython devices.

Example Project: IoT Thermometer

Let's consider a simple IoT project where we use a temperature sensor (DS18B20) to measure the temperature and then send this data over MQTT:

from machine import Pin
from time import sleep
import ds18x20
import onewire
import network
import umqtt.simple

# Connect to Wi-Fi
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("<your ssid>", "<your password>")
while station.isconnected() == False:
    pass

# Connect to the MQTT broker
client = umqtt.simple.MQTTClient("umqtt_client", "<broker_url>")
client.connect()

# DS18B20 data line connected to pin P10
ow = onewire.OneWire(Pin(10))
ds = ds18x20.DS18X20(ow)
roms = ds.scan()

while True:
    ds.convert_temp()
    sleep_ms(750)
    for rom in roms:
        temp = ds.read_temp(rom)
        client.publish("temperature", str(temp))
    sleep(60)
Enter fullscreen mode Exit fullscreen mode

In this script, we first connect to the Wi-Fi, then to the MQTT broker. We then read the temperature from the sensor every minute and publish it to the "temperature" topic on the MQTT broker.

Deep Sleep and Power Saving:

One major advantage of using MicroPython with microcontrollers is the ability to put the device into deep sleep, which is essential for battery-powered projects. When a device is in deep sleep, it consumes significantly less power. It can be awakened by a timer or an external interrupt.

from machine import Pin, deepsleep

# Put the device into deep sleep for 10 seconds
deepsleep(10000)
Enter fullscreen mode Exit fullscreen mode

The device will wake up from deep sleep as if it has been reset, and it will execute the script from the beginning.

Displaying Data:

MicroPython supports several types of displays. One common type is the OLED display, which can be used to display text, graphics, or data from sensors. Here's an example:

from machine import Pin, I2C
import ssd1306

i2c = I2C(scl=Pin(5), sda=Pin(4))
display = ssd1306.SSD1306_I2C(128, 64, i2c)

display.text('Hello, MicroPython!', 0, 0)
display.show()
Enter fullscreen mode Exit fullscreen mode

This script initializes an OLED display and displays the text 'Hello, MicroPython!' on it.

Interacting with Web APIs:

MicroPython can make HTTP requests and interact with web APIs. For example, it can send data to an API, or retrieve and process data from an API.

Here's how to make a GET request to an API:

import urequests

response = urequests.get('https://api.example.com/data')
data = response.json()

print(data)
Enter fullscreen mode Exit fullscreen mode

This script sends a GET request to 'https://api.example.com/data', retrieves the response, and parses it as JSON.

Using External Libraries:

Besides the built-in libraries, MicroPython has an ecosystem of external libraries that can be added to your projects. These include libraries for specific sensors, displays, and other hardware, as well as libraries for cloud services, protocols, and other utilities.

These libraries can usually be loaded onto your device using tools like ampy, rshell, or through the REPL.

Interrupts:

Interrupts are a powerful feature in MicroPython that allows a program to respond immediately to certain events. For instance, you can use interrupts to trigger a function call when a button is pressed:

from machine import Pin

def button_pressed(pin):
    print("Button pressed!")

button = Pin(14, Pin.IN)
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)
Enter fullscreen mode Exit fullscreen mode

In this example, the button_pressed function will be called immediately whenever the button is pressed.

Threading:

MicroPython supports basic multithreading with the _thread module, allowing you to run multiple functions at the same time. Note that threading can make programs more complex and harder to debug:

import _thread
import time

def task(name, delay):
    while True:
        print("Task", name)
        time.sleep(delay)

_thread.start_new_thread(task, ("A", 1))
_thread.start_new_thread(task, ("B", 2))
Enter fullscreen mode Exit fullscreen mode

This program runs two tasks in parallel that print their name every 1 or 2 seconds.

MicroPython with IoT Platforms:

MicroPython can be integrated with IoT platforms like AWS IoT, Google Cloud IoT, etc. These platforms can collect, process, analyze, and visualize IoT data, and they also provide other features like device management, security, and more.

Here is an example of publishing data to AWS IoT:

from umqtt.simple import MQTTClient
import network
import machine

# Connect to WiFi
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("<your ssid>", "<your password>")
while station.isconnected() == False:
    pass

# Create MQTT client and connect to AWS IoT
client = MQTTClient(machine.unique_id(), "<aws-endpoint>", port=8883, keepalive=4000)
client.connect()

# Publish data
while True:
    temperature = read_temperature()  # Your function to read temperature
    client.publish("sensors/temperature", str(temperature))
    time.sleep(10)
Enter fullscreen mode Exit fullscreen mode

In this example, the device continuously reads a temperature and publishes it.

Error Handling:

Like Python, MicroPython supports exceptions and error handling. Using try/except blocks, you can anticipate and respond to errors in your code. Here's an example:

try:
    # Code that may raise an exception
    x = 1 / 0
except ZeroDivisionError:
    print("Cannot divide by zero!")
Enter fullscreen mode Exit fullscreen mode

MicroPython's uasyncio Library:

MicroPython supports asynchronous I/O using the uasyncio library, which is a minimal implementation of Python's asyncio library. Asynchronous I/O is useful for managing tasks that can block program execution, such as reading from sensors or waiting for network data.

Here's an example of how to use uasyncio to blink an LED without using time.sleep():

import uasyncio as asyncio
from machine import Pin

led = Pin(2, Pin.OUT)

async def blink(led):
    while True:
        led.on()
        await asyncio.sleep(1)
        led.off()
        await asyncio.sleep(1)

# Run the blink coroutine
loop = asyncio.get_event_loop()
loop.run_until_complete(blink(led))
Enter fullscreen mode Exit fullscreen mode

Best Practices for MicroPython:

Comment your code: This is particularly important when working with hardware where code can interact with physical elements in non-obvious ways.

Handle exceptions: Microcontrollers work in the real world and things can go wrong. Exception handling helps to diagnose and recover from errors.

Keep it simple: MicroPython's environment has limited resources, so strive for simplicity and efficiency in your code.

Reuse and share code: Reuse your own code and leverage community libraries where possible. If you've written a useful library, consider sharing it with the community.

Optimize for low power: Many MicroPython applications are battery-powered. Use power-saving techniques like deep sleep, turning off unnecessary peripherals, etc.

Resources:

Official MicroPython Documentation: The official documentation is a comprehensive resource that provides detailed information about MicroPython, its functions, and modules. It's a great starting point for anyone looking to learn MicroPython.

Link: MicroPython Documentation

MicroPython for the Internet of Things by Charles Bell: This is a comprehensive book for those who prefer structured learning. It walks you through setting up and programming hardware to use MicroPython.

Link: MicroPython for the Internet of Things: A Beginnerโ€™s Guide to Programming with Python on Microcontrollers

Adafruit's MicroPython Tutorials: Adafruit, a popular platform for DIY electronics, has a series of tutorials on MicroPython that are easy to follow. They also sell hardware compatible with MicroPython.

Link: Adafruit MicroPython Tutorials

Online Course Platforms: Websites like Udemy, Coursera, and LinkedIn Learning often have courses on MicroPython.

YouTube Channels: There are several YouTube channels that post MicroPython tutorials and project guides, such as Tech With Tim, Andreas Spiess, and many more.

Forums and Community Groups: Online communities like the official MicroPython Forum, Stack Overflow, and Reddit often have threads dedicated to MicroPython. They can be a good place to ask questions and learn from others' experiences.

GitHub: Various projects and libraries on GitHub use MicroPython, providing real-world examples of how it can be used.

Remember, the best way to learn is by doing. Once you have a basic understanding of MicroPython, start a project and learn as you go. MicroPython opens a world of possibilities for Python programmers to enter into the realm of hardware and IoT devices. Enjoy exploring and building with MicroPython!

If you enjoy my technology-focused articles and insights and wish to support my work, feel free to visit my Ko-fi page at https://ko-fi.com/philipjohnbasile. Every coffee you buy me helps keep the tech wisdom flowing and allows me to continue sharing valuable content with our community. Your support is greatly appreciated!

Top comments (16)

Collapse
 
spo0q profile image
spO0q ๐Ÿ’

so cool!

Is the project still in beta?

Collapse
 
philipjohnbasile profile image
Philip John Basile

MicroPython offers a complete implementation of Python 3.4 and includes significant aspects of Python 3.5. However, it doesn't incorporate every feature introduced from Python 3.5 onwards. That said, it does adopt some fresh syntax from Python 3.6 and specific features from subsequent versions like 3.8 (assignment expressions) and 3.9. It also encompasses a selection of the standard library.

Collapse
 
spo0q profile image
spO0q ๐Ÿ’

๐Ÿค– It seems it's used in production, but I was not sure, hence my question. Thanks @andypiper !

Thread Thread
 
philipjohnbasile profile image
Philip John Basile

thanks @andypiper! Have you worked with it?

Thread Thread
 
andypiper profile image
Andy Piper

I don't use it in production myself, I'm a hobbyist and I do use it in my workshop - however folks who are part of the Melbourne MicroPython Meetup and MicroPython Discord that are available to participate in online, absolutely do use MicroPython in production.

Thread Thread
 
philipjohnbasile profile image
Philip John Basile

Ahh another discord to join! Thank you :) Build anything cool with it? Tie it together with something 3d printed?

Thread Thread
 
andypiper profile image
Andy Piper

yes, exactly that - I have it managing lighting for inside my Bambu X1 Carbon, progress light indicator for prints in a case on my desk, keypads, small robots, etc.

Thread Thread
 
philipjohnbasile profile image
Philip John Basile

hey ! have a Bambu X1 Carbon too! I have two ams's as well. I love love love it. My kids and their friends are always "putting orders in".

Collapse
 
andypiper profile image
Andy Piper

Definitely not in beta, it is being used in production in many places!

Collapse
 
philipjohnbasile profile image
Philip John Basile

know of any specifics items?

Collapse
 
andypiper profile image
Andy Piper

A couple of important tools you've missed out here are mpremote (the official command line tool for interacting with devices) and mip (the MicroPython equivalent to pip). Good post though!

Collapse
 
philipjohnbasile profile image
Philip John Basile

Oh true!! Thanks for adding that! Iโ€™ll probably add it in

Collapse
 
ganonbit profile image
Andrew Reese

Very informative, thanks for this โœŒ๐Ÿผ

Collapse
 
philipjohnbasile profile image
Philip John Basile

aww you're welcome! It was fun going from zero to 101.

Collapse
 
ganonbit profile image
Andrew Reese

For sure, I knew some of the similar knowledge from using arduino ide, but itโ€™s nice to see it broken down in a programming language Iโ€™m already familiar with from my software engineering career, python ๐Ÿค˜๐Ÿผ

Thread Thread
 
philipjohnbasile profile image
Philip John Basile

It's not perfect but if you know Python then it is.