This is one that I’ve been excited about for a long time. When element14 asked me to put together a holiday special, I knew just what to do. This episode is the most technically complex so far; it covers non-inverting op-amp circuits, low-pass envelope detection filters, buffers, power management, and some clever programming. Because of the complexity of the project, fellow Cornell Engineer, Brian Schiffer (whom you might remember from this article where we were both featured) co-hosted this tutorial with me. The end result is pretty spectacular – a chain of 50 LEDs reacting dynamically to music. The twist, however, is that the chain propogates color information from the center, resulting in a temporal visualization of the music. The schematics, programs, and parts list are available for download below:
No, that’s a puredata file. I show it in the video. It’s just a simple script for generating arbitrary frequency sine waves from your sound card. Visit http://www.puredata.info to download puredata.
Hi, all of this you are doing is great, thanks for allow all of us learn from your experience, I have a question, are you going to do any tutorial about gyroscopes or acellerometers some day?, thanks
Yes, eventually – I have a very long list of tutorials that I’d like to do. But, most gyros and accelerometers are either analog outputs, I2C, or SPI, all of which I’ve done tutorials on. So that should be enough to get you started.
That was a great electronic project. I was able to open the code but i could not compile and upload. It gave me error. Here is the error “Ws2801 does not a name type”.
yes, i downloaded the zip drive from https://github.com/adafruit/WS2801-Library. I put it on the desktop. What do you mean “add the WS2801 Library to your arduino library folder”. You mean put it inside the arduino zip drive 1.0 that i downloaded from arduino.cc
I have already tried. The code still give me the same error. Tell me what did i miss? Thank you.
Hello I’m Mark from Philippines. I watched your videos regarding arduino. It’s actually interesting. I also watched some arduino+android projects in youtube. I am graduating (ECE) student….got problem with our undergrad thesis. We are planning to make android plus arduino project…don’t know how to start…
Can you help me with this?
I am a huge fan and this tutorial got me super stoked. I did hit a snag though. I built out the breadboard from your awesome diagram. I think I got it right but the two 5mm LEDs light up as soon as I supply power to the LM324. If I unplug the audio and the wires from the arduino (except for power) they still light up by default. Even without audio and even if I totally remove the potentiometers entirely the bulbs stay on. If I adjust the potentiometers the lights barley respond by going just a bit dull but they stay on. I know how hard it is to troubleshoot something you can’t see but every clue helps. So the question is: why are my LEDs on by default? Any clues? Thanks again for all your hard work and for the record this tutorial caused me to make my first order from element 14 and my LEDs are on the way from Ladyada.
Got it working. Turns out that it the two LEDs will default to on unless there is an audio signal present. The audio jack in the parts list did not have a firm connection to the breadboard. Once I put together a better connection for the audio jack an LED started pulsating on one channel. Still working on the second channel.
Great news! Be sure to share a video when it’s complete, and let @element14 and @adafruit know on twitter that you’re using parts from their sites to make it!
I have been following your blog for some time now. And I love every on I have seen. I have been out of the design side of engineering for quite some time now and never came close to mastering programming (the closest I ever came was on a VIC 20) if that gives you some idea of how far I have to go. which brings be to my question…. controlling multiple servos/ motors seems to have me stumped… how do you assign and control two or more???
Its possible, but since a system timer is taken over to control the duty cycle of each servo, you need to detach() one servo before you can control another.
Hi Jeremy, I know that this question does not apply to video lesson.
Could you help me to upload AFMotor libriuary on my Arduino 1.0?
Thanks in advance!
I’m a fan of you
Hello Jeremy
I have a question for you
Whats whith this program?
sketch_jan24a.cpp: In function ‘float ping()’:
sketch_jan24a:17: error: ‘pingPin’ was not declared in this scope
sketch_jan24a:25: error: ‘microsecondsToInches’ was not declared in this scope
sketch_jan24a.cpp: In function ‘void forward()’:
sketch_jan24a:34: error: expected `;’ before ‘motor4′
sketch_jan24a.cpp: At global scope:
sketch_jan24a:45: error: expected constructor, destructor, or type conversion before ‘direction’
Read the errors – they tell you exactly what is wrong. You never set PingPin to a value before trying to set it as an output pin. The same is true for microseconds to Inches. You need to declare it be fore you use it. You are missing a semicolon in your forward() function.
hey Jeremy sweet videos i knew nothing about the arduino but have always wanted to build a autonomous/RC tank out of my old Heng Long tank and it would not have been posible with out you help so thank and also are there going to be any new arduino videos coming soon thanks again
Dear Jeremy, I’m a novice programmer when it comes to Arduino. I came up with the idea to make a clock based on something I’d seen before, a 60 RGB led clock, powered by an Uno r3, a LDR, a DS1307 (to be swapped by a Chronodot) and 60 LPD6803 led’s. It’s light intensity depends on the surrounding light. The clock works but not flawlessly… Green represents hours, red minutes en blue seconds. The seconds use 3 LED’s (first fading in, last fading out) to make the blue light gently move.
The clock uses the 1KHz SQW as an interrupt.
Is it the way I use the interrupt? Or is it simply to much for the Arduino? Should I skip the brightness control? Is the code written efficiently?
// LPD6802 pins
int dataPin = 11; // ‘green’ wire
int clockPin = 12; // ‘blue’ wire
// Don’t forget to connect ‘yellow’ to ground and ‘red’ to +5V
// LDR pin
int LDRPin = A2;
// Timer 1 is also used by the strip to send pixel clocks
#include
// Set the first variable to the NUMBER of pixels. 60 = 60 pixels in a row
LPD6803 strip = LPD6803(60, dataPin, clockPin);
//wire and rtc
#include
#include “RTClib.h”
// RTC_Millis is for a soft rtc
//RTC_Millis RTC;
RTC_DS1307 RTC;
// Define second, minute, hour
int s;
int m;
int h;
// Brightness fade up (1 or 2) depens on LDR reading
int z;
// Set brightness min 6, max 31.
int MinBright = 6;
int MaxBright = 31;
int brightness;
// LDR
int LDRValue;
void setup() {
Serial.begin(19200);
//start wire and rtc
Wire.begin();
RTC.begin();
{
//Serial.println(“RTC is NOT running!”);
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
// set 1hz sqw on DS1307 pin 7, we will using this for a interrupt on arduino pin 2
Wire.beginTransmission(0×68); // write the control register
Wire.send(0×07); // register address 07H)
Wire.send(0×90); // 0×90=1Hz, 0×91=4kHz, 0×92=8kHz, 0×93=32kHz
Wire.endTransmission();
// The Arduino needs to clock out the data to the pixels
// this happens in interrupt timer 1, we can change how often
// to call the interrupt. setting CPUmax to 100 will take nearly all all the
// time to do the pixel updates and a nicer/faster display,
// especially with strands of over 100 dots.
// (Note that the max is ‘pessimistic’, its probably 10% or 20% less in reality)
strip.setCPUmax(90); // up this if the strand flickers or is slow
// Start up the LED counter
strip.begin();
// Update the strip, to start they are all ‘off’
strip.show();
//Attach pin 7 from DS1307 to Arduino pin 2 and call function clock
attachInterrupt(0, clock, FALLING);
}
// Empty loop, all is done by the 1hz interrupt on pin 2
void loop () { }
void clock() {
interrupts(); //start all interrupts again.
//attach Interrupt stops the strip, so start it again
strip.begin();
//Get current time
DateTime now = RTC.now();
// mapping hour 24 => 12 => 60 (hour hand)
m = now.minute(), DEC;
s = now.second(), DEC;
h = now.hour(), DEC;
if (h >= 12) { h = h – 12; }
else if (h = 12) { h = 0; }
h = map(h, 0, 12, 0, 60);
if ( m <= 6 ) { h == h; }
else if ( m <= 18 ) { h = h + 1; }
else if ( m <= 30 ) { h = h + 2; }
else if ( m <= 42 ) { h = h + 3; }
else if ( m <= 54 ) { h = h + 4; }
// Get LDR vaulue and set brightness
LDRValue = analogRead(LDRPin);
brightness = map(LDRValue, 0, 1023, MinBright, MaxBright);
// set increase step
if ( brightness 0
if (s == 0) { strip.setPixelColor((58), 0, 0, 0); }
if (s == 1) { strip.setPixelColor((59), 0, 0, 0); }
if (m == 0) { strip.setPixelColor((59), 0, 0, 0); }
//start fade up/down
for (int y = 1; y < brightness; y = y + z) {
strip.setPixelColor((s – 1 ), (brightness – y), 0, 0);
if (s == 0) { strip.setPixelColor(59, (brightness – y), 0, 0); }
strip.setPixelColor(s, brightness, 0, 0);
strip.setPixelColor((s + 1 ), y, 0, 0);
if (s == 59) { strip.setPixelColor(0, y, 0, 0); }
// second equals minute
if ((s + 1) == m) { strip.setPixelColor(s + 1, y, brightness, 0); }
if (s == m) { strip.setPixelColor(s, brightness, brightness, 0); }
if ((s – 1) == m) { strip.setPixelColor(s – 1, (brightness – y), brightness, 0); }
// second equals hour
if ((s + 1) == h) { strip.setPixelColor(s + 1, y, 0, brightness); }
if (s == h) { strip.setPixelColor(s, brightness, 0, brightness); }
if ((s – 1) == h) { strip.setPixelColor(s – 1, (brightness – y), 0, brightness); }
// update strip
strip.show();
delay(105 – (2 * y));
}
// Debug
//Serial.print(now.year(), DEC);
//Serial.print('/');
//Serial.print(now.month(), DEC);
//Serial.print('/');
//Serial.print(now.day(), DEC);
//Serial.print(' ');
//Serial.print(now.hour(), DEC);
//Serial.print(':');
//Serial.print(now.minute(), DEC);
//Serial.print(':');
//Serial.print(now.second(), DEC);
//Serial.println();
Serial.print("raw LDR reading = ");
Serial.println(LDRValue); // the raw analog reading
Serial.print("mapped brightness level = ");
Serial.println(LDRPin); // the analog level
Serial.print("brightness level = ");
Serial.println(brightness); // the calculated level
Serial.println();
}
Hi Jeremy, have you ever minded to develop arduino on Qt creator? It would be awesome work to post a tutorial about that which includes building pro file, setting up libraries etc. even if it does not use qt library.
December 27, 2011 at 2:35 pm
Jeremy,
Could you explain more about the [LED Freq Control.pd] included in the zip file. Is that a Processing file? Thanks.
December 27, 2011 at 2:36 pm
No, that’s a puredata file. I show it in the video. It’s just a simple script for generating arbitrary frequency sine waves from your sound card. Visit http://www.puredata.info to download puredata.
December 27, 2011 at 5:59 pm
Hi, all of this you are doing is great, thanks for allow all of us learn from your experience, I have a question, are you going to do any tutorial about gyroscopes or acellerometers some day?, thanks
December 28, 2011 at 12:34 am
Yes, eventually – I have a very long list of tutorials that I’d like to do. But, most gyros and accelerometers are either analog outputs, I2C, or SPI, all of which I’ve done tutorials on. So that should be enough to get you started.
December 29, 2011 at 9:43 pm
Hello jeremy blum
That was a great electronic project. I was able to open the code but i could not compile and upload. It gave me error. Here is the error “Ws2801 does not a name type”.
December 30, 2011 at 10:59 am
Did you add the WS2801 Library to your arduino library folder?
December 30, 2011 at 12:31 pm
yes, i downloaded the zip drive from https://github.com/adafruit/WS2801-Library. I put it on the desktop. What do you mean “add the WS2801 Library to your arduino library folder”. You mean put it inside the arduino zip drive 1.0 that i downloaded from arduino.cc
I have already tried. The code still give me the same error. Tell me what did i miss? Thank you.
December 30, 2011 at 12:35 pm
You need to unzip it, and put the folder in the unzipped arduino application library folder. Follow this guide: http://www.ladyada.net/library/arduino/libraries.html
December 31, 2011 at 1:12 pm
That was very helpfull. It works now. Thank you for letting us learn. Happy new you.
December 31, 2011 at 1:16 pm
Have a happy, safe, and prosperous New Year.
January 3, 2012 at 8:41 pm
Hello I’m Mark from Philippines. I watched your videos regarding arduino. It’s actually interesting. I also watched some arduino+android projects in youtube. I am graduating (ECE) student….got problem with our undergrad thesis. We are planning to make android plus arduino project…don’t know how to start…
Can you help me with this?
Your HELP is much appreciated!
Tnx and GOD Bless!
January 3, 2012 at 8:43 pm
I don’t yet have an experience interfacing the arduino with android devices.
January 4, 2012 at 1:10 am
No problem…Tnx!
January 5, 2012 at 7:58 am
Jeremy, could you post some video controlling arduino throght the internet? I have an Ethernet Shield but i’m facing problems with this.
January 5, 2012 at 8:29 pm
I’m planning to. Not sure when Ill get to it, though.
January 5, 2012 at 8:37 pm
I hope it will be soon!
January 7, 2012 at 5:22 am
Hi
I am a huge fan and this tutorial got me super stoked. I did hit a snag though. I built out the breadboard from your awesome diagram. I think I got it right but the two 5mm LEDs light up as soon as I supply power to the LM324. If I unplug the audio and the wires from the arduino (except for power) they still light up by default. Even without audio and even if I totally remove the potentiometers entirely the bulbs stay on. If I adjust the potentiometers the lights barley respond by going just a bit dull but they stay on. I know how hard it is to troubleshoot something you can’t see but every clue helps. So the question is: why are my LEDs on by default? Any clues? Thanks again for all your hard work and for the record this tutorial caused me to make my first order from element 14 and my LEDs are on the way from Ladyada.
January 7, 2012 at 9:04 pm
Got it working. Turns out that it the two LEDs will default to on unless there is an audio signal present. The audio jack in the parts list did not have a firm connection to the breadboard. Once I put together a better connection for the audio jack an LED started pulsating on one channel. Still working on the second channel.
Thanks again for the great tutorial!
January 9, 2012 at 11:22 pm
Great news! Be sure to share a video when it’s complete, and let @element14 and @adafruit know on twitter that you’re using parts from their sites to make it!
January 7, 2012 at 6:00 pm
I have been following your blog for some time now. And I love every on I have seen. I have been out of the design side of engineering for quite some time now and never came close to mastering programming (the closest I ever came was on a VIC 20) if that gives you some idea of how far I have to go. which brings be to my question…. controlling multiple servos/ motors seems to have me stumped… how do you assign and control two or more???
January 9, 2012 at 11:29 pm
Its possible, but since a system timer is taken over to control the duty cycle of each servo, you need to detach() one servo before you can control another.
January 19, 2012 at 2:57 pm
Hi Jeremy, I know that this question does not apply to video lesson.
Could you help me to upload AFMotor libriuary on my Arduino 1.0?
Thanks in advance!
I’m a fan of you
January 21, 2012 at 10:44 pm
Follow this guide: http://www.ladyada.net/library/arduino/libraries.html
January 24, 2012 at 9:58 am
Hello Jeremy
I have a question for you
Whats whith this program?
sketch_jan24a.cpp: In function ‘float ping()’:
sketch_jan24a:17: error: ‘pingPin’ was not declared in this scope
sketch_jan24a:25: error: ‘microsecondsToInches’ was not declared in this scope
sketch_jan24a.cpp: In function ‘void forward()’:
sketch_jan24a:34: error: expected `;’ before ‘motor4′
sketch_jan24a.cpp: At global scope:
sketch_jan24a:45: error: expected constructor, destructor, or type conversion before ‘direction’
#include
AF_DCMotor motor1(1, MOTOR12_8KHZ);
AF_DCMotor motor2(2, MOTOR12_8KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
void setup() {
Serial.begin(9600);
motor1.setSpeed(200);
motor2.setSpeed(200);
motor3.setSpeed(200);
motor4.setSpeed(200);
}
float ping()
{ // This is the code that runs the PING)) Sensor
long duration, inches;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
inches = microsecondsToInches(duration);
return inches;
}
void forward()
{
motor1.run(FORWARD);
motor2.run(FORWARD);
motor3.run(FORWARD)
motor4.run(FORWARD);
}
void backward()
{
motor1.run(BACKWARD);
motor2.run(BACKWARD);
motor3.run(BACKWARD);
motor4.run(BACKWARD);
}
voidhaltMotors()
direction.)
{
motor1.run(RELEASE);
motor2.run(RELEASE);
motor3.run(RELEASE);
motor4.run(RELEASE);
February 13, 2012 at 10:43 am
Read the errors – they tell you exactly what is wrong. You never set PingPin to a value before trying to set it as an output pin. The same is true for microseconds to Inches. You need to declare it be fore you use it. You are missing a semicolon in your forward() function.
January 24, 2012 at 8:48 pm
hey Jeremy sweet videos i knew nothing about the arduino but have always wanted to build a autonomous/RC tank out of my old Heng Long tank and it would not have been posible with out you help so thank and also are there going to be any new arduino videos coming soon thanks again
ROBOT Dave
February 13, 2012 at 10:44 am
I’m always working on new videos – I’m busy with a lot of other things too.
January 28, 2012 at 8:08 am
Dear Jeremy, I’m a novice programmer when it comes to Arduino. I came up with the idea to make a clock based on something I’d seen before, a 60 RGB led clock, powered by an Uno r3, a LDR, a DS1307 (to be swapped by a Chronodot) and 60 LPD6803 led’s. It’s light intensity depends on the surrounding light. The clock works but not flawlessly… Green represents hours, red minutes en blue seconds. The seconds use 3 LED’s (first fading in, last fading out) to make the blue light gently move.
The clock uses the 1KHz SQW as an interrupt.
Is it the way I use the interrupt? Or is it simply to much for the Arduino? Should I skip the brightness control? Is the code written efficiently?
Here’s a video. The clock seems to work okay, but it’s not! It chrashes randomly…
http://www.facebook.com/photo.php?v=2972701567528&set=vb.1561464916&type=2&theater
Here’s the code. Can you have a look and help me on this one…
/*****************************************************************************/
// LPD6803 lib from ladyada
#include “LPD6803.h”
// LPD6802 pins
int dataPin = 11; // ‘green’ wire
int clockPin = 12; // ‘blue’ wire
// Don’t forget to connect ‘yellow’ to ground and ‘red’ to +5V
// LDR pin
int LDRPin = A2;
// Timer 1 is also used by the strip to send pixel clocks
#include
// Set the first variable to the NUMBER of pixels. 60 = 60 pixels in a row
LPD6803 strip = LPD6803(60, dataPin, clockPin);
//wire and rtc
#include
#include “RTClib.h”
// RTC_Millis is for a soft rtc
//RTC_Millis RTC;
RTC_DS1307 RTC;
// Define second, minute, hour
int s;
int m;
int h;
// Brightness fade up (1 or 2) depens on LDR reading
int z;
// Set brightness min 6, max 31.
int MinBright = 6;
int MaxBright = 31;
int brightness;
// LDR
int LDRValue;
void setup() {
Serial.begin(19200);
//start wire and rtc
Wire.begin();
RTC.begin();
{
//Serial.println(“RTC is NOT running!”);
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
// set 1hz sqw on DS1307 pin 7, we will using this for a interrupt on arduino pin 2
Wire.beginTransmission(0×68); // write the control register
Wire.send(0×07); // register address 07H)
Wire.send(0×90); // 0×90=1Hz, 0×91=4kHz, 0×92=8kHz, 0×93=32kHz
Wire.endTransmission();
// The Arduino needs to clock out the data to the pixels
// this happens in interrupt timer 1, we can change how often
// to call the interrupt. setting CPUmax to 100 will take nearly all all the
// time to do the pixel updates and a nicer/faster display,
// especially with strands of over 100 dots.
// (Note that the max is ‘pessimistic’, its probably 10% or 20% less in reality)
strip.setCPUmax(90); // up this if the strand flickers or is slow
// Start up the LED counter
strip.begin();
// Update the strip, to start they are all ‘off’
strip.show();
//Attach pin 7 from DS1307 to Arduino pin 2 and call function clock
attachInterrupt(0, clock, FALLING);
}
// Empty loop, all is done by the 1hz interrupt on pin 2
void loop () { }
void clock() {
interrupts(); //start all interrupts again.
//attach Interrupt stops the strip, so start it again
strip.begin();
//Get current time
DateTime now = RTC.now();
// mapping hour 24 => 12 => 60 (hour hand)
m = now.minute(), DEC;
s = now.second(), DEC;
h = now.hour(), DEC;
if (h >= 12) { h = h – 12; }
else if (h = 12) { h = 0; }
h = map(h, 0, 12, 0, 60);
if ( m <= 6 ) { h == h; }
else if ( m <= 18 ) { h = h + 1; }
else if ( m <= 30 ) { h = h + 2; }
else if ( m <= 42 ) { h = h + 3; }
else if ( m <= 54 ) { h = h + 4; }
// Get LDR vaulue and set brightness
LDRValue = analogRead(LDRPin);
brightness = map(LDRValue, 0, 1023, MinBright, MaxBright);
// set increase step
if ( brightness 0
if (s == 0) { strip.setPixelColor((58), 0, 0, 0); }
if (s == 1) { strip.setPixelColor((59), 0, 0, 0); }
if (m == 0) { strip.setPixelColor((59), 0, 0, 0); }
//start fade up/down
for (int y = 1; y < brightness; y = y + z) {
strip.setPixelColor((s – 1 ), (brightness – y), 0, 0);
if (s == 0) { strip.setPixelColor(59, (brightness – y), 0, 0); }
strip.setPixelColor(s, brightness, 0, 0);
strip.setPixelColor((s + 1 ), y, 0, 0);
if (s == 59) { strip.setPixelColor(0, y, 0, 0); }
strip.setPixelColor(m, 0, brightness, 0);
strip.setPixelColor(h, 0, 0, brightness);
// second equals minute
if ((s + 1) == m) { strip.setPixelColor(s + 1, y, brightness, 0); }
if (s == m) { strip.setPixelColor(s, brightness, brightness, 0); }
if ((s – 1) == m) { strip.setPixelColor(s – 1, (brightness – y), brightness, 0); }
// second equals hour
if ((s + 1) == h) { strip.setPixelColor(s + 1, y, 0, brightness); }
if (s == h) { strip.setPixelColor(s, brightness, 0, brightness); }
if ((s – 1) == h) { strip.setPixelColor(s – 1, (brightness – y), 0, brightness); }
// update strip
strip.show();
delay(105 – (2 * y));
}
// Debug
//Serial.print(now.year(), DEC);
//Serial.print('/');
//Serial.print(now.month(), DEC);
//Serial.print('/');
//Serial.print(now.day(), DEC);
//Serial.print(' ');
//Serial.print(now.hour(), DEC);
//Serial.print(':');
//Serial.print(now.minute(), DEC);
//Serial.print(':');
//Serial.print(now.second(), DEC);
//Serial.println();
Serial.print("raw LDR reading = ");
Serial.println(LDRValue); // the raw analog reading
Serial.print("mapped brightness level = ");
Serial.println(LDRPin); // the analog level
Serial.print("brightness level = ");
Serial.println(brightness); // the calculated level
Serial.println();
}
/*****************************************************************************/
February 2, 2012 at 11:35 am
Hi Jeremy, have you ever minded to develop arduino on Qt creator? It would be awesome work to post a tutorial about that which includes building pro file, setting up libraries etc. even if it does not use qt library.
February 16, 2012 at 2:42 am
I used WS2801 library (https://github.com/adafruit/WS2801-Library) in the following program, however I still don’t know how to change the last 6 LED into red before turning them off. Even I don’t know whether it is possible or not. Can anyone let me know? I used the WS2801strip from http://www.bestlightingbuy.com/ws2801-addressable-rgb-led-strip.html