GPIO and reTerminal
GPIO Overview
- 40 GPIO pins on Raspberry Pi / reTerminal
- Logic level: 3.3V (outputs HIGH = 3.3V, inputs accept up to 3.3V)
- Max per-pin current: 16mA
- No native ADC — use Grove Base Hat for analog sensors
Check pinout: pinout (provided by GPIO Zero package)
GPIO Zero — Python Library
Uses BCM (Broadcom) pin numbering by default — LED(17) means BCM17, not physical pin 17.
from gpiozero import LED, Button, PWMLED, Servo
from time import sleep
from signal import pauseLED (GPIO 17)
led = LED(17)
led.on()
led.off()
led.toggle()
led.blink() # blinks indefinitely in backgroundPWMLED (variable brightness)
led = PWMLED(17)
led.value = 0 # off
led.value = 0.5 # half brightness
led.value = 1 # full brightness
led.pulse() # continuously fade in/outButton (GPIO 2)
button = Button(2)
# Poll state
if button.is_pressed:
print("Pressed")
# Blocking waits
button.wait_for_press()
button.wait_for_release()
# Callbacks (non-blocking — MUST call pause() to keep script alive)
button.when_pressed = led.on
button.when_released = led.off
# Hold detection
btn = Button(17, hold_time=2)
btn.when_held = shutdown_function # fires after held 2 seconds
pause() # REQUIRED: keeps script alive so callbacks can firesignal.pause() — if you set callbacks and let the script end, GPIOs reset and callbacks never fire. Always call
pause()after setting callbacks.
Button + LED shorthand
led.source = button # LED mirrors button state directly (no loop needed)
pause()Button + LED explicit loop
from gpiozero import LED, Button
led = LED(17)
button = Button(2)
while True:
if button.is_pressed:
led.on()
else:
led.off()Enabling I2C (required for Grove Hat ADC)
I2C is disabled by default. Enable before using Grove Base Hat or AHT20.
sudo raspi-config # Interface Options → I2C → Yes → reboot
sudo apt-get install -y python3-smbus i2c-tools
i2cdetect -y 1 # verify devices detected (UU = in use by kernel driver)Grove Base Hat (ADC)
Adds 12-bit ADC to Pi (which has NO native ADC):
- 8 analog channels (A0–A7, 0–4095 values, 0–3.3V)
- Communicates to Pi over I2C (not SPI)
- Also: 6 digital, 3 I2C, 1 PWM, 1 UART connectors
grove.adc API
from grove.adc import ADC
import time
adc = ADC() # I2C address 0x04 by default
adc.read_voltage(0) # channel A0 → voltage in mV
adc.read_raw(0) # channel A0 → raw 12-bit int (0–4095)
adc.read(0) # channel A0 → ratio vs supply (0.1% units)
# Example: read joystick X/Y axes
x_mv = adc.read_voltage(0) # VRx → analog port A0
y_mv = adc.read_voltage(1) # VRy → analog port A1reTerminal Built-In Devices
LEDs and Buzzer via /sys/
| Device | Path |
|---|---|
| LED 0 | /sys/class/leds/usr_led0/brightness |
| LED 1 | /sys/class/leds/usr_led1/brightness |
| LED 2 | /sys/class/leds/usr_led2/brightness |
| Buzzer | /sys/class/leds/usr_buzzer/brightness |
Values: 0 = off, 255 = on (max brightness)
Problem: these files are root-owned — echo > file fails even with sudo.
Solution: sudo + tee
echo 255 | sudo tee /sys/class/leds/usr_led0/brightness # LED on
echo 0 | sudo tee /sys/class/leds/usr_led0/brightness # LED off
echo 1 | sudo tee /sys/class/leds/usr_buzzer/brightness # Buzzer onWhy tee works: sudo applies to tee, which writes to the file with root permission.
Luminosity Sensor
cat /sys/bus/iio/devices/iio:device0/in_illuminance_input
# Output: 2719 (Lux) — readable without sudoseeed-python-rpi Library
pip install git+https://github.com/Seeed-Studio/Seeed_Python_RPi/
pip install RPi-GPIOimport seeed_python_rpi.core as rt
import time
rt.buzzer = True # buzzer on
time.sleep(1)
rt.buzzer = False # buzzer off
# Also: rt.led0, rt.led1, rt.led2 etc.Run with root (required for hardware access)
sudo $(which python) script.py # recommended: use venv python with sudo
sudo ./.venv/bin/python script.py # alternative: direct pathAHT20 Sensor (I2C, via Grove Hat)
Temperature: -40°C to 85°C | Humidity: 0–100% RH
Preferred method: smbus2 direct (grove.py is broken as of A1).
Critical: reTerminal uses I2C bus 4, not bus 1.
from smbus2 import SMBus
from time import sleep
class AHT20:
def __init__(self, address=0x38, bus=4): # bus=4 on reTerminal!
self.address = address
self.bus = SMBus(bus)
self.bus.write_i2c_block_data(self.address, 0xBE, [0x08, 0x00])
sleep(0.02)
def read(self):
self.bus.write_i2c_block_data(self.address, 0xAC, [0x33, 0x00])
sleep(0.08)
data = self.bus.read_i2c_block_data(self.address, 0x00, 7)
humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4
humidity = humidity * 100 / 1048576.0
temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]
temperature = temperature * 200 / 1048576.0 - 50
return temperature, humidityInstall: pip install smbus2 or uv add smbus2
Alternative (adafruit, still works):
pip install adafruit-circuitpython-ahtx0 adafruit-extended-busydotool (Mouse/Keyboard Automation)
Used to control the reTerminal mouse programmatically (e.g. from joystick input).
# Start daemon first (required!)
sudo ydotoold & disown
# Add to ~/.bashrc
export YDOTOOL_SOCKET=/tmp/.ydotool_socket
# Optionally allow without sudo
sudo chmod 777 /tmp/.ydotool_socketydotool mousemove -x -100 -y 100 # relative move
ydotool mousemove --absolute -x 100 -y 100 # absolute move
ydotool click 0xC0 # left click
ydotool click 0xC1 # right click
ydotool type 'hello'From Python:
import subprocess
subprocess.run(['ydotool', 'mousemove', '-x', str(dx), '-y', str(dy)])
subprocess.run(['ydotool', 'click', '0xC0'])Permissions
User must be in gpio group (default user already is):
sudo usermod -a -G gpio <username>See Also
- GPIO concept, ADC concept, PWM concept, I2C concept
- Serial Protocols topic (for I2C/SPI/UART on GPIO)
- Electronics and Circuitry topic (for GPIO limits)
- FastAPI and HTTP Backend topic (for AHT20 + FastAPI)
- reterminal-built-in-devices source, reterminal-kit source
- gpiozero-recipes source, grove-adc source, ydotool source
- enable-i2c source, lab4-grove-joystick source