Flashing Sign Lights with Krida 8 channel AC dimmer

I’d recently bought a Krida Electronics 8 Channel AC Dimmer with the intention of using it to flash and dim the bulbs in a Marquee letter sign (a sign with bulbs inside a letter).

Krida provide 4 test sketches on a google drive link, I’ve linked to them here if you want to look at all of them and there’s a youtube video on their channel of the 4 test sketches running here. I’ve set up a test rig thats almost identical to the one they’re using in the video.

I was wondering if someone with more knowledge than me could help me to understand why test sketch 1, 2 and 3 don’t work correctly, but sketch 4 works.

Heres the code for sketch 1, i’ll not post the code for 2 and 3 as they’re pretty much the same.

#include <TimerOne.h>

unsigned char channel_1 = 4;  // Output to Opto Triac pin, channel 1
unsigned char channel_2 = 5;  // Output to Opto Triac pin, channel 2
unsigned char channel_3 = 6;  // Output to Opto Triac pin, channel 3
unsigned char channel_4 = 7;  // Output to Opto Triac pin, channel 4
unsigned char channel_5 = 8;  // Output to Opto Triac pin, channel 5
unsigned char channel_6 = 9;  // Output to Opto Triac pin, channel 6
unsigned char channel_7 = 10; // Output to Opto Triac pin, channel 7
unsigned char channel_8 = 11; // Output to Opto Triac pin, channel 8
unsigned char CH1, CH2, CH3, CH4, CH5, CH6, CH7, CH8;
unsigned char CHANNEL_SELECT;
unsigned char i=0;
unsigned char clock_tick; // variable for Timer1
unsigned int delay_time = 150;

unsigned char low = 70;
unsigned char high = 5;


unsigned char CH[]={CH1,CH2,CH3,CH4,CH5,CH6,CH7,CH8};

void setup() {

//CH1=CH2=CH3=CH4=CH5=CH6=CH7=CH8=95;
  
pinMode(channel_1, OUTPUT);// Set AC Load pin as output
pinMode(channel_2, OUTPUT);// Set AC Load pin as output
pinMode(channel_3, OUTPUT);// Set AC Load pin as output
pinMode(channel_4, OUTPUT);// Set AC Load pin as output
pinMode(channel_5, OUTPUT);// Set AC Load pin as output
pinMode(channel_6, OUTPUT);// Set AC Load pin as output
pinMode(channel_7, OUTPUT);// Set AC Load pin as output
pinMode(channel_8, OUTPUT);// Set AC Load pin as output
attachInterrupt(1, zero_crosss_int, RISING);
Timer1.initialize(100); // set a timer of length 100 microseconds for 50Hz or 83 microseconds for 60Hz;
Timer1.attachInterrupt( timerIsr ); // attach the service routine here

}

void timerIsr()
{
clock_tick++;

if (CH1==clock_tick)
{
digitalWrite(channel_1, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_1, LOW); // triac Off
}

if (CH2==clock_tick)
{
digitalWrite(channel_2, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_2, LOW); // triac Off
}

if (CH3==clock_tick)
{
digitalWrite(channel_3, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_3, LOW); // triac Off
}

if (CH4==clock_tick)
{
digitalWrite(channel_4, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_4, LOW); // triac Off
}

if (CH5==clock_tick)
{
digitalWrite(channel_5, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_5, LOW); // triac Off
}

if (CH6==clock_tick)
{
digitalWrite(channel_6, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_6, LOW); // triac Off
}

if (CH7==clock_tick)
{
digitalWrite(channel_7, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_7, LOW); // triac Off
}

if (CH8==clock_tick)
{
digitalWrite(channel_8, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_8, LOW); // triac Off
}


}



void zero_crosss_int() // function to be fired at the zero crossing to dim the light
{
// Every zerocrossing interrupt: For 50Hz (1/2 Cycle) => 10ms ; For 60Hz (1/2 Cycle) => 8.33ms
// 10ms=10000us , 8.33ms=8330us

clock_tick=0;
}



void loop() {


CH1=high;CH2=low;CH3=low;CH4=low;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=high;CH3=low;CH4=low;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=high;CH4=low;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=high;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=high;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=low;CH6=high;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=low;CH6=low;CH7=high;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=low;CH6=low;CH7=low;CH8=high;
delay(delay_time);


CH1=low;CH2=low;CH3=low;CH4=low;CH5=low;CH6=low;CH7=high;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=low;CH6=high;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=low;CH5=high;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=low;CH4=high;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=low;CH3=high;CH4=low;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);
CH1=low;CH2=high;CH3=low;CH4=low;CH5=low;CH6=low;CH7=low;CH8=low;
delay(delay_time);

}

The bulbs light up one by one right after you turn the whole setup on but they seem to jump to the last line in the loop skipping all the steps regardless of what you set the delay_time to. I’m after trying to understand whats missing in the code or whats going wrong and causing it not to function like it does in the video.

Here the code for test sketch 4 that I can make work correctly straight out the box, heres a link to how that one looks in the youtube video.

#include <TimerOne.h>

unsigned char channel_1 = 4;  // Output to Opto Triac pin, channel 1
unsigned char channel_2 = 5;  // Output to Opto Triac pin, channel 2
unsigned char channel_3 = 6;  // Output to Opto Triac pin, channel 3
unsigned char channel_4 = 7;  // Output to Opto Triac pin, channel 4
unsigned char channel_5 = 8;  // Output to Opto Triac pin, channel 5
unsigned char channel_6 = 9;  // Output to Opto Triac pin, channel 6
unsigned char channel_7 = 10; // Output to Opto Triac pin, channel 7
unsigned char channel_8 = 11; // Output to Opto Triac pin, channel 8
unsigned char CH1, CH2, CH3, CH4, CH5, CH6, CH7, CH8;
unsigned char CHANNEL_SELECT;
unsigned char i=0;
unsigned char clock_tick; // variable for Timer1
unsigned int delay_time = 50;

unsigned char low = 75;
unsigned char high = 5;
unsigned char off = 95;


void setup() {
  
pinMode(channel_1, OUTPUT);// Set AC Load pin as output
pinMode(channel_2, OUTPUT);// Set AC Load pin as output
pinMode(channel_3, OUTPUT);// Set AC Load pin as output
pinMode(channel_4, OUTPUT);// Set AC Load pin as output
pinMode(channel_5, OUTPUT);// Set AC Load pin as output
pinMode(channel_6, OUTPUT);// Set AC Load pin as output
pinMode(channel_7, OUTPUT);// Set AC Load pin as output
pinMode(channel_8, OUTPUT);// Set AC Load pin as output
attachInterrupt(1, zero_crosss_int, RISING);
Timer1.initialize(100); // set a timer of length 100 microseconds for 50Hz or 83 microseconds for 60Hz;
Timer1.attachInterrupt( timerIsr ); // attach the service routine here

}

void timerIsr()
{
clock_tick++;

if (CH1==clock_tick)
{
digitalWrite(channel_1, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_1, LOW); // triac Off
}

if (CH2==clock_tick)
{
digitalWrite(channel_2, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_2, LOW); // triac Off
}

if (CH3==clock_tick)
{
digitalWrite(channel_3, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_3, LOW); // triac Off
}

if (CH4==clock_tick)
{
digitalWrite(channel_4, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_4, LOW); // triac Off
}

if (CH5==clock_tick)
{
digitalWrite(channel_5, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_5, LOW); // triac Off
}

if (CH6==clock_tick)
{
digitalWrite(channel_6, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_6, LOW); // triac Off
}

if (CH7==clock_tick)
{
digitalWrite(channel_7, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_7, LOW); // triac Off
}

if (CH8==clock_tick)
{
digitalWrite(channel_8, HIGH); // triac firing
delayMicroseconds(5); // triac On propogation delay (for 60Hz use 8.33)
digitalWrite(channel_8, LOW); // triac Off
}


}



void zero_crosss_int() // function to be fired at the zero crossing to dim the light
{
// Every zerocrossing interrupt: For 50Hz (1/2 Cycle) => 10ms ; For 60Hz (1/2 Cycle) => 8.33ms
// 10ms=10000us , 8.33ms=8330us

clock_tick=0;
}



void loop() {


         for (i=95;i>10;i--)
          {
            CH1=CH2=CH3=CH4=CH5=CH6=CH7=CH8=i;
            delay(delay_time);
          }
          
           for (i=10;i<95;i++)
          {
            CH1=CH2=CH3=CH4=CH5=CH6=CH7=CH8=i;
            delay(delay_time);
          }





}

I reckon it'd be a lot better code if it was properly written 'software PWM' running at some pure multiple of the mains frequency rather than using nasty delays.

The existing Arduino hardware PWM would be too fast / not phase-locked from the mains cycles.
That would also make it easier to integrate other functions into the same Arduino sketch

Good job i've got 6 months to do this project in. I have no idea how i'd even go about doing that, can you recommend me some kind of starting point?

Search for software PWM.
I’ve done 72 channels on an 8MHz PIC in the past.
The only extra thing you need to add is the interrupt to reset the counter - just like it is in the existing code.

On a 16MHz cpu, you can possibly run the PWM cycles as fast as the loop() allows without any visible degradation. At least 4x the mains frequency is probably enough. Needs to be tested - esp with LEDs on the load. Incandescent loads will provide some visual smoothing.

Thanks, i'll do some reading up on that.

Out of curiosity, do you know why the code provided for test sketch one by Krida Electronics fails to loop? It'd be helpful to me to understand whats causing the issues.

To be honest, that sample code is so poorly written that I didn't bother loading it.

The structure and style is non-existent - possibly written by a high school student to help his uncle.
If it works - it's because he kept trying, not because it was thought through with understanding!

Sorry - harsh, but you'd be a lot better off studying the concept, hardware, and understanding what you need to achieve - then spending a week to make it work!

Get one channel working - without any delays(), then spin that out into an array of channels.

Here's my old project - more complex than yours - but similar code.
72-channel PWM on 8MHz
(Only 8x3 (=24) channels shown)

Its annoying that was the code thats been provided with board. I've emailed the guys who make them to tell them that but i've not heard anything back from them, hopefully I will.

Progress is being made at my end though, I've been reading posts from people who've built their own multi channel triac dimmers to see what approach they've taken. So far I've got all 8 channels to cycle on left to right and back off again, and most importantly without the bulbs flickering...which is a start.

Thanks for you help so far, I've still got a long way to go with this.

OK, here’s my old main() loop from PIC-land.
It’s not beautiful, but it works. It was definitely a hack for some fun with a bunch of RGB LEDs I had on hand

The ISR in this code is a ‘timer’ interrupt, but you can ignore that and work with a zero-crossing interrupt if you need - or choose a zero-crossing SSR that does the work for you

The external calls are self-explanatory, this isn’t meant to write the code for you but to give some ideas !!
It does add some interesting code to ‘mix’ between colours - as well as values for the non-linear response of the RGB response in the LEDs

main.c (11 KB)