ESP8266 adapter for AC-SSR boards - testers needed.

Barnabybear

New elf
Joined
Mar 30, 2012
Messages
42
Location
UK
Hi, this simply an ESP with zero cross detection that will plug directly into Renard type AS-SSR boards and control them from e1.31 packets. Early tests look good with 4 and 8 channels but I’m still working on the mods for the 8. Let me know what you think.

A schematic and code attached below and before that some notes / random thoughts:

This schematic and code only supports four channels on GPIOs 12 (D6), 13 (D7), 14 (D5), & 16 (D0).

The second four channels will be on GPIOs 0 (D3), 2 (D4), 4 (D2) & 5 (D1) and the zero cross will move to Rx (RXD), I’ve not implemented the Rx change yet as it will require a jumper to disconnect the zero cross to upload the software and that seems a bit silly at this stage of testing / development.

You will need to set your own network and show values in this section. These should be lines 26 to 29.
- const char ssid[] = "<YOUR_SSID>"; // AP SSID
- const char passphrase[] = "<YOUR_AP_PASSWORD>"; // AP password
- const int universe = 1; // universe number
- const int channel = 1; // start channel (first of the 4 consecutive to be used)

Until an E1.31 packet is received the outputs will send out the ‘= values’. Once a packet has been received its values will be sent out until a new one is received. These should be lines 14 to 17.
- int channel_value_1 = 255; // update & dummy values for channel data
- int channel_value_2 = 155; // update & dummy values for channel data
- int channel_value_3 = 55; // update & dummy values for channel data
- int channel_value_4 = 1; // update & dummy values for channel data

When compile/flashing, in tools set the CPU frequency to 160MHz for best results.

When booted the ESP will output through serial @ 115200 baud, its connection status and when connected the IP address.

The ESP will crash (WDT) if a zero cross signal is not seen before the Wi-Fi connection is completed / main loop starts to run. This is not thought to be a problem as the ESP is likely to be powered from the same AC source as the zero cross. Given the 2 to 5 seconds Wi-Fi connection time the zero cross signal will be in place before the main loop runs.

Reasons for this to not work:
- The most common value of series resistor on AC SSRs seems to be 680 ohms. This value was picked to be used with a 5V signal it may be to large when used with the 3.3V signal from an ESP.
- As I live in the UK where is mains 240V @ 50Hz, I’ve had to use an Arduino to emulate a zero cross signal at 60Hz. If you don’t get an output try reducing ‘unsigned int step_delay = 30; // delay for 60Hz’. It can be anything down to 1 but reduces the duty cycle.

An important thought – normally on any ESP project I would protect the outputs with a 270 ohm resistor as the outputs are only good for 12mA, yes 12mA. The SSRs already have current limiting resistors we can’t add any more. So please be careful not to short the pins on the RJ45s.

GPIO15 is toggled high and low buy the code as a debug. If things don't go well and you have a logic analyser or scope this will give some pointers as to the problem.

“WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x8000);” appears all over the place. It’s direct port addressing, the same as ‘digitalWrite (output_4, HIGH)’ but faster. If you’re interested, read the next text, if not skip it as it’s not important to know the details.

- The ESP is a little different to an Arduino in that it has three registers associated with the output port:
- GPIO_OUT this holds the value to be outputted, the same as ‘PORTD’.
- GPIO_OUT_W1TS (Write 1 To Set) writing a 1 to a bit in this register will set the same bit in GPIO_OUT without changing any of the other values. The same as ‘PORTD = PORTD |0x0001’.
- GPIO_OUT_W1TC (Write 1 To Clear) writing a 1 to a bit in this register will clear the same bit in GPIO_OUT without changing any of the other values. The same as ‘PORTD &= PORTD ~0x0001’.
- GPIO_OUT is at ‘BASEADDR + 0’ (0x60000300).
- GPIO_OUT_W1TS is at ‘BASEADDR + 4’ (0x60000304).
- GPIO_OUT_W1TC is at ‘BASEADDR + 8’ (0x60000308).

That’s all I can think of so thanks for trying this and have fun.

Development schematic - only outputs four channels.
ESP_AC_SSR_1.JPG



Code:
// ESP8266-12 development code V0.1 by Barnabybear (consider to be non-working).
#include <ESP8266WiFi.h>
#include <E131.h> // https://github.com/forkineye/E1.31

// set the pin numbers of the in/outputs
int output_1 = 12; // (D6) pin number of output 1 to triac
int output_2 = 13; // (D7) pin number of output 2 to triac
int output_3 = 14; // (D5) pin number of output 3 to triac
int output_4 = 16; // (D0) pin number of output 4 to triac
int output_D = 15; // (D8) debug waveform output
int input_zc = 4; // (D2) pin number of zero cross input

// variables for the DMX value & dummy untill E1.31 arrives
int channel_value_1 = 255; // update & dummy values for channel data
int channel_value_2 = 155; // update & dummy values for channel data
int channel_value_3 = 55; // update & dummy values for channel data
int channel_value_4 = 1; // update & dummy values for channel data

// general variables
long int num_channels; // number of DMX values in E1.31 packet
int loop_number = 255; // number of times too/looped
unsigned int step_ends; // single loop time value
unsigned int step_delay = 30; // delay for 60Hz

// E1.31 setup
const char ssid[] = "<YOUR_SSID>"; // AP SSID
const char passphrase[] = "<YOUR_AP_PASSWORD>"; // AP password
const int universe = 1; // universe number
const int channel = 1; // start channel
E131 e131;

void setup() {
  // start serial
  Serial.begin(115200); // outputs - IP etc
 
  // set the function & state of the in / output pins
  pinMode(input_zc, INPUT); // set pin 4 as input
  pinMode(output_1, OUTPUT); // set pin 12 (D6) as output
  pinMode(output_2, OUTPUT); // set pin 13 (D7) as output
  pinMode(output_3, OUTPUT); // set pin 14 (D5) as output
  pinMode(output_4, OUTPUT); // set pin 16 (D0) as output
  pinMode(output_D, OUTPUT); // set pin 15 (D8) as output
  digitalWrite(output_1, HIGH);  // set output low / off
  digitalWrite(output_2, HIGH);  // set output low / off
  digitalWrite(output_3, HIGH);  // set output low / off
  digitalWrite(output_4, HIGH);  // set output low / off
  digitalWrite(output_D, LOW);  // set output low / off
 
  // select unicast or multicast - one must be commented out
  //e131.begin(ssid, passphrase); // unicast
  e131.beginMulticast(ssid, passphrase, universe); // multicast
}

void loop() {
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x8000); // DEBUG LOW not part of finished code
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, 0x8000); // DEBUG HIGH not part of finished code
  num_channels = e131.parsePacket(); //if a new packet has arrived parse it
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x8000); // DEBUG LOW not part of finished code
  // do this if a new packet arrives
  if (num_channels) { // if a new packet has arrived - set new channel values
    channel_value_1 = (e131.data[channel + 1]);  // update with value from E1.31 packet
    channel_value_2 = (e131.data[channel + 2]);  // update with value from E1.31 packet
    channel_value_3 = (e131.data[channel + 3]);  // update with value from E1.31 packet
    channel_value_4 = (e131.data[channel + 4]);  // update with value from E1.31 packet
    step_ends += 870; // as we didn't look for the zero cross & set 'stop_ends' (don't have time to when a packet comes in)
    // use the value from the last loop and add some time to make the end time correct
  }
  else { // do this if NO new packet
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, 0x8000); //DEBUG HIGH not part of finished code
    while (!digitalRead(input_zc)); // loop untill zero cross pin goes high
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x8000); //DEBUG LOW not part of finished code
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, 0x8000); //DEBUG HIGH not part of finished code
    while (digitalRead(input_zc)) { // loop untill zero cross pin goes low
      step_ends = micros(); // set time to now - saves a little time doing it in this loop
    }
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x8000); //DEBUG LOW not part of finished code
  }
  do {
    // switch on output / triac if we have waited long enough
    if (loop_number == channel_value_1)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x1000); // set output low / on
    if (loop_number == channel_value_2)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x2000); // set output low / on
    if (loop_number == channel_value_3)
      WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 8, 0x4000); // set output low / on
    if (loop_number == channel_value_4)
 //     WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 9, 0x0001); // set output low / on
   digitalWrite(output_4, LOW); // set output low / on (haven't found the register for GPIO16)

    // wait untill it's time to loop & set the next outputs if required
    step_ends += step_delay; // add delay time to last end time to get new end time
    while (micros() < step_ends) { // check time now against end time & loop
      delay(0); // the magic delay - frees the processor to do some quick housekeeping, WiFi & stack stuff
    }
    loop_number--; // reduce loop counter by 1
  } while (loop_number > 0); // 'do' it all again unless ==0
 
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, 0xF000); // re-sets all outputs high as we are close to zero cross
  digitalWrite(output_4, HIGH); // apart from this one
  loop_number = 255; // re-set the value for loop counter ready for the next run
  WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + 4, 0x8000); //DEBUG HIGH not part of finished code
}
 
Last edited:

damo1271

Full time elf
Joined
Oct 12, 2011
Messages
202
Location
Adelaide
Wow an awesome project. I am replacing almost all of my 240V stuff this year, otherwise would have been very useful.
I do have some ESP modules around and If I get some time I will program one up to test.
 

SmartAlecLights

Im a SmartAlec what can i say!
Community project designer
Joined
May 4, 2010
Messages
1,533
Location
Murray Bridge, S.A.
great work Barnabybear,
I built a similar controller over a month ago for my home automation system
the only difference is it has 6 mosfets an it only does low voltage dc.

How easy do you think it would be to change your code to do 6 outputs instead?
thanks Alec
 
Top