Go Down

Topic: WS2801 5050s Flicker at 5v, work fine at 4.7v? (Read 2701 times) previous topic - next topic

fungus


I'm a little suspicious of advice given in the form of 'the largest cap you have'.  I'm staring at the guts of an old Agilent power supply with 4" caps I could harvest (3000uF).  I would be more comfortable with a range (50, 100, 1000, 3000uF...).


That's probably a bit too big... :)
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

poodull

#16
Jan 05, 2013, 07:15 pm Last Edit: Jan 05, 2013, 07:23 pm by poodull Reason: 1
Okay, for closure here is my answer (I hate when people never follow up)

First, the caps I used (up to 470uF) never worked.  The flicker wasn't better or worse.  It basically had no effect.  I didn't do a lot of testing, but that was the initial results and then xmas came.

So today I rewrote the adafruit ws2801 library to work with ChipMax Mega32 and DSPI.  Spoiler alert:  it works at 5v now.  Here's what I did to fix that code:

First, the version I downloaded wouldn't compile because of a implicit type conversion in the header.  The clockport and dataport variables are int32s, not int8s.

Code: [Select]
 volatile uint32_t
   *clkport  , *dataport;   // Clock & data PORT registers


Now it still won't compile in MPIDE because there are (I found via other people's gripes) AVR specific SPI calls in the show() method.  But we want DSPI anyway so here's what you need to add:
//I'm being verbose because I had NO IDEA of how to do this before today.

change the #include <SPI.h> to <DSPI.h>.
Add this to the private declarations in the header to define the DSPI class
Code: [Select]
#if defined(__PIC32MX__)
 DSPI0    
   spi;
#endif

Next, fix the startSPI() method because SPI static class is now 'spi' member variable and the DSPI calls are slightly different:
Code: [Select]
void Adafruit_WS2801::startSPI(void) {

#if defined(__PIC32MX__)
 spi.begin();
 //spi.enableInterruptTransfer(); //if using spi.intTransfer()
 //spi.setBitOrder(MSBFIRST);
 spi.setMode(DSPI_MODE0);
 //spi.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker
 spi.setSpeed(1000000); //1 MHz is default i think
#else
 SPI.begin();
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE0);
 SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker
#endif
}

You'll need to change the SPI.end() call in updatePins() as well to lowercase 'spi' like so:
Code: [Select]
   if(hardwareSPI == true)
   {    
#if defined(__PIC32MX__)
     spi.end();
#else
     SPI.end();
#endif
   }

Lastly change the show method to call spi in one whack:
Code: [Select]
 if(hardwareSPI)
 {
#if defined(__PIC32MX__)
     //spi.transfer(pixels[i]); //old way, one byte at a time
     spi.setSelect(LOW);       //start the transfer
     spi.transfer(nl3, pixels); //new way, send array
     spi.setSelect(HIGH);      //stop the transfer
#else
   for(i=0; i<nl3; i++)
   {
     SPDR = pixels[i];
     while(!(SPSR & (1<<SPIF)));  //These are the AVR specific SPI calls that should never be in a library like this.
   }
#endif
 }


That should be it.  I might have missed a SPI to spi somewhere, but that's easy to figure out.  And just for completion (and for my own lookup later on), these are the hardware specific definitions I found online (that affect me of course):

Code: [Select]
//#define  __PIC32MX__ 1 //any Chipkit PIC
//#define  __32MX320F128H__ 1 //Uno32
//#define  __32MX795F512L__ 1 //Max32
//#define  __AVR_ATmega1280__ 1 //Mega1280


And one more piece of info on the Max32:  DSPI0 is NOT pins 50-53.  The DSPI0 pins are in the middle of the board (J13) and numbered from left to right, top to bottom from 1, pin 3 (middle left) is clock and pin 4 (middle right) is Data Out (http://www.digilentinc.com/Data/Products/CHIPKIT-MAX32/chipKIT%20Max32_rm.pdf).  That took forever to figure out because there's a ton of posts online that contradict each other.

TLDR:  Caps didn't fix anything for me, even large ones.  Going from bit-banging to DSPI fixed the issue entirely.

Go Up