Making one sketch from multiple (5) other sketches

Hello everbody

I am new to Arduino and I'm having some troubles with my project. I am making a dimmer that uses phase cutting (50Hz) to dim 230V lamps. It uses a triac that is turned on by an Arduino at the right time. My goal is to control 5 dimming channels seperately via bluetooth. I used this Instructable as a guide: http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/. The hardware wasn't a problem at all, but i'm struggling with the arduino software for it. I already changed the software from the Instructable to make it work via a bluetooth module (HC-06) and 6 dimming levels instead of up and down buttons.

My problem is that I want to control 5 triac circuits independently with one Arduino. I have been searching on how to do this, but I can't get it to work. I know that I'll have to make 5 AC_pin's (outputs to turn on the triacs), 5 dim's,...

I added the sketch that I'm using to drive 1 triac circuit as an attachment.

Thanks!

dimmer_project_v002_verkort.ino (2.88 KB)

Planning and Implementing an Arduino Program

How to do Several Things at a Time

Welcome to the Forum. Please read the two posts by Nick Gammon at the top of this Forum for guidelines on posting here, especially the use of code tags for source code. Many users are reluctant to open internet files, so using code tags actually helps us help you. Also, you can use Ctrl-T while your cursor is in the code window of the IDE to format your code into a standard C format.

I have a similar project I'm working on :slight_smile:
first thought is that once a triac is on it remains on until it crosses zero even if you stop commanding it to be on

so in you code you turn off the command for on a little late!
only showing relevant code:

void setup() {  // Begin setup
  attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
}

// **** When the interrupt is triggeres the output voltage is already rising and you still have the triac commanded on!!!!
void zero_cross_detect() {    
  digitalWrite(AC_pin, LOW);   // **** you finally command the triac off and this might be too late because the next ac cycle has already started!
}

now it might work for one triac but when you start adding more your delay may have failing results

void allpinslow()
{
    digitalWrite(AC_pin, HIGH); // should this be LOW ?
}

I think this might be the best way to handle your code.

volatile int Pins[5] = {3, 4, 5, 6, 7};              // list Triac pin as output
volatile int dim[5] = {40, 60, 128, 0, 90};              // list of Dimming level (0-128)  0 = on, 128 = 0ff

void dim_check() { // this is automatically triggered by a timer
  i++; // this will get reset to zero with zero_cross_detect()
  for (int pin = 0; pin < 5; pin++) { // 0~4 gives us 5 counts for our 5 outputs
    if (i >= dim[pin]) { // Lets latch the triac
      if(dim[pin] < 128) digitalWrite(Pins[pin], HIGH);  // turn on light (if dim is 128 we want it off so lets not even try to turn it on)   }
    if (i >= dim[pin]+1) { // We have latched the triac and now we are 75 uS (50Hz)  or 65 uS (60Hz) later. The triac latches until it crosses zero so we can turn off the enable
      if(dim[pin] > 0 )  digitalWrite(Pins[pin], LOW); // if we are at 0 we need to trip this asap so lets not turn the request of    }
  }
}

Thanks for the replies!

@zhomeslice

Thank you for your help!

I had some flickering problems when I wanted to dim less powerful lamps. This might be due to the signal to turn on the triac turning off too late like you mentioned.

I used the dimming levels 40-55-70-85-100-115 because everything under 40 didn't change the brightness of my lamps anymore (I use dimmable 12V AC LED lamps via a 230V to 12V transformer). I also don't want the lamps to be able to turn completely off. I want to add a physical switch before the triac circuit. Like that, I can come into the room and turn on the light switch to make the lights go on without always having to take my phone. :slight_smile:

I have one more problem that I couldn't figure out after searching around. I don't understand how I have to differentiate between the 5 channels when I want them to be at a specific dimming level. I am talking about this part of the code:

 if (!strcmp(inStr,"115a")){     
  {
    dim = 115;                             // not working of course
    
  }
 }

 if (!strcmp(inStr,"100a")){     
  {
    dim = 100;
    
  }
 }

 if (!strcmp(inStr,"85a")){     
  {
    dim = 85;
    
  }
 }

 if (!strcmp(inStr,"70a")){    
  {
    dim = 70;
    
  }
 }

 if (!strcmp(inStr,"55a")){     
  {
    dim = 55;;
    
  }
 }

 if (!strcmp(inStr,"40a")){ 
  {
    dim = 40;
   
  }
  }

If I send for example the word '115a' via the bluetooth module, I want the lamp on channel 1 (pin 3) to dim to level 115. I can't make that to work.

This is the code that I have right now:

#include <TimerOne.h>           // Avaiable from http://www.arduino.cc/playground/Code/Timer1

volatile int i=0;               // Variable to use as a counter of dimming steps. It is volatile since it is passed between interrupts
volatile boolean zero_cross=0;  // Flag to indicate we have crossed zero
volatile int Pins[5] = {3, 4, 5, 6, 7};              // list Triac pin as output
int rx=0;
volatile int dim[6] = {40, 55, 70, 85, 100, 115};              // list of Dimming level (0-128)  0 = on, 128 = 0ff
int freqStep = 75;              // This is the delay-per-brightness step in microseconds. It allows for 128 steps
char inSerial[15];
 
void setup() {  // Begin setup
  Serial.begin(9600);   
  pinMode(rx, INPUT);
  pinMode(Pins[5], OUTPUT);                          // Set the Triac pin as output
  attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);      // Go to dim_check procedure every 75 uS (50Hz)  or 65 uS (60Hz)
  // Use the TimerOne Library to attach an interrupt

}

void zero_cross_detect() {    
  zero_cross = true;               // set flag for dim_check function that a zero cross has occured
  i=0;                             // stepcounter to 0.... as we start a new cycle
  digitalWrite(Pins[5], LOW);
}                                 

// Turn on the TRIAC at the appropriate time
// We arrive here every 75 (65) uS
// First check if a flag has been set
// Then check if the counter 'i' has reached the dimming level
// if so.... switch on the TRIAC and reset the counter

void dim_check() { // this is automatically triggered by a timer
  i++; // this will get reset to zero with zero_cross_detect()
  for (int pin = 0; pin < 5; pin++) { // 0~4 gives us 5 counts for our 5 outputs
    if (i >= dim[pin]) { // Lets latch the triac
      if(dim[pin] < 128) digitalWrite(Pins[pin], HIGH);  // turn on light (if dim is 128 we want it off so lets not even try to turn it on)   }
    if (i >= dim[pin]+1) { // We have latched the triac and now we are 75 uS (50Hz)  or 65 uS (60Hz) later. The triac latches until it crosses zero so we can turn off the enable
      if(dim[pin] > 0 )  digitalWrite(Pins[pin], LOW); // if we are at 0 we need to trip this asap so lets not turn the request of    }
  }
}
}
}

void loop(){
    int i=0;
    delay(500);                                         
    if (Serial.available() > 0) {             
       while (Serial.available() > 0) {
         inSerial[i]=Serial.read(); 
         i++;      
       }
       inSerial[i]='\0';
      Check_Protocol(inSerial);
     }} 
     
void allpinslow()
{
digitalWrite(Pins[5], LOW);
} 

 void Check_Protocol(char inStr[]){   
  int i=0;
  Serial.println(inStr);
  
 if (!strcmp(inStr,"115a")){     
  {
    dim = 115;
    
  }
 }

 if (!strcmp(inStr,"100a")){     
  {
    dim = 100;
    
  }
 }

 if (!strcmp(inStr,"85a")){     
  {
    dim = 85;
    
  }
 }

 if (!strcmp(inStr,"70a")){    
  {
    dim = 70;
    
  }
 }

 if (!strcmp(inStr,"55a")){     
  {
    dim = 55;;
    
  }
 }

 if (!strcmp(inStr,"40a")){ 
  {
    dim = 40;
   
  }
  } 
}

Thank you once again! :slight_smile:

when you wish to set a value for the pin

int pin; // this should be up top
pin = 0; // this will alter the first pin in  your list
pin = 1; // this will alter the second pin in  your list
// make pin equal to the position of the pin in your pins array starting with 0 as the first postion
// now after setting what pin you wish to alter run your loop
if (!strcmp(inStr,"115a")){     
  {
    dim[pin] = 115;                             // not working of course  
  }
 }
//.....

I am unclear as to how you select which pin you wish to change using your phone

I created an app that exists out of 5 rows with 6 buttons. When the buttons are pressed they send a specific code to the arduino via the bluetooth module. The first row sends 115a, 100a... The second row 115b, 100b and so on with c, d and e for the following rows of buttons.

It would be easy to switch you number around to test for the Letter first then the number
"a115" for example

if (inStr[0] == 'a') pin = 0;

then you could easily test for the level

if (!strcmp(inStr + 1,"115")){  // adding 1 to the pointer to the string will skip the first character
   dim[pin] = 115;
}

or you could convert the string to a number

if (inStr[0] == 'a') pin = 0; // read the first character to see if it is the character 'a'
if (inStr[0] == 'b') pin = 1;
// etc.
dim[pin] = atoi(inStr+1); // inStr+1 skips the first character

for information on atoi() http://www.cplusplus.com/reference/cstdlib/atoi/