0

I'm trying to control a LED strip that has a custom protocol (developed above of I2C).

But in my tests i was successful figuring out how it works :

You set Clk to zero , you send a bit in the data line , then you set Clk to high. Based on the pixels number , i should send 16bits for each color (Red Green Blue).

I was able to generate a Clock signal at 8MHz with this code :

const byte Clock = 9;
const byte Data = 10;
void setup ()
{
 pinMode (Clock, OUTPUT);
 pinMode (Data, OUTPUT); 
 digitalWrite(Data, HIGH);
 TCCR1A = bit (COM1A0);
 TCCR1B = bit (WGM12) | bit (CS10);
 OCR1A = 0; 
 } 
 void loop ()
 {
 ...
 } 

My questions : How could i send data at that specific time when the clock is at zero ?

Note that using digitalWrite() function was not working due to the frequency limitation of that function.

Thanks for any helpful information. enter image description here

enter image description here

enter image description here

asked Jun 11, 2020 at 9:55
13
  • @Nick Gammon : i think i have to mention you :p Commented Jun 11, 2020 at 9:58
  • 2
    That sounds more like SPI than I2C to me. You can change the clock polarity and the sampling edge by changing the SPI mode. Commented Jun 11, 2020 at 10:14
  • The SPI sends bytes separated with a small time interval , is't possible to send multiple bits with no time interval ? Commented Jun 11, 2020 at 11:01
  • 1
    When you have a synchronous clock there is no concept of "time interval". Time is irrelevant. That's why you have a clock signal. Only the change of signal level in the clock is relevant. If you have something that requires data at precise times with no variance in the timing then you don't have a clock signal, and the communication is asynchronous (like UART). Commented Jun 11, 2020 at 11:08
  • 2
    Thank you for this clear and simple clarification of how SPI works , i'm sure SPI is the choice to go with , the above code turns on all the LEDs with high intensity since data is always at 1. Now i'll try to instantiate an SPI communication with the LEDs and see how it works. Commented Jun 11, 2020 at 11:50

2 Answers 2

0

It sounds like you have some misconceptions.

In order to work with clocked signals like in SPI, you set your data line(s) to the desired value, and then raise the clock signal from low to high. The receiving device detects the low to high transition and reads the state of the data lines.

If you did it in the other order (switch the clock signal from low to high, then set the data pin(s).) then the receiver would detect the clock rising edge and try to read the data value before it was set correctly.

With a clock line like in your setup, the communication doesn't rely on fixed timing. The clock line tells the receiver when the data is available, and you can use whatever clock timing you want (up to the max speed supported by the hardware.)

answered Jun 11, 2020 at 14:29
1
  • Absolutely right , i figure out the solution after a nightmare of testing. The problem was actually with the LED driver ,it's not working with any common serial protocol. Thanks for the help Commented Jun 12, 2020 at 11:08
0

After a night of continuous tests i figure out how to control correctly the LED strip using the following :

1- To apply any RGB value (a pixel) you have to send a compete frame of data to all the pixels. In my strip i have 12 pixels ,so to turn for example the first pixel into red , i have to send 11 zero pixels then the red pixel.

2- The delay and timing as mentioned above by @Majenko was the key, you just set the data and pulse the clk , that easy.

3- the protocol used isn't SPI or I2C , it's a custom protocol based on a custom driver developed by a private company (not a driver for general use or market , it was dev for a big wall lighting project).

#define setPin(b) ( (b)<8 ? PORTD |=(1<<(b)) : PORTB |=(1<<(b-8)) )
#define clrPin(b) ( (b)<8 ? PORTD &=~(1<<(b)) : PORTB &=~(1<<(b-8)) )
#define Data 7
#define Clk 9
void setup() {
pinMode(Data,OUTPUT);
pinMode(Clk, OUTPUT);
Serial.begin(9600);
}
void loop() {
int i, j, k, q, r, lim_j, lim_i;
int red, green, blue;
for(k=0; k<12; k++)
{
r= k%3;
lim_j = 2 - r;
q = k/3;
lim_i = 3 - q;
Serial.print(lim_i); Serial.println(lim_j);
clrPin(Clk);
delayMicroseconds(5);
setPin(Clk);
delayMicroseconds(5);
for(i=0; i<4; i++)
{
 for(j=0; j<3; j++)
 {
 if(i==lim_i && j==lim_j)
 one_pixel(1200, 0, 0); 
 else
 one_pixel(0, 0, 0);
 }
}
clrPin(Clk);
delay(1000);
}
}
int one_pixel(int red, int green, int blue)
{
rapid_serialize(red);
delayMicroseconds(5);
rapid_serialize(green);
delayMicroseconds(5);
rapid_serialize(blue);
delayMicroseconds(5);
clrPin(Clk); 
}
inline void rapid_serialize (uint16_t color) //just a copy for now , not a pointer
{ 
uint16_t bit_shift = 32768;
while (bit_shift)
{
 clrPin(Clk);
 bit_shift = bit_shift>>1;
 if ((bit_shift & color) == 0)
 clrPin(Data);
 else 
 setPin(Data);
 delayMicroseconds(5);
 setPin(Clk);
 delayMicroseconds(5);
 }
 }
answered Jun 12, 2020 at 11:06

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.