Go Down

Topic: ShiftPWM support topic. Latest update: Schematics, high power LED's, LED strips (Read 83 times) previous topic - next topic

elcojacobs



It would be possible to use ShiftPWM to drive each row. The difference with a matrix and a chain is that in a matrix, you basically alternate in driving multiple chains. The maximum duty cycle for the LED's is 1/rows.
If each time you reset the counter, you also switch rows you can make some modifications to use it for matrices.
How would this be achieved? I don't see a reference to a counter inside the example code? Would it require another interrupt to fire when the counter reached 0? Sorry for the questions just trying to understand. I have a hand made matrix that I would like to try this out on. Thanks.


The counter is in the library code. If you can send me a schematic, I'll  have a look how much work it is to change the code for the matrix. It's quite popular so I might add a different version of shiftpwm to work with matrices. I cannot test it, because I don't have a led matrix.

cubaman

Hey, working with your code and am slightly confused as how you got this to work without a function really being created as to how this works or i simply can not find it...

// The macro below uses 3 instructions per pin to generate the byte to transfer with SPI
// Retreive duty cycle setting from memory (ldd, 2 clockcycles)
// Compare with the counter (cp, 1 clockcycle) --> result is stored in carry
// Use the rotate over carry right to shift the compare result into the byte. (1 clockcycle).
#define add_one_pin_to_byte(sendbyte, counter, ledPtr) .

which is than used in the intterupt routine by :
   add_one_pin_to_byte(sendbyte, counter, --ledPtr);

i understand that
                        if ledPtr >= counter, sendbyte(actually bit) = 1
                        else                       sendbyte(actually bit) = 0
but i don't see how its actually done.

The reason why i am asking is because i want to add this look-up table for gamma correction to create a more realistic appearance of how the lights should look and possibly create more performance.

Gamma array size: 64
Total PWM steps: 255
Gamma correction: .74

static int Gamma_Cor[64] = {
  0,  1,  2,  2,  2,  2,  3,  3,  3,  4,
  4,  5,  5,  6,  6,  7,  8,  9,  9, 10,
11, 12, 13, 14, 16, 17, 18, 20, 22,
23, 25, 27, 30, 32, 34, 37, 40, 43,
46, 50, 54, 58, 62, 66, 71, 76, 82,
88, 94,101,108,116,124,132,141,
151,162,173,184,197, 210,224,239,255
};

using look-up table during interrupt would yield:
   add_one_pin_to_byte(sendbyte, Gamma_Cor[counter], --ledPtr);
if i am not mistaken.

If the counter has to only go through 64 steps instead of 255 to complete a full pwm cycle, would that not cut down the need of the interrupt to send bytes out by 75% or so lessening the load of the program? 

elcojacobs

#57
Aug 29, 2011, 12:52 pm Last Edit: Aug 29, 2011, 12:54 pm by elcojacobs Reason: 1
You are confused by the fact that sendbyte contains 8 bits, for 8 pins when it is sent to the SPI. These bytes are put in by making clever use of the rotate over carry right (ror) instruction.
If we assume it starts at 0000 0000.

The the first bit, a 1, is put in by the ror instruction.
1000 0000

The the second bit, a 0, is put in by the ror instruction.
0100 0000

The the third bit, a 1, is put in by the ror instruction.
1010 0000

See that each time these 3 assembly instructions are executed, all bits already in the byte are shifted right (rotate right) and the new compare result (which is stored in the carry) is shifted in (over carry). After doing this 8 times, the sendbyte contains the new bits for 8 pins and is sent to the SPI.

If you want to use 64 levels, you can set maxbrightness to 63. What you are proposing is that the time between interrupts is not constant. You have 2 options to achieve that:
- change the timer compare register each interrupt
- leave the compare register and use 256 interrupts, but on values of the counter that are not in your lookup table, leave the interrupt immediately.

If you don't necessarily want the performance increase, but you do want the gamma correction, do it before the interrupt. Leave maxbrightness at 255 and create a function that does the gammacorrection before using the library functions.
Code: [Select]

unsigned char get_gamma_corrected_value(unsigned char original_value){
  unsigned char corrected_value;

// set correct value here;

 return corrected_value;
}


Then use the function like this:
Code: [Select]
ShiftPWM.SetOne(3, get_gamma_corrected_value(original_value));

milamber


It would be possible to use ShiftPWM to drive each row. The difference with a matrix and a chain is that in a matrix, you basically alternate in driving multiple chains. The maximum duty cycle for the LED's is 1/rows.
If each time you reset the counter, you also switch rows you can make some modifications to use it for matrices.
Investigating this some more, I think I understand. If I switch the column(using your above example) when the counter reaches 0 then each pwm cycle will happen on a new set of LED's. This would effectively drop the overall refresh rate by the number of columns being used.
Say you were using an 8x10 matrix at pwm speed 50hz. The 8 Rows being driven by the 595's and some other way of selecting the columns(there seem to be mulitple ways of doing this). It would take 10 PWM cycles to complete 1 refresh of the whole matrix. Meaning 5hz for the whole screen. Can your PWM cycle speed be increased high enough to bring the whole matrix up to 50hz? Does this mean straight multiplying the PWM hz by the number of columns, in this case equalling 500hz?

I am sorry if any of the above is incorrect. I am just trying to understand as I would like to use your library. I am trying to see if I could drive a 16x16 RGB matrix this way. ( if above is correct that would need 800hz for the pwm cycle but there would only be 6 SR's being driven)

spiltmidi

I have replicated this on a breadboard using common Cathode RGB LED's. You have stated above to look for "#define statement to invert the outputs, just toggle it to suit your LED's." I am unable to find the correct value to change in the code to suite my LED's. Sorry if this is clear as day, would you be able to assist me to find this to change.

The only #define I could find was "#define RGB2HSV_h" in the "hsv2rgb.h"

I am new to Arduino and this is my first play around.

Cheers in advance.

Go Up