luni, 25 martie 2013

Variator de tensiune pentru un bec cu Arduino (II)

    Mi-am facut un pic de timp sa finalizez placuta amintita in articolul initial (Variator de tensiune pentru bec folosind un Arduino) si sa conectez o dulie cu bec (60W/230V~) si un cablu cu stecher:
   La primele teste nu am obtinut rezultate, in sensul ca becul nu se aprinde, desi LED-ul se aprindea slab. Dupa ce am schimbat optocuplorul de comanda (MOC3040/MOC3041) cu MOC3020 si triacul (BT134/BT136) mi-am dat seama ca am omis un traseu. Dupa corectarea traseului de pe cablaj, am obtinut si rezultatele.
    Schema este cea "clasica" cu precizarile ca eu am folosit la detectorul trecerii prin zero un optocuplor 4N35 si 2 rezistente de 91K (se pot folsit si de 100k) iar puntea redresoare am recuperat-o dintr-o sursa de calculator, iar optocuplorul de comanda este MOC3020 MOC3040, dar merge foarte bine si MOC3041 (care are in plus partea de trecere prin zero).
    Semnalul de trecere prin zero l-am conectat la terminalul digital D2, iar comanda LED-ului si a MOC-ului la terminalul digital D3 de la Arduino.


   La primul test am folosit sketch-ul din articolul http://arduinodiy.wordpress.com/2012/10/19/dimmer-arduino/ deoarece are explicatii foarte detaliate in el:

/*
AC Voltage dimmer with Zero cross detection
Author: Charith Fernanado http://www.inmojo.com
License: Creative Commons Attribution Share-Alike 3.0 License. 


Attach the Zero cross pin of the module to Arduino External Interrupt pin
Select the correct Interrupt # from the below table:
(the Pin numbers are digital pins, NOT physical pins:
digital pin 2 [INT0]=physical pin 4 
and digital pin 3 [INT1]= physical pin 5)

 Pin    |  Interrrupt # | Arduino Platform
 ---------------------------------------
  2      |  0            |  All
  3      |  1            |  All
 18     |  5            |  Arduino Mega Only
 19     |  4            |  Arduino Mega Only
 20    |  3            |  Arduino Mega Only
 21     |  2            |  Arduino Mega Only
In the program pin 2 is chosen
 */

int AC_LOAD = 3;    // Output to Opto Triac pin
int dimming = 128;  // Dimming level (0-128)  0 = ON, 128 = OFF
/* Due to timing problems, the use of ‘0’ can sometimes make the circuit 
flicker. It is safer to use a value slightly higher than ‘0’
*/
void setup()
{
  pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
  attachInterrupt(0, zero_crosss_int, RISING);  
// Chooses '0' as interrupt for the zero-crossing
}
// the interrupt function must take no parameters and return nothing
void zero_crosss_int()  
// function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms  
  // Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle) For 60Hz => 8.33ms
  
  // 10ms=10000us
  // (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65
  int dimtime = (75*dimming);    // For 60Hz =>65     
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(AC_LOAD, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
                                 //(for 60Hz use 8.33)
  digitalWrite(AC_LOAD, LOW);    // triac Off
}
void loop()  {
 for (int i=5; i <= 128; i++)
{
 dimming=i;
 delay(50);
 }
 }

    Am realizat un filmulet numit ac light dimmer with Arduino (I), care prezinta functionarea:

   Am modificat un pic acest prim sketch pentru a avea o crestere, apoi o scaderere a intensitatii luminoase a becului cu incandescenta:


/*
AC Voltage dimmer with Zero cross detection
Author: Charith Fernanado http://www.inmojo.com
License: Creative Commons Attribution Share-Alike 3.0 License. 


Attach the Zero cross pin of the module to Arduino External Interrupt pin
Select the correct Interrupt # from the below table:
(the Pin numbers are digital pins, NOT physical pins:
digital pin 2 [INT0]=physical pin 4 
and digital pin 3 [INT1]= physical pin 5)

 Pin    |  Interrrupt # | Arduino Platform
 ---------------------------------------
 2      |  0            |  All
 3      |  1            |  All
 18    |  5            |  Arduino Mega Only
 19    |  4            |  Arduino Mega Only
 20   |  3            |  Arduino Mega Only
 21    |  2            |  Arduino Mega Only
In the program pin 2 is chosen
 */

int AC_LOAD = 3;    // Output to Opto Triac pin
int dimming = 128;  // Dimming level (0-128)  0 = ON, 128 = OFF
/* Due to timing problems, the use of ‘0’ can sometimes make the circuit 
flicker. It is safer to use a value slightly higher than ‘0’
*/
void setup()
{
  pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
  attachInterrupt(0, zero_crosss_int, RISING);  
// Chooses '0' as interrupt for the zero-crossing
}
// the interrupt function must take no parameters and return nothing
void zero_crosss_int()  
// function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation : 1 full 50Hz wave =1/50=20ms  
  // Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle) For 60Hz => 8.33ms
  
  // 10ms=10000us
  // (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65
  int dimtime = (75*dimming);    // For 60Hz =>65     
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(AC_LOAD, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
                                 //(for 60Hz use 8.33)
  digitalWrite(AC_LOAD, LOW);    // triac Off
}
void loop()  {
 for (int i=128; i > 5; i--)
{
dimming=i;
delay(20);
}
dimming=10;
delay(20);

  for (int i=5; i < 128; i++)
{
 dimming=i;
 delay(20);
 }
 dimming=128;
  }

   Filmuletul numit ac light dimmer with Arduino (II) prezinta modul de aprindere si stingere al becului:

    Am constatat ca dupa finalizarea buclei de numarare catre aprindere la intensitate maxima si trecere la scadere apare un "gol" (se stinge scurt becul), asa ca am mai cautat documentatie is am ajuns la DXARTS - AC DIMMER CIRCUIT unde se foloseste biblioteca TomerOne.h, pe care trebuie descarcata de la http://playground.arduino.cc/Code/Timer1.
    Sketch-ul adaptat si folosit este:


/*
AC Light Control
 Updated by Robert Twomey <rtwomey@u.washington.edu>
 Changed zero-crossing detection to look for RISING edge rather
 than falling.  (originally it was only chopping the negative half
 of the AC wave form). 
 Also changed the dim_check() to turn on the Triac, leaving it on 
 until the zero_cross_detect() turn's it off.
 Adapted from sketch by Ryan McLaughlin <ryanjmclaughlin@gmail.com>
 */

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

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 3;                // Output to Opto Triac
int dim = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff
int inc=1;                      // counting up or down, 1=up, -1=down

int freqStep = 65;    // This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want. 
// 
// The only tricky part is that the chopper circuit chops the AC wave twice per
// cycle, once on the positive half and once at the negative half. This meeans
// the chopping happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply. 

// To calculate freqStep you divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps. 
//
// (1000000 uS / 120 Hz) / 128 brightness steps = 65 uS / brightness step
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave.

void setup() {                                      // Begin setup
  pinMode(AC_pin, 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);      
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is 
  // the right time to fire the triac.  This function 
  // will now run every freqStep in microseconds.                                            
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);       // turn off TRIAC (and AC)
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH); // turn on light       
      i=0;  // reset time step counter                         
      zero_cross = false; //reset zero cross detection
    } 
    else {
      i++; // increment time step counter                     
    }                                
  }                                  
}                                   

void loop() {                        
  dim+=inc;
  if((dim>=128) || (dim<=0))
    inc*=-1;
  delay(50);
}

    De data asta trecerea este lina, filmuletul ac light dimmer with Arduino (III) prezinta cum se aprinde si se stinge becul:
   In articolul de la DXARTS este si o varianta in care controlul intensitatii luminoase se face cu un potentiometru, dar nu am reusit sa-l testez, deoarece am avut probleme cu cablurile. mufele sau chiar cu.. Arduino... se facuse tarziu si nu am avut rabdare sa verific... dar o sa revin cu rezultatele, pana atunci postez schema de conecate necesara si sketch-ul despre care vorbeam:
/*
AC Light Control

 Updated by Robert Twomey <rtwomey@u.washington.edu>

 Changed zero-crossing detection to look for RISING edge rather
 than falling.  (originally it was only chopping the negative half
 of the AC wave form). 

 Also changed the dim_check() to turn on the Triac, leaving it on 
 until the zero_cross_detect() turn's it off.

 Ryan McLaughlin <ryanjmclaughlin@gmail.com>

 The hardware consists of an Triac to act as an A/C switch and 
 an opto-isolator to give us a zero-crossing reference.
 The software uses two interrupts to control dimming of the light.
 The first is a hardware interrupt to detect the zero-cross of
 the AC sine wave, the second is software based and always running 
 at 1/128 of the AC wave speed. After the zero-cross is detected 
 the function check to make sure the proper dimming level has been 
 reached and the light is turned on mid-wave, only providing 
 partial current and therefore dimming our AC load.

 Thanks to http://www.andrewkilpatrick.org/blog/?page_id=445 
 and http://www.hoelscher-hi.de/hendrik/english/dimmer.htm

 */

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

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 3;                // Output to Opto Triac
int POT_pin = A3;             // Pot for testing the dimming
int LED = 11;                    // LED for testing
int dim = 0;                    // Dimming level (0-128)  0 = on, 128 = 0ff

int freqStep = 75;    // This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want. 
// 
// The only tricky part is that the chopper circuit chops the AC wave twice per
// cycle, once on the positive half and once at the negative half. This meeans
// the chopping happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply. 

// To calculate freqStep you divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps. 
//
// (1000000 uS / 120 Hz) / 128 brightness steps = 65 uS / brightness step
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave.

void setup() {                                      // Begin setup
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  pinMode(LED, OUTPUT);                             // Set the LED 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);      
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is 
  // the right time to fire the triac.  This function 
  // will now run every freqStep in microseconds.                                            
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH);  // turn on light       
      i=0;  // reset time step counter                         
      zero_cross=false;    // reset zero cross detection
    } 
    else {
      i++;  // increment time step counter                     
    }                                
  }                                  
}                                      

void loop() {                        
  dim = analogRead(POT_pin) / 8;  // read dimmer value from potentiometer
  analogWrite(LED, dim);  // write dimmer value to the LED, for debugging
}

25.03.2013
   Din testele preliminare, Arduino are defecta partea de intrari analogine, inca nu stiu de ce, dar... am pus un buton pe intrarea digitala 4, cu care voi creste si scadea intensitatea luminoasa, folosindu-ma de sketch-ul cu potentiometru de la DXARTS.
   Am adaptat sketch-ul incat sa pot folosi butonasul meu fara retinere sa realizez 8 trepte de regaj (LED-ul rosu se aprinde la intensitate luminoasa invers decat becul):


/*
AC Light Control

 Updated by Robert Twomey <rtwomey@u.washington.edu>

 Changed zero-crossing detection to look for RISING edge rather
 than falling.  (originally it was only chopping the negative half
 of the AC wave form). 

 Also changed the dim_check() to turn on the Triac, leaving it on 
 until the zero_cross_detect() turn's it off.

 Ryan McLaughlin <ryanjmclaughlin@gmail.com>

 The hardware consists of an Triac to act as an A/C switch and 
 an opto-isolator to give us a zero-crossing reference.
 The software uses two interrupts to control dimming of the light.
 The first is a hardware interrupt to detect the zero-cross of
 the AC sine wave, the second is software based and always running 
 at 1/128 of the AC wave speed. After the zero-cross is detected 
 the function check to make sure the proper dimming level has been 
 reached and the light is turned on mid-wave, only providing 
 partial current and therefore dimming our AC load.

 Thanks to http://www.andrewkilpatrick.org/blog/?page_id=445 
 and http://www.hoelscher-hi.de/hendrik/english/dimmer.htm

adapted skech by niq_ro from http://www.nicuflorica.blogspot.com
                                                      http://www.tehnic.go.ro
 */

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

volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 3;                // Output to Opto Triac
int buton1 = 4;             // first button at pin 4
int LED = 11;                    // LED for testing
int dim = 128;                    // Dimming level (0-128)  0 = on, 128 = 0ff
int pas = 16; // step for count;

int freqStep = 75;    // This is the delay-per-brightness step in microseconds.
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want. 
// 
// The only tricky part is that the chopper circuit chops the AC wave twice per
// cycle, once on the positive half and once at the negative half. This meeans
// the chopping happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply. 

// To calculate freqStep you divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps. 
//
// (1000000 uS / 120 Hz) / 128 brightness steps = 65 uS / brightness step
//
// 1000000 us / 120 Hz = 8333 uS, length of one half-wave.

void setup() {  // Begin setup
  pinMode(buton1, INPUT);  // set buton1 pin as input
  pinMode(AC_pin, OUTPUT);                          // Set the Triac pin as output
  pinMode(LED, OUTPUT);                             // Set the LED 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);      
  // Use the TimerOne Library to attach an interrupt
  // to the function we use to check to see if it is 
  // the right time to fire the triac.  This function 
  // will now run every freqStep in microseconds.                                            
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH);  // turn on light       
      i=0;  // reset time step counter                         
      zero_cross=false;    // reset zero cross detection
    } 
    else {
      i++;  // increment time step counter                     
    }                                
  }                                  
}                                      

void loop() {                        
  if (digitalRead(buton1) == LOW)   
   {
  if (dim>125 || dim<15) 
  {
     pas = - pas;
  }
      dim = dim + pas;
    while (digitalRead(buton1) == LOW) {  }              
      delay(10); // waiting little bit...  
   }  
           
  analogWrite(LED, dim);  // write dimmer value to the LED, for debugging
  delay (100);
}

   Filmuletul demonstrativ se numeste ac light dimmer with Arduino (IV):
   Daca se doresc mai putine trepte de variatie, de la 8 se pot reduce la 4 (0-25%-50%-75%-100%-75%-50%-25%-0-25%...), modificarea consta in valoarea variabilei "pas":
int pas = 32; // step for count;
    Filmuletul, care prezinta modul de functionare, se numeste ac light dimmer with Arduino (V):

28.03.2013
    Un alt film (tot cu 4 trepte de reglaj) se numeste ac light dimmer with Arduino (VI):
    Pentru 3 trepte de iluminare (0-33%-67%-100%-67%-33%-0-33%...), se modifica putin sketch-ul modificand linia:
int pas = 42; // step for count;
iar pentru 2 trepte de iluminare (0-50%-100%-50%-0-...)
int pas = 64; // step for count;

    Pentru varianta cu 3 trepte de reglaj al intensitatii becului, an facut poze cu cele 4 stari:
- bec stins:
- bec la 33%:
- bec la 67%:
- bec la maxim: 
si un filmulet numit ac light dimmer with Arduino (VII):
    Pentru varianta cu 2 trepte de intensitatea, am facut poze cu cele 3 stari:
- bec stins:
- bec la 50%:
- bec la maxim:
iar filmul cu functionarea in cele 2 trepte de intensitate se numeste ac light dimmer with Arduino (VIII):
    Dupa ce o sa schimb microcontrolerul ATMega328 de pe placa Arduino, o sa reiau testele pentru varianta cu reglajul intensitatii cu un potentiometru...

3 comentarii:

  1. salut, nu se aprinde deloc am incarcat mai multe sketch-uri, iar la sketch-ul DXARTS - AC DIMMER CIRCUIT se aprinde doar in perioada de maxim. Ce am gresit?
    Nu am facut inventii, am pus: BT134, moc3041, 4n35, rezistentele care limiteaza curentul inainte de punte sun 85K nu am avut altele. Restul este lafel ca la tine
    multumesc

    RăspundețiȘtergere
  2. salut, tot eu.
    Gata, functioneaza !!! Am schimbat MOC3041 (cu detector de trecere prin 0) cu un MOC3021 (fara detector de trecere prin 0)

    RăspundețiȘtergere
    Răspunsuri
    1. so for the code up down button also work with moc3041? because I'm using moc3021 the light only will glow 100%

      Ștergere