Lets Make Tech

Arduino Music Box

Credit to David Mills http://webshed.org/wiki/AD9850_Arduino for the code to interface with the signal generator.   

Here is a video to show what to expect from this project. I got a couple of the notes wrong in this video but they have been corrected in the code below.  

 

 

Bill of Materials:

-1 Arduino

-1 LCD display (optional)

-1 AD9850 DDS signal generator

-1 pizzo electric buzzer

 

I will leave the LCD up to you, and just provide instructions on how to make some music with the AD9850 DDS and an Arduino.  

Note the connections between the arduino and the AD9850 DDS signal generator. Feel free to change them if you need.  

#define CLOCK 2 //pin connections for DDS
#define LOAD 3
#define DATA 7
#define RESET 8

Hook the pizzo buzzer to the square wave output and ground.

Now we need some notes, I referred to http://www.phy.mtu.edu/~suits/notefreqs.html to get a few. 

To play a note you can use this function: note(G*10, 750);  Place the desired note, the octave, then the length to play the note.

The octave scale is not linear.

Please note that I do not use real notes in the Waltz program, but it uses relative frequencies. The scale program does use real notes.

A*20 comes after G*10 however these will not be real musical notes.

 

To use real notes start with A*1, A*2, A*4, A*8, etc. If you are not worried about using real notes then just be sure that your are consistent relative the note you start on.  

This code is a little rushed and could be cleaned up a lot and is just for reference. If you use it be sure to credit David Mills http://webshed.org/wiki/AD9850_Arduino   for the part he wrote as well as me for the parts I wrote and don't claim the code as your own or try to prevent anyone else using it other than that do with it what you will. 

Below is the code to play Waltz From Sleeping Beauty and the code to play all of the real musical notes.

You can also turn this into a musical instrument by adding buttons that play notes.

Scale

#include <LiquidCrystal.h>

LiquidCrystal lcd(5, 6, 9, 10, 11, 12);


#define DDS_CLOCK 125000000

#define  CLOCK  2  //pin connections for DDS
#define  LOAD 3 
#define  DATA  7
#define  RESET 8
#define  POTPIN A0
#define  MODE 13

//Notes
#define A 27.5
#define AS 29.14
#define B 30.87
#define C 32.7
#define CS 34.65
#define D 36.71
#define DS 38.89
#define E 41.2
#define F 43.65
#define FS 46.25
#define G 49
#define GS 51.91

float hrz;
float time;
void setup()
{
  pinMode(DATA, OUTPUT); 
  pinMode(CLOCK, OUTPUT); 
  pinMode(LOAD, OUTPUT); 
  pinMode(RESET, OUTPUT); 
  pinMode(POTPIN, INPUT);
  pinMode(MODE, INPUT);
  AD9850_init();
  AD9850_reset();
  lcd.begin(16, 2);
  
  Serial.begin(9600);
    lcd.setCursor(0, 0);
    lcd.print("Note");
    lcd.setCursor(0, 1);
    lcd.print("Range");
  //SetFrequency(hrz);

}

void loop()
{ 
  int x=1;
  for (int i=0;i<10;i++)
  {
    intro(x);
    x=x*2;
  }
  for (int i=0;i<10;i++)
  {
    outro(x);
    x=x/2;
  }
} 


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

    digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}

void note(float hrz, float time)
{
   SetFrequency(hrz);
   delay(time);
}



void intro(int i)
{
    note(A*i, 250);
    note(AS*i, 250);
    note(B*i, 250);
    note(C*i, 250);
    note(CS*i, 250);
    note(D*i, 250);
    note(DS*i, 250);
    note(E*i, 250);
    note(F*i, 250);
    note(FS*i, 250);
    note(G*i, 250);
    note(GS*i, 250);    
}

void outro(int i)
{
  note(GS*i, 250);  
  note(G*i, 250);
  note(FS*i, 250); 
  note(F*i, 250);
  note(E*i, 250);
  note(DS*i, 250);
  note(D*i, 250);
  note(CS*i, 250);
  note(C*i, 250);
  note(B*i, 250);
  note(AS*i, 250);
  note(A*i, 250);


  
  
}

 

 

 

 

 

 

Waltz From Sleeping Beauty

#include <LiquidCrystal.h>

LiquidCrystal lcd(5, 6, 9, 10, 11, 12);


#define DDS_CLOCK 125000000

#define  CLOCK  2  //pin connections for DDS
#define  LOAD 3 
#define  DATA  7
#define  RESET 8


//Notes
#define A 27.5
#define As 29.14
#define B 30.87
#define C 32.7
#define Cs 34.65
#define D 36.71
#define Ds 38.89
#define E 41.2
#define F 43.65
#define Fs 46.25
#define G 49
#define Gs 51.91

float hrz;
float time;
void setup()
{
  pinMode(DATA, OUTPUT); 
  pinMode(CLOCK, OUTPUT); 
  pinMode(LOAD, OUTPUT); 
  pinMode(RESET, OUTPUT); 
  pinMode(POTPIN, INPUT);
  pinMode(MODE, INPUT);
  AD9850_init();
  AD9850_reset();
  lcd.begin(16, 2);
  
  Serial.begin(9600);
    lcd.setCursor(0, 0);
    lcd.print("Waltz From");
    lcd.setCursor(0, 1);
    lcd.print("Sleeping Beauty");
  //SetFrequency(hrz);

}

void loop()
{ 
  intro();
  //Start repeat sign
  repeatedmusic();
  repeatedone();
  repeatedmusic();
  repeatedtwo();
  ending();
} 


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

    digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}

void note(float hrz, float time)
{
   SetFrequency(hrz);
   delay(time);
}



void intro()
{
    note(G*10, 1000);
  
  note(Fs*10, 1000);
  
  note(G*10, 750);
  note(E*10, 250);
  
  note(Fs*10, 250);
  note(G*10, 250);
  note(E*10, 250);
  
  note(Fs*10, 500);
  note(A*20, 250);
  
  note(B*20, 500);
  note(Gs*10, 250);
  
  note(A*20, 1500);
  
  note(D*20, 750);
  
  note(Cs*20, 750);

  note(C*20, 500);
  note(A*20, 250);
  
  note(C*20, 250);
  note(B*20, 250);
  note(A*20, 250);
  
  note(E*20, 500);
  note(D*20, 250);
  
  note(C*20, 500);
  note(B*20, 250);
  note(0,1);
  
  note(B*20,250);
  note(A*20,250);
  note(Gs*10, 250);
  
  note(A*20,250);
  note(E*10,250);
  note(Fs*10,250); 
  
  note(G*10,750);
  
  note(Fs*10,750);
  
  note(G*10,500);
  note(E*10,250);
 
  note(Fs*10,250);
  note(G*10, 250);
  note(E*10,250);
  
  note(Fs*10,500);
  note(A*20,250);
  
  note(B*20,500);
  note(Gs*10, 250);
  
  note(A*20,1500);
  
  note(B*20,500);
  note(C*20,250);
  
  note(C*20,250);
  note(Cs*20,500);
  
  note(E*20,500);
  note(D*20,250);
  
  note(D*20,250);
  note(Fs*20,500);
  
  note(G*20,500);
  note(Fs*20,250);
  
  note(Fs*20,250);
  note(E*20,500);
  note(0, 10);
  
  note(D*20,125);
  note(0,125);
  note(Cs*20,125);
  note(D*20,125);
  note(E*20,125);
  
  note(D*20,125);
  note(B*20,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  note(Fs*10,125);
  
  note(D*10,125);
  note(0,125);
  note(D*20,500);
  
  note(E*20,500);
  note(Fs*20,250);
}


void repeatedmusic()
{
  note(G*20,125);  
  note(0,125);
  note(As*20,125);
  note(B*20,125);
  note(C*20,125);
  note(B*20,125);
  
  note(D*20,125);
  note(0,125);
  note(G*10,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(B*20,125);
  note(0,125);
  note(Fs*10,125);
  note(G*10,125);
  note(A*20,125);
  note(G*10,125);
  
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(E*10,125);
  
  note(D*10,125);
  note(0,125);
  note(Cs*20,125);
  note(D*20,125);
  note(E*20,125);
  note(D*20,125);
  
  note(Fs*20,125);
  note(E*20,125);
  note(D*20,125);
  note(Cs*20,125);
  note(D*20,125);
  note(As*20,125);
  
  note(B*20,125);
  note(0,125);
  note(D*20,500);
  
  note(E*20,500);
  note(Fs*20,250);
  
  note(G*20,125);
  note(0,125);
  note(As*20,125);
  note(B*20,125);
  note(C*20,125);
  note(B*20,125);
  
  note(D*20,125);
  note(0,125);
  note(Gs*10,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(B*20,125);
  note(0,125);
  note(Fs*10,125);
  note(G*10,125);
  note(A*20,125);
  note(G*10,125);
  
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(E*10,125);
  
  note(Cs*10,125);
  note(0,125);
  note(C*20,125);
  note(Cs*20,125);
  note(D*20,125);
  note(Cs*20,125);
  
}


void repeatedone()
{
    note(Fs*20,125);
    note(E*20,125);
    note(D*20,125);
    note(Cs*20,125);
    note(B*20,125);
    note(A*20,125);
    
    note(D*20,125);
    note(0,125);
    note(D*20,500);
    
    note(E*20,500);
    note(Fs*20,250);
}

void repeatedtwo()
{
  note(D*20,125);
  note(Cs*20,125);
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125); 
  
}

void ending()
{
  note(D*20,125);
  note(C*20,125);
  note(B*20,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(Fs*10,125);
  note(E*10,125);
  note(D*10,125);
  
  note(Fs*10,125);
  note(E*10,125);
  note(D*10,125);
  note(C*10,125);
  note(E*10,125);
  note(D*10,125);
  
  note(C*10,125);
  note(B*10,125);
  note(D*10,125);
  note(C*10,125);
  note(B*10,125);
  note(D*10,125);
  
  note(G*10,750);
  
  note(Fs*10,750);
  
  note(G*10,500);
  note(C*10,250);
  
  note(E*10,250);
  note(E*10,250);
  
  note(Fs*10,250);
  note(G*10,250);
  note(E*10,250);
  
  note(F*10,500);
  note(A*20,250);
  
  note(B*20,500);
  note(G*10,250);
  
  note(A*20,1500);
  
  note(Ds*20,750);
  
  note(D*20,750);
  
  note(C*20,500);
  note(A*20,250);
  
  note(C*20,250);
  note(B*20,250);
  note(A*20,250);
  
  note(E*20,500);
  note(D*20,250);
  
  note(C*20,500);
  note(B*20,250);
  delay(1);
  
  note(B*20,250);
  note(A*20,250);
  note(G*10,250);
  
  note(A*20,250);
  note(E*10,250);
  note(F*10,250);
  
  note(G*10,750);
  
  note(F*10,750);
  
  note(G*10,500);
  note(E*10,250);
  
  note(Fs*10,250);
  note(G*10,250);
  note(Gs*10,250);
  
  note(A*20,500);
  note(Fs*10,250);
  
  note(B*20,500);
  note(Gs*20,250);
  
  note(A*20,125);
  note(0,125);
  note(E*10,125);
  note(Gs*5,125);
  note(A*10,125);
  note(C*10,125);
  
  note(E*10,125);
  note(Ds*10,125);
  note(E*10,125);
  note(Gs*10,125);
  note(A*20,125);
  note(C*20,125);
  
  note(Ds*20,500);
  note(E*20,250);
  
  note(E*20,250);
  note(Fs*20,500);
  
  note(A*40,250);
  note(G*20,250);
  
  note(G*20,250); 
  note(B*40,500);
  
  note(C*40,500);
  note(B*40,250);
  
  note(B*40,250);
  note(A*40,500);
  
  note(G*20,125);
  note(0,125);
  note(Fs*20,125);
  note(G*20,125);
  note(D*20,125);
  note(B*20,125);
  
  note(G*10,125);
  note(0,625);
}

Time Script For Beagle Bone Black

I wrote this script for dealing with time on the beagle bone black. First run set the timezone to where you live on the 4th line. Any runs after that have the 3rd and 4th lines commented. If the time resets after each time you boot and doesn't automatically change to the correct time you can place this script in the auto run folder in the cloud 9 IDE (save it as time.sh, or whatever you like with a .sh extension. This script doesn't seem to be required for Debian on beagle bone, but other people on Angstom have reported that the time is not updating automatically after rebooting.   

#!/bin/bash
#update time
#rm -rf /etc/localtime
#ln -s /usr/share/zoneinfo/America/New_York /etc/localtime

c=0
x=1
while [ $x -ne 0 ]
do
    let c=$c+1
    if [ $c -gt 10 ]; then
    let x=0
    fi
    ntpdate -b -s -u pool.ntp.org
    if [ $ -ne 0 ]; then
    sleep 60
    else x=0
    fi
done

 

 

 

 

 

 

 

 

Newer posts → Home ← Older posts