JeremyBlum.com

v3.0

Tutorial 14 for Arduino: Holiday Lights and Sounds

| 30 Comments

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:

You can download the files associated with this episode here: Arduino Tutorial 14 Files

Source materials for all my arduino tutorials can be found in my github repository.

GNU GPL License Distributed under the GNU General Public (Open-Source) License.
Please Attribute and Share-Alike.

 

30 Comments

  1. Jeremy,
    Could you explain more about the [LED Freq Control.pd] included in the zip file. Is that a Processing file? Thanks.

  2. 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.

  3. 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”.

  4. 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.

  5. That was very helpfull. It works now. Thank you for letting us learn. Happy new you.

  6. Have a happy, safe, and prosperous New Year.

  7. 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!

  8. No problem…Tnx!

  9. Jeremy, could you post some video controlling arduino throght the internet? I have an Ethernet Shield but i’m facing problems with this.

  10. 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.

    • 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!

  11. 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???

  12. 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

  13. 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);

    • 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.

  14. 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

  15. 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();
    }

    /*****************************************************************************/

  16. 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.

  17. 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

Leave a Reply

Required fields are marked *.

*