Show Posts
Pages: [1]
1  Community / Exhibition / Gallery / Arduino Playing Glockenspiel on: February 05, 2013, 10:56:38 pm
I have a Glockenspiel I have been driving with hardware and thought it would be fun to play with an Arduino.  Here's what I did.  MIDI data comes from Power Tracks Pro Audio (or a keyboard) into a opto circuit.  Output from the opto goes to a Software Serial port on the Arduino.  This allows using the serial port for the Serial Monitor to debug this mess.  I only look for MIDI commands to turn notes on or off and just ignore the rest.  If I get a MIDI on, I read the note and the velocity, and convert the velocity to either on or off.  There are only 24 notes, so I need three bytes of data sent to two 4x4 Logos Driver Shields.  The driver shields powers the door bell magnets that are mounted on top of the bells.  I don't use any librarys other than for the software serial port and the turnaround time to ring a bell is in the order of 2 milliseconds.  I'm not a programmer but rather in the spirit of all of this, stole most of the code in the sketch below.  A video off the glock is at this link

  #include <SoftwareSerial.h>
  SoftwareSerial mySerial(5,6); // RX, TX
  int value;
  byte incomingByte;
  byte note;
  byte notes[24];
  byte notetoplaynow;
  byte velocity; 
  byte highByte;
  byte lowByte;
  byte lastByte;
  unsigned long lasttimenotesent;
  byte channel = 3;     //set the MIDI channel here
  void setup() {
    pinMode(6,OUTPUT);  //MIDI out not used
    pinMode(7,OUTPUT);  //Register Latch
    pinMode(8,OUTPUT);  //Register Latch
    pinMode(9,OUTPUT);  //Middle C light
    pinMode(11,OUTPUT); //Register Input
    pinMode(13,OUTPUT);} //Clock Pin for 4x4

   void loop (){  //This only looks for on or off messages and the note and velocity  MIDI 0 files do not work
      incomingByte =;
      //If the incomming byte just read was a command byte to turn a note on or off, read the next two bytes.  Ignore everything else.
      //1001nnnn (144=channel) is a turn on command byte.  1000nnnn (128) is a note off command where nnnn is the channel.
      if (incomingByte== (127+16+channel) || incomingByte== (127+channel)){
        note =;
        velocity =;
        if (note>=57 && note<=80)playNote(note, velocity); }  // Only play with useful notes
      else if((millis()-lasttimenotesent)>1000)  SendNotes(0, 0, 0); }//Don't leave notes stuck on 
   void playNote(byte note, byte velocity) {
    value=LOW;   //Set the note to either on or off regardless of velocity
    if (velocity >10) value=HIGH; 
    notetoplaynow=note-57;  //convert notetoplaynow to the right output register
    if (value==HIGH) notes[notetoplaynow]=1;  //notes[turn notetoplaynow] on
    else if (value==LOW) notes[notetoplaynow]=0; //turn notes[notetoplaynow] off
    byte lowByte = 0;
    byte highByte = 0;
    for ( byte i=0; i < 8; ++i )
     lowByte |= (notes[i] << i );  //shift each note one register and keep oring them
     highByte |= (notes[8+i] << i );
     lastByte |= (notes[16+i] << i );
   SendNotes(highByte, lowByte, lastByte);   //go play the note
  void SendNotes(byte highByte, byte lowByte, byte lastByte){
   digitalWrite(7, LOW); // Prepares latch
   digitalWrite(8, HIGH); // Deactivates master reset
   shiftOut(11, 13, MSBFIRST, 0);
   shiftOut(11, 13, MSBFIRST, lastByte);   
   shiftOut(11, 13, MSBFIRST, highByte); // shift data for OUT8-OUT15
   shiftOut(11, 13, MSBFIRST, lowByte);  // shift data for OUT0-OUT7
   digitalWrite(7, HIGH);}
2  Using Arduino / Sensors / Re: Basic ADC/Analog read question on: November 02, 2012, 09:09:17 pm
It looks like this Vcc calculation is gonna work just fine.   It doesn't mean much until Vcc goes below 5 volts, but then I use it to correct the analog readings for my TMP36 and other analog sensors.  I measured the temperature of a glass of ice water and it measured a pretty constant 32 degrees as the battery went dead.   I added a routine that posts like a low battery on the LCD when Vcc drops below 5 Volts and stops the routine when Vcc gets below 4 volts.  Thanks to Lefty and Coding Badly for the routine and the others for your comments and help. My first project is to log temperatures along the fuel system of an antique car to investigate vapor locking.  Bill
3  Using Arduino / Sensors / Re: Basic ADC/Analog read question on: October 30, 2012, 10:09:02 pm
Thanks for the help.  I measured the Internal Reference Voltage and made the adjustment.  I've got it set up to measure Vcc with the lefty routine and Vin with a voltage divider and at the same time use the TMP36 to make a temperature measurement.  As soon as Vcc starts to drop then the temperature measurement will go out of control.   As you pointed out, the trick is to find the voltage where the errors start.  Unfortunately, my battery is not dead yet and I need to take a nap.  I'll leave it running, writing to my SD card.
Why does Vin, when connected to the USB cable, measure to be lower than Vcc?
Please send me your thoughts on correcting the measurements as Vcc drops
Thanks again for your help.
4  Using Arduino / Sensors / Re: Basic ADC/Analog read question on: October 29, 2012, 11:18:27 pm

I've attached a cut and paste from the serial monitor for the case of powering from the USB, but for the battery power I have no serial monitor.  You have to take my word for it.smiley  I am measuring between Vin and Ground on the Uno and that seems to match the battery voltage.  I guess my confusion was the reference to Vcc and actual battery voltage.  I'm even more confused about AVCC.  It may be that I can check the Vcc that is calculated and if it ever goes below 472, then toot a horn warning of danger ahead.  What is the difference between AVCC and Vcc on the UNO?

Following is a screen shot of my serial monitor for the USB case.
volts X 100

Initializing LCD card...Battery Vcc volts =  474
Analog pin 0 voltage = 105

Battery Vcc volts =  474
Analog pin 0 voltage = 115

Battery Vcc volts =  474
Analog pin 0 voltage = 116
5  Using Arduino / Sensors / Re: Basic ADC/Analog read question on: October 29, 2012, 10:37:05 pm

I think this routine is exactly what I want to check the battery.  I've noticed that when the battery goes dead, temperature results I make using a TMP36 are all wrong.  If I could get this working, I could set an alarm if the battery is too low.

I'm an old person but a brand new user, new coder, new everything, so I'm pretty limited.  I copied the code from lefty above and add some stuff to output onto an LCD so I could see Vcc when powered by a nine volt battery.   I'm using an Uno R3 with nothing connected except the LCD.   While the battery was connected, using a volt meter, I measured the voltage from Vin to Ground.   I got the following results that seem to indicate something is not working as expected.

Power Source  Vcc   Vanalog Pin 0   Vin to Ground
USB               472       117             4.48
dead 9v bat    460       115             5.6
new 9v bat     474       117             7.98

My code is below.  What to you suppose is wrong?

// Function created to obtain chip's actual Vcc voltage value, using internal bandgap reference
// This demonstrates ability to read processors Vcc voltage and the ability to maintain A/D calibration with changing Vcc
// Now works for 168/328 and mega boards.
// Thanks to "Coding Badly" for direct register control for A/D mux
// 1/9/10 "retrolefty"  from,86516.0.html

  #include <LiquidCrystal.h>  // include the LCD library
  #include <SD.h>             // include the SD library
  LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int battVolts;   // made global for wider avaliblity throughout a sketch if needed, example a low voltage alarm, etc

void setup(void)
     lcd.begin(16, 2);  // set up the LCD's number of columns and rows:   
     lcd.print("Vcc VPin0");  // Print a header on the LCD. 
     Serial.print("volts X 100");
     Serial.println( "\r\n\r\n" );
     Serial.print("Initializing LCD card...");  //write to the serial monitor
void loop(void)
     battVolts=getBandgap();  //Determins what actual Vcc is, (X 100), based on known bandgap voltage
     Serial.print("Battery Vcc volts =  ");
     Serial.print("Analog pin 0 voltage = ");
     Serial.println(map(analogRead(0), 0, 1023, 0, battVolts));
   //display the result on the LCD
      lcd.setCursor(0, 1);           
      lcd.print(map(analogRead(0), 0, 1023, 0, battVolts));

int getBandgap(void) // Returns actual value of Vcc (x 100)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
     // For mega boards
     const long InternalReferenceVoltage = 1115L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc reference
        // MUX4 MUX3 MUX2 MUX1 MUX0  --> 11110 1.1V (VBG)         -Selects channel 30, bandgap voltage, to measure
     ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
     // For 168/328 boards
     const long InternalReferenceVoltage = 1056L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
        // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
     ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
     delay(50);  // Let mux settle a little to get a more stable A/D conversion
        // Start a conversion 
     ADCSRA |= _BV( ADSC );
        // Wait for it to complete
     while( ( (ADCSRA & (1<<ADSC)) != 0 ) );
        // Scale the value
     int results = (((InternalReferenceVoltage * 1023L) / ADC) + 5L) / 10L; // calculates for straight line value
     return results;
Pages: [1]