Project in progress
Boom Box

Boom Box © GPL3+

Building a Son, first Arduino project and reconnecting with a joy lost to time.

  • 456 views
  • 0 comments
  • 2 respects

Components and supplies

Necessary tools and machines

Mill
09507 01
Soldering iron (generic)

Apps and online services

Proteus 8 Pro
Used to do the circuit diagrams and lay the circuit board
Ide web
Arduino IDE

About this project

Boom Box – Building a Son (our first project together)

It all started back in 2015 when my son who is autistic took systems engineering in his final years at high school. He came home with an assignment to build some sort of circuit board and amplifier as a major project. I had of course been helping with homework and while reading his text book, I was rather taken by the 'Arduino' section of the otherwise boring tome. Having seen some pictures of last years projects my only though was, “we must be able to do better than that”.

So we started out to build our first project together, for him it would be his first microprocessor controlled item, for me it would be a discovery of a joy lost to my younger years which can now be shared.

Orion wanted the big loud boom box like “tradies” use at work. I was sure he hadn’t thought this through as he hated loud noises. He did however love coloured lights. The discovery of RGB LED strips was rapidly followed by neo pixel strips which mesmerized the lad. Reading the spec sheet I wondered, how on earth we were going to send data to these little blighter's at near video speed. Then a thought struck me, just as fish needs a bicycle, an amplifier needs a microprocessor's of course! Well the YouTube video from Pololu and a test run with the Christmas lights demo code on an Arduino Uno meant the neo pixels where a done deal.

Now how was I going to make all this fore fill his course outline? While aimlessly browsing the seemingly endless number of “shields” for the Arduino on ebay it struck me, what about a shield that allows the imput from the boom box amp to go into the A/D converter on the Arduino. This would enabled us do some pretty patterns based on the input numbers. Maybe even an FFT or two to break the data into spectral components, more coloured patterns. But what were we going to connect all this too? Orion suggested blue tooth from this cellphone, being wireless sounded good to me avoiding cables and plugs, which would keep the project neat.

So next came the box, Orion decided he like the idea of it being round. Round things are difficult! Jim suggested a pipe as an enclosure and I pointed out car speakers might fit at each end if you looked hard enough to find the right size. So before you can say “ebay and credit card” he had found a bluetooth power amp and some car speakers that would fit inside his class 16 ABS pipe which Jim found in the back of his truck. But how to fit the LED's, well Jim showed us his “liquid glass” epoxy and I suggested we cut slots into the pipe and embed the led strips. Good thing Orion also took engineering and had learned to drive a mill. He worked out a nice pattern and milled out six slots to take the 120 LED's in lots of 20. Took him 3 days to work out how to hold the pipe down on the mill and 3 hours to cut the slots.

With slots cut into the case it was onto building the electronics “carrier”out of MDF, this would also hold the batteries. Being a fit strong lad we filled all the unused internal space with 4 x seven amp hour 12 Volt UPS batteries. This in turn meant we needed a volt meter to show the charge state of the unit and a socket to charge the batteries. EBay to the rescue again with the purchase of and automotive outlet and voltmeter combo. I also picked up a battery charger to which we fitted an automotive cigarette lighter plug should we ever need to charge the beast up.An interesting side effect was that the unit also became a battery bank that could change the cell phone which after all was the source of the music via Bluetooth.

So back to ticking boxes on school projects, a circuit had to be designed and built. With some gentle prodding and examples from old 80's electronics magazines, Orion cobbled together a circuit schematic in Proteus 8.The circuit comprised of an op-amp package configured as a variable gain instrumentation amp with low pass filter. This CAD package also allowed him to create a circuit board directly from the design. So after several attempts and some father to son coaching on PCB layout we arrived at our first double sided circuit board “shield” for the Arduino. Proteus was great as it didn't allow him to make a mistake translating the schematic to the circuit board and it managed clearances between features on the board. Now you will have to forgive us for not getting the shield circuit right first time, we had only written our first programs literally days before. I was not sure what pins where normally assigned to what tasks and I was yet to read the Atmel manuals. Orion was still grappling with C++ but it looked close enough to J++ (the stuff of “minecraft”) so all was going relatively well.

I then had a horrible thought that I simply wasn't up to making double sized circuit boards like I had been in my youth, what to do? Well, Orion came home from school the next day with a big grin an told me you can get boards made in China and sent back by mail. He was armed with a web address and a ton of teenage enthusiasm.Within minutes we had created an ITead studio account and where busy reading all the FAQ's on how to upload and pay for a circuit board. I was skeptical that this would work but the process was seamless and fault free. The people at ITead where brilliant, the board arrived back in around 10 days and they looked fantastic.

It was soldering time, ahh the simple pleasures. I helped load parts, Orion soldered and in what seemed like no time at all we had partially loaded one board and attached it to our Uno R3. Low and behold there were blinking neopixel lights and an input signal into the A/D converter channel. Looking good for the next step I thought. Orion was over the moon that we had built a shield and it actually worked. I was just grateful that CAD had done most of the “heavy lifting” and checking, the only mistakes where in the schematic itself.

It didn’t take long for us to knock out some light patterns, the first problem being how to switch between them. That was solved with a potentiometer hooked to another AD converter input the result being used to switch the code between effects. There where some backlit led's in the speakers which seemed to respond very nicely to PWM based the music channels ADC value. It was suggested we add a white only mode as a room light, this morphed into several other colours in the blink of an eye. Orion came up with an ADC values sparkles of colour which looked great. He wanted to get the “band hero” look but it didn't quite happen, we got a river of modulated colour which looked nice ish. I tried the FFT thing but didn't spend enough time to get it working right. We tried rotating patterns at various speeds based on the music and many other variations. Some things worked well and some didn’t but we where having way to much fun each night to notice that due date was fast approaching.

Anyhow the hand in date for this school project came all to soon, so we never finished all that we set out to try in the software. The teachers were not impressed with it, which was very sad. They didn't understand the ardunio bit it even though Orion tried to explain it to them out of their own class textbook. Grades aside, we both had a ball building this hugely heavy (13kg) boom box which runs for many hours on a single charge. So if your wondering how to reconnect with your youth in more ways than one then build a arduino project with your kids and share the joy.

Code

Orion_Box_290915.inoC/C++
Our first go at programmings
/* LedStripRainbow: Example Arduino sketch that shows
 * how to make a moving rainbow pattern on an
 * Addressable RGB LED Strip from Pololu.
 *
 * To use this, you will need to plug an Addressable RGB LED
 * strip from Pololu into pin 12.  After uploading the sketch,
 * you should see a moving rainbow.
 */

#include <PololuLedStrip.h>


// Create an ledStrip object and specify the pin it will use.
PololuLedStrip<12> ledStrip;

// Create a buffer for holding the colors (3 bytes per color).
#define LED_COUNT 120
rgb_color colors[LED_COUNT];

#define LOG_OUT 1 // use the log output function
#define LIN_OUT 1
#define OCTAVE 1
#define FFT_N 32 // set to 256 point fft

#include <FFT.h> // include the library

int j = 0 ;
int jLoop = 0 ;
uint8_t k = 0 ;
int iMode = 0 ;
int iHue = 0 ;
int iLum = 0 ;
int z = 0 ;

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT); 

  Serial.begin(115200); // use the serial port

  DIDR0 = 0x1F; // 0x01 turn off the digital input for adc0
  randomSeed(analogRead(4));
}

// Converts a color from HSV to RGB.
// h is hue, as a number between 0 and 360.
// s is the saturation, as a number between 0 and 255.
// v is the value, as a number between 0 and 255.
rgb_color hsvToRgb(uint16_t h, uint8_t s, uint8_t v)
{
    uint8_t f = (h % 60) * 255 / 60;
    uint8_t p = (255 - s) * (uint16_t)v / 255;
    uint8_t q = (255 - f * (uint16_t)s / 255) * (uint16_t)v / 255;
    uint8_t t = (255 - (255 - f) * (uint16_t)s / 255) * (uint16_t)v / 255;
    uint8_t r = 0, g = 0, b = 0;
    switch((h / 60) % 6){
        case 0: r = v; g = t; b = p; break;
        case 1: r = q; g = v; b = p; break;
        case 2: r = p; g = v; b = t; break;
        case 3: r = p; g = q; b = v; break;
        case 4: r = t; g = p; b = v; break;
        case 5: r = v; g = p; b = q; break;
    }
    return (rgb_color){r, g, b};
}

void loop(){
  while(1){
    iMode =  analogRead(1)/4 ;
    // Update the colors.
//    uint16_t time = millis() >> 2;
    switch(iMode){
        case 0 ... 4 :  // test patern
            for(uint16_t i = 0; i < LED_COUNT; i++){
              byte x = (jLoop) - (i << 3);
              colors[i] = hsvToRgb((uint32_t)x * 359 / 256, 255, iMode*50+50);
            }
            delay(iMode*5);
        break;
        case 16 ... 31 :  // wave effect
            for(uint16_t i = 19 ; i > 0 ; i--){
              byte x = ( iMode - 221 ) * 16 ;
              colors[19-i] = colors[20-i];
              colors[20+i] = colors[19+i];
              colors[59-i] = colors[60-i];
              colors[60+i] = colors[59+i];
              colors[99-i] = colors[100-i];
              colors[100+i] = colors[99+i];
            }
            k = (analogRead(4)/4)  ;
            if ( k > 100 ){
              iLum = k ;
            }
            iLum-- ;
            colors[19] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            colors[20] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            colors[59] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            colors[60] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            colors[99] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            colors[100] = hsvToRgb(analogRead(4)/4 , 255, iLum);
            delay(50);
        break;
        case 32 ... 47 :  // random effect
            for(uint16_t i = 0 ;  i < LED_COUNT ; i++){
              colors[random(LED_COUNT)] = hsvToRgb(analogRead(4)/4 , 255, 50);
            }
        break;        
        case 48 ... 63 :  // equaliser FFT display (first cut)
            for(int i = 0; i < LED_COUNT; i++){
              colors[i].red =0 ;
              colors[i].green =0 ;
              colors[i].blue =0 ;             
            }
            for (uint16_t i = 0 ; i < (FFT_N*2) ; i += 2) { // save 32 samples
              fft_input[i] = analogRead(4) ; // put real data into even bins
              fft_input[i+1] = 0; // set odd bins to 0
            }
            fft_window(); // window the data for better frequency response
            fft_reorder(); // reorder the data before doing the fft
            fft_run(); // process the data in the fft
            fft_mag_log(); // take the output of the fft
            fft_mag_lin(); // take the output of the fft
            
           // z = ( fft_log_out[i]/16 )            
//            for (byte i = 3 ; i < FFT_N/2 ; i++) {
            for (byte i = 0 ; i < 20 ; i++) {
              z = fft_log_out[3] / 3 ;
              if ( i < z ){
                colors[119-i].blue = 127 ;
              }
              z = fft_log_out[4] / 3 ;
              if ( i < z ){
//                colors[119-i].green = 127 ;
              }
              z = fft_log_out[5] / 3 ;
              if ( i < z ){
//                colors[119-i].red = 127 ;
              }
              z = fft_log_out[6] / 3 ;
              if ( i < z ){
                colors[80+i].blue = 127 ;
              }
              z = fft_log_out[7] / 3 ;
              if ( i < z ){
//                colors[80+i].green = 127 ;
              }
              z = fft_log_out[8] / 3 ;
              if ( i < z ){
//                colors[80+i].red = 127 ;
              }
              z = fft_log_out[9] / 3 ;
              if ( i < z ){
                colors[79-i].blue = 127 ;
              }
              z = fft_log_out[10] / 3 ;
              if ( i < z ){
//                colors[79-i].green = 127 ;
              }
              z = fft_log_out[11] / 3 ;
              if ( i < z ){
//                colors[79-i].red = 127 ;
              }
              z = fft_log_out[12] / 3 ;
              if ( i < z ){
                colors[40+i].blue = 127 ;
              }
              z = fft_log_out[13] / 3 ;
              if ( i < z ){
//                colors[40+i].green = 127 ;
              }
              z = fft_log_out[14] / 3 ;
              if ( i < z ){
//                colors[40+i].red = 127 ;
              }
              z = fft_log_out[15] / 3 ;
              if ( i < z ){
                colors[39-i].blue = 127 ;
              }
              z = fft_log_out[16] / 3 ;
              if ( i < z ){
//                colors[39-i].green = 127 ;
              }
              z = fft_log_out[17] / 3 ;
              if ( i < z ){
//                colors[39-i].red = 127 ;
              }
              z = fft_log_out[18] / 3 ;
              if ( i < z ){
                colors[i].blue = 127 ;
              }
              z = fft_log_out[19] / 3 ;
              if ( i < z ){
//                colors[i].green = 127 ;
              }
              z = fft_log_out[21] / 3 ;
              if ( i < z ){
//                colors[i].red = 127 ;
              }
            }
            switch(jLoop/42){
              case 0:
                colors[19].red =255 ;
              break;
              case 1:
                colors[20].red =255 ;
              break;
              case 2:
                colors[59].red =255 ;
              break;
              case 3:
                colors[60].red =255 ;
              break;
              case 4:
                colors[99].red =255 ;
              break;
              case 5:
                colors[100].red =255 ;
              break;
            }
        break;        
        case 64 ... 79 :  // color bars
            for(uint16_t i = 0; i < 20; i++){
              int x = (((uint32_t)analogRead(4)/4 * 360 / 256 ) ) % 360 ;
              colors[i] = hsvToRgb(x , 255, 255);
              x = (((uint32_t)analogRead(4)/4 * 360 / 256 ) +(360/6 )) % 360 ;
              colors[i+20] = hsvToRgb(x , 255, 255);
              x = (((uint32_t)analogRead(4)/4 * 360 / 256 )+ (360/6*2 )) % 360 ;
              colors[i+40] = hsvToRgb(x , 255, 255);
              x = (((uint32_t)analogRead(4)/4 * 360 / 256 )+ (360/6*3 ) ) % 360 ;
              colors[i+60] = hsvToRgb(x , 255, 255);
              x = (((uint32_t)analogRead(4)/4 * 360 / 256 )+ (360/6*4 ) ) % 360 ;
              colors[i+80] = hsvToRgb(x , 255, 255);
              x = (((uint32_t)analogRead(4)/4 * 360 / 256 )+ (360/6*5 ) ) % 360 ;
              colors[i+100] = hsvToRgb(x , 255, 255);
            }
        break;
        case 80 ... 87 :  // color moving
            for(uint16_t i = 0; i < 20; i++){
              int x = (((uint32_t)analogRead(4)/4 * 360 / 256 ) + ((uint32_t)(i * 360 ) / 19  )) % 360 ;
              colors[i] = hsvToRgb(x , 255, 150);
              colors[39-i] = hsvToRgb(x , 255, 100);
              colors[i+40] = hsvToRgb(x , 255, 75);
              colors[79-i] = hsvToRgb(x , 255, 50);
              colors[i+80] = hsvToRgb(x , 255, 25);
              colors[119-i] = hsvToRgb(x , 255, 10);
            }
        break;
        case 88 ... 95 : // color moving 
            for(uint16_t i = 0; i < 20; i++){
              int x = (((uint32_t)jLoop * 360 / 256 ) + ((uint32_t)(i * 360 ) / 19  )) % 360 ;
              colors[i] = hsvToRgb(x , 255, 150);
              colors[39-i] = colors[i];
              colors[i+40] = colors[i];
              colors[79-i] = colors[i];
              colors[i+80] = colors[i];
              colors[119-i] = colors[i];
            }
        break;
        case 96 ... 111:  // god knows
            k = (analogRead(4)/4)  ;
            if ( k < 50 ){
              iHue++ ;
              if (iHue > 255){
                iHue = 0 ;
              }
            }
            if ( k > 100 ){
              iLum = k ;
            }
            iLum-- ;
            if ( iLum < 0 ){
              iLum = 0 ;
            }
            if ( k <  0 ){
              k = 0 ;
            }   
            colors[0] = hsvToRgb(iHue , 255, iLum );
            for(uint16_t i = 1 ; i < LED_COUNT ; i++){
              colors[i] = colors[0];
            }
        break;
        case 205 ... 220 :  // sparkles
            for(uint16_t i = 0; i < LED_COUNT; i++){
              colors[i].red =0 ;
              colors[i].green =0 ;
              colors[i].blue =0 ;             
            }
            k = (analogRead(4)/5)  ;  // should be 8 ????
            if ((k<120) && (k > 0) ) {
              colors[k] = hsvToRgb(jLoop , 255, 255);
            }
        break;
        case 221 ... 238 :   // solid color
            for(uint16_t i = 0; i < LED_COUNT; i++){
              byte x = ( iMode - 221 ) * 16 ;
              colors[i] = hsvToRgb((uint32_t)x , 255, 255);
            }
         break;   
        case 239 ... 256 :   // white light - work light
            for(uint16_t i = 0; i < LED_COUNT; i++){
              k = (( iMode - 238 ) * 15 )  ;
              colors[i].red = k ;
              colors[i].blue = k ;
              colors[i].green = k ;            
            }
         break;   
         default:
            Serial.print(jLoop) ; 
            Serial.println(" no Mode");
            for(uint16_t i = 0; i < LED_COUNT; i++){
              colors[i].red = 0 ;
              colors[i].blue = 0 ;
              colors[i].green = 0 ;            
            }
         break;
    }
    // Write the colors to the LED strip.
    ledStrip.write(colors, LED_COUNT);
    analogWrite(5, analogRead(4)/4);  // speaker leds
    
    if ( jLoop > 127 ){   // flash the built in Arduino board
      digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    }else{              // wait for a second
      digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    }             // wait for a second
    if ( jLoop > 255 ){
      jLoop=0 ;
    }  
    jLoop++ ;
  }
}

Custom parts and enclosures

Circuit Board made from the circuit

Schematics

Boom box amplifier schematic
Grand designs bit in the end we only loaded a fraction of the circuit

Comments

Team Trouble

Dougalplummer
DougalPlummer
  • 4 projects
  • 13 followers
Default
orionplummer
  • 2 projects
  • 3 followers

Additional contributors

  • Advice and instruction on the correct use of tools. use of his workshop. by Jim Andrews

Published on

November 4, 2018

Members who respect this project

Default

and 3 others

See similar projects
you might like

Similar projects you might like

Kid's Majestic Streamer Fan Light Button Box

Project in progress by Team Max 35

  • 1,462 views
  • 0 comments
  • 0 respects

Arduino Mystery Box - Beginners

Project tutorial by Dragos

  • 1,048 views
  • 1 comment
  • 5 respects

The Light Box

Project tutorial by Wpeeters

  • 3,116 views
  • 1 comment
  • 17 respects

Interactive Toddler Music Box Toy

Project tutorial by Christopher Monreal and Nick Udell

  • 662 views
  • 0 comments
  • 2 respects

Programmable Pocket Power Supply with OLED Display

Project tutorial by Shahariar

  • 6,202 views
  • 6 comments
  • 27 respects
Add projectSign up / Login