KevsRobots Learning Platform
48% Percent Complete
By Kevin McAleer, 9 Minutes
Arduino uses separate functions for pin setup and control: pinMode(), digitalWrite(), and digitalRead(). MicroPython uses an object-oriented approach with the Pin class.
Instead of treating pins as numbers and calling global functions, you create Pin objects and call methods on them. Itโs cleaner and more Pythonic.
Arduino C++:
const int LED_PIN = 13;
const int BUTTON_PIN = 2;
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
}
MicroPython:
from machine import Pin
LED_PIN = 25
BUTTON_PIN = 14
led = Pin(LED_PIN, Pin.OUT)
button = Pin(BUTTON_PIN, Pin.IN)
Key differences:
machine modulepinMode()Pin.OUT and Pin.IN instead of OUTPUT and INPUTled or button)Pin numbers vary by board. Hereโs a quick reference:
Arduino Nano ESP32:
Raspberry Pi Pico / Pico W / Pico 2W:
Example for built-in LED:
# Pico / Pico 2W
led = Pin(25, Pin.OUT)
# Pico W (WiFi LED is different)
led = Pin("LED", Pin.OUT)
# Arduino Nano ESP32
led = Pin(13, Pin.OUT)
Arduino C++:
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
MicroPython:
import time
while True:
led.on() # or led.value(1)
time.sleep(1)
led.off() # or led.value(0)
time.sleep(1)
MicroPython gives you two ways to control pins:
.on() and .off() - Clear and readable.value(1) and .value(0) - More explicitBoth do the same thing. Most code uses .on() and .off() for clarity.
Arduino C++:
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == HIGH) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
}
MicroPython:
while True:
button_state = button.value()
if button_state == 1:
led.on()
else:
led.off()
.value() reads the pin state:
1 for HIGH0 for LOWYou can also use .value() to write by passing an argument: .value(1) or .value(0).
Buttons need pull-up or pull-down resistors. MicroPython makes this easy:
Arduino C++:
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
// or INPUT_PULLDOWN (if supported)
}
MicroPython:
# Pull-up resistor (default state HIGH)
button = Pin(14, Pin.IN, Pin.PULL_UP)
# Pull-down resistor (default state LOW)
button = Pin(14, Pin.IN, Pin.PULL_DOWN)
# No resistor (floating - not recommended)
button = Pin(14, Pin.IN)
When to use which:
Pin.PULL_UP - Button connects pin to GND. Pressed = LOW (0), Released = HIGH (1)Pin.PULL_DOWN - Button connects pin to 3.3V. Pressed = HIGH (1), Released = LOW (0)Most buttons use pull-up configuration.
Hereโs a handy method Arduino doesnโt have:
MicroPython:
led = Pin(25, Pin.OUT)
# Toggle the LED state (onโoff or offโon)
led.toggle()
This is perfect for simple blinking:
import time
led = Pin(25, Pin.OUT)
while True:
led.toggle()
time.sleep(0.5) # Blink every 500ms
You can read back the current state of an output pin:
MicroPython:
led = Pin(25, Pin.OUT)
led.on()
print(led.value()) # Prints: 1
led.off()
print(led.value()) # Prints: 0
This is useful for maintaining state in complex programs.
Arduino C++:
const int LED_PIN = 13;
const int BUTTON_PIN = 2;
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
// Active LOW (pressed = LOW)
if (buttonState == LOW) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
}
MicroPython:
from machine import Pin
led = Pin(25, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)
while True:
button_state = button.value()
# Active LOW (pressed = 0)
if button_state == 0:
led.on()
else:
led.off()
Mechanical buttons bounce - they send multiple signals when pressed. Hereโs a simple debounce pattern:
Arduino C++:
const int BUTTON_PIN = 2;
const int DEBOUNCE_DELAY = 50;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
void loop() {
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
// Button state is stable
if (reading == LOW) {
// Button pressed
}
}
lastButtonState = reading;
}
MicroPython:
from machine import Pin
import time
button = Pin(14, Pin.IN, Pin.PULL_UP)
DEBOUNCE_DELAY = 0.05 # 50ms
last_state = 1
last_time = 0
while True:
current_state = button.value()
if current_state != last_state:
last_time = time.ticks_ms()
if (time.ticks_ms() - last_time) > DEBOUNCE_DELAY * 1000:
# Button state is stable
if current_state == 0:
# Button pressed
print("Button pressed!")
last_state = current_state
time.sleep(0.01) # Small delay
Simpler approach - just add a delay:
from machine import Pin
import time
button = Pin(14, Pin.IN, Pin.PULL_UP)
led = Pin(25, Pin.OUT)
last_state = 1
while True:
current_state = button.value()
# Detect button press (transition from HIGH to LOW)
if last_state == 1 and current_state == 0:
led.toggle()
time.sleep(0.2) # Simple debounce
last_state = current_state
time.sleep(0.01)
Working with multiple pins is cleaner in Python:
Arduino C++:
int leds[] = {10, 11, 12, 13};
int numLeds = 4;
void setup() {
for (int i = 0; i < numLeds; i++) {
pinMode(leds[i], OUTPUT);
}
}
void loop() {
// Turn all on
for (int i = 0; i < numLeds; i++) {
digitalWrite(leds[i], HIGH);
}
delay(1000);
// Turn all off
for (int i = 0; i < numLeds; i++) {
digitalWrite(leds[i], LOW);
}
delay(1000);
}
MicroPython:
from machine import Pin
import time
# Create list of Pin objects
leds = [Pin(pin_num, Pin.OUT) for pin_num in [10, 11, 12, 13]]
while True:
# Turn all on
for led in leds:
led.on()
time.sleep(1)
# Turn all off
for led in leds:
led.off()
time.sleep(1)
That list comprehension [Pin(pin_num, Pin.OUT) for pin_num in [10, 11, 12, 13]] creates all Pin objects in one line!
MicroPython:
from machine import Pin
import time
leds = [Pin(pin_num, Pin.OUT) for pin_num in [10, 11, 12, 13]]
while True:
# Light up LEDs in sequence
for led in leds:
led.on()
time.sleep(0.2)
led.off()
# Light up in reverse
for led in reversed(leds):
led.on()
time.sleep(0.2)
led.off()
Interrupts let you respond to pin changes instantly without polling. This is advanced but powerful:
MicroPython:
from machine import Pin
import time
led = Pin(25, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)
# Interrupt handler function
def button_pressed(pin):
led.toggle()
print("Button interrupt!")
# Set up interrupt on falling edge (HIGHโLOW)
button.irq(trigger=Pin.IRQ_FALLING, handler=button_pressed)
# Main loop can do other things
while True:
print("Doing other work...")
time.sleep(2)
Interrupt triggers:
Pin.IRQ_FALLING - HIGH to LOW transitionPin.IRQ_RISING - LOW to HIGH transitionPin.IRQ_FALLING | Pin.IRQ_RISING - Both transitionsImportant: Interrupt handlers should be short and fast. Donโt use delays or print statements in production interrupt handlers.
Exercise 1: Traffic Light
Create a traffic light with 3 LEDs (red, yellow, green) on pins 10, 11, 12:
Answer:
from machine import Pin
import time
red = Pin(10, Pin.OUT)
yellow = Pin(11, Pin.OUT)
green = Pin(12, Pin.OUT)
def all_off():
red.off()
yellow.off()
green.off()
while True:
all_off()
red.on()
time.sleep(5)
all_off()
green.on()
time.sleep(5)
all_off()
yellow.on()
time.sleep(2)
Exercise 2: Button Counter
Create a program that:
Answer:
from machine import Pin
import time
button = Pin(14, Pin.IN, Pin.PULL_UP)
leds = [Pin(pin_num, Pin.OUT) for pin_num in [10, 11, 12, 13]]
count = 0
last_state = 1
def display_binary(number):
"""Display a number on 4 LEDs in binary"""
for i in range(4):
bit = (number >> i) & 1 # Extract bit i
leds[i].value(bit)
while True:
current_state = button.value()
# Detect button press (HIGH to LOW)
if last_state == 1 and current_state == 0:
count = (count + 1) % 16 # Wrap at 16
display_binary(count)
print(f"Count: {count} (Binary: {count:04b})")
time.sleep(0.2) # Debounce
last_state = current_state
time.sleep(0.01)
Exercise 3: Button-Controlled Patterns
Create a program with:
Answer:
from machine import Pin
import time
button = Pin(14, Pin.IN, Pin.PULL_UP)
leds = [Pin(pin_num, Pin.OUT) for pin_num in [10, 11, 12, 13]]
pattern = 0
last_state = 1
def set_pattern(pattern_num):
if pattern_num == 0: # All on
for led in leds:
led.on()
elif pattern_num == 1: # All off
for led in leds:
led.off()
elif pattern_num == 2: # Alternating 1
leds[0].on()
leds[1].off()
leds[2].on()
leds[3].off()
elif pattern_num == 3: # Alternating 2
leds[0].off()
leds[1].on()
leds[2].off()
leds[3].on()
while True:
current_state = button.value()
# Detect button press
if last_state == 1 and current_state == 0:
pattern = (pattern + 1) % 4
set_pattern(pattern)
print(f"Pattern: {pattern}")
time.sleep(0.2)
last_state = current_state
time.sleep(0.01)
You can use the arrows โ โ on your keyboard to navigate between lessons.
Comments