In this final chapter of the MicroPython 101 course, you will find code & circuit examples for popular components, such as motors, displays and sensors. These components can be combined to make fun projects, and works out of the box with the Nano ESP32 & MicroPython.
External modules used in this chapter are third party and has not been developed by the Arduino team. Credit is due to the developers of these modules.
Many of these modules are not included in your MicroPython installation, but don't worry, installing them are very easy and require no additional software!
To install an external module, use the script below. Inside the script, the
URL
variable needs to be replaced with a valid URL that leads to a module. The URL can look like the following:Make sure to add your own Wi-FiĀ® network & password to the
and WIFI_NETWORK
variables.WIFI_PASSWORD
1"""2This script first connects to Wi-Fi,3then installs the module specified4in the URL variable.5"""6
7import network8import mip9
10WIFI_NETWORK='YOUR_NETWORK_NAME'11WIFI_PASSWORD='YOUR_NETWORK_PASSWORD'12URL = "github.com/example"13
14wlan = network.WLAN(network.STA_IF)15wlan.active(True)16wlan.connect(WIFI_NETWORK, WIFI_PASSWORD)17
18print()19print("Connected to ",WIFI_NETWORK)20
21mip.install(URL)
Running this script will install the module on your board, inside a folder called
lib
. You can check this out under "Files" while your board is connected via your MicroPython editor.How to install modules are explained in more detail in the Introduction to MicroPython chapter.
If you install too many modules, you will run out of space. You can remove a module directly in the editor, by selecting the file and clicking on the "Delete" icon.
For more detailed instructions, see the Removing Modules section in the second chapter.
This example shows how to use a pushbutton with MicroPython. Connect the button as shown below. Even though the Grove cable has four cables we only need three (Power, GND, Signal).
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import the Pin class from the machine module2from machine import Pin3# Import the sleep function from the time module4from time import sleep 5
6# Create a Pin object for pin 5 as an input with a pull-up resistor7button = Pin(9, Pin.IN, Pin.PULL_UP) 8
9# Start an infinite loop10while True:11 # Read the current state of the button 12 button_state = button.value() 13 # Check if the button state is LOW (0)14 if button_state == 0: 15 # If the button is not pressed, print a message16 print("Button not pressed") 17 else:18 # If the button is pressed, print a message19 print("Button pressed") 20 # Pause the program for 0.5 seconds21 sleep(0.5)
Now whenever you press the button you should see
Button pressed
being printed in the REPL. This example shows how to create the classic blink example using MicroPython and a Grove LED.
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import the Pin class from the machine module2from machine import Pin 3# Import the sleep function from the time module 4from time import sleep 5
6# Create a Pin object for pin 5 as an output7led = Pin(9, Pin.OUT) 8
9# Start an infinite loop10while True: 11 # Turn on the LED12 led.on() 13 # Pause the program for 1 second 14 sleep(1) 15 # Turn off the LED 16 led.off() 17 # Pause the program for 1 second 18 sleep(1)
You should now see the led blinking. Change the code to make it speed up or slow down.
This code controls a servo motor connected to Pin 5 (D2) using PWM. As with any motor if the current is being drawn due to the motor needing too much power the board resets.
You should always use an external power supply when powering a servo. Servo motor consume very high amounts of current when initiated, which can reset your board or damage it.
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import the Pin and PWM classes from the machine module2from machine import Pin, PWM 3# Import the time module4import time 5
6# Create a PWM object named 'servo' on pin 5 configured as an output7servo = PWM(Pin(9, mode=Pin.OUT)) 8# Set the frequency of the PWM signal to 50Hz9servo.freq(50) 10
11# Start an infinite loop12while True: 13 # Set the duty cycle of the PWM signal to 26 (position 1 of the servo)14 servo.duty(26) 15 # Pause the program for 1 second 16 time.sleep(1) 17 # Set the duty cycle of the PWM signal to 123 (position 2 of the servo)18 servo.duty(123) 19 # Pause the program for 1 second 20 time.sleep(1)
You should now see the servo moving back and forth in an endless loop.
This example shows how to use a NeoPixel strip with 10 RGB LEDs. Although we are addressing 10 LEDs at once we luckily still only need one signal pin making our setup super easy. Connect the RGB strip as seen in the circuit below, copy the code to
main.py
and press play.To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import the Pin class from the machine module2from machine import Pin3# Import the sleep class from the time module4from time import sleep5#Import the neopixel module6import neopixel7
8# Set the number of pixel on the RGB strip9PIXEL_NUMBER = 1010# Create a NeoPixel object with 24 pixels connected to pin 2111np = neopixel.NeoPixel(Pin(9), PIXEL_NUMBER) 12
13# Define colors14purple = (200, 0, 200)15black = (0, 0, 0)16
17# Fill the entire strip with black color (turn off all pixels)18np.fill(black) 19# Update the NeoPixel strip to reflect the changes20np.write() 21
22# Function for turning on all pixels on after the other23def ringUp():24 #loop through all pixels25 for i in range(0, PIXEL_NUMBER):26 # Set the i-th pixel to purple color27 np[i] = purple 28 # Update the NeoPixel strip to reflect the changes29 np.write() 30 # Pause for 0.1 seconds 31 sleep(0.1) 32 33# Function for turning on all pixels off after the other34def ringDown():35 for i in range(0, PIXEL_NUMBER):36 np[i] = black 37 np.write() 38 sleep(0.1) 39 40# Function for turning on all pixels off41def ringOff():42 for i in range(0, PIXEL_NUMBER):43 np[i] = black 44 np.write() 45 46# Function looping through ringUp() and ringDown()47def runPixelRun():48 while(1): 49 ringUp() 50 ringDown() 51 52# Start running the pixel animation53runPixelRun()
You should now see a the LED RGB strip fade in and out.
This example shows how to use a DHT11 with an Arduino Nano ESP32. DHT sensors are temperature and humidity sensors and make use of the built-in
dht
module.To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1#import dht module2import dht3#import Pin class from machine module4from machine import Pin5# Import sleep_ms class from time module6from time import sleep_ms7
8# Define sensor pin9SENSOR_PIN = 910
11# Create a DHT11 object with the specified pin number12TEMP_SENSOR = dht.DHT11(Pin(SENSOR_PIN)) 13# Pause for 500 milliseconds to allow the sensor to stabilize 14sleep_ms(500) 15
16# Loop indefinitely17while(1): 18 # Trigger a measurement from the DHT11 sensor 19 TEMP_SENSOR.measure() 20 # Print the measured temperature 21 print("Temperature:",TEMP_SENSOR.temperature()) 22 print("Humidity:",TEMP_SENSOR.humidity()) 23 # Pause for 1 second before taking the next measurement24 sleep_ms(1000)
You should now see the temperature and humidity printed in the REPL, every second.
This example demonstrates how to use an OLED screen via I2C.
This module is not part of the MicroPython installation, and needs to be installed via the following command:
1import mip2mip.install("https://raw.githubusercontent.com/micropython/micropython-lib/master/micropython/drivers/display/ssd1306/ssd1306.py")
Once installed, you can run the script below, by clicking the "Run" button.
If you are using a different OLED screen make sure to adjust the screen size in the code to display the content properly.
1# Import the Pin class and SoftI2C class (for using I2C) form the machine module2from machine import SoftI2C, Pin3# Import Oled module4import ssd13065# Import the sleep_ms class from the time module6from time import sleep_ms7
8# Set the display width to 128 pixels9DISPLAY_WIDTH = 128 10# Set the display height to 64 pixels11DISPLAY_HEIGHT = 64 12
13class Point():14 def __init__(self, x, y):15 # Initialize the x-coordinate of the point16 self.x = x 17 # Initialize the y-coordinate of the point18 self.y = y 19
20# Create a Point object with initial coordinates (64, 32)21old_coords = Point(64, 32) 22# Create a Point object with initial coordinates (64, 32)23new_coords = Point(64, 32) 24
25# Create a SoftI2C object for I2C communication with the specified pins and frequency26i2cbus = SoftI2C(scl=Pin(12), sda=Pin(11), freq=100000) 27print(i2cbus)28
29# Create an SSD1306 OLED object with the specified width, height, and I2C bus30oled = ssd1306.SSD1306_I2C(DISPLAY_WIDTH, DISPLAY_HEIGHT, i2cbus) 31# oled.fill(0)32oled.show()33
34# Display the text "Hello" at the specified coordinates35oled.text('Arduino', 40, 12) 36
37# Display the text "World" at the specified coordinates 38oled.text('MicroPython', 23, 45) 39
40# Update the OLED display to reflect the changes41oled.show()
You should now see
Hello World
printed on the screen.This example shows how to use a Grove Buzzer. Following the same principle connect the button as shown in the circuit below.
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1from machine import Pin, PWM2import time3
4# Pin connected to the Grove Speaker5SPEAKER_PIN = 96
7# Frequency and duration of the sound8FREQUENCY = 220 # Hz9DURATION = 2 # seconds10
11# Create a controllable Pin for the speaker12speaker = PWM(Pin(SPEAKER_PIN))13
14# Function to play a sound15def play_sound(frequency, duration):16 speaker.freq(frequency)17 speaker.duty(512)18 time.sleep(duration)19 speaker.duty(0)20
21# Play the sound22play_sound(FREQUENCY, DURATION)
Now your buzzer should be making a buzzing sound. You can now change the code and play with the intensity and duration.
This example shows how to use a Grove Accelerometer using I2C. This particular sensor can measure acceleration and its position in space. Because it's using I2C it needs all four wires as shown in the circuit below.
This module is not part of the MicroPython installation, and needs to be installed via the following command:
1import mip2mip.install("https://raw.githubusercontent.com/tinypico/tinypico-micropython/master/lis3dh%20library/lis3dh.py")
Once installed, you can run the script below, by clicking the "Run" button.
1# Import lis3dh, time, and math classes2import lis3dh, time, math3# Import Pin and SoftI2C class from the machine module4from machine import Pin, SoftI2C5
6i2c = SoftI2C(scl=Pin(12), sda=Pin(11)) # I2C7imu = lis3dh.LIS3DH_I2C(i2c, address=0x19)8
9last_convert_time = 010convert_interval = 100 #ms11pitch = 012roll = 013
14
15# Convert acceleration to Pitch and Roll16def convert_accell_rotation( vec ):17 x_Buff = vec[0] # x18 y_Buff = vec[1] # y19 z_Buff = vec[2] # z20
21 global last_convert_time, convert_interval, roll, pitch22
23 # We only want to re-process the values every 100 ms24 if last_convert_time < time.ticks_ms():25 last_convert_time = time.ticks_ms() + convert_interval26
27 roll = math.atan2(y_Buff , z_Buff) * 57.328 pitch = math.atan2((- x_Buff) , math.sqrt(y_Buff * y_Buff + z_Buff * z_Buff)) * 57.329
30 # Return the current values in roll and pitch31 return ( roll, pitch )32
33# If we have found the LIS3DH34if imu.device_check():35 # Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G).36 imu.range = lis3dh.RANGE_2_G37
38 # Loop forever printing values39 while True:40 # Read accelerometer values (in m / s ^ 2). Returns a 3-tuple of x, y,41 # z axis values. Divide them by 9.806 to convert to Gs.42 x, y, z = [value / lis3dh.STANDARD_GRAVITY for value in imu.acceleration]43 print("x = %0.3f G, y = %0.3f G, z = %0.3f G" % (x, y, z))44
45 # Convert acceleration to Pitch and Roll and print values46 p, r = convert_accell_rotation( imu.acceleration )47 print("pitch = %0.2f, roll = %0.2f" % (p,r))48
49 # Small delay to keep things responsive but give time for interrupt processing.50 time.sleep(0.1)
Move around your sensor to see the numbers in the REPL change. This is the acceleration data recorded. This data can be used to trigger specific things whenever a specific movements is initialized.
This example shows how to use a sound sensor. This is a simple microphone that provides an analog output signal.
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import Pin and ADC class from the machine module2from machine import Pin, ADC3# Import the time module4import time5
6# Create an ADC object and associate it with pin 57pin_adc = ADC(Pin(9)) 8# Set the attenuation level to 11dB, which allows for a wider input voltage range9pin_adc.atten(ADC.ATTN_11DB) 10
11while True:12 sum_value = 013
14 for i in range(32):15 # Read the ADC value and add it to the sum16 sum_value += pin_adc.read() 17
18 # Right shift the sum by 5 bits (equivalent to dividing by 32) to get the average value19 sum_value >>= 5 20
21 # Print the average value 22 print(sum_value) 23 # Pause for 100 milliseconds24 time.sleep_ms(100)
After running the script, test it out by clapping your hands or making other loud noises next to the sensor. You should see the output change in the REPL.
This example shows how to use a Grove 4-digit display.
4 digit displays are very basic types of displays that are often seen in alarm clocks as they can display any number between 0-9. This sensors also uses I2C which is why we need all four wires as shown below.
This module is not part of the MicroPython installation, and needs to be installed via the following command:
1import mip2mip.install("https://raw.githubusercontent.com/mcauser/micropython-tm1637/master/tm1637.py")
Once installed, you can run the script below, by clicking the "Run" button.
1from machine import Pin2from time import sleep3import tm16374
5tm = tm1637.TM1637(clk=Pin(12), dio=Pin(11))6
7tm.write([63, 191, 63, 63]) # Write a specific pattern of segments to the TM1637 display8sleep(1)9
10tm.numbers(17, 23) # Display the numbers 17 and 23 on the TM1637 display11sleep(1)12tm.show('abcd') # Display the characters 'abcd' on the TM1637 display13sleep(1)14tm.show('bcde') # Display the characters 'bcde' on the TM1637 display15sleep(1)16tm.show('cdef') # Display the characters 'cdef' on the TM1637 display17sleep(1)18
19tm.temperature(20) # Display the temperature value 20 on the TM1637 display
You should now see the display showing different numbers, where the final frame is a simulated temperature value (20).
This example shows how to use a moisture sensor.
This sensor is used to measure moisture by measuring the resistance between the two probes. Dry soil has less conductivity than wet soil and the difference in resistance and the resulting drop/increase in voltage can be measured by the Arduino.
To use this component, copy the script script below into your
main.py
file, and run it by clicking the "Run" button.1# Import machine module2import machine3# Import time module4import time5
6# Define sensor pin7adc_pin = machine.Pin(4)8# Create ADC object and associate it with sensor pin9adc = machine.ADC(adc_pin)10
11#function mapping sensor values from 0 to 100.12def map_value(value, in_min, in_max, out_min, out_max):13 return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min14
15# Infinite loop16while True:17 # Read sensor values18 reading = adc.read_u16()19 # Map sensor readings from 0 - 100 for improved user experience20 mapped_reading = map_value(reading, 0, 65535, 0, 100)21 # Print values in REPL22 print("Moisture: ", reading, " Mapped Moisture: ", mapped_reading)23 # Add short sleep timer for improved readability24 time.sleep_ms(500)
After running the script, you should see the values from the moisture sensor printed in the REPl.