I'm making a dimmer with my Arduino Nano, This get's values between 0-128 from an ESP8266 controller via I2C. This works fine on the nano until the interrupt (zero cross detection) interrupts this.
I've tried dimming with a potentiometer and this worked perfectly, I've tried doing this without the intterupt (in serial monitor), this worked correctly. I've also tried replacing interrupts and noInterrupts by sei() and cli() with no results. I do sometimes get it working for a moment, but then it looks like this.
63
64
65
66
67
-1
69
-1
72
-1
74
Afterwards it stops working.
Below is my code for the ESP8266 device (This is temporary test code). This only sends Value's to the nano.
#include <Wire.h>
void setup() {
Wire.begin();
}
void loop() {
for (int dimValue = 0; dimValue <= 128; dimValue++)
{
delay(50);
Wire.beginTransmission(8);
Wire.write(dimValue);
Wire.endTransmission();
}
}
Below The code for the Nano responsible for dimming and receiving commands via I2C.
#include <Wire.h>
int AC_LOAD = 8; // Output to Opto Triac pin
int dimming = 128; // Dimming level (0-128) 0 = ON, 128 = OFF
int zeroCross = 3; // zerocross pin
void setup()
{
pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
attachInterrupt(digitalPinToInterrupt(3), zero_crosss_int, RISING);
Serial.begin(115200);
Wire.begin(8);
Wire.onReceive(receiveEvent);
}
void zero_crosss_int() //function to be fired at the zero crossing to dim the light
{
int dimtime = (75 * dimming); // For 60Hz =>65
delayMicroseconds(dimtime); // Wait till firing the TRIAC
digitalWrite(AC_LOAD, HIGH); // Fire the TRIAC
delayMicroseconds(10); // triac On propogation delay
// (for 60Hz use 8.33) Some Triacs need a longer period
digitalWrite(AC_LOAD, LOW); // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
}
void loop()
{
}
void receiveEvent() {
noInterrupts();
int x = Wire.read();
dimming = x;
Serial.println(x);
interrupts();
}
The results I should get from the nano should look like this
63
64
65
66
67
68
69
70
71
72
73
74
The problem was that the interrupt handler was busy for too long wich interrupted the I2C receive handling wich overflowed it. Now it's fully working by putting the code from the interrupt in the loop()
.
#include <Wire.h>
int AC_LOAD = 9; // Output to Opto Triac pin
int dimming = 128; // Dimming level (0-128) 0 = ON, 128 = OFF
int zeroCross = 3; // zerocross pin
boolean triacFire = false;
void setup()
{
pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output
attachInterrupt(digitalPinToInterrupt(zeroCross), zero_crosss_int, RISING);
Serial.begin(115200);
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
}
void zero_crosss_int() //function to be fired at the zero crossing to dim the light
{
triacFire = true;
}
void loop()
{
if (triacFire == true)
{
int dimtime = (75 * dimming); // For 60Hz =>65
delayMicroseconds(dimtime); // Wait till firing the TRIAC
digitalWrite(AC_LOAD, HIGH); // Fire the TRIAC
delayMicroseconds(10); // triac On propogation delay
// (for 60Hz use 8.33) Some Triacs need a longer period
digitalWrite(AC_LOAD, LOW); // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
triacFire = false;
}
}
void receiveEvent() {
noInterrupts();
byte x = Wire.read(); // receive byte as an byte
dimming = x;
Serial.println(x);
interrupts();
}
Thank you, everyone who helped me with this problem!