AC Dimmer keeps crashing at the interrupt line

I am trying to code a Blynk AC dimmer to run on the Wemos Mini/Wemos D1.
Currently, I find myself in a dark place without a torch to light my way.
I am using as a starting point of the basic code that started by https://community.blynk.cc/u/hbadotti Corrected by https://community.blynk.cc/u/Costas I then added on bits and compiles the system before adding more still not sure what to add, however, my code keeps crashing at the interrupt line where the ISR returns with the error" ‘zero_crossOver’ was not declared in this scope"
so I get no further can someone please help to fix this?
Does someone possibly have a system that works that I could use? I have completed building the hardware for this and really would like to get the system running.

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char auth[] = "xxxx";
char ssid[] = "xxxx";         // Your WiFi credentials.
char pass[] = "xxxx";    // Set password to "" for open networks.

#define triacPulse 13  // Output to Opto Triac at Gpio 13 means D7
#define zcPin 12         // Input From Optocoupler to detect zerocrossing
                      //  signal at Gpio 12 means D6

void setup()
{ pinMode(zcPin, INPUT_PULLUP);
  pinMode(triacPulse, OUTPUT);
  // digitalWrite(triacPulse, INPUT_PULLUP); // pull up
  attachInterrupt(digitalPinToInterrupt(zcPin), zero_crossOver, FALLING);

  //Serial.begin(9600);
  Serial.begin(115200);
  Serial.println();
  Serial.println("Project started");
  Blynk.begin(auth, ssid, pass);
}

void zero_crossOver()
{
for(int i=0; i++)
{
int dimtime = (65*dimming[i]);
delayMicroseconds(dimtime);
digitalWrite(triacPulse, HIGH);
delayMicroseconds(8.33);
digitalWrite(triacPulse, LOW);
}

}
int autodimmer; // (BLYNK) Auto Dimmer Button
int dimmer;

void loop()
{
  Blynk.run(); // (BLYNK) Run
}

void DimmerFunction()

{
  if (autodimmer >= 1)// Button on
  {
    Serial.println("autodimmer >= 1");
    
    digitalWrite(triacPulse, HIGH);       // turn ON TRIAC (and AC)   Code

  }
  else
  {
    // Do nothing
  }
}

BLYNK_WRITE(V18)  // (BLYNK) Botão Auto Dimmer
{
  autodimmer = param.asInt();
  if (autodimmer == 1) // If Auto dimmer is ON then calls function Dimmer()
  {
    DimmerFunction();
  }
}

BLYNK_WRITE(V1)  // (BLYNK) Slider Dimmer
{
  dimmer = param.asInt(); // dimmer = Value got from dimmer Slider
  Serial.println(autodimmer);
  Serial.println(dimmer);
  if (autodimmer == 0) // If auto dimmer is OFF then set the dimmer according slider value
  {
    Serial.println("Set.dimmer(dimmer)");
    //Set.dimmer(dimmer);
  }
  // If AutoDimmer button is true, then do nothing
}

I assume you mean that the code fails to compile?
“Crashing” is normally used to describe a situation where the code has been compiled and uploaded, then the code execution fails.

You have multiple issues that I can see just by looking through the sketch on my iPad - there may be more…

  1. The syntax of your for loop in the ISR handler is incorrect, you are missing one of the arguments.

  2. Depending on which version of the ESP8266 core you are using when You compile your code, you may have a problem with the code crashing after upload with an “ISR not in IRAM” message. You can fix this by adding ICACHE_RAM_ATTR to your ISR’s declaration - google if you need more info.

  3. When you do step 2, you will then get the same “not declared in scope” message that you are at the moment. You can fix this by moving your ISR above your void setup in the sketch, or by pre-declaring the ISR function at the top of your code.

  4. You may need to set your serial baud rate to 74880 to see the ‘ISR not in IRAM” message mentioned in Step 2.

  5. You should probably use volatile variable types within your ISR

  6. It’s always good practice to declare your global variables at the top of your code, for clarity and ease of reference. It’s also a good idea to add meaningful descriptions to your variables so it’s clear what they are used for. You declare autodimmer and dimmer must before your void loop, which makes things very messy. It’s also a good idea to use proper indents within your code to allow you to easily see the sub sections of code in your functions.

Pete.

I have done some editing/correcting some of the code however I am currently at a dead end and do not know what seems to be the problem or what to do to fix it.
It compiles and uploaded it fine with no errors evident but that is all, it does not trigger the Triac. I can get the Triac turned on via the virtual button but cannot turn it off again via the V18 button.
I really would appreciate it if you could help fig the problem.
the Slider has no effect on it.
I don’t know enough about the dimming system to fix it.

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define zcPin 13         // Output to Opto Triac at Gpio 13 means D7
#define  triacPulse 12  // Input From Optocoupler to detect
                        // zerocrossing signal at Gpio 12 means D6

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;  // Boolean to store a "switch" to tell us if we have crossed zero

char auth[] = "xxxxxx";
char ssid[] = "xxxxxx";         // Your WiFi credentials.
char pass[] = "xxxxxx";    // Set password to "" for open networks.

int autodimmer; // (BLYNK) Auto Dimmer Button V18
int dimmer; 
int dimming = 128;   // Dimming level (0-128)  0 = on, 128 = 0ff
int freqStep = 75;    // This is the delay-per-brightness step in microseconds for 50Hz (change the value in 65 for 60Hz)
   
ICACHE_RAM_ATTR void zero_crossOver()                       
{
   for(int i=0; i++;)
     {
      volatile int dimtime = (75*dimming);  // For 60Hz = 65  
        delayMicroseconds(dimtime);
          digitalWrite(triacPulse, HIGH);
            delayMicroseconds(8.33);
              digitalWrite(triacPulse, LOW);
     } 
 }
void setup()
{
  
    attachInterrupt(digitalPinToInterrupt(zcPin), zero_crossOver, FALLING); 
      pinMode(zcPin, INPUT); // Set the zcPin as Input
        pinMode(triacPulse, OUTPUT); // Set the Triac pin as Output
          digitalWrite(triacPulse, LOW);
    Serial.begin(9600);
      Serial.println();
        Serial.println("Project started");
    
    Blynk.begin(auth, ssid, pass);
}

void loop()
{
  Blynk.run(); // (BLYNK) Run
}

void DimmerFunction()
{
  if (autodimmer >= 1)// (BLYNK) Auto Dimmer Button ON 
  {
    digitalWrite(triacPulse, HIGH);       // turn On TRIAC and AC digitalWrite(triacPulse, HIGH); // turn OM TRIAC (and AC)  
      Serial.println("autodimmer >= 1");
  }
  else  
  {
    digitalWrite(triacPulse, LOW);       // turn off TRIAC and AC)
       Serial.println("autodimmer = 0");
  }
}
BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  autodimmer = param.asInt();
   if (autodimmer == 1) // If Auto dimmer is ON then calls function Dimmer()
   {
      DimmerFunction(); 
   }
}
BLYNK_WRITE(V1)  // (BLYNK) Slider Dimmer
{
  dimmer = param.asInt(); // dimmer = Value got from dimmer Slider
     Serial.println(autodimmer);
      Serial.println(dimmer);
      if (autodimmer == 0) // If auto dimmer is OFF then set the dimmer according slider value
     {
       Serial.println("Set.dimmer(dimmer)");
       //Set.dimmer(dimmer);
     }
       // If AutoDimmer button is true, then do nothing
}

I assume that when you say “via the virtual button” you mean “via the virtual button attached to pin V18”?

Take a look at the logic within this function. You’ll see that the DimmerFunction is only called if the value of autodimmer == 1 (in other words, if the switch widget attached to V18 is On).

Also, I would have expected this…

to look like this…

void ICACHE_RAM_ATTR zero_crossOver()

Pete.

Pete
Yes, I was referring to V18 .
I made changes to the V18 routine the triacPulse pin GPIO12 = D6 now can be turned on or off.
however, how do I get the crossover routine to run so that the dimmer can contol the lamp when D6 is turned on.
The Opto Isolator Switches on and off as does the lamp but have no dimming control via the V1 slider.

Art.

BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  autodimmer = param.asInt();
  switch (autodimmer)
  {
  case 0:
       digitalWrite(triacPulse, LOW);       // turn off TRIAC and AC)
       Serial.println("autodimmer = 0");    
    //do something when var equals 1
    break;
    
  case 1:
       digitalWrite(triacPulse, HIGH);       // turn On TRIAC and AC digitalWrite(triacPulse, HIGH); // turn OM TRIAC (and AC)  
       Serial.println("autodimmer >= 1");
       //do something when var equals 2
    break;
  default:
    // if nothing else matches, do the default
    // default is optional
    break;
  }
}

That’s a very bizarre way of approaching the changes needed to make your V18 button work.
I’d have done EITHER this…

BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  autodimmer = param.asInt();
  DimmerFunction(); 
}

and kept your DimmerFunction as it was, or removed the DimmerFunction and done this…

BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  if (autodimmer  param.asInt();// (BLYNK) Auto Dimmer Button ON 
  {
    digitalWrite(triacPulse, HIGH);       // turn On TRIAC and AC 
    Serial.println("autodimmer On");
  }
  else  
  {
    digitalWrite(triacPulse, LOW);       // turn Off TRIAC and AC)
    Serial.println("autodimmer = Off");
}

Your V1 slider doesn’t appear to do anything other than print some messages to the serial monitor.

Also, did you make this change…

Pete.

This seems odd. Can you explain? Why bother incrementing “i” if there is no check or reset…

Yep, me too…

Pete.

Pete I Fixed this

 ICACHE_RAM_ATTR void zero_crossOver()

to this as you suggested.

void ICACHE_RAM_ATTR zero_crossOver()    

Did you perhaps include (V18) code to the main sketch replacing the case routine that you suggested in the sketch and did it compile?

BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  if (autodimmer  param.asInt();// (BLYNK) Auto Dimmer Button ON 
  {
    digitalWrite(triacPulse, HIGH);       // turn On TRIAC and AC 
    Serial.println("autodimmer On");
  }
  else  
  {
    digitalWrite(triacPulse, LOW);       // turn Off TRIAC and AC)
    Serial.println("autodimmer = Off");
}

Firstly it failed to compile with error "expected ‘)’ before ‘param’
I added the ) and tried to compile it this too was unsuccessful with the error “‘else’ without a previous ‘if’” and there was an IF curly closing bracket missing at the end. I added this but again failed to compile with error ‘else’ without a previous ‘if’
Any suggestions to fix this.
With regards to the If statement, I have no answer as stated I am at a loss with this crossover system. I did change the crossover system to this not sure if this is correct please help get this right will be much appreciated.

void ICACHE_RAM_ATTR  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 (10.000/120)
  // 10ms=10000us
  // (10000us - 10us) / 98 = 102 (Approx) For 60Hz =>65

  int dimtime = (102*dimming);    // For 60Hz =>65    
  delayMicroseconds(dimtime);    // Wait till firing the TRIAC
  digitalWrite(triacPulse, HIGH);   // Fire the TRIAC
  delayMicroseconds(10);         // triac On propogation delay (for 60Hz use 8.33)
  digitalWrite(triacPulse, LOW);    // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
}  

Apologies, I wrote this on my iPad and it should have sais…

if (param.asInt());// (BLYNK) Auto Dimmer Button ON

Look-up the syntax for the if statement in C++, you’ll see that it needs three arguments.

Pete.

Of course, this should say “Look-up the syntax for the for statement in C++…”

Pete.

Eventually back was tied up and could not have another go at this.
I have the system compiling and running with no errors.
The V18 virtual button works and I can turn the Triac on and of via the Blynk app however that is as far I got have tried to solve the crossover and dimming with no results have had a look at a number of different Arduino version but have had no success. It does not turn the Triac on and does not control via the slider V1 .
Can you please help resolve this? Would much be appreciated. I am definitely not good at coding at this level.

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define zcPin 13         // Output to Opto Triac at Gpio 13 means D7
#define  triacPulse 12  // Input From Optocoupler to detect
                        // zerocrossing signal at Gpio 12 means D6

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;  // Boolean to store a "switch" to tell us if we have crossed zero

char auth[] = "xxxxxxxxxx";  // You should get Auth Token in the Blynk App.
char ssid[] = "xxxxxxxxxx";         // Your WiFi credentials.
char pass[] = "xxxxxxxxx";    // Set password to "" for open networks.
int curBrightness = 0;
int dimDelay;
int autodimmer; // (BLYNK) Auto Dimmer Button V18
int dimmer; 
int dimming = 128;   // Dimming level (0-128)  0 = on, 128 = 0ff
int freqStep = 75;    // This is the delay-per-brightness step in microseconds for 50Hz (change the value in 65 for 60Hz)
   
ICACHE_RAM_ATTR void zero_crossOver()                       
{
    if (autodimmer == 0) // Button os off
    {
      digitalWrite(triacPulse, 0);        //fully shut down the triac
    }
    else if (autodimmer >= 1)
    {
    Serial.println("autodimmer >= 1");  
      digitalWrite(triacPulse, 1);        //fully open the triac
    }
    else
    {
      delayMicroseconds(dimDelay);    //wait "delay" for first half period
      digitalWrite(triacPulse, 1);    //generate the pulse for the MOC input
      delayMicroseconds(100);
      digitalWrite(triacPulse, 0);
      delayMicroseconds(9900);        //jumpt to the second half period
      digitalWrite(triacPulse, 1);    //generate the pulse for the MOC input
      delayMicroseconds(100);
      digitalWrite(triacPulse, 0);
    }
 }
void setup()
{
  
    attachInterrupt(digitalPinToInterrupt(zcPin), zero_crossOver, FALLING); 
      pinMode(zcPin, INPUT); // Set the zcPin as Input
        pinMode(triacPulse, OUTPUT); // Set the Triac pin as Output
          digitalWrite(triacPulse, LOW);
    Serial.begin(9600);
      Serial.println();
        Serial.println("Project started");
    
    Blynk.begin(auth, ssid, pass);
}

void loop()
{
  Blynk.run(); // (BLYNK) Run
}

void DimmerFunction()
{
  if (autodimmer >= 1)// (BLYNK) Auto Dimmer Button ON 
  {
    digitalWrite(triacPulse, HIGH);       // turn On TRIAC and AC digitalWrite(triacPulse, HIGH); // turn OM TRIAC (and AC)  
      Serial.println("autodimmer >= 1");
      zero_crossOver();
  }
  else  
  {
    digitalWrite(triacPulse, LOW);       // turn off TRIAC and AC)
       Serial.println("autodimmer = 0");
  }
}
BLYNK_WRITE(V18)  // (BLYNK)  Auto Dimmer
{
  autodimmer = param.asInt();
      DimmerFunction(); 
}
BLYNK_WRITE(V1)  // (BLYNK) Slider Dimmer
{
  dimmer = param.asInt(); // dimmer = Value got from dimmer Slider
     Serial.println(autodimmer);
      Serial.println(dimmer);
      if (autodimmer == 0) // If auto dimmer is OFF then set the dimmer according slider value
     {
       Serial.println("Set.dimmer(dimmer)");
       //Set.dimmer(dimmer);
     }
       // If AutoDimmer button is true, then do nothing
}

What do you imagine that your BLYNK_WRITE(V1) callback actually achieves?

As far as I can see, when you change the slider attached to V1, the value of the dimmer variable changes and you print some data to the serial monitor.

You’re not initiating any loop process and not using the dimmer in any way.

Pete.

Yes I am aware that this is so but how would I use the dimmer variable in the zero_crossOver function to make this function work?

I really don’t understand why you are attempting to write your own zero crossing code if your coding skills are so poor that you don’t know how to do it.
You’d be better either finding a working project from the forum, or googling a non-Blynk solution, getting it working then adding Blynk into the equation.

Also, triac dimmers are rapidly going out of favour, as most LED based bulbs can’t be dimmed this way. You’d be far better going for a cheap smart bulb and using its native app, or flashing the bulb with your own code and controlling it via Blynk.

Pete.

My question is can an 8266 monitor 0 crossing and also run blynk? It probably won’t for sure with your convoluted interrupt routine.