LED Piano: A3BU PWM Code

The A3BU code interacts with TeraTerm to receive a serial input from the user. Once the user types in the key word of a song, the A3BU will be notified and will transmit a PWM signal from the SCL on header J1 to the Arduino. Once the Arduino receives its PWM signal, a pre-programmed song will play on our instrument.
#define USART_SERIAL_EXAMPLE &USARTC0
#define USART_SERIAL_EXAMPLE_BAUDRATE 9600
#define USART_SERIAL_CHAR_LENGTH USART_CHSIZE_8BIT_gc
#define USART_SERIAL_PARITY USART_PMODE_DISABLED_gc
#define USART_SERIAL_STOP_BIT false

#include <conf_board.h>
#include <string.h>
#include <board.h>
#include <sysclk.h>
#include <st7565r.h>
#include <asf.h>

int main(void)
{
struct pwm_config mypwm[1];
board_init();
sysclk_init();
//initializes the graphics mono
gfx_mono_init();
//prepares the LCD back light to receive an input
PORTE_DIR = 0x10;
//turns the LCD back light to ON
PORTE_OUT = 0x10;
//prints the designated string value
gfx_mono_draw_string("Enter the song you wish to play!",18,10,&sysfont);

pwm_init(&mypwm[0], PWM_TCC0, PWM_CH_B, 500);//SCL on J1

// Set each of the 4 PWM channel duty cycles independently, and start them going pwm_start(&mypwm[0], 10);
pwm_start(&mypwm[0],0);

while (true) 
{
uint8_t tx_buf[] = "\n\rHello\n\rEnter song:";
uint8_t tx_length = 22;
uint8_t received_byte;
uint8_t i;
uint8_t j = 0;
uint8_t start_line_address = 0;
uint8_t x = 0;
char *song1 = "star";
char message[30];
char letter;

/* Initialize the board.
* The board-specific conf_board.h file contains the configuration of
* the board initialization.
*/
gfx_mono_init();
st7565r_init();

st7565r_set_column_address(0);
st7565r_set_page_address(0);

// USART options.
static usart_rs232_options_t USART_SERIAL_OPTIONS = {
.baudrate = USART_SERIAL_EXAMPLE_BAUDRATE,
.charlength = USART_SERIAL_CHAR_LENGTH,
.paritytype = USART_SERIAL_PARITY,
.stopbits = USART_SERIAL_STOP_BIT
};

// Initialize usart driver in RS232 mode
usart_init_rs232(USART_SERIAL_EXAMPLE, &USART_SERIAL_OPTIONS);

// Send "message header"
for (i = 0; i < tx_length; i++) 
{
usart_putchar(USART_SERIAL_EXAMPLE, tx_buf[i]);
}
// Get and echo a character forever, specific '\r' processing.
while (true) 
{
//received_byte = usart_getchar(USART_SERIAL_EXAMPLE);
PORTE_OUT = 0xff;
letter = usart_getchar(USART_SERIAL_EXAMPLE);
PORTE_OUT = 0x00;
//strcat(message, letter);
if(j < 30)
{
if(letter != '\r')
{
message[j] = letter;
j++;
}
}

if (letter == '\r') 
{
if(strcmp(message, song1) == 0)
{
gfx_mono_draw_string(" ", 0,0, &sysfont);
gfx_mono_draw_string("Ready to Play!", 44, 0, &sysfont);
pwm_start(&mypwm[0],80);
delay_ms(2000);
pwm_start(&mypwm[0],0);

}
else
{
for (i = 0; i < tx_length; i++) 
{
while(true)
{
PORTE_OUT = 0xff;
st7565r_set_display_start_line_address(start_line_address = start_line_address + 2);
for(i = 0; i < j; i++)
{
gfx_mono_draw_char(message[i], i*8, 0, &sysfont);
delay_ms(50);
}
/*for(i = 0; i < j; i++)
{ 
gfx_mono_draw_char(message[i], (x*8) + (i*8), 0, &sysfont);
}
delay_ms(200);
gfx_mono_draw_string(" ", 0,0, &sysfont);
x++;
if(((x*8) + (i*8)) >= 128)
{
x = 0;
}*/
}
usart_putchar(USART_SERIAL_EXAMPLE, tx_buf[i]);
}

}
} 
else
{
usart_putchar(USART_SERIAL_EXAMPLE, letter);
for(i = 0; i < j; i++)
{
gfx_mono_draw_char(message[i], i*8, 0, &sysfont);
}
}
}
}
}

LED Piano: Using Shift Registers

Shift Registers 1 Shift Registers 2

(Note from instructor: the LED Piano project was a great example of using shift register chips to get more digital outputs!)

General Operation

The SN74HC595 is a serial to parallel 8-bit shift register. The function of this IC is to receive a serial bite of data and output the sequential data to 8 different pins. This allows for the user to control multiple outputs with only 3 pins: the serial input (SER), clock pin (SRCLK), and latch pin (RCLK). The clock pin enables action of the shift register depending on its state. Once the clock pin transitions to a low, we are able to input data. The serial input receives the bite of data from the Arduino and places it in the SN74HC595 storage register. Once all data is inputted into the shift register the latch pin is toggled to high, which transfers the serial data in the storage register to the eight output pins. The Output Enable pin (OE) needs to be set to a logic LOW for the data to be transferred to the outputs. Once the Serial Clear pin (SRCLR) receives a logic LOW, it erases the data from the outputs. So, in order for it to operate, we leave Serial Clear with a logic HIGH.

Cascading

The SN74HC595 can be daisy chained multiple times to produce infinite outputs, while still only using the three pins. In order to do this, we need to connect the clock pins together and the latch pins together. For the data to be transferred to each cascading pin, we need to connect the QH’ output pin to the serial input pin of the next IC. In doing this, it allows us to clock in eight additional outputs. Once we clock in the whole combination, we can do the same process as in the General Operation to latch the outputs to the corresponding IC pins.

 

LED Piano: Code

We used the function “tone” to output the sound on the speaker.

To control the LED outputs, we had to make function called “OutputRegister.” This function enables output registers to load bits that we want in register. Once loaded in, they latch to the outputs. The first number you input to the function accepts how many LEDs you want to turn on. The second number is how many spaces you want between the LEDs.

To have capacitive touch interact with the LEDs and music, we wrote a function called “PianoPlay.” This is basically a “free play function.” Once we put in our main loop it allows the user to play anything on the instrument freely. The function consists of a combination of “if” and “else” statements. A threshold is set for the capacitive touch pins and once a pin exceeds the threshold (you touch the wire with your finger), it produces a tone.

We combined “tone” “OutputRegister” and “PianoPlay” to complete the code for our project.

 

Two ways to play a pre-programmed song:

Button:

The button we have uses an interrupt. The button is hooked to the interrupt pin on the Arduino through a pull up resister. When the button is pressed, the pin receives a low signal which activates interrupt. This makes it go to the button function in the code, which then toggles the state variable to high. Once state is high, a pre-programmed song is played.

Pulse Width Modulation:

PWM is our interface with the A3BU. We’re using A3BU to transmit a PWM signal. If we type a certain word in TeraTerm, a PWM signal is inputted into one Arduino pin. Once the Arduino senses it, it will play a pre-programmed song.

Here is the code for the Arduino part of the project.


#include <SPI.h>
#include <CapacitiveSensor.h>
#include "pitches.h"

//Pin Color Code
//White = Clock and Latch
//Blue = Serial
//Yellow = Output
//Red = Power
//Black/Green = GND

//LED Setup
int serialIn = 8; //inputs serial to the shift register
int latchIn = 9; //latches the serial data in the register to the parallel outputs
int clockIn = 10; //allows the shift register to function. Action occurs when clock is low
boolean registers[32];

//BUTTON Setup
int buttonIn = 1; //Pin 3
volatile int state = LOW;

//PWM Setup
byte PWM_PIN = 5;
int pwm_value;

//MUSIC Setup
#define COMMON_PIN 2 // The common 'send' pin for all keys
#define BUZZER_PIN A4 // The output pin for the piezo buzzer
#define NUM_OF_SAMPLES 10 // Higher number whens more delay but more consistent readings
#define CAP_THRESHOLD 150 // Capactive reading that triggers a note (adjust to fit your needs)
#define NUM_OF_KEYS 8 // Number of keys that are on the keyboard
#define CS(Y) CapacitiveSensor(2, Y)
int notes[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; // C-Major scale
int total[NUM_OF_KEYS];
CapacitiveSensor keys[] = {CS(A0), CS(4), CS(A1), CS(6), CS(7), CS(11), CS(12), CS(13)};

/******SETUP BEGIN*******/
void setup() {
Serial.begin(9600);

//LED Matrix Setup
pinMode(serialIn, OUTPUT);
pinMode(latchIn, OUTPUT);
pinMode(clockIn, OUTPUT);

//Button Setup
attachInterrupt(buttonIn, buttonControl, LOW);

//PWM Setup
pinMode(PWM_PIN, INPUT);

//MUSIC Setup
for (int i = 0; i < 8; ++i) {
keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF);
}
pinMode(BUZZER_PIN, OUTPUT);
}
/*****SETUP END******/

/******FUNCTIONS BEGINS******/

/*****CLEAR FUNCTION******/
void clearAll() {
//SETUP
digitalWrite(latchIn, LOW);
digitalWrite(clockIn, HIGH);

//WRITE LOW's
digitalWrite(serialIn, LOW);
for (int i = 0; i < 32; i++) {
digitalWrite(clockIn, LOW);
digitalWrite(clockIn, HIGH);
}

//LATCH
digitalWrite(latchIn, HIGH);
}
/*****PIANO FUNCTION*****/
void pianoPlay() {
if (total[0] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[0]);
clearAll();
outputRegister(4, 0);
} else if (total[1] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[1]);
clearAll();
outputRegister(4, 4);
} else if (total[2] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[2]);
clearAll();
outputRegister(4, 8);
} else if (total[3] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[3]);
clearAll();
outputRegister(4, 12);
} else if (total[4] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[4]);
clearAll();
outputRegister(4, 16);
} else if (total[5] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[5]);
clearAll();
outputRegister(4, 20);
} else if (total[6] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[6]);
clearAll();
outputRegister(4, 24);
} else if (total[7] > CAP_THRESHOLD)
{
tone(BUZZER_PIN, notes[7]);
clearAll();
outputRegister(4, 28);
} else
{
noTone(BUZZER_PIN);
clearAll();
}
}
/*****LED OUTPUT FUNCTION*****/
void outputRegister(int leds, int spaces) {

//SETUP
digitalWrite(latchIn, LOW);
digitalWrite(clockIn, HIGH);

//WRITE HIGH's
digitalWrite(serialIn, HIGH);
for (int i = 0; i < leds; i++) {
digitalWrite(clockIn, LOW);
digitalWrite(clockIn, HIGH);
}

//WRITE LOW's
digitalWrite(serialIn, LOW);
for (int i = 0; i < spaces; i++) {
digitalWrite(clockIn, LOW);
digitalWrite(clockIn, HIGH);
}

//LATCH
digitalWrite(latchIn, HIGH);

}
/****BUTTON CONTROL FUNCTION****/
void buttonControl() {
for (int j = 0; j < 50; j++)
{
delayMicroseconds(1000);
}
state = !state;
Serial.println("Goodbye");
}

/*******FUNCTIONS END********/

/*********MAIN LOOP BEGIN**********/
void loop() {

//ENABLE TOUCH
total[0] = keys[0].capacitiveSensor(30);
total[1] = keys[1].capacitiveSensor(30);
total[2] = keys[2].capacitiveSensor(30);
total[3] = keys[3].capacitiveSensor(30);
total[4] = keys[4].capacitiveSensor(30);
total[5] = keys[5].capacitiveSensor(30);
total[6] = keys[6].capacitiveSensor(30);
total[7] = keys[7].capacitiveSensor(30);

//TOUCH SENSOR PRINT
Serial.println(total[0]);
Serial.println(total[1]);
Serial.println(total[2]);
Serial.println(total[3]);
Serial.println(total[4]);
Serial.println(total[5]);
Serial.println(total[6]);
Serial.println(total[7]);
//FREE PLAY
pianoPlay();

//BUTTON SONG
//if(state == HIGH)
//{
//}
//PWM SONG
// pwm_value = pulseIn(PWM_PIN, HIGH);
// Serial.println(pwm_value);
//if(pwm_value<400 && pwm_value>370)
//{
//}

}
/**********MAIN LOOP END**********/

LED Piano: Schematics

The capacitive touch part of our project required an Arduino, wires, a resistor, and buzzer. The rest of the capacitive touch portion was created with coding.

The aspect of achieving multiple outputs was a challenge. It was based on theory and research because couldn’t test it without parts. Using an Arduino, we have limited pins (12) but we needed 32 outputs for our LEDs.

We researched videos and articles to find the best way to overcome this issue and the best we found was to use shift registers. We started by testing one shift register: inputting a series of 8 bits and making sure we get 8 outputs. We then tested our daisy chain method: stacking the ICs. We daisy chained four chips together and tested that all 32 outputs worked.

Once the two parts were complete individually, we put them together on one breadboard. Now the capacitive touch triggers sound and a combo of LEDs.Schematic part 1 Schematic part 2 Schematic part 3

LED Piano – The Big Picture

The Big Picture - Photo 1The objective of our final project was to create a musical instrument using an LED matrix controlled by buttons and implement touch sensors that control certain frequencies on a speaker. Basically an LED piano. We used a speaker/buzzer to play the frequencies and we implemented capacitive touch for the “playing” of the instrument. The wire you choose to touch determines the note played. We housed the circuit in a cardboard box modeled as a piano to make it more appealing to the eye and to create an actual playable instrument.

The Big Picture - Photo 2

On the inside of the piano box, the touch sensor wires are connected to rectangular pieces of aluminum foil that, on the top of the box, represent the “keys” of the piano. When a piece of foil is touched, the respective note is played. This resulted in a playable piano!

We ended up having trouble using multiple buttons for the LEDs so after that issue, we decided to use only one button that will play a pre-programmed song. The LEDs are now placed in the box in groups of four above each key. We combined the code for the LEDs and the capacitive touch and set our instrument to light up the LEDs above the key touched.

The Big Picture - Photo 3

Please see our attached videos!