Pico W getting the time from an NTP server

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:

import network
import socket
import time
import struct
import secrets
import machine
import timeoffset

from machine import Pin

NTP_DELTA = 2208988800
host = "time-c.nist.gov"


def set_time():
    NTP_QUERY = bytearray(48)
    NTP_QUERY[0] = 0x1B
    addr = socket.getaddrinfo(host, 123)[0][-1]
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.settimeout(1)
        res = s.sendto(NTP_QUERY, addr)
        msg = s.recv(48)
    finally:
        s.close()
    NTPSeconds= struct.unpack("!I", msg[40:44])[0]
    #print("val: ",NTPSeconds)
    t = NTPSeconds- NTP_DELTA    #NTP_DELTA?
    datetimetuple = time.gmtime(t)
    machine.RTC().datetime((datetimetuple[0], datetimetuple[1], datetimetuple[2], datetimetuple[6] + 1, datetimetuple[3], datetimetuple[4], datetimetuple[5], 0))
    return t

def get_hours(datetimetuple):
    hours = datetimetuple[3]
    return hours

def get_minutes(datetimetuple):
    minutes = datetimetuple[4]
    return minutes

def get_my_time(epochtimeseconds):
     epochtimeseconds = epochtimeseconds + timeoffset.TIMEOFFSETSECONDS
     return epochtimeseconds
#devices
led = Pin("LED", Pin.OUT)
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(secrets.SSID, secrets.PASSWORD)

max_wait = 10
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    max_wait -= 1
    print('waiting for connection...')
    time.sleep(1)

if wlan.status() != 3:
    raise RuntimeError('network connection failed')
else:
    print('connected')
    status = wlan.ifconfig()
    print( 'ip = ' + status[0] )

led.on()
epochTime = set_time()
print("set time epoch: ",epochTime)
print("time tuple: ",time.gmtime())
localEpoch = get_my_time(epochTime)
print("local epochtimeseconds: ",localEpoch)
print("my time tuple: ",time.gmtime(localEpoch))
print("hours: ", get_hours(time.gmtime(localEpoch)))
print("minutes: ",get_minutes(time.gmtime(localEpoch)) )
led.off()

Similar to the previous example, I have my security information in a secrets.py file and my local offset in a timeoffset.py file.

I still need to see if I can get it to be more robust though, since every once in a while, I get a timeout error.

Pico W project

You may not have noticed but a Raspberry Pico came out with wireless support. – the Pico W. I’ve been thinking about a project to create a linear clock where there is a horizontal sliding scale showing the time in 24 hours.

I threw together a quick prototype using:

Naturally, there was also quite a bit of 3D design and printing needed for the mounts of the rods, motor…

I have the code working. When you first turn it:

  • runs the rod until the limit switch is triggered
  • runs the rod back until it is at the zero position
  • gets the time off the internet
  • moves the pointer to the current time.

It then ticks off the needed rotations to advance the rod each minute.

A fairly simple design that I made much more complicated originally by using interrupts for the limit switch (which defines the end of day). Eventually, I realized that I knew exactly how many pulses there were in a day, so I didn’t really to use interrupts. When the limit switch is triggered, it is the end of the day by definition, so we move the pointer back to the beginning, get the time and start over again.

The design will run off 3 AAA batteries. Now all that is left to do is create a case for it with a laser scribed indicator of time of day.

I made it so that I should easily be able to create a larger (say 400mm long) version in the future, since that is also a common length of rod.

Linear clock mechanism

The current breadboarded design is shown above. The pointer will be mounted on the other side of the linear slide.

I’ll show some more later, but here is a simple example of getting the current time from a web service using urequests capabilities:

import network
import machine
import time
import rp2
import secrets
import urequests
import timeoffset
#devices
led_onboard = machine.Pin("LED", machine.Pin.OUT) #this is different for the pico W
#functions
def get_the_time():
# Get IP address for jsontest
    r = urequests.get("http://date.jsontest.com")
    temp = r.json()
    r.close()
    mstime = temp["milliseconds_since_epoch"]
    epochtimeinseconds = mstime//1000
    epochtimeinseconds = epochtimeinseconds + timeoffset.TIMEOFFSETSECONDS
    datetimetuple = time.localtime(epochtimeinseconds)
    return datetimetuple

def get_hours(datetimetuple):
    hours = datetimetuple[3]
    return hours

def get_minutes(datetimetuple):
    minutes = datetimetuple[4]
    return minutes

#main
led_onboard.on() #just to show its working
rp2.country('US')
#set up LAN
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(secrets.SSID,secrets.PASSWORD)
while not wlan.isconnected() and wlan.status()>=0:
    print("Waiting to connect")
    time.sleep(1)
# Should be connected and have an IP address
status = wlan.status() # 3 == success
if status ==3: # 3 == success
    try:
        datetimetuple = get_the_time()
        print(datetimetuple)
        print("hours: ",get_hours(datetimetuple))
        print("minutes: ",get_minutes(datetimetuple))
    except Exception as e:
        print("time exception: ",e)
else:
    print("wlan.status error: ",status)
led_onboard.off() #just to show its stopped working

Where the SSID and PASSWORD are including in a separate python file that looks like:

SSID = "PUT YOUR SSID HERE"
PASSWORD = "PUT YOUR PASSWORD HERE"

That makes it easier to keep the security information separate from the code you’re working on. Note that this python file needs to be on your Pico.

Ham radio fox hunting

Over the weekend we had 6 people participate in a hidden transmitter hunt (fox hunt). Here is a video that answers a few questions, you may have about fox hunting.

The hidden transmitter started at 9AM and all of us found the box, hidden in the woods, by 9:30.

the camo box is the transmitter

The transmitter was about 10 feet off one of the walking paths in Sun City Hilton Head.

I was a bit worried when we started, since it had rained (heavily) the night before. Wet pine trees do strange thing to radio propagation (multipath). It was not that much of an issue though.

When we got close, I used by body as a reflector and rotated around to help identify the direction of the signal.

I’d totally forgotten about was using a metal can and placing a handheld radio without an antenna in the can for direction finding. One of the other folks had his can out and it seemed to work well. This is a cheap alternative to more dedicated specialty devices for direction finding.

We had a good time and must be getting better, since we found the transmitter so quickly.

Skyrim VR and Oculus

I mentioned a while back that I received an Oculus for my birthday. So far, I have been very pleased. It took me a while to find a program that I would go to on a regular basis. That program is Skyrim VR. I played Skyrim a decade ago for a while, but since they released it in VR form, I’ve found it even more fascinating than the first time.

Skyrim VR is runs under StreamVR. I did finally shift from using the Oculus PC interface program to Virtual Desktop Streamer. This program greatly enhanced the reliability and the capabilities of the wireless interface to Oculus.

If you have never played Skyrim, it is a very large world:

A view of the map from a corner of Skyrim

The destinations do not show up on the map until you have visited them. So, you can see I have visited a few in this area.

A view going down a mine

The views outside can be spectacular — this is not one of them, but it does show that you can see far into the distance, until the fog obscures the view (in this case). These pictures were actually a bit difficult for me to take, since I had to remove the headset to see the keyboard and moving the headset shifts the view to a different perspective.

The Oculus itself

The one area that I have been disappointed in the programs available for the Oculus is in the area for free .STL display. I have yet to find a program that will take an STL file and show it in virtual reality. The best I have found is taking STL files over to OBJ file. I have found a few Open Source projects in the works, but not one that I’ve got working. Since I do quite a bit of 3D design, I thought it would be interesting to see it in a virtual world as well.

By the way, Facebook just announced that: “A Facebook account is no longer required to use Meta VR devices. Instead, you’ll need to set up a Meta account, which lets you log into your VR devices and view and manage your purchased apps in one place.” Considering how often Facebook accounts get hacked, I know I will be switching over to a more VR focused account soon.

A matrix tray using a Dado

The other day one of my friends from the woodshop showed me a picture of a tray he saw at a craft show. He was thinking through the process of making it.

I was looking for a project to help those in the shop understand the setup and use of the dado blade. This project seemed like a good fit, since it was simple and involved numerous cuts. It has only 3 unique part shapes (if you don’t count the handles).

A dado blade is a circular saw blade that cuts grooves into the wood that are much wider than traditional saw blade cuts. They are used for interlocking applications. Typically, the dado blade is ‘built’ by stacking blade cutting components into a blade assembly that is mounted in the table saw.

Here is the design for the tray I put together in Fusion 360:

Vertical bar
Horizontal bar
Side bar

And a range of handles that could be added to the ends:

Angular end
Curved end

Handle end

To make the tray, you cut a series of grooves in a plank and then slice that board into the bars required. These bars interlock into a matrix that is used as the foundation for the tray.

Also, to help with the fence positioning against the blade, I 3D printed an alignment jig:

Matrix Table Jig

The groove on the right helps you set up the initial fence alignment for the first cut. After that you can use the groove on the left for the subsequent cuts. The height of the slots is 7/16, so it should also help you get the initial blade height close to where it needs to be. You can find the design on Thingiverse.

The jig design was done in Microsoft 3D builder, since it is made of very basic structures. I have yet to see how this tool works in the class to help speed up setting the fence on the saw, but it should make a real difference.

I am just finishing the class, so we’ll see how the design of the tray goes over with the students.

Another light and sound project for the G gage train

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:

  1. A buck converter — to take the 12 volts around the layout and step it down to the 5V needed for the project.
  2. The Pico
  3. 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:

Sound and light module

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.

Field day is over for 2022…

Our club’s field day effort is over. We probably had close to 20 people show up at various times.

Sun City Hilton Head Field Day – lunch

After we finished up our club’s effort on Saturday, I came home and operated FT8 and FT4 on Sunday until almost noon.

My breakdown of contacts was for the 102 contacts I made:

BandCount of Contacts
10m5
15m27
20m43
40m6
80m22
Grand Total103

I learned that 40 isn’t worth the effort on digital. 80 meters at night and then go straight to 20 after sun rise. Though I did work NZ and AU on 40.

By mode:

ModeCount of Contacts
FT874
FT429
Grand Total103

By section:

SectionCount of contacts
AL2
AR2
CT3
EMA1
ENY2
EPA6
GA3
IA4
IL2
IN2
KY2
MB1
MDC3
MI3
MO3
MS1
NC2
NLI1
NNJ1
NTX2
OH16
ONE1
QC2
RI1
SCV1
SFL3
SNJ2
STX3
TN5
VA4
VT1
WCF3
WI3
WMA1
WPA4
WTX2
WV2

Not a great performance, but not bad. I did work New Zealand and Australia on 40 on Sunday morning.

Ham Radio Field Day 2022 — a hybrid

This year Field Day  has hybrid rules allowing for club operation and work at home affiliated to a club. I have my rig (ICOM 7100) set up to run on batteries with the KE4HAM club, using the Buddipole. We will probably not be operating 24 hours, but still get out and have fun. You can use the field day locator app, and type in KE4HAM as the callsign to find us.

I plan to get everything set up about 2PM using my VNA to tune the antenna. Naturally, when I set up the day before, all the software I normally use has updated since the last time the computer connected to the rig.

testing my setup

Using the Pico to add sound to a model train layout

Once you get a train layout designed and working, one way to add greater interest is through sound and automation. I was looking for reduced cost approach that would be flexible and reliable. I’ve mentioned before that I’ve been experimenting with the Raspberry Pico. They can be purchased for around $5 and are both powerful and versatile.

I was also using MicroPython, since it is straightforward for others to learn. I’ve been putting together a class for the others in the Sun City Hilton Head Model Railroad group, so they can experiment on their own.

Here is the lesson I pulled together on adding sound:

Lesson 13 – Adding sound

There currently no well supported way to add sound on the Pico with MicroPython (that I could find). There is an article covering how to add sound with CircuitPython, but that environment does not support multitasking.

One simple way to play sound is using a relay and a dedicated sound board, like the WayinTop Sound Module (or one of the many others out on Amazon).

This sound board is triggered by a button and will play any MP3 data that is stored within it. Replace the button with a relay circuit and write your code to trigger the relay.

The Bill of Materials needed (in addition to the Pico):

  • Relay $2
  • The WayinTop Sound Module about $15

This approach will play mono sounds (it plays through the stored sound files sequentially). That’s nice, but a bit more expensive and less flexible, since there is relatively little control.

Instead, we are going to use a sound card that can be controlled using the UART serial port. Though the example plays through all the sounds stored on the card, you have the option to play specific songs on demand… using this MP3 sound module. It supports multiple songs, stored on a micro-SD card. It also will drive stereo sound, but the programming is a bit more complicated.

The bill of materials needed:

  • Anmbest YX5200 DFPlayer Mini MP3 Player $3
  • Micro SD card $5
  • Speaker $1

The sound module has the following pin configuration:

Pin NumberPin NameDescriptionNotes
1VCCDC 3.2~5.0V 
2RXUART serial input3.3V TTL level
3TXUART serial output3.3V TTL level
4DAC_RAudio output right channelFor an earphone
5DAC_LAudio output left channelor an external amp
6SPK+Speaker+3W
7GNDGround 
8SPK-Speaker- 
9IO1Trigger port 1Short press to play previous
10GNDGround 
11IO2Trigger port 2Short press to play next
12ADKEY1AD port 1Trigger to play first segment
13ADKEY2AD port 2Trigger to play fifth segment
14USB+USB+ DPTo connect to USB flash
15USB-USB- DMDrive or PC
16BUSYBusy outputLow when playing, high when standby

We will only be using a subset of these pins. The wiring diagram for this project is:

The module needs to have the sound files stored on the micro-SD card in a very specific way. The sound files need to be called xxx.mp3 and be located in a top-level folder called MP3. Look to the datasheet for the sound module for more details.

The sound module support numerous commands to perform a range of tasks. The serial communication format is the standard baud rate of 9600 bps with Data bits: 1 Check: none Flow Control: none.

The commands follow the following format:

Byte functionDescriptionContents
$$Start byte0x7E
VersionVersion0xFF by default
LengthNumber of bytes from version to Check_LSBTypically 0x06
CMDThe command codeDependent on what you are trying to do
FeedbackNeed feedback, send confirmation to the computer0x01 (no feedback needed)
Para_MSBMost significant byte of the parameterDependent on what you are trying to do
Para_LSBLeast significant byte of the parameterDependent on what you are trying to do
Check_MSBMost significant byte of the checksumDependent on buffer contents
Check_LSBLeast significant byte of the parameterDependent on buffer contents
$0End byte0xEF

You can leave out the checksum bits if you desire or calculate the checksum:

 Checksum (2 bytes) = 0xFFFF–(Ver.+Length+CMD+Feedback+Para_MSB+Para_LSB)+1

For example, if we specify playback of SD card, we need to send the command “7E FF 06 09”

Some of the commands supported by the device are:

Command descriptionCommand
Play next0x01
Play previous0x02
Specify the playback of a track0x03
Increase volume0x04
Decrease volume0x05
Specify volume0x06
Specify equalization0x07
Specify single repeat playback0x08
Specify playback of a device0x09
Set sleep0x0A
N/A0x0B
Reset0x0C
Play0x0D
Pause0x0E

There are many more commands that can play a specific sound file, play in a loop… To find out more look at the datasheet document for the sound module.

The code to play a sound file is:

from machine import Pin,UART
import time
#constant
UART_TX = 0
UART_RX = 1
## command to play the sound
PLAY_ARRAY = bytearray(8)
PLAY_ARRAY[0] = 0x7E
PLAY_ARRAY[1] = 0xFF
PLAY_ARRAY[2] = 0x06
PLAY_ARRAY[3] = 0x0D
PLAY_ARRAY[4] = 0x00
PLAY_ARRAY[5] = 0x00
PLAY_ARRAY[6] = 0x00
PLAY_ARRAY[7] = 0xEF
## command to define the device to play
DEVICE_ARRAY = bytearray(8)
DEVICE_ARRAY[0] = 0x7E
DEVICE_ARRAY[1] = 0xFF
DEVICE_ARRAY[2] = 0x06
DEVICE_ARRAY[3] = 0x09
DEVICE_ARRAY[4] = 0x00
DEVICE_ARRAY[5] = 0x00
DEVICE_ARRAY[6] = 0x02
DEVICE_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 #doesn't seem to change if you go above 30
VOLUME_ARRAY[7] = 0xEF
#device definition
uart = UART(0, baudrate=9600, tx=Pin(UART_TX), rx=Pin(UART_RX))
uart.write(DEVICE_ARRAY)
time.sleep(0.1) # give it some time to read the data
uart.write(VOLUME_ARRAY)
time.sleep(0.1) # give it some time to read the data
uart.write(PLAY_ARRAY)

The DEVICE and VOLUME commands are not really necessary, since those are the default when the device powers up but wanted to show sending multiple commands.

One of the things I try to do in my lessons is add a challenge at the end based on what the students have learned previously. The challenge takes the concepts in new directions that hopefully encourages to learn more than what was covered in the lesson.

Lesson challenge

Lesson challenge – How would you play a sound when a button is pressed? Go back to the circuit we used for the crosswalk lesson and make it say ‘Walk’ ten times, instead of using the buzzer (a walk.mp3 file has been provided in the lesson program folder). Make a flashing crossing gate circuit using the red LEDs? How would you make the lights flash for only as long as the sound is playing, using the Busy pin? Could you do the same thing using only UART commands?

Final example:

Here is an example with UART status sensing that only flashes the lights while the sound is playing. This should enable you to change sound files, without having to change light timing:

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 the sound
PLAY_ARRAY = bytearray(8)
PLAY_ARRAY[0] = 0x7E
PLAY_ARRAY[1] = 0xFF
PLAY_ARRAY[2] = 0x06
PLAY_ARRAY[3] = 0x0D
PLAY_ARRAY[4] = 0x00
PLAY_ARRAY[5] = 0x00
PLAY_ARRAY[6] = 0x00
PLAY_ARRAY[7] = 0xEF
## command to define the device to play
DEVICE_ARRAY = bytearray(8)
DEVICE_ARRAY[0] = 0x7E
DEVICE_ARRAY[1] = 0xFF
DEVICE_ARRAY[2] = 0x06
DEVICE_ARRAY[3] = 0x09
DEVICE_ARRAY[4] = 0x00
DEVICE_ARRAY[5] = 0x00
DEVICE_ARRAY[6] = 0x02
DEVICE_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 #doesn't seem to change if you go above 30
VOLUME_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
#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
led_onboard.value(1) #to show the program is running
uart.write(DEVICE_ARRAY)
utime.sleep(0.1) # give it some time to read the data
uart.write(VOLUME_ARRAY)
utime.sleep(0.1) # give it some time to read the data
while True:
    if button.value()==1:
        uart.write(PLAY_ARRAY)
        #flash the lights
        left_LED.value(1)
        utime.sleep(0.5)
        playing = 1
        while playing>0:
            left_LED.toggle()
            right_LED.toggle()
            utime.sleep(0.5)
            uart.write(STATUS_ARRAY) # ask for the status
            utime.sleep(0.1)
            statusBytes = uart.read()
            playing = statusBytes[6]
        left_LED.value(0)
        right_LED.value(0)
    utime.sleep(0.2)

Pasta Drying Rack

I’ve not posted in a while and although I have been busy doing many things, I’ve not had anything thought worth posting about. But…

Over the weekend my son and I were talking about his love of cooking and the pasta maker he received for Christmas last year. I saw a pasta drying rack at the store, but it was difficult to store and cost quite a bit for what it was. I told him I bet I could make something better than the one I saw and with scrap I had lying around the house.

Here is that design:

Overview of the drying rack

It comes apart into 4 pieces, the base, top and 2 vertical supports. The other pieces I glues together with waterproof glue. It may not be the biggest… drying rack in the world, but it did meet the need and I was able to make the prototype in less than an hour.

Here are the other design elements:

Hopefully, the drawings are all accurate and detailed enough so that anyone with the skills could make on.