amplifying the Rainbowduino

Hey Guys, I've got a Question :slight_smile:

I’ve got a Rainbowduino and want to use him with 4 Superflux RGB LED per "Dot" unfortunately the Rainbowduino is not strong enough to provide that much power.

I tried to design a amplifier circuit but I don’t know where I have to use pnp transistors and where npn. Since rows are anodes on the Rainbowduino matrix I think ive got to use pnp's for the rows and npn's for the columns. Am I right?

I’m using the same power supply for the Rainbowduino and for the led’s.

I know I’ve forgotten the resistors for the led’s (shame on me :D)

Your help is greatly appreciated and thx in advance!!

Apart from missing the resistors in series with each led, you've got all the transistors upside down, i.e. emitter and collector reversed. But you do have PNP and NPN transistors in the right places.

thx for the quick reply.

Would you mind looking over it again. I did the changes you've told me.

That looks better. The 2n706 is a very old transistor and I would use something more modern with a higher gain and better max current and power, such as the BC337.

Yeah I used them just as space holders :D. They where the first in the eagle library :stuck_out_tongue_winking_eye:

Hi.

I need your help again.

The circuit seems to work great but the multiplexing thing is confusing me.

The brightness of one pixel is ok when all other pixels have the same color to.

But when I set just one pixel to lets say blue and all othe pixels are off the leds are very dim. (They get brighter the more leds on the same column are on)

Has anybody out there got an explanation for this ?

Can you post your sketch?

Well IAm using the standard neorainbowduino firmware.

That's what the rainbowduino is doing:

#include <Wire.h>
#include <FlexiTimer2.h>

#include "Rainbow.h"

/*
A variable should be declared volatile whenever its value can be changed by something beyond the control 
 of the code section in which it appears, such as a concurrently executing thread. In the Arduino, the 
 only place that this is likely to occur is in sections of code associated with interrupts, called an 
 interrupt service routine.
 */

extern unsigned char buffer[2][96];  //two buffers (backbuffer and frontbuffer)

//interrupt variables
byte g_line,g_level;

//read from bufCurr, write to !bufCurr
//volatile   //the display is flickerling, brightness is reduced
byte g_bufCurr;

//flag to blit image
volatile byte g_swapNow;
byte g_circle;

//data marker
#define START_OF_DATA 0x10
#define END_OF_DATA 0x20

//FPS
#define FPS 80.0f

#define BRIGHTNESS_LEVELS 16
#define LED_LINES 8
#define CIRCLE BRIGHTNESS_LEVELS*LED_LINES

void setup() {
  DDRD=0xff;        // Configure ports (see http://www.arduino.cc/en/Reference/PortManipulation): digital pins 0-7 as OUTPUT
  DDRC=0xff;        // analog pins 0-5 as OUTPUT
  DDRB=0xff;        // digital pins 8-13 as OUTPUT
  PORTD=0;          // Configure ports data register (see link above): digital pins 0-7 as READ
  PORTB=0;          // digital pins 8-13 as READ

  g_level = 0;
  g_line = 0;
  g_bufCurr = 0;
  g_swapNow = 0; 
  g_circle = 0;

  Wire.begin(I2C_DEVICE_ADDRESS); // join i2c bus as slave
  Wire.onReceive(receiveEvent);   // define the receive function for receiving data from master
  // Keep in mind:
  // While an interrupt routine is running, all other interrupts are blocked. As a result, timers will not work 
  // in interrupt routines and other functionality may not work as expected
  // -> if i2c data is receieved our led update timer WILL NOT WORK for a short time, the result
  // are display errors!

  //redraw screen 80 times/s
  FlexiTimer2::set(1, 1.0f/(128.f*FPS), displayNextLine);
  FlexiTimer2::start();                            //start interrupt code
}

//the mainloop - try to fetch data from the i2c bus and copy it into our buffer
void loop() {
  if (Wire.available()>97) { 
    
    byte b = Wire.receive();
    if (b != START_OF_DATA) {
      //handle error, read remaining data until end of data marker (if available)
      while (Wire.available()>0 && Wire.receive()!=END_OF_DATA) {}      
      return;
    }

    byte backbuffer = !g_bufCurr;
    b=0;
    //read image data (payload) - an image size is exactly 96 bytes
    while (b<96) { 
      buffer[backbuffer][b++] = Wire.receive();  //recieve whatever is available
    }

    //read end of data marker
    if (Wire.receive()==END_OF_DATA) {
        //set the 'we need to blit' flag
  	g_swapNow = 1;
    } 
  }
}



//=============HANDLERS======================================

//get data from master - HINT: this is a ISR call!
//HINT2: do not handle stuff here!! this will NOT work
//collect only data here and process it in the main loop!
void receiveEvent(int numBytes) {
  //do nothing here
}


//============INTERRUPTS======================================

// shift out led colors and swap buffer if needed (back buffer and front buffer) 
// function: draw whole image for brightness 0, then for brightness 1... this will 
//           create the brightness effect. 
//           so this interrupt needs to be called 128 times to draw all pixels (8 lines * 16 brightness levels) 
//           using a 10khz resolution means, we get 10000/128 = 78.125 frames/s
// TODO: try to implement an interlaced update at the same rate. 
void displayNextLine() { 
  draw_next_line();									// scan the next line in LED matrix level by level. 
  g_line+=2;	 								        // process all 8 lines of the led matrix 
  if(g_line==LED_LINES) {
    g_line=1;
  }
  if(g_line>LED_LINES) {								// when have scaned all LED's, back to line 0 and add the level 
    g_line=0; 
    g_level++;										// g_level controls the brightness of a pixel. 
    if (g_level>=BRIGHTNESS_LEVELS) {							// there are 16 levels of brightness (4bit) * 3 colors = 12bit resolution
      g_level=0; 
    } 
  }
  g_circle++;
  
  if (g_circle==CIRCLE) {							// check end of circle - swap only if we're finished drawing a full frame!

    if (g_swapNow==1) {
      g_swapNow = 0;
      g_bufCurr = !g_bufCurr;
    }
    g_circle = 0;
  }
}


// scan one line, open the scaning row
void draw_next_line() {
  DISABLE_OE						//disable MBI5168 output (matrix output blanked)
  //enable_row();				                //setup super source driver (trigger the VCC power lane)
  CLOSE_ALL_LINE					//super source driver, select all outputs off
  open_line(g_line);

  LE_HIGH							//enable serial input for the MBI5168
  shift_24_bit();	// feed the leds
  LE_LOW							//disable serial input for the MBI5168, latch the data
  
  ENABLE_OE							//enable MBI5168 output
}

//open correct output pins, used to setup the "super source driver"
//PB0 - VCC3, PB1 - VCC2, PB2 - VCC1
//PD3 - VCC8, PD4 - VCC7, PD5 - VCC6, PD6 - VCC5, PD7 - VCC4
void enable_row() {
  if (g_line < 3) {    // Open the line and close others
    PORTB = (PINB & 0xF8) | 0x04 >> g_line;
    PORTD =  PIND & 0x07;
  } else {
    PORTB =  PINB & 0xF8;
    PORTD = (PIND & 0x07) | 0x80 >> (g_line - 3);
  }
}

// display one line by the color level in buffer
void shift_24_bit() { 
  byte color,row,data0,data1,ofs; 

  for (color=0;color<3;color++) {	           	//Color format GRB
    ofs = color*32+g_line*4;				//calculate offset, each color need 32bytes
    			
    for (row=0;row<4;row++) {    
      
      data1=buffer[g_bufCurr][ofs]&0x0f;                //get pixel from buffer, one byte = two pixels
      data0=buffer[g_bufCurr][ofs]>>4;
      ofs++;

      if(data0>g_level) { 	//is current pixel visible for current level (=brightness)
        SHIFT_DATA_1		//send high to the MBI5168 serial input (SDI)
      } 
      else {
        SHIFT_DATA_0		//send low to the MBI5168 serial input (SDI)       
      }
      CLK_RISING		//send notice to the MBI5168 that serial data should be processed 

      if(data1>g_level) {
        SHIFT_DATA_1		//send high to the MBI5168 serial input (SDI)
      } 
      else {
        SHIFT_DATA_0		//send low to the MBI5168 serial input (SDI)
      }
      CLK_RISING		//send notice to the MBI5168 that serial data should be processed
    }     
  }
}

void open_line(unsigned char line) {    // open the scaning line 
  switch(line) {
  case 0: {
      open_line0
      break;
    }
  case 1: {
      open_line1
      break;
    }
  case 2: {
      open_line2
      break;
    }
  case 3: {
      open_line3
      break;
    }
  case 4: {
      open_line4
      break;
    }
  case 5: {
      open_line5
      break;
    }
  case 6: {
      open_line6
      break;
    }
  case 7: {
      open_line7
      break;
    }
  }
}

I don't think it's a software problem since this firmware is running on many other rainbowduinos without any problems.

Right know I have just hocked up one pixel(X:1 Y:1) to the matrix. Could this be the problem? Maybe the coulmn is switched one more often or so. I will check that with an oscilloscope next tuesday.

I think I can see the problem. I've just found the schematic for the Rainbowduino at http://www.trochotron.com/w/images/0/01/Rainbowduino_v2.0.pdf. Are your RGB row inputs the left hand inputs to the device marked RGB1 in that schematic, and are your column inputs the right hand inputs on that device? If so, it looks like the RGB row outputs of the Rainbowduino are active low, and the column outputs are active high.This is the opposite way round to the way your circuit is designed to work.

I can see two ways of fixing it:

  1. Swap the NPN transistors for PNP transistors and connect their emitters to +5v instead of ground. Likewise, swap the PNP transistors for NPN transistors and connect their emitters to ground instead of +5v. Also reverse the polarity of all the LEDs.

OR

  1. Leave the circuit as it is, but invert each row and column input using another transistor.

PS - also:

  1. What is the current per LED?

  2. What transistors are you using, and what value resistors are you using between the inputs and the bases of the transistors?

Thank you for your help.

I will try that tomorrow.

To your questions:

1.20mA per LED (actually one color in one of four LEDs) => 80mA per Color
Datasheet: http://www.impolux.de/extern/datasheet/LED/09266_Superflux6gdif_Datenblatt.jpg

I have also changed the sourcing transistor (Column) with this circuit:


And also the supply voltage to 12V( Iam sorry i didn't mention that earlier)

PNP:2n3906
NPN:2n3904
(with just one pixel (4 LEDs) connected they are strong enough)

1kOhm

Looks like you've already got an extra inverter in the column driver circuit then, so it's only the RGB inputs that need inverting, if your RGB inputs are active low. However, I'm somewhat surprised that it is working at all, so I think something else may be going on.

Hmm strange things going on in my circuit :smiley:

I can't get it working with inverting the RGB inputs( Still the brightness problem). Maybe Ia'm doing something wrong there... Would you mind drawing up the circuit of the inverter for me :blush: ? (There is no eagle installed on this computer were iam working on right now so i cant show you mine)

But I think ive really got to check the inputs / outputs of the rainbowduino with an oscilloscop so iam sure everything is working porperly on that side.

BTW: One error could be that the column is not switching properly. The more leds are on in one row the more often the RGB inputs get turned on for this row. But when the column is not switching correctly all the current is flowing threw my single pixel ... so the brightness is increasing (for the human eye). But these are just some thoughts havent found the error in the column circuite ... if there is one.

If the RGB inputs to your circuit are the outputs of the MB5168 chips that normally drive the LEDs, then I would use the attached circuit for each of the row drivers. The MB5168 sinks a constant current, so there is no need for a resistor between the input and the base of the first transistor.

I don't understand your current calculation. You said each LED runs at 1.2mA (which is extremely low - the datasheet you referred to specified 50mA continuous, 100mA peak), and that the total current per column is 80mA. I assume you have 8 LEDs of each colour per column. But 3 * 8 *1.2 is only 28.8 mA.

What value resistor do you have in series with each LED?