Pages: [1]   Go Down
Author Topic: 10 RGB leds  (Read 417 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Full Member
***
Karma: 1
Posts: 130
mini mini mini
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, in the case of the breadboard, RGY??...
Just have to use your imagination smiley

Anyway, I've been wanting to make an audio visualiser for a while, looked at many ways of going about driving lots of LEDs with brightness control almost all using various chips to generate a separate PWM for each LED, to me this sounds all to easy... So I set about doing it with just an Arduino with an ATMEGA168.

The layout is basically the same as a normal common anode LED matrix, except the anodes are PWN driven.

The software is all done through the main loop, no interrupts. This makes things a little more interesting, having to keep the loop nice and short, basically as long as it's under around 800us it wont interfere with running the LEDs.

Plan is to connect up a pair of these giving 10 leds per audio channel using serial to keep things in sync, such as the mode, buffer size etc.

Oh and the matrix scans at 100Hz, which beats a little with my 50Hz camera, to the human eye the effect is smooth.

[media]http://www.youtube.com/watch?v=nBDrcngNGDM[/media]

http://www.beigematchbox.co.uk/blog/?p=1453

Once I can find some nice small 4 pin polarised connectors for the LEDs I can hook them up, which should show off the effect nicely.

Code:
/*
BeigeMatchbox.co.uk 8/8/2010
If you use any of my code please pop a credit in your source
*/


// Pin asignments
#define OPTIONPOT 2
#define MODEBUTTON 15
#define REDBUTTON 17
#define GREENBUTTON 18
#define BLUEBUTTON 19
const char pots[] = {3, 4, 5};
const char led[] = {9, 10, 11};
const char anode[] = {2, 3, 4, 5, 6, 7, 8, 12, 13, 14};

// ADC Values
byte audioSamples[4] = {0, 0, 0};
byte optionPot = 0;

// Audio Smoothing Buffers
byte sampleBufferOne[192];  // due to overhead the sample buffers are split
byte sampleBufferTwo[192];
byte sampleBufferThree[192];
byte samplePointers[3];

// Current lit LED
char clockCount = 0;

// Mode selection
char modeNumber = 0;
const char maxMode = 4;

// Misc vars for demos
byte refByte = 0;
byte refByteTwo = 0;
boolean getBrighter = true;
unsigned long dimmerMicros = 0;
long millisOne = 0;
long millisTwo = 0;
long millisThree = 0;
long millisFour = 0;

// var for scan freq
unsigned long scanMicros = 0;

// Full frame buffer R, G, B
//   0 == off, 255 == on
byte frame[11][4] = {
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0},
  {0, 0, 0}
};


// ************************
// * Hardware Setup        *
// ************************

void setup(){
  // Set dividers on timer 1 and 2 to 1
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
  TCCR2B = TCCR2B & 0b11111000 | 0x01;
  
  Serial.begin(19200);

  pinMode(MODEBUTTON, INPUT);
  pinMode(REDBUTTON, INPUT);
  pinMode(GREENBUTTON, INPUT);
  pinMode(BLUEBUTTON, INPUT);
  
  for (char i=0; i <= 2; i++){
    pinMode(led[i], OUTPUT);
    analogWrite(led[i], 255);
  }
  
  for (char i=0; i <= 9; i++){
    pinMode(anode[i], OUTPUT);
    digitalWrite(anode[i], HIGH);
  }

  digitalWrite(MODEBUTTON, HIGH);
  digitalWrite(REDBUTTON, HIGH);
  digitalWrite(GREENBUTTON, HIGH);
  digitalWrite(BLUEBUTTON, HIGH);
  
}


// ************************
// * Main Loop              *
// ************************

void loop(){
  
 doScan();
 doButton();
 doMode();
 doOptionPot();
  
}


// ************************
// * Mode Loops                *
// ************************

void doMode(){
  switch (modeNumber) {
    case 0:
      blinkerMode();
      break;
    case 1:
      knightMode();
      break;
    case 2:
      randomMode();
      break;
    case 3:
      snakeMode();
      break;
    case 4:
      sampleMode();
      break;
    default:
      break;
  }
}


// ************************
// * Mode Button        *
// ************************

void doButton(){
  if(digitalRead(MODEBUTTON) == LOW){
    clearFrame();
    clearLeds();
    modeNumber ++;
    if(modeNumber > maxMode){
      modeNumber = 0;
    }
    
    waitForButtons();
    
    dimmerMicros = micros();
    millisOne = millis();
    millisTwo = millis();
    millisThree = millis();
    getBrighter = true;
    refByte = 0;
    refByteTwo = 0;
    
  }
}


// ************************
// * Option Pot                *
// ************************

void doOptionPot(){
  if (millis() - millisFour > 10) {
    millisFour = millis();
    if(modeNumber == 4){
      optionPot = map(analogRead(OPTIONPOT), 0, 1023, 1, 192);
    }
    else{
      optionPot = map(analogRead(OPTIONPOT), 0, 1023, 0, 255);
    }
  }
  
  
}


// ************************
// * Blinker Mode        *
// ************************

void blinkerMode(){
  if (millis() - dimmerMicros > 1){
    dimmerMicros = millis();
    for (char i=0; i <= 9; i++){
      for (char j=0; j <= 2; j++){
        frame[i][j] = refByte;
      }
    }
  
  if(getBrighter == true){
    refByte ++;
    if(refByte == 255){
      getBrighter = false;
    }
  }
  else{
    refByte --;
    if(refByte == 0){
      getBrighter = true;
    }
  }
  }
}


// ************************
// * Knight Mode        *
// ************************

void knightMode(){
  dimLeds(1250);
  
  if (millis() - millisOne > -(optionPot-255)) {
    millisOne = millis();
    
    if(getBrighter == true){
        refByte ++;
        for (char j=0; j <= 2; j++){
          frame[refByte-1][j] = 255;
        }
      if(refByte == 10){
        getBrighter = false;
      }
    }
    else{
      refByte --;
      for (char j=0; j <= 2; j++){
        frame[refByte-1][j] = 255;
      }
      if(refByte == 1){
        getBrighter = true;
      }
    }
  }
}


// ************************
// * snakeMode              *
// ************************

void snakeMode(){
  dimLeds(7500);
  
  if (millis() - millisOne > -(optionPot-255)) {
    millisOne = millis();
    
    frame[refByte][refByteTwo] = 255;
    
    if(getBrighter == true){
      if(refByteTwo >= 2){
        getBrighter = false;
        refByte ++;
        if(refByte > 9){
          refByte = 0;
        }
      }
      else{
        refByteTwo ++;
      }
    }
    else{
      if(refByteTwo <= 0){
        getBrighter = true;
        refByte ++;
        if(refByte > 9){
          refByte = 0;
        }
      }
      else{
        refByteTwo --;
      }
    }
  }
}


// ************************
// * random Mode        *
// ************************

void randomMode(){
  dimLeds(2500);

  if (millis() - millisOne > -(optionPot-255)) {
    millisOne = millis();
    frame[random(0, 10)][random(0, 3)] = 255;
  }
}


// ************************
// * Audio Sample Mode    *
// ************************

void sampleMode(){

  if (millis() - millisThree > 3) {
    millisThree = millis();
    
    unsigned int smoothed = 0;

    audioSamples[refByte] = -analogRead(pots[refByte])/4-255;
    
      switch (refByte) {
       case 0:
        sampleBufferOne[samplePointers[refByte]] = audioSamples[refByte];
        break;
       case 1:
        sampleBufferTwo[samplePointers[refByte]] = audioSamples[refByte];
        break;
       case 2:
        sampleBufferThree[samplePointers[refByte]] = audioSamples[refByte];
        break;
       default:
        break;
       }
    
    for (byte j=0; j <= optionPot-1; j++){
      switch (refByte) {
       case 0:
        smoothed += sampleBufferOne[j];
        break;
       case 1:
        smoothed += sampleBufferTwo[j];
        break;
       case 2:
        smoothed += sampleBufferThree[j];
        break;
       default:
        break;
       }
    //  smoothed += sampleBuffer[refByte][j];
    }
    smoothed /= optionPot;
    if(samplePointers[refByte] <= optionPot-2){
      samplePointers[refByte] ++;
    }
    else{
      samplePointers[refByte] = 0;
    }


    frame[0][refByte] = smoothed;
      
    if(refByte < 2){
      refByte++;
    }
    else{
      refByte = 0;
    }

  }
  
  if (millis() - millisTwo > 50) {
    millisTwo = millis();
    for (char i=9; i >= 1; i--){
        for (char j=0; j <= 2; j++){
          frame[i][j] = frame[i-1][j];
        }
      }
    }
  
}
    

// ************************
// * Scan Led array and   *
// * dim any lit LEDs     *
// ************************

void dimLeds(int dimSpeed){
  
  if (micros() - dimmerMicros > dimSpeed) {
    dimmerMicros = micros();
    
    for (char i=0; i <= 9; i++){
      for (char j=0; j <= 2; j++){
        if (frame[i][j] > 0){
          frame[i][j] -= 1;
        }
      }
    }
  }
  
}


// ************************
// * Scan the matrix        *
// ************************

void doScan(){
  if (micros() - scanMicros > 1000) {
    scanMicros = micros();
    
    clearLeds();
  
    digitalWrite(anode[clockCount], HIGH);
    delayMicroseconds(25); //Without this delay there is a flicker
  
    if(clockCount < 9){
      clockCount ++;
    }
    else{
      clockCount = 0;
    }
    
    digitalWrite(anode[clockCount], LOW);
    
    setLeds();
  }
}

void setLeds(){
  for (char i=0; i <= 2; i++){
    analogWrite(led[i], frame[clockCount][i]);
  }  
}

void clearLeds(){
  
    analogWrite(led[0], 0);
    analogWrite(led[1], 0);
    analogWrite(led[2], 0);

}

void clearFrame(){
  for (char i=0; i <= 9; i++){
      for (char j=0; j <= 2; j++){
        frame[i][j] = 0;
      }
  }
}


// ************************
// * Wait for any buttons *
// ************************

void waitForButtons(){
  
 while(digitalRead(MODEBUTTON) == LOW){
      //wait for button up
    }
  
}
Logged

Niagara on the Lake, Ontario
Offline Offline
Full Member
***
Karma: 0
Posts: 144
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks excellent, great work! Ive always wondered how a bunch of graphical functions worked, and this details them very well. Your coding is very well laid out too! Thanks a lot.
Logged

Pages: [1]   Go Up
Jump to: