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

  • @Nick Gammon : i think i have to mention you :p – Mohammed BENHADINE Jun 11 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. – Majenko Jun 11 at 10:14
  • The SPI sends bytes separated with a small time interval , is't possible to send multiple bits with no time interval ? – Mohammed BENHADINE Jun 11 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). – Majenko Jun 11 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. – Mohammed BENHADINE Jun 11 at 11:50
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.)

| improve this answer | |
  • 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 – Mohammed BENHADINE Jun 12 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);
  }
 }
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.