ChickBot Pi sings!

Let’s get your ChickBot singing! So start up Geany (or select New from the File menu if you already have it running).

First of all, we need to import the usual modules:

import RPi.GPIO as GPIO
import time

Then we need to tell ChickBot how to sing in tune – and to do that, we need to tell it what notes to play. For this example, we’ll be using just a few notes. Later on, you’ll have access to a whole piano’s worth of notes.

Copy and paste this block above the setup section:

NOTE_F3 = 175
NOTE_G3 = 196
NOTE_A3 = 220
NOTE_B3 = 247
NOTE_C4 = 262

This setups a simple way for us to know what note we want but for the ChickBot to know what that notes is as a frequency. We’ll find out a bit more about music and frequencies in another tutorial, for now, just know that C4 is what is commonly known as middle C.

Now we can tell ChickBot which notes to play and how long to play them for with this:

tune = [ NOTE_C4, 4, NOTE_G3, 8, NOTE_G3, 8, NOTE_A3, 4, NOTE_G3, 4, 0, 4, NOTE_B3, 4, NOTE_C4, 4 ]

You can see we have pairs to tell the program the note and its duration using whole, half, quarter (4) and eighths (8) as sheet music To put a space, we use a note of 0 with whatever duration that’s needed.

As with most programs, some setup is needed:

def Setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(7, GPIO.OUT)

The piezo sounder is on pin 7. Now for two blocks of code that take the note frequencies that have been added to the tune and plays them for us. Definitely copy & paste time!

def PlayTone(frequency, duration):
    p = GPIO.PWM(7, 0.5)
    p.start(50)
    p.ChangeFrequency(frequency)
    time.sleep(duration)
    p.stop()

This plays an individual note – it setups an output for pulse width modulation (PWM), starts it, sets the frequency, pause (sleep) for the required amount of time the note should play and then stop the tone.

Setup()
for i in range(0, len(tune) / 2):
   duration = 1 / float(tune[i*2+1])
   if (tune[i*2]):
     PlayTone(tune[i*2], duration)
   else:
     time.sleep(duration)
   time.sleep(0.2 * duration)

This code steps through the pairs of numbers in tune, picking up the information on what note and duration to play. For each note (or space), it calculates the duration of the note and then uses the PlayTone function to play that note. If it’s a space (ie silence) then it just sleeps for the duration of the space. At the bottom we have a smaller delay so that there is a space between notes.

Your program should now look like this:

import RPi.GPIO as GPIO 
import time

NOTE_F3 = 175
NOTE_G3 = 196
NOTE_A3 = 220
NOTE_B3 = 247
NOTE_C4 = 262

tune = [ NOTE_C4, 4, NOTE_G3, 8, NOTE_G3, 8, NOTE_A3, 4, NOTE_G3, 4, 0, 4, NOTE_B3, 4, NOTE_C4, 4, 0, 0 ];

def Setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(7, GPIO.OUT)

def PlayTone(frequency, duration):
  p = GPIO.PWM(7, 0.5)
  p.start(50)
  p.ChangeFrequency(frequency) 
  time.sleep(duration)
  p.stop()

Setup()
for i in range(0, len(tune) / 2):
  duration = 1 / float(tune[i*2+1])
  if (tune[i*2]):
     PlayTone(tune[i*2], duration)
   else:
     time.sleep(duration)
  time.sleep(0.2 * duration)

You can then click the Execute button and you should hear a short little melody.

How about a different tune? Replace the tune line with this:

int tune = [ NOTE_F3, 8, NOTE_G3, 8, NOTE_A3, 8, NOTE_C4, 4, NOTE_A3, 8, NOTE_C4, 4 ]

If you don’t yet know how to read music, we’ll show you how to do that in another tutorial. If you can read music, you can put your own tunes in – at the bottom of this page is the definitions for two octaves including the sharps. Remember, C4 is middle C.

But now, we will expand on our button pressing, tune playing, moving  ChickBot program so you can get it dancing and singing to your commands.

NOTE_C3 = 131
NOTE_CS3 = 139
NOTE_D3 = 147
NOTE_DS3 = 156
NOTE_E3 = 165
NOTE_F3 = 175
NOTE_FS3 = 185
NOTE_G3 = 196
NOTE_GS3 = 208
NOTE_A3 = 220
NOTE_AS3 = 233
NOTE_B3 = 247
NOTE_C4 = 262
NOTE_CS4 = 277
NOTE_D4 = 294
NOTE_DS4 = 311
NOTE_E4 = 330
NOTE_F4 = 349
NOTE_FS4 = 370
NOTE_G4 = 392
NOTE_GS4 = 415
NOTE_A4 = 440
NOTE_AS4 = 466
NOTE_B4 = 494
NOTE_C5 = 523