Skip to content

Digital Lutherie ESP32 Micropython

Enrique Tomás -ultranoise edited this page Mar 19, 2024 · 124 revisions

Intro

This page serves as tutorial and code repository for those interested in learning how to design musical interfaces with ESP32 boards under micropython. Looking for Arduino code? Please check my other page here for a similar wiki with Arduino.

CircuitPython

In this tutorial CircuitPython will be our programming language. It is a micro version of python, or a micropython wrap with plenty of sensor and hardware libraries already included in the main package for our creative use of microcontrollers and microprocessors.

If you want to know more, visit the CircuitPython Essentials Documentation.

The documentation of the core modules is here: https://docs.circuitpython.org/en/latest/docs/index.html

The reference of each core module can be found here: https://docs.circuitpython.org/en/latest/shared-bindings/index.html#modules

Flashing and Reflashing Circuit Python

First time flashing? Your board needs to be enabled by pressing this combination of two buttons:

  • Press button "0" and do not release

  • Press button "RST" and release

  • Release button "0"

Your board will be now enabled to be flashed with Circuit Python.

If reflashing Circuit Python is needed open this page preferably with Chrome: https://circuitpython.org/downloads and look for your board. In the following sections links to particular boards we use are provided.

  • connect USB-C cable to the COM port of the ESP32-S3

  • Run the installer from the website clicking on "Open Installer"

  • In the first pop-up window, click on Connect and select your Serial Port (I selected the wchusb version)

  • Click Next and the process of erasing and flashing the board will begin. The installer first creates a boot drive called S3DKC1BOOT (or S2MINI or similar) but it can only be accessed when the USB cable is at the USB Port labelled "USB" (not at COM). When the installer asks for the S3DKC1BOOT Drive disconnect the cable to the USB Port or just unplug and plug it again, wait a few seconds, and the drive will appear in your Finder or Windows browser. Select it.

  • The installer will install the adafruit libraries and will rename the boot drive as CIRCUITPY. Please select it when a pop-up window requires it.

*Add the WIFI details if wanted and check if the board can be accessed with Thonny.

*If you are flashing many boards, the webpage sometimes needs to be reloaded to find the serial port.

IDE Installation

Install Thonny for your platform: download

Connect the board to the USB labelled port (not COM) and check:

  • you see a new mass storage folder called "CIRCUITPY" at your files browser

  • Download this ZIP file, extract it and copy its contents (and not the zip file) to the folder /CIRCUITPY/lib in the ESP32.

  • at Thonny's preferences interpreter you see the ESP32 port. Also select "CircuitPython (generic)" as your interpreter.

thonny's preferences

Other Libraries

If you are missing some module or external module, or want to install your own libraries, you can download libraries from https://circuitpython.org/libraries (also from the community bundle). You just have to copy the .mpy files to the /lib folder in the mass storage folder CIRCUITPY. You can also read a tutorial about libraries in circuit python: https://learn.adafruit.com/adafruit-pyportal/circuitpython-libraries

Boards Pinouts

We are using two boards:

  1. a ESP32-S3 WROOM-1 N8R2 with two USB-C ports. It has Wi-Fi + Bluetooth LE, 2 MB PSRAM and 8 MB SPI Flash.

  2. a ESP32-S2 WROOM with one microUSB port

  3. a ESP32-S2 with USB-C port

ESP32-S3 N8R2

It is similar to the original Espressif ESP32-S3-DevKit-1

ESP32-S3

Pinout (although this is a different board, their pinouts are the same):

RGB LED Addressable RGB LED, driven by GPIO48.
USB Port ESP32-S3 full-speed USB OTG interface, compliant with the USB 1.1 specification. The interface is used for power supply to the board, for flashing applications to the chip, for communication with the chip using USB 1.1 protocols, as well as for JTAG debugging.

Do Not Use (generally)

gpio.43 Used for USB/Serial U0TXD
gpio.44 Used for USB Serial U0RXD
gpio.19 Used for native USB D-
gpio.20 Used for native USB D+

Strapping Pins

Typically these can be used, but you need to make sure they are not in the wrong state during boot.

gpio.0 Boot Mode. Weak pullup during reset. (Boot Mode 0=Boot from Flash, 1=Download)
gpio.3 JTAG Mode. Weak pull down during reset. (JTAG Config)
gpio.45 SPI voltage. Weak pull down during reset. (SPI Voltage 0=3.3v 1=1.8v)
gpio.46 Boot mode. Weak pull down during reset. (Enabling/Disabling ROM Messages Print During Booting)

Reflashing this ESP32-S3

If reflashing is needed (only admin) open this page with chrome: https://circuitpython.org/board/espressif_esp32s3_devkitc_1_n8r2/

ESP32-S2 MINI (WEMOS, LOLIN, HEILEGE, etc)

ESP32-S2FN4R2 WiFi SoC, 4 MB Flash (embedded) and 2 MB PSRAM (embedded)

Circut Python installation: https://circuitpython.org/board/lolin_s2_mini/

ESP32-S2

ESP32- S2 board by Olimex

ESP32-S2 pinout

Circuit Python Install with https://circuitpython.org/board/lilygo_ttgo_t8_esp32_s2_wroom/

RGB LED: board.IO18

Behavior

  • boot.py (if it exists) runs only once on start up before workflows are initialized. This lays the ground work for configuring USB at startup rather than it being fixed. Since serial is not available, output is written to boot_out.txt.

  • code.py (or main.py) is run after every reload until it finishes or is interrupted. After it is done running, the vm and hardware is reinitialized.

Pure Data Examples

A few pure data examples to practice mapping can be downloaded from here: https://github.com/tamlablinz/learn-esp32/tree/master/pd-patches

If you need to install Pure Data: https://puredata.info/downloads/pure-data

Code

Specifics for ESP32

There are plenty specificities of Circuit Python for ESP32. Take a look: https://learn.adafruit.com/circuitpython-with-esp32-quick-start/

Discover the name of your pins and your available modules

This is how you will call them in CircuitPython

import board
dir(board)

The pin names available through board are not the same as the pins labelled on the microcontroller itself. The board pin names are aliases to the microcontroller pin names. If you look at the datasheet of your microcontroller, you'll likely find a pinout with a series of pin names, such as "PA18" or "GPIO5". If you want to get to the actual microcontroller pin name in CircuitPython:

import microcontroller
dir(microcontroller.pin)

Finally, get the list of available modules:

help("modules")

Blinking RGB LED

The RGB LED is accessible on pin 48, and it is programmable through the neopixel library. More info about neopixel usage can be found here.

import board
import neopixel
import time
from rainbowio import colorwheel

#print(board.NEOPIXEL)

led = neopixel.NeoPixel(board.NEOPIXEL, 1)  # for S3 boards
#led = neopixel.NeoPixel(board.IO18, 1) # for S2 boards only

led.brightness = 0.3

while True:
    led[0] = (255, 0, 0)
    time.sleep(0.5)
    led[0] = (0, 255, 0)
    time.sleep(0.5)
    led[0] = (0, 0, 255)
    time.sleep(0.5)

Capacitive Touch

Read and detect capacitive touch on one pin (here IO4)

# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT

#CircuitPython Essentials Capacitive Touch example
import time
import board
import touchio

touch_pad = board.IO4

touch = touchio.TouchIn(touch_pad)
touch.threshold = 20000

while True:
    print(touch.raw_value)
    if touch.value:
        print("Touched!")
        
    time.sleep(0.05)

Analog Input test

Connect a potentiometer to IO14.

import time
import board
from analogio import AnalogIn

analog_in = AnalogIn(board.IO14)

def get_voltage(pin):
    return (pin.value * 3.3) / 65536  # max voltage and digital value

while True:
    print((analog_in.value,get_voltage(analog_in)))
    time.sleep(0.1)

Connecting Buttons

import time
import board
import digitalio

#buttons definition
button1 = digitalio.DigitalInOut(board.IO13)
button1.switch_to_input(pull=digitalio.Pull.UP)

while True:
    print(button1.value)
    time.sleep(0.1)

Connect to Wifi

import ipaddress
import wifi

ssid="xxxxx"
passwd="xxxxxxx"

print('Hello World!')

for network in wifi.radio.start_scanning_networks():
    print(network, network.ssid, network.channel)
wifi.radio.stop_scanning_networks()

print("joining network...")
print(wifi.radio.connect(ssid=ssid,password=passwd))
# the above gives "ConnectionError: Unknown failure" if ssid/passwd is wrong

print("my IP addr:", wifi.radio.ipv4_address)

Create Access Point

More info on the wifi module: https://docs.circuitpython.org/en/latest/shared-bindings/wifi/index.html# or https://learn.adafruit.com/pico-w-wifi-with-circuitpython/pico-w-basic-wifi-test

# import wifi module
import wifi

# set access point credentials
ap_ssid = "myAP"
ap_password = "password123"

# You may also need to enable the wifi radio with wifi.radio.enabled(true)

# configure access point
wifi.radio.start_ap(ssid=ap_ssid, password=ap_password)

"""
start_ap arguments include: ssid, password, channel, authmode, and max_connections
"""

# print access point settings
print("Access point created with SSID: {}, password: {}".format(ap_ssid, ap_password))

# print IP address
print("My IP address is", wifi.radio.ipv4_address)

OSC communication as access point

# import wifi module
import wifi
import time
import os
import socketpool
import microosc
import board
import touchio

# set access point credentials
ap_ssid = "myAP2"
ap_password = "password123"

# configure access point
wifi.radio.start_ap(ssid=ap_ssid, password=ap_password)

# print IP address
print("AP active: ", wifi.radio.ap_active)
print("Access point IP: ", wifi.radio.ipv4_address_ap) # esp32: 192.168.4.1

#Configure OSC
socket_pool = socketpool.SocketPool(wifi.radio)
osc_client = microosc.OSCClient(socket_pool, "192.168.4.2", 5000) # connected laptop: 192.168.4.2
msg = microosc.OscMsg( "/capacitive", [0,], ("f",) )

#capacitive touch pin definition
touch_pad = board.IO4
touch = touchio.TouchIn(touch_pad)
touch.threshold = 20000


while True:
    try:
        msg.args[0] = touch.raw_value
        osc_client.send(msg)
        time.sleep(0.1)

    except Exception as e:  #in case there is no client connected
        print("Error: (no client connected)", e)
        time.sleep(0.1)





OSC communication with external router

OSC requires the library microosc (https://circuitpython-microosc.readthedocs.io/en/latest/), which can be downloaded with the Circuit Python community bundle (https://circuitpython.org/libraries). We have also included it into our particular lib.zip bundle.

"""send capacitive touch value with OSC, assumes native `wifi` support"""

import time
import os
import wifi
import socketpool

import microosc

import board
import touchio


#capacitive touch pin definition
touch_pad = board.IO4
touch = touchio.TouchIn(touch_pad)
touch.threshold = 20000

#Connect to the network
wifi.radio.connect("xxxxx","xxxxxxxx")
print("my ip address:", wifi.radio.ipv4_address)

socket_pool = socketpool.SocketPool(wifi.radio)
osc_client = microosc.OSCClient(socket_pool, "192.168.1.34", 5000)

#message definition
msg = microosc.OscMsg( "/capacitive", [0,], ("f",) ) 
#msg = microosc.OscMsg( "/capacitive", [0.99, 3, ], ("f", "i", ) ) #for more


while True:
   
    msg.args[0] = touch.raw_value
    osc_client.send(msg)
    time.sleep(0.1)
    

MIDI Communication

ESP S2 and S3 models provide USB Host capabilities. Therefore it is possible to implement the USB MIDI protocol (https://docs.circuitpython.org/en/latest/shared-bindings/usb_midi/index.html).

The general information about circuit python and USB can be found here: https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial

An important detail with USB MIDI is that it is only possible to configure USB devices in the boot.py file. If you try to configure or change the USB device after boot.py you will get an error. For this reason, it is mandatory to have a boot.py file (create this file if necessary) with the following:

import usb_midi
import usb_hid

usb_hid.disable()
usb_midi.enable()

Everytime you change the boot.py it is necessary to hard reset the board by presing RST button.

MIDI: sensor value to Control Change

Once you have the boot.py file as it is explained in the previous section, you can create another .py file with:

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# simple_test
# modified by enrique tomas

import time
import random
import usb_midi
import board
import touchio
import adafruit_midi
from adafruit_midi.control_change import ControlChange


#set MIDI ports
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)


# Prepare capacitive touch input
touch_pad = board.IO4
touch = touchio.TouchIn(touch_pad)

while True:
    # note how a list of messages can be used
    print(int(touch.raw_value/512))
    midi.send(ControlChange(3,int(touch.raw_value/512))) #65536 ->128
    time.sleep(0.1)

MIDI note on/off test

(do not forget the boot.py file)

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# simple_test
# modified by enrique tomas

import time
import random
import usb_midi

import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn

#set MIDI ports
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
print("Midi test: send a note on/off")

# Convert channel numbers at the presentation layer to the ones musicians use
print("Default output channel:", midi.out_channel + 1)
print("Listening on input channel:", midi.in_channel + 1)

while True:
    midi.send(NoteOn(44, 120))  # G sharp 2nd octave
    time.sleep(0.5)
    # note how a list of messages can be used
    midi.send(NoteOff("G#2", 120))
    time.sleep(0.5)

More information about usb_midi can be found here. More information about adafruit_midi can be found here.

Exercise 1: Program a monophonic midi instrument which triggers a random MIDI note after touching a pin



Play in loop MIDI notes from a list

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# simple_test
# modified by enrique tomas

import time
import random
import usb_midi

import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn

#set MIDI ports
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
print("Midi test: send a note on/off")

# Convert channel numbers at the presentation layer to the ones musicians use
print("Default output channel:", midi.out_channel + 1)
print("Listening on input channel:", midi.in_channel + 1)

notes_list = [60, 62, 63, 65, 67, 68, 70] #a scale 

i = 0 #index to read the list
while True:
    midi.send(NoteOn(notes_list[i], 120))  # G sharp 2nd octave
    time.sleep(0.5)
    # note how a list of messages can be used
    midi.send(NoteOff(notes_list[i], 120))
    time.sleep(0.5)
    i = (i + 1) % 7  # run from 0 to 6
    print(i)

MIDI Control Change with Capacitive Touch

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# simple_test
# modified by enrique tomas

import time
import random
import usb_midi

import board
import touchio

import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn

#set MIDI ports
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)
print("Midi test: send a note on/off")

# Convert channel numbers at the presentation layer to the ones musicians use
print("Default output channel:", midi.out_channel + 1)
print("Listening on input channel:", midi.in_channel + 1)

# Prepare capacitive touch input
touch_pad = board.IO4
touch = touchio.TouchIn(touch_pad)

while True:
    # note how a list of messages can be used
    print(int(touch.raw_value/512))
    midi.send(ControlChange(3,int(touch.raw_value/512))) #65536 ->128
    time.sleep(0.05)

## Non-blocking Blinking RGB LED

# SPDX-FileCopyrightText: 2020 FoamyGuy for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# modified by enrique tomas

"""
Using time.monotonic() to blink the built-in LED.
"""
import time
import digitalio
import board
import neopixel

# How long we want the LED to stay on
BLINK_ON_DURATION = 0.5
# How long we want the LED to stay off
BLINK_OFF_DURATION = 0.5
# When we last changed the LED state
LAST_BLINK_TIME = -1

print(board.NEOPIXEL)

led = neopixel.NeoPixel(board.NEOPIXEL, 1)
led.brightness = 0.3
ledState = True

while True:
    # Store the current time to refer to later.
    now = time.monotonic()
    if not ledState:
        # Is it time to turn on?
        if now >= LAST_BLINK_TIME + BLINK_OFF_DURATION:
            led[0] = (255, 0, 0)
            ledState = True
            LAST_BLINK_TIME = now
    if ledState:
        # Is it time to turn off?
        if now >= LAST_BLINK_TIME + BLINK_ON_DURATION:
            led[0] = (0, 0, 0)
            ledState = False
            LAST_BLINK_TIME = now

Non-blocking MIDI player

# SPDX-FileCopyrightText: 2020 FoamyGuy for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# modified by enrique tomas


import time
import usb_midi

import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn

# How long we want the note to stay on and off
NOTE_ON_DURATION = 1.5
NOTE_OFF_DURATION = 1.5

# Variable to store when we last played the last note
LAST_NOTE_TIME = -1


#set MIDI ports
print(usb_midi.ports)
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
)


playing = False

while True:
    # Store the current time to refer to later.
    now = time.monotonic()
    
    if not playing:
        # Is it time to Note on?
        if now >= LAST_NOTE_TIME + NOTE_OFF_DURATION:
            midi.send(NoteOn(44, 120))
            print("midi Note On")
            playing = True
            LAST_NOTE_TIME = now      
        
        
    if playing:
        # Is it time to Note off?
        if now > LAST_NOTE_TIME + NOTE_ON_DURATION:
            midi.send(NoteOff(44, 120))
            print("midi Note Off")
            playing = False
            LAST_NOTE_TIME = now



Exercise 2: Play a list of MIDI notes in loop using the non-blocking method and modify their pitch with capacitive touch



Assignment:

Program a NON-BLOCKING 16 step sequencer with three analog controllable inputs (potentiometers, capacitive touch, LDR, etc): tempo, timbre and volume AND use the RGB LED as indicator: sync blink to tempo per step. Add two buttons to start and stop the sequencer. By default the sequencer should not play at startup.

If possible -> explore more possibilities: arpegios, modulations, chords, etc. Add more and more controls.... an enclosure etc :)


## Piezo Sensor Trigger with FFT

Connect a Piezo disc to your Analog Input and GND, using a 1 MOhm resistor between both pins. 

import array import board from analogio import AnalogIn import neopixel import time from ulab import numpy as np

#led led = neopixel.NeoPixel(board.IO18, 1) # for S2 boards only #led = neopixel.NeoPixel(board.NEOPIXEL, 1) # for S3 boards led.brightness = 0.3

analog_in = AnalogIn(board.IO17) #piezo pin

fft_size = 8 #array for the piezo readings samples_bit = array.array('H', [0] * (fft_size+3))

print("begin_________________")

Main Loop

while True: #read the piezo for x in range(fft_size): samples_bit[x] = analog_in.value

#put in numpy array    
samples = np.array(samples_bit[3:])
real,b = np.fft.fft(samples)    
print(real)  #print fft real part

if real[0] > 5000.0 : #check over a threshold the first partial
    led[0] = (255, 0, 0)
    print("ON___________________________")
else:
    led[0] = (0, 0, 0)
    
# to see elapsed time
print("time ", time.monotonic_ns())

## ESPNOW

We recommend using "espnow" instead of "OSC". More information here: https://docs.circuitpython.org/en/latest/shared-bindings/espnow/index.html

## Waveforms

https://learn.adafruit.com/cpx-midi-controller/basic-synthesizer

# More sensors

## MPU-6050 Accel and Gyro

Copy the adafruit_mpu6050 library to the lib folder.Connect the sensor to 3V, GND, SCL and SDA. Most ESP32s allow using any pin as SCL and SDL. In this case we use SCL->IO9 and SDA->IO8.

If you want to know more about how circuit python deals with I2C you can visit: https://docs.circuitpython.org/en/latest/shared-bindings/busio/#busio.I2C and https://learn.adafruit.com/circuitpython-basics-i2c-and-spi/i2c-devices

import time import busio import board import adafruit_mpu6050

i2c = busio.I2C(board.IO9, board.IO8)

mpu = adafruit_mpu6050.MPU6050(i2c)

while True: print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (mpu.acceleration)) print("Gyro X:%.2f, Y: %.2f, Z: %.2f rad/s" % (mpu.gyro)) print("Temperature: %.2f C" % mpu.temperature) print("") time.sleep(1)


calculate inclination angles between X and Y

import time import busio import board from math import atan2, degrees import adafruit_mpu6050

i2c = busio.I2C(board.IO9, board.IO8)

sensor = adafruit_mpu6050.MPU6050(i2c)

def vector_2_degrees(x, y,l=False): if l: angle = degrees(atan2(y, x)) else: angle = degrees(atan2(y, x)) if angle < 0: angle += 360 return angle

def get_inclination(_sensor): x, y, z = _sensor.acceleration return vector_2_degrees(x, z,True), vector_2_degrees(y, z), int(x),int(y),int(z)

x,y,z=0,0,0

while True:

turn, ac,x,y,z = get_inclination(sensor)
turn=int(turn)
ac=int(ac)

print(turn,ac,x,y,z,sep=" : ")
time.sleep(0.1)

Orientation in MIDI

import time import busio import board from math import atan2, degrees import adafruit_mpu6050

import usb_midi import board import adafruit_midi from adafruit_midi.control_change import ControlChange

#set MIDI ports print(usb_midi.ports) midi = adafruit_midi.MIDI( midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 )

i2c = busio.I2C(board.IO9, board.IO8)

sensor = adafruit_mpu6050.MPU6050(i2c)

def vector_2_degrees(x, y,l=False): if l: angle = degrees(atan2(y, x)) else: angle = degrees(atan2(y, x)) if angle < 0: angle += 360 return angle

def get_inclination(_sensor): x, y, z = _sensor.acceleration return vector_2_degrees(x, z,True), vector_2_degrees(y, z), int(x),int(y),int(z)

x,y,z=0,0,0

while True:

turn, ac,x,y,z = get_inclination(sensor)
turn=int(turn/360*128)
ac=int(ac)

print(turn,ac,x,y,z,sep=" : ")
midi.send(ControlChange(3,int(turn))) #65536 ->128
time.sleep(0.1)

## VL53LOx distance sensor

Copy the adafruit_vl53l0x library to the lib folder. Connect the sensor to 3V, GND, SCL and SDA.  Most ESP32s allow using any pin as SCL and SDL. In this case we use SCL->IO9 and SDA->IO8. 

More information about this library can be found here: https://github.com/adafruit/Adafruit_CircuitPython_VL53L0X

import time

import board import busio

import adafruit_vl53l0x

Initialize I2C bus and sensor.

i2c = busio.I2C(board.IO9, board.IO8) vl53 = adafruit_vl53l0x.VL53L0X(i2c)

Optionally adjust the measurement timing budget to change speed and accuracy.

See the example here for more details:

For example a higher speed but less accurate timing budget of 20ms:

vl53.measurement_timing_budget = 20000

Or a slower but more accurate timing budget of 200ms:

vl53.measurement_timing_budget = 200000

The default timing budget is 33ms, a good compromise of speed and accuracy.

Main loop will read the range and print it every second.

while True: print("Range: {0}mm".format(vl53.range)) time.sleep(1.0)


## Website Reading

import time import ipaddress import wifi import socketpool import ssl import adafruit_requests import adafruit_requests as requests

ssid="xxxxx" passwd="xxxxxx"

print('Hello World!')

for network in wifi.radio.start_scanning_networks(): print(network, network.ssid, network.channel) wifi.radio.stop_scanning_networks()

print("joining network...") print(wifi.radio.connect(ssid=ssid,password=passwd))

the above gives "ConnectionError: Unknown failure" if ssid/passwd is wrong

print("my IP addr:", wifi.radio.ipv4_address)

print("pinging 1.1.1.1...") ip1 = ipaddress.ip_address("1.1.1.1") print("ip1:",ip1) print("ping:", wifi.radio.ping(ip1))

pool = socketpool.SocketPool(wifi.radio) request = adafruit_requests.Session(pool, ssl.create_default_context())

print("Fetching wifitest.adafruit.com..."); response = request.get("http://wifitest.adafruit.com/testwifi/index.html") print(response.status_code) print(response.text)

print("Fetching http://www.elpais.com"); response = request.get("http://www.elpais.com") print(response.status_code) #print(response.json()) print(response.text[:2500])


# Internet of Things

## Connect to Adafruit IO via MQTT

SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries

SPDX-License-Identifier: MIT

import os import time import ssl import socketpool import wifi import adafruit_minimqtt.adafruit_minimqtt as MQTT

Add settings.toml to your filesystem CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD keys

with your WiFi credentials. DO NOT share that file or commit it into Git or other

source control.

Set your Adafruit IO Username, Key and Port in settings.toml

(visit io.adafruit.com if you need to create an account,

or if you need your Adafruit IO key.)

aio_username = os.getenv("aio_username") aio_key = os.getenv("aio_key")

print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") wifi.radio.connect( os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") ) print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!")

Feeds

Setup a feed named 'photocell' for publishing to a feed

photocell_feed = aio_username + "/feeds/photocell"

Setup a feed named 'onoff' for subscribing to changes

onoff_feed = aio_username + "/feeds/onoff"

Code

Define callback methods which are called when events occur

pylint: disable=unused-argument, redefined-outer-name

def connected(client, userdata, flags, rc): # This function will be called when the client is connected # successfully to the broker. print(f"Connected to Adafruit IO! Listening for topic changes on {onoff_feed}") # Subscribe to all changes on the onoff_feed. client.subscribe(onoff_feed)

def disconnected(client, userdata, rc): # This method is called when the client is disconnected print("Disconnected from Adafruit IO!")

def message(client, topic, message): # This method is called when a topic the client is subscribed to # has a new message. print(f"New message on topic {topic}: {message}")

Create a socket pool

pool = socketpool.SocketPool(wifi.radio) ssl_context = ssl.create_default_context()

If you need to use certificate/key pair authentication (e.g. X.509), you can load them in the

ssl context by uncommenting the lines below and adding the following keys to the "secrets"

dictionary in your secrets.py file:

"device_cert_path" - Path to the Device Certificate

"device_key_path" - Path to the RSA Private Key

ssl_context.load_cert_chain(

certfile=secrets["device_cert_path"], keyfile=secrets["device_key_path"]

)

Set up a MiniMQTT Client

mqtt_client = MQTT.MQTT( broker="io.adafruit.com", port=1883, username=aio_username, password=aio_key, socket_pool=pool, ssl_context=ssl_context, )

Setup the callback methods above

mqtt_client.on_connect = connected mqtt_client.on_disconnect = disconnected mqtt_client.on_message = message

Connect the client to the MQTT broker.

print("Connecting to Adafruit IO...") mqtt_client.connect()

photocell_val = 0 while True: # Poll the message queue mqtt_client.loop()

# Send a new message
print(f"Sending photocell value: {photocell_val}...")
mqtt_client.publish(photocell_feed, photocell_val)
print("Sent!")
photocell_val += 10
time.sleep(5)
Clone this wiki locally