AC Dimming with zero crossing



  • I have a Wipy 2.0 and want to use it to dim an AC bulb with zero detection. I have the hardware I am having issues in the code. I tried to replicate an Arduino code. Both codes are below. The hardware works fine with an Arduino.
    The Wipy code is running perfectly fine but the bulb is not actually turning on or dimming.

    Arduino Code :

    #include <TimerOne.h>           // Avaiable from
    http://www.arduino.cc/playground/Code/Timer1
    //#include <Ticker.h> // For ESP8266
    
    const int ampSense = A0;
    int mVperAmp = 100; // use 100 for 20A Module and 66 for 30A Module
    int RawValue = 0;
    int ACSoffset = 2500;
    double Voltage = 0;
    double Amps = 0;
    
    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 = 11;                // 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 = 78;    // 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.
    
    //Ticker flipper; // ESP8266
    
    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.
      // flipper.attach_ms(freqStep, dim_check); // For ESP8266
    
      Serial.begin(9600);
    }
    
    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;
        
      RawValue = analogRead(ampSense);
      Voltage = (RawValue / 1023.0) * 5000; // Gets you mV
      Amps = ((Voltage - ACSoffset) / mVperAmp);
      Serial.print(dim);
      Serial.print("\t Amps = "); // shows the voltage measured 
      Serial.println(Amps,3); // the '3' after voltage allows you to display 3 digits after decimal point
    
      delay(20);
    }
    

    Wipy 2.0 Code :

    from machine import Pin
    from machine import Timer
    from machine import ADC
    import time
    
    #zero cross detect pin
    detect = Pin('P22', mode=Pin.IN, pull=Pin.PULL_UP)
    
    acPin = Pin('P12', mode=Pin.OUT, pull=None)
    
    adc = ADC(0)
    ampSense = adc.channel(pin='P13')
    
    # Variables
    mVperAmp = 100
    rawValue = 0
    acsOffset = 2500
    voltage = 0
    amps = 0
    i = 0
    zeroCross = False
    dim = 0
    inc = 1
    freqStep = 78
    
    def zero_cross_detect(self):
        #10,000 microseconds for half cycle and 6250 counts for half cycle
        zeroCross = True
        i = 0
        acPin.value(0)
        
    
    class Clock:
    
        def __init__(self):
            self.__alarm = Timer.Alarm(self._seconds_handler, us=freqStep, periodic=True)
    
        def _seconds_handler(self, alarm):
    		global zeroCross, i, dim, acPin
    		if zeroCross == True :
    			if i >= dim :
    				acPin.value(1)
        			i = 0
        			zeroCross = False
        		else :
        			i += 1
    clock = Clock()
    detect.callback(Pin.IRQ_RISING , zero_cross_detect)
    
    
    
    while (1) :
    	dim += inc
    	if dim >= 128 or dim<=0 :
    		inc *= -1
    	
    	rawvalue = ampSense.value()
    	voltage = (rawValue/4095.0)*5000
    	amps = ((voltage - acsOffset) / mVperAmp)
    	print(str(dim) + '\t Amps = ' + str(amps))
    	time.sleep(0.02)
    

 

Pycom on Twitter