You can pick these sensors up for about $1 apiece on Amazon.
The sound detection sensor detects whether sound has exceeded a threshold value. Sound is detected via microphone and fed into an LM393 op amp. The sound level set point is adjusted via an on board potentiometer. When the sound level exceeds the set point, an LED on the module is illuminated and the output is set low.
Specifications of sound detection sensor module:
Working voltage: DC 3.3-5V
Adjustable Sensitivity
Dimensions: 32 x 17 mm
Signal output indication LED
Single channel output in the form of digital switching outputs (0 and 1 high and low)
Outputs low level and the signal light when there is sound
Schematic Diagram
The circuit
The program
The Pico MicroPython program to access the signal via any GPIO port. In this case we will use GPIO 16.
from machine import Pin
import utime
di=Pin(16,Pin.IN)
def sound_handler(pin):
utime.sleep_ms(100)
if pin.value()==False:
print("ALARM! Sound detected!")
di.irq(trigger=machine.Pin.IRQ_RISING,handler=sound_handler)
This is a simple program that prints “Alarm! Sound detected” when the interrupt is triggered. You could do the sensing in a main loop as well. You will want to adjust the pot on the sound sensor board to get the desired level of sensitivity. I looked at using the one that also had analog output, but it output an analog audio signal that is more difficult to sense effectively and those boards cost slightly more as well.
I recently saw some interesting applications of an inexpensive round LCD display. In looking around I didn’t see any good explanations on how to use the display with the Pico and MicroPython, so I thought I’d write one up.
Armed with all this information, I dug into the project. The first issue I encountered was that the firmware didn’t load properly (who knows what I had on that Pico previously), so I did a hard reset and loaded in the developer’s firmware. Now Thonny worked correctly accessing the device.
I next had to figure out the correct pins to use on the Pico that had the features I needed. That breadboard illustration above was the result of overcoming those issues. I ended up with a working test program that looked like:
You can see below that the program draws blue, green, and red squares on the display.
Now that I had a handle on getting the screen to display something, I needed to create the tft_config.py file used in all the examples.
It ended up looking like:
"""Generic 240x240 GC9A01
Generic display connected to a Raspberry Pi Pico.
"""
# hardware config
SCL_PIN = 14 #chip pin 19
SDA_PIN = 15 #chip pin 20
DC_PIN = 4 #chip pin 6
CS_PIN = 5 #chip pin 7
RST_PIN = 6 #chip pin 9
from machine import Pin, SPI
import gc9a01
TFA = 0
BFA = 0
WIDE = 0
TALL = 1
def config(rotation=0, buffer_size=0, options=0):
"""Configure the display and return an instance of gc9a01.GC9A01."""
spi = SPI(1, baudrate=60000000, sck=Pin(SCL_PIN), mosi=Pin(SDA_PIN))
return gc9a01.GC9A01(
spi,
240,
240,
reset=Pin(RST_PIN, Pin.OUT),
cs=Pin(CS_PIN, Pin.OUT),
dc=Pin(DC_PIN, Pin.OUT),
rotation=rotation,
options=options,
buffer_size=buffer_size,
)
Now, I can pull in one of the examples and as long as the python code and the tft_config.py file are in the same directory the sample code should work. Here is the lines sample program:
"""
lines.py
========
.. figure:: /_static/lines.png
:align: center
Benchmarks the speed of drawing horizontal and vertical lines on the display.
"""
import random
import time
import gc9a01
import tft_config
tft = tft_config.config(tft_config.TALL)
WIDTH = tft.width()
HEIGHT = tft.height()
def time_function(func, *args):
"""time a function"""
start = time.ticks_ms()
func(*args)
return time.ticks_ms() - start
def horizontal(line_count):
"""draw line_count horizontal lines on random y positions"""
for _ in range(line_count):
y = random.randint(0, HEIGHT)
tft.line(
0,
y,
WIDTH,
y,
gc9a01.color565(
random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
),
)
def vertical(line_count):
"""draw line_count vertical lines on random x positions"""
for _ in range(line_count):
x = random.randint(0, WIDTH)
tft.line(
x,
0,
x,
HEIGHT,
gc9a01.color565(
random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
),
)
def diagonal(line_count):
"""draw line_count diagnal lines on random y positions"""
x = 0
for _ in range(line_count):
x += 1
x %= WIDTH
tft.line(
x,
0,
WIDTH - x,
HEIGHT,
gc9a01.color565(
random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
),
)
def main():
tft.init()
tft.fill(0)
print("")
print("horizonal: ", time_function(horizontal, 1000))
print("vertical: ", time_function(vertical, 1000))
print("diagonal: ", time_function(diagonal, 1000))
main()
The output generated was:
horizonal: 289
vertical: 283
diagonal: 2093
Meaning that the MicroPython version of this sample code took 289 ms to draw 1000 horizontal random color lines… Just as a test I took the random generator out and about 25ms of the time was taken generating the random colors for each type of line.
Now that I have this testing behind me, I can move on to something more interest…
Since I have been playing with ChatGPT, and Bing Chat came out, I thought I’d try it. I already had a baseline dealing with writing Python for dice rolling, so I thought I’d start with the same kind of query for Bing Chat.
I asked:
Using the Visual Studio Python IDE Python Development Tools to deploy an application for the Android platform?
The answer I got back was:
Hello, this is Bing. I searched the web for your query and found some results that might be helpful.
That was nice, and clear about the Android side of things but still left be wondering about the Visual Studio installation. I had to ask a follow up question:
What would I need to do on Windows Visual Studio to install kivy to develop for the android platform?
And the reply was:
I searched the web for your query and found some results that might be helpful.
Here is an example of a Python file and a Kivy file for a graphic user interface that rolls two dice using Kivy:
# dice.py
import kivy
kivy.require('2.1.0')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
import random
class DiceApp(App):
# A property to store the result of the dice roll
result = StringProperty('Roll the dice!')
def build(self):
# Create a box layout to hold the widgets
layout = BoxLayout(orientation='vertical')
# Create a label widget to display the result
self.label = Label(text=self.result, font_size=50)
# Create a button widget to trigger the dice roll
self.button = Button(text='Roll', font_size=50, on_press=self.roll_dice)
# Add the widgets to the layout
layout.add_widget(self.label)
layout.add_widget(self.button)
# Return the layout as the root widget
return layout
def roll_dice(self, instance):
# Generate two random numbers between 1 and 6
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
# Update the result property with the dice values
self.result = f'{dice1} + {dice2} = {dice1 + dice2}'
# Run the app
if __name__ == '__main__':
DiceApp().run()
# dice.kv
<DiceApp>:
# Define the appearance of the widgets
label:
color: 0, 0, 0, 1 # Black text
size_hint: 1, 0.8 # Take 80% of the vertical space
button:
background_color: 0, 0, 1, 1 # Blue background
color: 1, 1, 1, 1 # White text
size_hint: 1, 0.2 # Take 20% of the vertical space
It did give me some code and it gave me references that were totally missing from ChatGPT but I was not as impressed.
I will need to try and go back and forth between the two and see what happens.
It did make me think about writing a paper with Bing Chat (to get the references) and then having ChatGPT make it better. So, I asked my question that started me down the path of looking at ChatGPT:
Write 500 words about the origin of computer aided design.
Even though it said it couldn’t do it, it produced a surprisingly good response:
I searched the web for your query and found some results that might be helpful.
With references that were totally missing from the ChatGPT response.
So I went to Chat GPT and asked it to improve the essay. ChatGPT produced the following:
Computer-aided design (CAD) is a technology that has revolutionized the way that engineers and designers create and refine products. Simply put, CAD is the use of computers to facilitate or assist in the design process, particularly in the fields of engineering and architecture. From its humble beginnings in the 1950s to its current use in a wide range of industries, CAD has come a long way in terms of both capabilities and accessibility.
The term “CAD” is commonly credited to Douglas Ross, a computer scientist who was working at MIT when the acronym was coined in the 1950s. However, the origins of CAD can be traced back even further, to the Second World War, when there was a huge wave of development in computing. One of the earliest examples of CAD was the Program for Numerical Tooling Operations (PRONTO), which was the very first Computer Numerical Control (CNC) programming system. PRONTO allowed the creation of numerical control programs for machining parts using a computer. Another pioneer of CAD was Ivan Sutherland, who developed Sketchpad in 1963. This was the first interactive computer graphics program that allowed users to draw and manipulate geometric shapes on a screen using a light pen.
The development of CAD was influenced by the advancement of computer hardware and software, such as the invention of the transistor, the integrated circuit, the mouse, the graphical user interface, and the object-oriented programming. The first commercial CAD systems were introduced in the late 1960s and early 1970s, such as ADAM (Automated Drafting And Machining), DAC-1 (Design Augmented by Computer), and CADAM (Computer Augmented Drafting And Manufacturing). These systems were mainly used for 2D drafting and design, and were expensive and limited to large corporations and institutions.
The 1980s and 1990s saw the emergence of 3D modeling and rendering, parametric and feature-based modeling, solid and surface modeling, and computer-aided engineering (CAE) and manufacturing (CAM) integration. Some of the notable CAD systems of this era were AutoCAD, CATIA, Pro/ENGINEER, SolidWorks, and Unigraphics. These systems were more affordable and accessible, and enabled more complex and realistic design and simulation.
The 21st century has witnessed the development of cloud-based, web-based, and mobile CAD systems, as well as the application of CAD in various fields, such as animation, gaming, biomedical, and fashion. Some of the current trends and challenges in CAD are artificial intelligence, virtual and augmented reality, additive manufacturing, and collaborative and distributed design. CAD has become an indispensable tool for designers and engineers and has revolutionized the design process and the quality of the products.
A definite style improvement though now all the references disappeared.
I saw a post yesterday in the media stating that ChatGPT is not particularly innovative. This statement was made by one of Meta‘s AI chief scientists. He said, “It’s nothing revolutionary, although that’s the way it’s perceived in the public. It’s just that, you know, it’s well put together, it’s nicely done.”
Guess what, a usable tool is innovative. Look at the Lisa (predecessor to the Macintosh). Did it have anything all that innovative compared to what Xerox was doing already? Not really, but it was well integrated and thought out. By the time it became the Macintosh, it was also accessible and easy to use.
I got my Python environment setup to use the PythonPyQt5 library. Now I have the following screen displayed and working:
Not too bad for someone who is barely functional in Python…
Now I need to determine how to move the software program over to Android, so I asked ChatGPT:
Using the Visual Studio Python IDE Python Development Tools to deploy an application for the Android platform?
The answer I got back was:
Deploying an application for the Android platform using the Visual Studio Python IDE and Python Development Tools (PTVS) is not a straightforward process and requires some setup and additional tools. Here's an overview of the steps you can take:
Install the Android SDK on your computer:
Download the Android SDK from the official website (https://developer.android.com/sdk)
Install the SDK and set the ANDROID_HOME environment variable to the path of the SDK
Install the Java Development Kit (JDK) on your computer:
Download the JDK from the official website (https://www.oracle.com/java/technologies/javase-downloads.html)
Install the JDK and set the JAVA_HOME environment variable to the path of the JDK
Install Python for Android (python-for-android) on your computer:
Run the command pip install python-for-android
Create a new project in Visual Studio using the Python Development Tools:
Open Visual Studio and create a new project
Select the "Python Application" template
Write your Python code for the application
Use python-for-android to create an APK file:
Open a command prompt or terminal window
Navigate to the directory where your Python code is located
Run the command python-for-android apk --private . --package org.test.myapp --name "My App" --version 0.1 --bootstrap=sdl2
This will create an APK file in the bin directory of the project
Install the APK file on your Android device:
Connect your Android device to your computer
Copy the APK file to your device
Open the file manager on your device and navigate to the location where you copied the APK file
Tap on the APK file to start the installation process
Note that this process may require some tweaking and adjustments to your script and settings to make it run well on mobile devices, also it's not as simple as using Kivy, which is a more complete framework for building mobile applications.
Kivy is an Open Source Python application development Framework to build and distribute Python cross-platform GUI apps. These instructions are going to have to wait to test out another day.
My first thought was what are the GUI options for Python, so I asked:
How to generate a gui interface from python code?
What resulted from this request was:
There are several libraries that can be used to generate a GUI interface from Python code, some of the most popular ones include:
Tkinter: This is a built-in Python library that provides a simple way to create graphical user interfaces. It is a powerful tool for creating desktop applications.
PyQt: This is a set of Python bindings for the Qt application framework and runs on all platforms supported by Qt including Windows, OS X, Linux, iOS, and Android.
wxPython: This is a set of Python bindings for the wxWidgets toolkit, which allows you to create graphical user interfaces that are compatible with Windows, OS X, and Linux.
PyGTK: PyGTK is a set of Python bindings for the GTK toolkit. It is the foundation for the GNOME desktop environment and is compatible with Windows, OS X, and Linux.
PySide: PySide is a set of Python bindings for the Qt toolkit and runs on all platforms supported by Qt including Windows, OS X, Linux, iOS, and Android.
Each of these libraries has its own strengths and weaknesses, so you should choose the one that best suits your needs.
That was a pretty useful overview of the options, so I thought I’d just let it take a crack at it and asked:
write a graphic user interface in python that rolls two dice
What I got back definitely worked:
import tkinter as tk
import random
def roll_dice():
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
result_label.config(text=f"Dice 1: {dice1}\nDice 2: {dice2}")
root = tk.Tk()
root.title("Dice Roller")
result_label = tk.Label(root, text="Welcome to Dice Roller", font=("Helvetica", 20))
result_label.pack()
roll_button = tk.Button(root, text="Roll Dice", command=roll_dice)
roll_button.pack()
root.mainloop()
This GUI has a button labeled "Roll Dice" and a label that displays the results of the dice roll (e.g. "Dice 1: 4\nDice 2: 5"). When the button is clicked, the roll_dice() function is called, which generates random numbers between 1 and 6 for each dice and updates the label with the results.
This is just a simple example, you can customize it as you like and add more functionality, for example you can add a history of rolls or a picture of the dices, etc.
No comments, but when I ran it, the GUI generated showed:
And when I clicked Roll Dice it displayed a window:
And new random numbers were displayed every time I clicked Roll Dice. Not too bad with the level of direction I gave it. So, I asked it to improve upon the design, by stating:
add to the GUI the ability to have pictures of the dice
It already knew about the previous program so I was hoping it would just build upon that result. This was what was generated.
import tkinter as tk
from PIL import Image, ImageTk
import random
def roll_dice():
dice1 = random.randint(1, 6)
dice2 = random.randint(1, 6)
dice1_image = ImageTk.PhotoImage(Image.open(f"dice{dice1}.png"))
dice2_image = ImageTk.PhotoImage(Image.open(f"dice{dice2}.png"))
dice1_label.config(image=dice1_image)
dice2_label.config(image=dice2_image)
dice1_label.image = dice1_image
dice2_label.image = dice2_image
root = tk.Tk()
root.title("Dice Roller")
result_label = tk.Label(root, text="Welcome to Dice Roller", font=("Helvetica", 20))
result_label.pack()
dice1_label = tk.Label(root)
dice1_label.pack(side=tk.LEFT)
dice2_label = tk.Label(root)
dice2_label.pack(side=tk.RIGHT)
roll_button = tk.Button(root, text="Roll Dice", command=roll_dice)
roll_button.pack()
root.mainloop()
Here, I'm using the PIL library to open and display images of dice. I'm assuming that the images are in the same folder as the script, and are named dice1.png, dice2.png, etc.
In the roll_dice() function, I'm generating random numbers between 1 and 6 for each dice, and then creating PhotoImage objects for each dice using the ImageTk.PhotoImage method. I'm then configuring the dice1_label and dice2_label to display the corresponding images and updating the labels' images.
You can use your own images of the dices, just make sure that the images are in the same folder as the script and the name of the images match the code, for example if you have a dice with the number 3, the image should be named dice3.png
Keep in mind that the images must be in a format that the PIL library can open, like PNG, JPG, etc.
I now had to find some dice images for it to display, which I just pulled off the internet into the folder with the file names stated. I dropped those into the folder, so now the display looked like:
This is better, so now I realize it is not compatible with Android, one platform where I would like this to run. I asked it:
write a graphic user interface in python that rolls two dice PyQt
and the following was generated:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
from random import randint
class DiceRoller(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Dice Roller")
self.initUI()
def initUI(self):
self.dice1_label = QLabel()
self.dice1_label.setAlignment(Qt.AlignCenter)
self.dice2_label = QLabel()
self.dice2_label.setAlignment(Qt.AlignCenter)
roll_button = QPushButton("Roll Dice")
roll_button.clicked.connect(self.roll_dice)
layout = QVBoxLayout()
layout.addWidget(self.dice1_label)
layout.addWidget(self.dice2_label)
layout.addWidget(roll_button)
self.setLayout(layout)
def roll_dice(self):
dice1 = randint(1, 6)
dice2 = randint(1, 6)
self.dice1_label.setPixmap(QPixmap(f"dice{dice1}.png"))
self.dice2_label.setPixmap(QPixmap(f"dice{dice2}.png"))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DiceRoller()
window.show()
sys.exit(app.exec_())
This GUI has a button labeled "Roll Dice" and two labels that displays the results of the dice roll (dice images). When the button is clicked, the roll_dice() function is called, which generates random numbers between 1 and 6 for each dice, loads the images using the QPixmap class and updates the labels with the images.
As in the previous example, I'm assuming that the images are in the same folder as the script, and are named dice1.png, dice2.png, etc. and you can use your own images, just make sure the name of the images match the code, for example if you have a dice with the number 3, the image should be named dice3.png.
Keep in mind that the images must be in a format that PyQt can open, like PNG, JPG, etc.
If this code is error free (and it should be), that definitely took some of the grunt work out of learning GUI programming with Python. I’ll have to get back to this tomorrow though.
Way back in July and August I posted about purchasing a Pico W and using it to create an analog clock. I didn’t get back to the effort for a while but finally pulled it together. Here is what it looks like:
The box is about 15 inches long and the clock time pointer moves horizontally to indicate the time over about a 9-inch path.
The real purpose of this effort was to bring together many of the elements in a microcontroller class I’ve been giving at the woodshop, showing the students something that works. This class is based on the Pico documentation but incorporates several other components, as well as American version of the examples.
When you turn the clock on, the pointer is moved until the end of day limit switch is hit. The clock then rewinds until the start of day limit switch is hit. The Pico W then gets the time off the Internet and then moves the pointer to the current time of day. After that, each minute the pointer is advanced the correct amount, until it hits the end of day limit switch. I originally tried to do everything without limit switches, but there is enough friction and slippage that I couldn’t get it exactly right every time. Limit switches used concepts from the class and allowed the program to reset the time each midnight (or so) — the best approach to keep the clock relatively accurate.
If you look inside the box:
You’ll see the:
Pico W
Stepper motor
Parts normally used on a 3D printer
Two limit switches
Batteries
For those who look closely, you’ll notice that the rod supporting the pointer movement is disconnected. I didn’t realize that when I took the picture – that’s fixed now.
The entire box is made out of Alder wood. I used my laser to inscribe the lid. I think the saying is unique and interesting, since it can be interpreted in multiple ways. All the nonmetal mounting components were 3D printed to minimize the size of the structures.
The current draw for the stepper motor was a bit more than I expected. The power supply contains 3 AA batteries (to get about 5 V) and that does not last long, but I was doing quite a few power-on resets when I got started. A power-on moves the pointer the entire length of the rod, twice.
I will probably not do too much more with it. For demonstration purposes it is good enough. All in, there is about $7 worth of wood and $25 worth of parts, as well as uncounted hours of effort figuring the whole design, debug, assembly process out.
Rather than continuing to use the kludge that I showed in the last example, I asked a question in Reddit if someone has an example of an NTP connection from the Pico W. I got a pointer to a git site back the same day.
I am still not sure about the constant NTP_DELTA, but the rest of the code makes sense and is much more reliable. Here is how I incorporated it into my test:
I have been working on numerous projects to make the outdoor train at Sun City more interesting. The latest is to add siren sounds and flashing lights to the fire station. After putting all the effort into putting together a training session using the Pico, covering sound and lights…
I thought I’d make a small 3D printed box to hold it all together. There are 3 major components:
A buck converter — to take the 12 volts around the layout and step it down to the 5V needed for the project.
The Pico
A sound module — this holds the MP3 files and talks to the Pico via a serial interface.
The finished product (with the top off and connected to my test harness) looks like:
In the various jacks I’ve plugged in the speaker, switch, and two LEDs. Those would be removed and replaced with the actual connections.
The code for the project is:
from machine import Pin,UART
import utime
#constant
UART_TX = 0
UART_RX = 1
ONBOARD_LED_GPx = 25
LEFT_RED_GPx = 14
RIGHT_RED_GPx = 15
BUTTON_GPx = 13
## command to play through all the sounds
PLAY_NEXT_ARRAY = bytearray(8)
PLAY_NEXT_ARRAY[0] = 0x7E
PLAY_NEXT_ARRAY[1] = 0xFF
PLAY_NEXT_ARRAY[2] = 0x06
PLAY_NEXT_ARRAY[3] = 0x01
PLAY_NEXT_ARRAY[4] = 0x00
PLAY_NEXT_ARRAY[5] = 0x00
PLAY_NEXT_ARRAY[6] = 0x00
PLAY_NEXT_ARRAY[7] = 0xEF
## command to get status
STATUS_ARRAY = bytearray(8)
STATUS_ARRAY[0] = 0x7E
STATUS_ARRAY[1] = 0xFF
STATUS_ARRAY[2] = 0x06
STATUS_ARRAY[3] = 0x42
STATUS_ARRAY[4] = 0x00
STATUS_ARRAY[5] = 0x00
STATUS_ARRAY[6] = 0x00
STATUS_ARRAY[7] = 0xEF
## command to reset the device
STOP_ARRAY = bytearray(8)
STOP_ARRAY[0] = 0x7E
STOP_ARRAY[1] = 0xFF
STOP_ARRAY[2] = 0x06
STOP_ARRAY[3] = 0x16
STOP_ARRAY[4] = 0x00
STOP_ARRAY[5] = 0x00
STOP_ARRAY[6] = 0x00
STOP_ARRAY[7] = 0xEF
## command to set max volume
VOLUME_ARRAY = bytearray(8)
VOLUME_ARRAY[0] = 0x7E
VOLUME_ARRAY[1] = 0xFF
VOLUME_ARRAY[2] = 0x06
VOLUME_ARRAY[3] = 0x06
VOLUME_ARRAY[4] = 0x00
VOLUME_ARRAY[5] = 0x00
VOLUME_ARRAY[6] = 0x1E # 30 is the max?
VOLUME_ARRAY[7] = 0xEF
#device definition
uart = UART(0, baudrate=9600, tx=Pin(UART_TX), rx=Pin(UART_RX))
led_onboard = machine.Pin(ONBOARD_LED_GPx, machine.Pin.OUT)
left_LED = machine.Pin(LEFT_RED_GPx, machine.Pin.OUT)
right_LED = machine.Pin(RIGHT_RED_GPx, machine.Pin.OUT)
button = machine.Pin(BUTTON_GPx, machine.Pin.IN, machine.Pin.PULL_DOWN)
#main program
uart.write(VOLUME_ARRAY)
utime.sleep(0.1) # give it some time to read the data
led_onboard.value(1) # to show the program is running
utime.sleep(0.3)
led_onboard.value(0) # flash to show the program is running
utime.sleep(0.3)
led_onboard.value(1) # to show the program is running
while True:
if button.value()==1:
uart.write(PLAY_NEXT_ARRAY)
utime.sleep(0.1)
#initialize the lights
left_LED.value(1)
right_LED.value(0)
playing = True;
while playing:
left_LED.toggle()
right_LED.toggle()
uart.write(STATUS_ARRAY) # ask for the status
utime.sleep(0.3)
statusBytes = uart.read()
utime.sleep(0.2) # give the device time to respond
if len(statusBytes)>5:
if statusBytes[6] == 1:
playing = True
else:
playing = False
uart.write(STOP_ARRAY) # work around for issue with playing
utime.sleep(0.1)
left_LED.value(0)
right_LED.value(0)
led_onboard.value(0) # flash to show the program is running
utime.sleep(0.3)
led_onboard.value(1) # to show the program is running
utime.sleep(0.2)
The sound module replies with an invalid status the first time the loop is triggered, so I had to add a bit of code to work around that. This code will play through any number of MP3s that are placed on a microSD card, one sound file for each button press. The lights will flash for the duration the sound is playing.
Overall, a fun project for the layout. The total cost is less than $20.
I have continued work on my Pico class and model railroad automation. An effort like this would definitely be incomplete without triggering some relays. Here is a slightly modified version of the lession.
What if your device needs 12vdc or 120vac or even just 3.3vdc but with more current than the 16 milliamps (mA) a Pico GPIO pin can provide? You need add a device or logic to isolate the power circuit from the PICO. There are two ways to do this … with a relay, or a transistor. This post explains how to use a low-cost relay (about $1) to switch just about anything on or off.
Relays are, in effect, electronic switches that can switch higher voltages and currents than the triggering device can handle. In nearly all cases, the working voltage being switched by the device is supplied externally. The PICO will simply turn the relay on and off.
Note that the voltages used in this class will not hurt you, but when you start working with the kind of voltages and currents that are possible to switch with the relay, you need to be very careful.
Many relays operate using a coil to switch mechanical contacts. There can be many relays mounted in a single relay system. Many devices are available commercially with 1 to 16 relays.
Two SPDT relay module
A coil triggered relay has an operating voltage and current requirement. The Pico has a maximum current load for all pins at 50 mA, so keep that in mind when you design your circuit.
The relay used here employs an Optocoupler (a FL-3FF) inside. These draw significantly lower current (as little as 5 mA) than the ones using coils, so our Pico can easily switch them.
A board mount relay example
The two positions of relays are either considered Normally Open (NO) and Normally Closed (NC).
The relay logical diagram
The normal position is when the circuit is not energized. This is when the GPIO pin controlling the relay is low (and drawing no current). The pins on our relay are:
NO = Normally Open connection
COM = Line being switched
NC = Normally Closed connection
IN = The volage triggering the switch
DC- = DC circuit ground
DC+ = 3V3 (3.3 volts from the Pico) in our case
For our circuit example, the wiring looks like:
We wire NO to the yellow LED and the NC to the red LED. The COM line that is being switched goes to VBUS (5V). The controlling signal is connected to GP15 of the Pico and the DC- goes to ground and the DC+ can go to either VBUS or 3V3.
With the following code, the relay should switch on the yellow LED for on 5 seconds and then the red LED on for 1 second, in a loop.
The next thing I thought I would try with the Pico is have an autorun program that starts as soon as you plug the device in. It is a pretty straightforward process — you just name the program main.py.
Sure enough, after saving the file, I plug in the device and the program starts running. In my case, it started the servo moving as defined. I then encountered a real problem with Thonny on a Raspberry Pi there was no way to make the program stop. I tried all kinds of things to interrupt the program flow and none of them worked.
Finally, I hooked the Pico up to a Windows machine running Thonny and it was able to stop the program fine. Actually, it works under Windows a bit better than fine, so I think I’ll be doing most of my development under Windows now. I also noticed when Thonny started on my Raspberry Pi, my Bluetooth keyboard stopped working — how frustrating.