 # 8 x 56 LED matrix controlled by sensor

I am attempting to build a large scale LED matrix that is controlled by reading a sensor. The aim is to play around with a number of sensors, but for this instance lets say the sensor is to determine volume changes in sound.
I am fairly new to using the Arduino, and especially coding, so here is a break down of what I have so far.

I’m using an ArduinoMega 2560.
I’m looking to build an 8 x 56 LED MATRIX.

First, can I place the rows directly to the Arduino mega, or will I have to use 1 x 75HC595 to drive the 8 rows? And have 7 x TPIC6C595 to drive the columns.
LEDs (10mm 3.0 - 3.2 / 24mA), so am I right in thinking 82ohm resistors for each column?

As I understand, I need to multiplex the LEDs - so activating one column (i.e. TPIC6C595 pin). The more columns, the time needed to refresh will become greater and so the display will have more of a flicker.

I have found this post that shows the initial build of the MATRIX: http://g33k.blogspot.co.uk/2010/02/arduino-56x8-scrolling-led-matrix.html

As for finding/writing code, and implementing a sensor to the read data I am clueless. I’m not sure where to start here.
I don’t want scrolling text, I want to have random dotting that grows as incoming data value increases.
Something like this, but a lot faster: LED Matrix Effects - YouTube

Is there MATRIX ANIMATION software I can use which is easy to implement into an existing arduino code?

Any direction would much appreciated.

Thank you!

On the page you linked, they seem to scan through the 56 columns and use the 8 rows turn on the right LEDs in that column. This is rather slow if you compare it to scanning through 8 rows (meaning more flicker).
Also, the maximum current that can be drawn by 1 row is about 200mA, while the TPIC6C595 can only supply 100mA (250mA peak).
Therefore, I'd scan through the 8 rows

beamtetrode:
First, can I place the rows directly to the Arduino mega, or will I have to use 1 x 75HC595 to drive the 8 rows? And have 7 x TPIC6C595 to drive the columns.
LEDs (10mm 3.0 - 3.2 / 24mA), so am I right in thinking 82ohm resistors for each column?

The maximum recommended current draw/sink to from an Arduino pin is 20mA (40mA absolute max.), so there is no way you can drive the rows directly from the Mega. If there were less columns (10 or less), you could use the Mega to drive them, but the total current draw of the Mega is 200mA.
Imagine the extreme case where all 56 LEDs on a row are on at the same time, you would have a total current draw of 0.024A * 56 = 1.344A, which is way too high.

This is also the reason why you can't use a 75HC595 to drive the rows directly: they can only supply 35mA. This means you need a 75HC595 with 8 MOSFETs (or power transistors), to supply the 1.344A needed to turn on a full row.

7 75HC595's on the columns is fine, because there's only one active LED per output.
82 Ohms is indeed the right resistance for your particular type of LEDs @5V.

beamtetrode:
Is there MATRIX ANIMATION software I can use which is easy to implement into an existing arduino code?

Not that I know of ...

beamtetrode:
I want to have random dotting that grows as incoming data value increases.

Do you mean like analog TV static, with more LEDs on if the sensor value is higher? In that case you could use something like:

``````int sensorValue = analogRead(A0);
if (sensorValue > random(1024)) ...
// turn LED on
``````

to determine whether one specific LED should be on.

This information is great, thank you.

Yes, TV static is a better way to describe the effect.
Like this

It is the code that I am still having difficulty with knowing where to start. I've played around with small sized matrix designs and done the whole switching one LED after another off. But something on this scale is beyond me, and especially when it comes to having the number more, or less, LEDs switch on incoming data.

Is there a good starting point for this kind of thing? And in the example code you gave, would that command be given prior to giving an LEDs coordinates?

The code is just to decide for 1 individual LED if it should be on. The probability of the LED being on will equal the sensor value divided by 1023. This means that if your sensor value is 512, around 50% of the LEDs will be on at a given time, if it’s 256 around 25%, etc.

Maybe change “random(1024)” to “random(1023)” to ensure that 100% of the LEDs is on at a sensor value of 1023 (max).

Do you understand how a shift register works, and how you can drive it with an Arduino?
Do you understand how to drive an LED matrix by scanning over the rows?
If you don’t, check out these links: Shift registers, Multiplexing animation, Multiplexing explained

In pseudocode:

``````sensorValue = analogRead(A0)
output 0b00000001 to the rows register
for 7 times     //total of 8 rows
for 7 times     // 7 shift registers for the columns, chained together
shiftout(randomByte(sensorValue)) to columns registers    // write data to the 56 LEDs on one line, one byte at a time
shift rows register 1 bit further    // to activate the next row: 0b00000001 → 0b00000010 etc.
repeat
``````
``````uint8_t randomByte(int value) {
uint8_t result = 0;
for (int i = 0; i < 8; i++){
if (value > random(1023)){
result = result | (1<<i);
}
}
return result;
}
``````

| is the bitwise or operator, and << is left bitshift.

Thanks Wawa, but I’m actually wanting to custom build this for an unusual space. It’s a fairly long passage, that is only 2 foot wide. The aim is to be in complete darkness apart from this piece.

Pieter P - I understand how a shift register works, and how multiplexing works.

So, do in the code do I const int latch, clock and data pins as follows

``````//Pin connected to latch pin 75HC595
const int latchPin = 8;
//Pin connected to clock pin 75HC595
const int clockPin = 12;
////Pin connected to Data in 75HC595
const int dataPin = 11;

void setup() {
//set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
Serial.begin(9600);
Serial.println("reset");
``````

Or do I const int my rows and columns to the number of shift registers?

``````const int row[] = {3, 4, 5, 6, 7, 8, 9};        // rows are anodes. Consider them 'common' anodes
const int col[] = {11};      // columns are cathodes and will have PWM applied to them
``````

Or both?

I’m finding it hard to visualize how the code is set up to work in this way as I’m not familiar coding. I’ve been looking at various sketches… even after looking at a number ones online.

In regards to a transistors, I’m thinking NPN 2N2222 on the 8 rows to the 75HC595.

beamtetrode:
In regards to a transistors, I’m thinking NPN 2N2222 on the 8 rows to the 75HC595.

They are signal switching transistors, their maximum collector current is (only) 600mA, go with MOSFETs or power transistors (1.5A or more) instead.

I’ll take a look at your code tomorrow.

``````int latchPin1 = 2; // columns
int clockPin1 = 3;
int dataPin1 = 4;

int latchPin2 = 5; //rows
int clockPin2 = 6;
int dataPin2 = 7;

int sensorValue = analogRead(A0); // sensor

//Bits in this array represents one LED of the matrix
byte bitmap; // // 8 is # of rows, 7 is # of LED matrix we have
int numZones = sizeof(bitmap) / 8; // I will refer to each group of 8 columns (represented by one matrix) as a Zone.
int maxZoneIndex = numZones-1;
int numCols = numZones * 8;

void setup() {
pinMode(latchPin1, OUTPUT);
pinMode(clockPin1, OUTPUT);
pinMode(dataPin1, OUTPUT);

pinMode(latchPin2, OUTPUT);
pinMode(clockPin2, OUTPUT);
pinMode(dataPin2, OUTPUT);

// Clear bitmap
for (int row = 0; row < 8; row++) {
for (int zone = 0; zone <= maxZoneIndex; zone++) {
bitmap[row][zone] = 0;
}
}
}
void RefreshDisplay()
{
uint8_t randomByte(int value) {
uint8_t result = 0;
for (int i = 0; i < 8; i++){
if (value > random(1023)){
result = result | (1<<i);
}
}
return result;
}
``````

Actually… more kind like this? but then how to digitalWrite, and I’m implement sensor. Would be looking to input the ‘static pattern’ manually by stating each location of the LED wished to be on or off?

``````int latchPin1 = 2; // arduino connected to RCK
int clockPin1 = 3; // arduino connected to SRCK
int dataPin1 = 4; // arduino connected to SER IN

int latchPin2 = 5;
int clockPin2 = 6;
int dataPin2 = 7;

byte bitmap ;
int numZones = sizeof(bitmap) / 8;
int maxZonesIndex = numZones-1;
int numCols = numZones * 8;

byte stat1[] = {
562949953421313,
1970350606843904,
565174746710784,
66304,
12582912,
2251799826272272,
7882948615350275,
2253449081131011};

byte stat2[] = {
617375785287693,
20042337520519180,
618364031173440,
412316930817,
4513529654706240,
2462909398258000,
8100698357840259,
2255648272158723};
``````

Is this the kind of starting point to take. I used LED MATRIX studio to put the byte data in. I have a feeling that this is totally wrong. Looking at 7.8 in the Arduino cookbook on displaying images on an LED martix. Ah... ``````byte stat1[] = {
``````

562949953421313,
1970350606843904,
565174746710784,
66304,
12582912,
2251799826272272,
7882948615350275,
2253449081131011};

byte stat2 = {
617375785287693,
20042337520519180,
618364031173440,
412316930817,
4513529654706240,
2462909398258000,
8100698357840259,
2255648272158723};

What is this? The data type is byte, which means 8 bits, or values between 0 and 255, so any value outside that range will overflow and will make no sense.

And did you already write the code to control the shift registers? Or if you don't know how to do that, maybe post your ideas in pseudocode, so we can work on that.

I could just give you a finished piece of code, but that would not be helpful, my goal is to teach people how to do it on their own, not how to copy-and-paste-and-compile code made by others.

Also, for scanning the rows, you could use a 4017 decade counter instead of a shift register. It's faster and uses less pins.
It's really simple, anytime it gets a pulse, it enables the next of its 10 outputs. Exactly what you need.

I've been fairly quiet on this one, as I've been going back to the start to try and get a better understanding of each step.

The example code you give, is it in C++ or C?

beamtetrode:
The example code you give, is it in C++ or C?

It wasn't really an example, just a rudimentary piece of pseudocode, you have to 'convert' it to Arduino C++ before compiling. The randomByte function should work in C++ though.

Pieter

``````int dataPin = 12;
int latchPin = 11;
int clockPin = 10;
int pause = 90;

long myData;

unsigned long LEDrow[] =
{1, 2, 4, 8, 16, 32, 64, 128, 256,
512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216,
33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,

};

void setup() {
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
for(int i = 1; i < 33; i++) {
if(i <= 31) {
myData = LEDrow;
Serial.print(i);
Serial.print(" ");
Serial.print("myData= ");
Serial.println(myData);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 24));
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 16));
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 8));
shiftOut(dataPin, clockPin, MSBFIRST, myData);
digitalWrite(latchPin, HIGH);
delay(pause);
}
else {
for(int i = 33; i > 1; i--) {
myData = LEDrow;
Serial.print(i);
Serial.print(" ");
Serial.print("myData= ");
Serial.println(myData, BIN);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 24));
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 16));
shiftOut(dataPin, clockPin, MSBFIRST, (myData >> 8));
shiftOut(dataPin, clockPin, MSBFIRST, myData);
digitalWrite(latchPin, HIGH);
delay(pause);
}
}
}
}
``````

I’ve managed to get write this line controlling an LED chaser consisting of 32 LEDs, with some help and adjustments.

I’m controlling one line with 4 shift registers connected in series. The only problem is just before the LED return, it looks as if a random value is being sent, as a number of LEDs turn on for a moment and then the chaser starts its return.

I thought if I could get at least one line working, and understand it, then I can start building up from there. The next step is to use line with a sensor (like mentioned above), and begin to turn on random LEDs given the incoming data.

It looks like line 32 is where the problem is, do you know where the random number is coming from to have the LEDs turn on before the return?