Friday 1 April 2016

Something completely different - a PIC16 i2c to ws2812 LED driver

I've been messing around with some ws2812 LEDs and want to make a computer for my 18month old daughter. I've decided on a boxed up Raspberry PI with some WS2812 LEDs and some big round one-arm-bandit buttons I got from China. The buttons came with white LEDs but I found that some IOT modules neopixels fit nicely!

Now, it is theoretically possible to drive WS2812 LEDs direct from the PI but that uses the PWM system and I want to be able to play video and sound back whilst the LEDs are going so that's a non-starter.

So, I decided to use the i2c bus to send the LED info out of the PI and then to use a PIC16F to interface to the LEDs. I've not seen anything on the net that does this without external circuitry. Getting the timing right in a 16F is a challenge. However, at 20MHz it is possible to get the correct timings for the LEDs and loop through a buffer putting out the bits. I decided to use a PIC16F88 - I have a lot of them!

The main part of the problem is how to get each bit and turn the port on off, in a six cycle loop with different mark/space ratios for 0's and 1's. I faffed around a bit and got the capture compare/PWM module to do the actual pulses and a tight 6 cycle loop to do each bit for each byte. There is a small each byte has an extra pause between them but it doesn't seem to hurt.

The code accepts i2c data on address 0x24 up to 96 bytes can be sent. Data is sent out to the LED's on PORTB. No external parts needed except two pull up resistors for the i2c lines and the crystal can caps.

The i2c code is pretty simple and runs in a polling loop that waits for a start bit, then a valid address then just keeps reading bytes until a P bit comes along or the buffer is full. Then the number of bytes read are sent out the LEDs.

This should work with any i2c bus not just the PI.

If you'd like the code get in touch.





D