Go Down

Topic: Ghosting effect with 4x4x4 LED-Cube (Read 2376 times) previous topic - next topic

Just_some_dude

#15
Aug 09, 2019, 02:57 am Last Edit: Aug 09, 2019, 02:58 am by Just_some_dude
I noticed that I had some resistors with a higher resistance in my circuit, but I exchanged them now. I got the following measurements (again with an analog multimeter):

one Layer, 16 LEDs:

current (just the LEDs): 62,5mA

voltage drops:
-supply voltage (Arduino 5V to GND): 4,7V
-across 595's (5V to outputs): 0,7V
-across resistors (220 Ohm): 1V
-across mosfets (source to drain): 0V
-across LED (same for all LEDs): 2,9V

4,7V-(0,7+1+0+2,9)V=0,1V    ->adds up, close enough


four layers, 64 LEDs:

current: 67,5mA

voltage drops:
-supply voltage: 4,7V
-across 595's: 0,7V
-across resistors: 0,9V
-across mosfets: 0V
-across LED: 2,6V

4,7V-(0,7+0,9+0+2,6)V=0,5V  ->does not really add up



My issue in my last post was that I thought with 4 layers the current should be 4 times as high. But actually it should be pretty much the same, because the resistance in both cases is almost the same (a little lower with all 4 layers, therefore a higher current). Is that correct?


Also that means that the resistance of my circuit (with one layer) is:

(4,7V-2,9V)/(62,5mA/16)= 461 Ohm

"(supply voltage - LED forward voltage) / (current / number of LEDs) = resistance"


Subtracting the 220 Ohm from the resistor leaves my circuit with a resistance of 240 Ohm. That seems pretty bad to me. Is my math correct or am I missing something here?




Also, did someone find out why my code is not eliminating the ghosting effect despite using the outputenable on the shift registers?

Paul__B

Also, did someone find out why my code is not eliminating the ghosting effect despite using the output enable on the shift registers?
What code?  The last code that I have seen you post generates only one static pattern, if that.

And it is awfully difficult to read.  Double spaced makes it almost illegible.  You need to use single bank lines only between functional units, double between functions to demarcate them.  And your comments are too long and wordy.

PaulRB

Quote
4,7V-(0,7+0,9+0+2,6)V=0,5V  ->does not really add up
I should have said it must add up. Voltage cannot disappear to nowhere.

With all 4 MOSFETS switched on, there will be 4 current paths for the current to get from the series resistor to ground. You have to measure the voltage drops along a single current path for it to add up.

My guess at this point is that a single layer is close to the 70mA limit for the shift register. When you switch on all 4 layers at once, the shift register is throttling the current down. But I would expect it to do that by dropping more voltage, witch does not seem to be happening.


Just_some_dude

What code?  The last code that I have seen you post generates only one static pattern, if that.

And it is awfully difficult to read.  Double spaced makes it almost illegible.  You need to use single bank lines only between functional units, double between functions to demarcate them.  And your comments are too long and wordy.
I'm sorry for that, I'll try to avoid the double spacing in the future. My comments are long and wordy because I want to remember why I did something if I look back at my code in the future.

I was talking about the last code I posted. Dynamic patterns make it pretty hard to make out the ghosting effect, that's why I chose a static pattern as an example. It is not a big deal, but the fact it is still there bothers me.
Should I post my code again in a more readable way?

I should have said it must add up. Voltage cannot disappear to nowhere.

With all 4 MOSFETS switched on, there will be 4 current paths for the current to get from the series resistor to ground. You have to measure the voltage drops along a single current path for it to add up.

My guess at this point is that a single layer is close to the 70mA limit for the shift register. When you switch on all 4 layers at once, the shift register is throttling the current down. But I would expect it to do that by dropping more voltage, witch does not seem to be happening.


That was probably my mistake. I averaged my measurements and then calculated the voltage drop in my last post. When measuring the voltage drops for each column independently, the difference between the voltage drop and the supply voltage is about 0,2V. I know it needs to add up, but this might just be a measuring error.

I measured the current by hooking up the multimeter to the common ground, meaning I measured the combined current of the whole circuit. Since I have 2 shift registers for driving the LEDs, one should not get more than about 30-35mA. So I don't think they are throttling.

PaulRB

Quote
Also, did someone find out why my code is not eliminating the ghosting effect despite using the outputenable on the shift registers?
Can't see a problem in your code causing that. But did expect you to connect OE of all 3 shift registers together, so maybe try that.

Just_some_dude

I tried it, but the effect remains.

Paul__B

#21
Aug 09, 2019, 03:27 pm Last Edit: Aug 09, 2019, 11:47 pm by Paul__B Reason: Slight modifications ...
I was talking about the last code I posted. Dynamic patterns make it pretty hard to make out the ghosting effect, that's why I chose a static pattern as an example. It is not a big deal, but the fact it is still there bothers me.
Should I post my code again in a more readable way?
OK, so edited to a plausibly readable version and slightly adjusted, this was the last code you posted:

Code: [Select]

#include <SPI.h>
#define t 1                   //on-time of the LEDs
#define latchPin 10
#define outputenable 3

//Array with hexadecimal values to turn on the LED according to the index, "hex[x][y]"
byte hex[5][5] = {
  {0, 0, 0, 0, 0},                     // So that the indexes can start with 1
  {0x00, 0x01, 0x02, 0x04, 0x08},      // Row 1
  {0x00, 0x10, 0x20, 0x40, 0x80},      // Row 2
  {0x00, 0x01, 0x02, 0x04, 0x08},      // Row 3 = Row 1, avoiding if-statement in the "buffer_write" function
  {0x00, 0x10, 0x20, 0x40, 0x80},      // Row 4 = Row 2
};

//Array to buffer the current pattern, again one bigger than needed for easier use of indexes
byte buffer_pattern[5][5][5];

//Function to store the LED to be turned on to the buffer
void buffer_write(byte x, byte y, byte z) {
  buffer_pattern[x][y][z] = hex[x][y];
}

//Function to shift out the buffer. Each latch-cycle displays one level (8 LEDs for each register),
//meaning that the registers need to latch 4 times to display the whole cube one time
void buffer_shift() {
  for (byte level = 1; level < 5; level++) {              //z, iterating through all levels
    byte cache_8 = 0;                                   //needs to be reset with every iteration, storing final pattern for columns 1-8
    byte cache_16 = 0;                                  //columns 9-16
    //Column 1-8: "creating" byte for the first register by adding the bytes of each LED to get the final pattern
    for (byte row = 1; row < 3; row++) {                  //x, iterating through first 2 rows
      for (byte column = 1; column < 5; column++) {   //y, iterating through the 4 columns in each row
        cache_8 = cache_8 | buffer_pattern[row][column][level];
      }
    }
    //Column 8-16: Same procedure as before, now for the 2nd register
    for (byte row = 3; row < 5; row++) {                  //x, iterating through last 2 rows
      for (byte column = 1; column < 5; column++) {   //y, iterating through the 4 columns in each row
        cache_16 = cache_16 | buffer_pattern[row][column][level];
      }
    }
    shift(cache_8, cache_16 , level);             //shifting the pattern for the whole level, 4 times for the whole cube
    delay(t);                                     //delay, so that the LEDs are on for longer, makes them shine brighter
    //delayMicroseconds(t);
  }
}
//Clearing the buffer. Necessary because only 1s get filled into the buffer, but no 0s
//Meaning that existing 1s only get overwritten by another 1 if buffer does not get cleared
void buffer_clear() {
  for (byte x = 1; x < 5; x++) {
    for (byte y = 1; y < 5; y++) {
      for (byte z = 1; z < 5; z++) {
        buffer_pattern[x][y][z] = 0;
      }
    }
  }
}

//Shifting the pattern from function "buffer_shift"
void shift(byte cache_8, byte cache_16, byte level) {
  digitalWrite(outputenable, HIGH);
  digitalWrite(latchPin, LOW);
  SPI.transfer(hex[1][level]);
  SPI.transfer(cache_16);
  SPI.transfer(cache_8);
  digitalWrite(latchPin, HIGH);
  digitalWrite(outputenable, LOW);
}


void setup() {
  pinMode(outputenable, OUTPUT);
  digitalWrite(outputenable, HIGH);                           //Disabling output, preventing whole cube from lighting up on startup
  SPI.begin();
  SPI.beginTransaction(SPISettings(800000, MSBFIRST, SPI_MODE0));
  pinMode(latchPin, OUTPUT);
  randomSeed(analogRead(0));
  //Clearing registers to be sure everything is off
  buffer_clear();
  buffer_shift();                                             //Clearing registers
  digitalWrite(outputenable, LOW);                            //Enabling output, startup complete
}

void loop() {
  //cube_outline();

  //moving_plane();

  //bouncing_plane();

  //raindrops();

  //diagonal line
  for (byte i = 1; i < 5; i++) {
    buffer_write(i, i, i);
  }
  buffer_shift();
  buffer_clear();
}

(Right, so I actually checked it in the IDE!)

So I haven't quite figured it all out, but explain to me, this is a static pattern, what exactly is this "ghosting" effect?  Have a picture?

PaulRB

Maybe try lighting one led in the cube (while multiplexing), flashing on for one for 1s, off for 1s. Do you see ghosting then? If so, which led(s)? Always in the same led ghosting? Then try other single leds. Do you always see ghosting? If so, see if you can figure out the relationship between the led being flashed and the led that is ghosting. There is probably some pattern to be found.

Just_some_dude

#23
Aug 09, 2019, 05:57 pm Last Edit: Aug 09, 2019, 11:35 pm by Just_some_dude Reason: Adding pictures that were too large
OK, so edited to a plausibly readable version, this was the last code you posted:
Thank you! Since you asked: I started the indexes with 1 because it made more sense to me at the time. I just didn't bother to change it since I don't think it is a huge issue.


Here you can see one column. The top LED is supposed to be on, the two below shouldn't. It is not that bright actually, the camera enhanced it. The third LED from the top is only visible in a dark room.




Here you can see the diagonal line. There are a lot of reflections, because I did not think of painting the LEDs from below. But you can also see the ghosting LEDs below the diagonal LEDs.




In words: I try to light (1,1,1), (2,2,2), (3,3,3),(4,4,4), but I also see a weak light for (1,1,4), (2,2,1), (3,3,2), (4,4,3)  and a very weak light in (1,1,3), (3,3,1), (3,3,4), (4,4,2).

Projected into 2D it would look like this (Edit: The picture describes a side-on view):




Just_some_dude

Maybe try lighting one led in the cube (while multiplexing), flashing on for one for 1s, off for 1s. Do you see ghosting then? If so, which led(s)? Always in the same led ghosting? Then try other single leds. Do you always see ghosting? If so, see if you can figure out the relationship between the led being flashed and the led that is ghosting. There is probably some pattern to be found.
Ok I tried it with all 64 LEDs and got the same result for each one: When flashing one LED for one second, I see ghosting in all LEDs in that column. I made sure it's no reflection.
I then turned up the delay time after shifting out the bytes so that the desired LED actually stayed on for half a second. I noticed that the other LEDs were flashing very shortly when turning the desired LED on. After the inital flash they stayed off until the next time the desired LED was turned on again.

PaulRB

#25
Aug 09, 2019, 08:12 pm Last Edit: Aug 09, 2019, 08:14 pm by PaulRB
Quote
Projected into 2D it would look like this:
2D protection from what point of view? Top-down, side-on? Are the ghosts always in the same column as a led which is on?

If so, it sounds like the MOSFETs are not switching off quickly. But the '595 should be capable of doing this quickly. How long are the wires between the '595 and the MOSFETs?

Just_some_dude

2D protection from what point of view? Top-down, side-on? Are the ghosts always in the same column as a led which is on?

If so, it sounds like the MOSFETs are not switching off quickly. But the '595 should be capable of doing this quickly. How long are the wires between the '595 and the MOSFETs?
It's from a side-on view. Yes, the ghosts are always in the same column. The cables are 10cm jumper wires. At the moment everything is still on a breadboard, if that matters.

Paul__B

If so, it sounds like the MOSFETs are not switching off quickly. But the '595 should be capable of doing this quickly.
And for that very reason, you do not want to use ~OE on that shift register.

How long are the wires between the '595 and the MOSFETs?
Hmmm, wouldn't have thought that would be significant.  :smiley-eek:

Still cannot see the problem either.  Still looking!

The 100 µF capacitor on each register is unnecessary, the 0.1 µF is plenty.  :smiley-eek:

PaulRB

Quote
And for that very reason, you do not want to use ~OE on that shift register.
Yes, of course! The MOSFET gates need to discharge through the 595 outputs. @Just_some_dude forget I suggested that, connect the OE of the third 595 back to ground.

But the ghosting was present before that change. The change should have made matters worse, but it didn't.

Maybe try 10K between the MOSFET gates and ground?

Paul__B

That appears to already be in the schematic, FWIW.

While it obviously is not as I would have done it myself and the code seems rather convoluted, I cannot see the basis for the ghosting yet it must be in there somewhere!  :smiley-eek:

Go Up