2 min read

Simple UART Project Using pyboard and Arduino Uno

How to communicate between an Arduino Uno and a pyboard to start/stop playing music using the UART protocol
Arduino Uno, pyboard and a buzzer
Arduino Uno, pyboard and a buzzer

In this article, we'll go over an example of how to communicate between an Arduino Uno and a pyboard using the UART protocol.

We'll use a buzzer to demonstrate the outcome.
The pyboard receives the signals from the Arduino and then starts or stops playing music accordingly.

Required Components

Circuit Diagram

Arduino Uno is connected to the Feather 32u4, which receives signals from the distance sensor.
Arduino Uno is connected to the pyboard, which receives signals from the Arduino and starts/stops playing music on the buzzer.

Code (Arduino)

Click to see some code.
#include 

SoftwareSerial softSerial(10, 11); //RX, TX

char serial_data;

void setup() {
  softSerial.begin(9600);
  Serial.begin(9600);
}

void loop() {
  // Send signals using the Serial Monitor. 
  // To start playing music, send 'p'.
  // To stop playing music, send 's'.
  while (Serial.available())
  {
    serial_data = Serial.read();
    softSerial.print(serial_data);
    Serial.print(serial_data);
  }
}

Code (pyboard)

Make sure you are on the latest firmware version for the pyboard. This solution uses the ´uasyncio´ which was introduced after V1.13. For more details see Guide to uasyncio.

For the RTTTL library see Ring Tone Text Transfer Language Parser.

Click to see some code.
import pyb
import songs
import uasyncio as asyncio
from rtttl import RTTTL

class UART_receiver():
    def __init__(self) -> None:
        self.uart = pyb.UART(1, 9600)
        self.data = ''

        self.uart.init(9600, bits=8, parity=None, stop=1)

        asyncio.create_task(self.run())

    async def run(self):
        while True:
            if self.uart.any():
                res = self.uart.read()
                self.data = res.decode("utf-8").strip()
            await asyncio.sleep(0)

    def getData(self):
        return self.data

class Radio():
    def __init__(self, uart) -> None:
        self.buz_tim = pyb.Timer(8, freq=440)
        self.buz_ch = self.buz_tim.channel(2, pyb.Timer.PWM, pin=pyb.Pin('Y2'), pulse_width=0)
        self.pwm = 50 # reduce this to reduce the volume
        self.uart = uart

    async def play_tone(self, freq, msec):
        print('freq = {:6.1f} msec = {:6.1f}'.format(freq, msec))
        if freq > 0:
            self.buz_tim.freq(freq)
            self.buz_ch.pulse_width_percent(self.pwm)
        pyb.delay(int(msec * 0.9))
        self.buz_ch.pulse_width_percent(0)
        pyb.delay(int(msec * 0.1))
        await asyncio.sleep(0)

    async def play(self, tune):
        try:
            for freq, msec in tune.notes():
                await self.play_tone(freq, msec)
                await asyncio.sleep(0)
                if self.uart.getData() == 's':
                    self.play_tone(0, 0)
                    break
                
        except KeyboardInterrupt:
            await self.play_tone(0, 0)

async def main():
    uart_msg = UART_receiver()
    radio = Radio(uart_msg)
    trackNumber = 7 # Just a random number to start somewhere
    rx_data = ''
    while True:
        await asyncio.sleep(0)
        rx_data = uart_msg.getData()

        if rx_data == 'p':
            track = RTTTL(songs.index(trackNumber))
            await radio.play(track)
        
        trackNumber = trackNumber + 1
        if trackNumber > songs.size():
            trackNumber = 0

asyncio.run(main())

Wiring

The Arduino is powered by the computer via USB, and the pyboard is powered by 5V from the Arduino.

Arduino Uno pyboard Buzzer
5V V+ -
GND GND -
10 X9 -
11 X10 -
- GND GND
- Y2 V

Results

Once everything is connected you should start to hear some music being played, coming from the buzzer.

0:00
/0:15

Demo of music playing on the buzzer based on messages received by the pyboard from the Arduino.

Well done!


Thank you for reading.