1

I am working on an AC Dimmer project using ESP32 and Attiny85.

Note : I know ATtiny85 is overkill for this project, And it can be done without Attiny85, I have already done this using ESP32 alone. But I have some PCB laying around designed in such a manner. So thought of doing this.

Here ESP32 communicates to Attiny over i2c. ESP - Master Attiny - Slave enter image description here Here Zero Cross Detector(ZCD) circuit is connected to PB1. and T1 to Triac Circuit

Depending on the commands over i2c from ESP to each Attiny, It controls the brightness.

The Problem

I am able to set the brightness using i2c (like LOW, MED, HIGH, OFF). But only once. For example, if I set it to HIGH state initially it will get stuck in that state, Even if any other command is given, Similar for all others. Basically, it will only work once.

I think the interrupt is causing the problem, once interrupt is attached the i2c isn't responding

Here are codes
Slave https://pastebin.com/sqsMYLa0

#include "PinChangeInterrupt.h"
#include "TinyWireS.h"
 
#define I2C_SLAVE_ADDR  2
int AC_LOAD = 3;
int ZCD_Pin = 1;
int dimming = 128;    
int Speed[3] = {90, 50, 20};
int speedValue;
bool fan;


void setup() {
  pinMode(AC_LOAD, OUTPUT);       
  TinyWireS.begin(I2C_SLAVE_ADDR);
  TinyWireS.onReceive(receiveEvent);
  pinMode(ZCD_Pin, INPUT_PULLUP);
}
 
 
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(100);         // 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 receiveEvent(uint8_t howMany)
{
  byte byteRcvd = 0;
  if (TinyWireS.available()) {
    byteRcvd = TinyWireS.receive();     // get the byte from master
 
    if (byteRcvd == '0') {
      fan = false;
      detachPinChangeInterrupt(digitalPinToPCINT(ZCD_Pin));
      digitalWrite(AC_LOAD, LOW);
    }
    if (byteRcvd == '1') {
      fan = true;
      speedValue = Speed[0];
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    if (byteRcvd == '2') {
      fan = true;
      speedValue = Speed[1];   
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    if (byteRcvd == '3') {
      fan = true;
      speedValue = Speed[2];
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    dimming = speedValue;
  }
}
 
void loop() {
  delay(100);
}

Master https://pastebin.com/E5U74LEx

#include <Wire.h>
//#define I2C_SLAVE_1_ADDR  1
#define I2C_SLAVE_2_ADDR  2
 
void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  Serial.print("Ready");
}
 
char x = 0;
 
void loop() {
  if (Serial.available() > 0) {
 
    x = Serial.read();
 
    if (x == '0') {
      Wire.beginTransmission(2); 
      Wire.write('0');              
      Wire.endTransmission();    
      Serial.print("Send 0");
    }
    if (x == '1') {
      Wire.beginTransmission(2); 
      Wire.write('1');           
      Wire.endTransmission();   
      Serial.print("Send 1");
    }
    if (x == '2') {
      Wire.beginTransmission(2); 
      Wire.write('2');              
      Wire.endTransmission();    
      Serial.print("Send 2");
    }
    if (x == '3') {
      Wire.beginTransmission(2); 
      Wire.write('3');              
      Wire.endTransmission();  
      Serial.print("Send 3");
    }
  }
}

For testing, I have used Serial monitor for sending commands. Later It will be done using MQTT

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.