Go Down

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

Paul__B

By the way, try the code exactly as I last posted it.  :smiley-lol:

Just_some_dude

#31
Aug 10, 2019, 03:52 pm Last Edit: Aug 15, 2019, 11:44 am by Just_some_dude
The 100 µF capacitor on each register is unnecessary, the 0.1 µF is plenty.  :smiley-eek:
Is there a rule of thumb for that? I read somewhere that you should put a smaller capacitor with 0.01µF-0.1µF as close as possible to the chip, and one bigger with 10µF-100µF in the proximity. At least for every other chip, but better for every chip. Actually the capacitors I am using are only 0.068µF, but I forgot to update my schematic. Sorry for that.

@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?
Yes, it didn't make it worse. I connected it back to ground.

The MOSFETs are already in place as @Paul__B mentioned.

Edit: meant to say: The pull-downs on the MOSFET gates [...].

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:
Ahhh it hurts, I tried my best :D
But it's my first real project, so I think it can't be perfect. Do you have any suggestions for improvement? I think you are especially not impressed by my code, while I'm just glad that I got it running :D

By the way, try the code exactly as I last posted it.  :smiley-lol:
I did, unfortunately same result.

PaulRB

The MOSFETs are already in place as @Paul__B mentioned.
I don't understand. I was trying to suggest some 10K pull-downs on the MOSFET gates.

david_2018

Could you post a picture of the breadboard to show the actual wiring?

Just_some_dude

I don't understand. I was trying to suggest some 10K pull-downs on the MOSFET gates.
Sorry, I meant to say the pull-downs on the MOSFET gates are already in place.

Could you post a picture of the breadboard to show the actual wiring?
Well...it is a huge mess, and I would rather not show it :D
It's really hard to see on a picture. But I attached some pictures.
The little breadboard is not in use for the code that is discussed right now.

david_2018

In your buffer_shift() function, try turning off all the LEDs and the MOSFETs before writing out the new values.  It could be that the shift registers directly driving the LEDs are switching faster than the MOSFETs, causing the wrong LEDs to very briefly turn ON before the MOSFET has had time to switch to the next level.

Code: [Select]

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(0,0,0);  //<<<< add this line to turn off all LEDs before writing out new pattern >>>>
    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);
  }
}


Paul__B





Regarding the capacitors, the point is that the smaller ceramics are suppressing impulses caused by the switching of the CMOS chips themselves which are of significance because even short lengths of PCB track conveying power to the chips will have significant inductance.  The larger capacitors are more to absorb surges from bulk switching events of the whole assembly and compensating for resistance in the wiring rather than inductance, thus only one per whole section is really required.

Now we are reminded that you do not have a PCB, but a breadboard.  In fact, you have not placed the 0.068µF capacitors across the chips.  Instead, you have placed them across the power busses which is useful in itself, but not as effective and the electrolytics are effectively all in the one place anyway.

The ceramics - need long wires for the breadboard - really should be bridged directly across the chips themselves, pins 8 and 16.  On a PCB this is generally done by running the Vcc track under the chip to the ground end and placing the capacitor immediately at the end of the chip.  Whether it will make a difference in your breadboarded setup I don't know; I still suspect there is something in your code we haven't quite twigged to and it will be interesting to see what David's suggestion achieves.

PaulRB

#37
Aug 11, 2019, 08:33 am Last Edit: Aug 11, 2019, 08:50 am by PaulRB
I have to say you've done an amazing job to get this far, breadboarding with that technique. I don't think I could have done that without multiple wiring errors.

There are other techniques you can adopt using breadboards. I prefer to use smaller breadboards that can be clipped together in different configurations to suit the circuit, and use solid core wire cut to length and laid flat to the breadboard. Here's a cube I built on breadboard as an example:

The Nano here is not even part of the final circuit. Its running the ArduinoISP sketch to upload code to the attiny85 in the foreground, which controls a max7219 which drives the cube. Its not easy to see in this picture, but the "cube"is actually in two separate halves of 2x4x4 each.

Just_some_dude

In your buffer_shift() function, try turning off all the LEDs and the MOSFETs before writing out the new values.  It could be that the shift registers directly driving the LEDs are switching faster than the MOSFETs, causing the wrong LEDs to very briefly turn ON before the MOSFET has had time to switch to the next level.
I am really sorry to say it once again, but I tried it according to your suggestion, and unfortunately the effect remains.

Now we are reminded that you do not have a PCB, but a breadboard.  In fact, you have not placed the 0.068µF capacitors across the chips.  Instead, you have placed them across the power busses which is useful in itself, but not as effective and the electrolytics are effectively all in the one place anyway.
Thank you for the explanation. I had trouble getting the ceramics in there so I thought it would be close enough. I will try to change it.

I have to say you've done an amazing job to get this far, breadboarding with that technique. I don't think I could have done that without multiple wiring errors.

There are other techniques you can adopt using breadboards. I prefer to use smaller breadboards that can be clipped together in different configurations to suit the circuit, and use solid core wire cut to length and laid flat to the breadboard.
Thank you :) I didn't know of this technique, definitely looks a lot cleaner! Also looks like the max7219  makes the circuit a bit simpler. Would it make any sense to use multiple of these for a 8x8x8 cube? I have no idea how that chip works.

PaulRB

An 8x8x8 cube could be done with max7219, but I don't know if it would be the easiest way. Each chip could control one layer of 64 LEDs and 8 chips would be needed. The layers controlled by each chip could be horizontal or vertical, but would need to be held in position with the other layers to form a cube, while insulating the layers from each other.

The max7219 is a purpose designed led driver chip (unlike 74hc595). It performs the multiplexing itself, rather than relying on the MCU to do that. It has constant-current outputs so that series resistors are not needed, and multiple chips can be chained together so that only 3 Arduino pins are needed to control them all. The chip contains both anode and cathode drivers, so that extra transistors are not needed, and can provide much more current than 74hc595 leading to a brighter display.

Paul__B

#40
Aug 12, 2019, 12:30 am Last Edit: Aug 12, 2019, 12:44 am by Paul__B Reason: Spelling
Also looks like the max7219  makes the circuit a bit simpler. Would it make any sense to use multiple of these for a 8x8x8 cube? I have no idea how that chip works.
That is of course, what I pointed out in #2.  It drives an 8 by 8 matrix so you can easily  make that into a 4 by 4 by 4 cube.

For an 8 by 8 by 8 cube you would have eight entirely separate planes, each driven by a single MAX7219.  The chips themselves chain one to the next, being driven by only 3 pins and their behaviour is essentially that of a set of 74HC595s (each chip appears as two 8-bit registers which in turn address 14 control registers for data and functions).  Quite simple to code and used for "times square" display as 8 by 32 or 8 by 64 modules.

The point is that the MAX7219 performs all of the multiplexing for you, requiring only to be updated when you need to change the pattern.

Now the downside is that there is no common connections to the 8 by 8 planes, so you would most likely mount them in "toast rack" style with insulating spacers between and the row drives running down the edges as a group.  The upside as well as vastly easier programming, is massively greater brightness with good visibility in daylight.

And a cheap way to approach using them is to just buy eight of these kits:


Or these ones

which used to be more expensive but are now actually cheaper and more useful if you with to stack matrix arrays.

The point is that you do not install the matrix arrays themselves - or their socket pins, but just solder to the positions on the PCB and you have a durable and reliable assembly to drive your own matrix arrays or in this case, cube.

Just_some_dude

Thank you for the information guys :)

I'll definitely keep it in mind. I was just wondering if it is an option (for the 8x8x8), because it's getting a bit frustrating that the ghosting still remains, and maybe it might be even worse for a bigger cube.

But as for now I will work with the 74HC595's, as my cube is soldered accordingly. Besides the ghosting it also works quite well, the brightness is sufficient in my opinion, and I like that it is an actual cube and not "toast rack" style.

david_2018

One last thing to try, put a short delay between turning everything off and outputting the new values.

Just_some_dude

One last thing to try, put a short delay between turning everything off and outputting the new values.
Do you mean like this? If so, I already tried that. I do not understand how it is even possible that the ghosting still appears.  ::)

Code: [Select]

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(0,0,0);  //<<<< add this line to turn off all LEDs before writing out new pattern >>>>
    delay(1);
    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);
  }
}

PaulRB

#44
Aug 12, 2019, 05:54 pm Last Edit: Aug 12, 2019, 06:04 pm by PaulRB
I do not understand how it is even possible that the ghosting still appears.  ::)
Ghosting is a common problem that is asked about on this forum, for cubes, 2D led matrices and 7-segment displays. I can't remember a case where its taken this long to find and fix the problem.

Ghosting is mostly caused by a commonly made error in the code where the led layer drivers are not switched off before the next column data is shifted out.

The next most common cause the hardware design error of relying on the propagation delays of the shift registers being exactly equal. I've never understood how the differences in propagation delays can be enough to cause anything visible to the human eye, but using the OE pins has always fixed that, as far as I can remember.

This problem, at the moment, does not appear to be either of the above.

Do you have any spare leds left over from building the cube? Try setting up a pattern with a single led that is on and you can see a ghost below/above it. Then disconnect the entire cube and attach one led to the shift register output and the MOSFET corresponding to the ghost position. Do you see the ghost? If so, replace the led with another colour, e.g. red. Still see the ghost? If not, add a second led in the position corresponding to the led which is on (it should of course light). Does the ghost appear in the other led now?

Go Up