AC dimmer / ESP32-Wroom32d

I am making Leading Edge AC dimmer with ESP32-Wroom32d. I have problem with esp timer intterupts. So I want to create a delay after zero-crossing(z.c.) (7ms) and then turn on Ac Pump and leave it on untill next z.c.. My problem is that timer interupt generates nonuniform pulses visible in the attachments (screenshot from osiloscope.) What am I doing wrong? How can I create uniform pulses?

/*  
 *  timer_frequency = clock_frequency / prescaler
 *  timer_duration = 7ms
 *  B = timer_frequency * timer_duration
 *  B = (80MHz / 16) * 7ms
 *  B = 35000
 *   
 *   
*/
volatile int B = 0;
hw_timer_t * timer = NULL;
int pumpa = 26;

void IRAM_ATTR skozi_nic() {
  digitalWrite(pumpa, LOW);
  timerAlarmWrite(timer, B, true);
  timerAlarmEnable(timer);
}

void IRAM_ATTR tim0_poln() {
  timerAlarmDisable(timer);
  digitalWrite(pumpa, HIGH);
}

void setup() {
  pinMode(pumpa, OUTPUT);
  Serial.begin(115200);

  timer = timerBegin(0, 16, true); // timer 0, prescaler 16, count up
  timerAttachInterrupt(timer, &tim0_poln, true);
  //timerAlarmWrite(timer, 240, true);

  attachInterrupt(digitalPinToInterrupt(17), skozi_nic, RISING);
}

void loop() {
  Serial.println("Dimmer zatemnitev");
  B = 35000; // 5000
} 

aaaFile0

Your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advice on) your project :wink: See About the Installation & Troubleshooting category.

So the timer is generating incorrect timing pulses?

What Hz is the AC frequency?

Lets say 50Hz a period of .02mS and you want to delay the pump on for 7mS which is how many periods of 50Hz?

Thank you for your answer.

So the timer is generating incorrect timing pulses?

That is correct.

What Hz is the AC frequency?

AC frequency is 50hz (europe standard U=230v f=50hz)

Lets say 50Hz a period of .02mS and you want to delay the pump on for 7mS which is how many periods of 50Hz?

We have 10 ms between two zerocrossing pulses, that is half the period. I want to turn pump on after 7ms and leave it on until next z.c. (Toff= 7 ms, Ton = 3 ms).

How is the hardware timer generating incorrect timing pulses?

How is zero crossing being detected?

Why not when zero crossing has occurred trigger a one shot hardware timer for 7mS?

void IRAM_ATTR oneshot_timer_callback( void* arg )
{
  BaseType_t xHigherPriorityTaskWoken;
  xEventGroupSetBitsFromISR( eg, evtDoParticleRead, &xHigherPriorityTaskWoken ); //freeRTOS event trigger made for ISR's
} //void IRAM_ATTR oneshot_timer_callback( void* arg )


vioded setup()
{

  // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html?highlight=hardware%20timer High Resoultion Timer API
  esp_timer_create_args_t oneshot_timer_args = {}; // initialize High Resoulition Timer (HRT) configuration structure
  oneshot_timer_args.callback = &oneshot_timer_callback; // configure for callback, name of callback function
  esp_timer_create( &oneshot_timer_args, &oneshot_timer ); // assign configuration to the HRT, receive timer handle

}

void fDoParticleDetector( void * parameter )
{
  /*
    ug/m3     AQI                 Lvl AQ (Air Quality)
    (air Quality Index)
    0-35     0-50                1   Excellent
    35-75    51-100              2   Average
    75-115   101-150             3   Light pollution
    115-150  151-200             4   moderate
    150-250  201-300             5   heavy
    250-500  >=300               6   serious
  */
  float ADbits = 4095.0f;
  float uPvolts = 3.3f;
  float adcValue = 0.0f;
  float dustDensity = 0.0f;
  float Voc = 0.6f; // Set the typical output voltage, when there is zero dust.
  const float K = 0.5f; // Use the typical sensitivity in units of V per 100ug/m3.
  xEventGroupWaitBits (eg, evtWaitForBME, pdTRUE, pdTRUE, portMAX_DELAY );
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 100; //delay for mS
  for (;;)
  {
    //enable sensor led
    gpio_set_level( GPIO_NUM_4, HIGH ); // set gpio 4 to high to turn on sensor internal led for measurement
    esp_timer_start_once( oneshot_timer, 280 ); // trigger one shot timer for a 280uS timeout, warm up time.
    xEventGroupWaitBits (eg, evtDoParticleRead, pdTRUE, pdTRUE, portMAX_DELAY ); // event will be triggered by the timer expiring, wait here for the 280uS
    adcValue = float( adc1_get_raw(ADC1_CHANNEL_0) ); //take a raw ADC reading from the dust sensor
    gpio_set_level( GPIO_NUM_4, LOW );//Shut off the sensor LED
    adcValue = ( adcValue * uPvolts ) / ADbits; //calculate voltage
    dustDensity = (adcValue / K) * 100.0; //convert volts to dust density
    if ( dustDensity < 0.0f )
    {
      dustDensity = 0.00f; // make negative values a 0
    }
    if ( xSemaphoreTake( sema_PublishPM, 0 ) == pdTRUE )  // don't wait for semaphore to be available
    {
      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY );
      //log_i( "ADC volts %f Dust Density = %ug / m3 ", adcValue, dustDensity ); // print the calculated voltage and dustdensity
      MQTTclient.publish( topicInsidePM, String(dustDensity).c_str() );
      xSemaphoreGive( sema_MQTT_KeepAlive );
      x_eData.PM2 = dustDensity;
    }
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    //log_i( " high watermark % d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}// end fDoParticleDetector()

Here I use a one shot hardware timer that delay for 280 mS. You can change the timer to delay for 7mS after a zero crossing trigger. I use an event trigger to cause the resumption of the task which was delayed by 280uS.

I use similar curcit as this one.

Shematic of my project -https://easyeda.com/editor#id=6545393486a4424eaf98763f684daf0a

I will try that, in your code I saw that it was made for freeRTOS does this change anything when using arduino?

Yes, it does change things as freeRTOS does not run well on a Uno. You'd have to refactor the code to run on a Uno.

You'd have to refactor the code to run on a Uno.

Thank you for your response. I think we had some missunderstandment. Just to clarify, I am actually using an ESP32 WROOM processor, not an Uno. But I am programing it in arduino.

I program using the Arduino IDE as well. The code I posted works in the Arduino IDE.

Where does the 5V pulse from the opto coupler attach to the ESP32? As a note the ESP32 is not 5V tolerant and may get broken with 5V on its GPIO pins.

Thank you for bringing up this concern. I apologize for any confusion the schematic may have caused. I used that schematic only as an example, as I didn't draw a schematic for a zero-crossing detector myself. In my circuit, I use 3v3 instead of 5v.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.