Description
hello im not sure if you can help but im only amateur at best with coding. attached i will show the coding i used
Problem (if i run the blink sketch with the relays on the arduino they work) did this to confirm boards are functioning correctly
when i connect everything up and run it through home assistant (esphome) it shows i2c has been found, and arduino serial logger show pin 2 pulled high, pin 2 pulled low when switch is toggled, however the relay does not do anything.
if i connect a voltage meter whilst all is still plugged in i get 4.83 volts and when the switch is toggled to on i get 0.10 volts
attached is both your code and the esphome code (example i am using to test before changing it)
Edit: i should also mention, if i connect a blue led (all i have) between ground and pin 2 it toggles with everything connected as expected.
power supply is 12v 1amp connected to arduino for testing purposes. As show in diagram at bottom arduino is powering the esp8266 (even separately powered i have the same issue)
Your code
/*
Ports:
0 0 .. 13 13 .. 53 53
Uno: A0: 14, A1: 15, A2: 16, A3: 17: A4: 18: A5: 19: A6: 20, A7: 21
Mega: A0: 54, A1: 55, A2: 56, A3: 57: A4: 58: A5: 59: A6: 60, A7: 61...
port bits: 5 ... 0..32
0: 0: 00000
1: 1: 00001
A7: 21: 10101
*/
#include <Arduino.h>
#include <Wire.h>
#define DEBUG // remove debug so pin 0 and 1 can be used for IO
//#define DEBUG_READ // more advanced debuging
#define I2C_ADDRESS 8 //i2c starts at pin 8
void onRequest();
void onReceive(int);
void setup()
{
#ifdef DEBUG
Serial.begin(115200);
Serial.println(F("Init "));
#endif
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
analogReference(INTERNAL1V1);
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
analogReference(INTERNAL);
#endif
Wire.begin(I2C_ADDRESS);
Wire.onRequest(onRequest);
Wire.onReceive(onReceive);
#ifdef DEBUG
Serial.println(F("Wire ok"));
#endif
}
void loop()
{
//int temp = analogRead(A1);
//Serial.println(temp);
}
volatile byte buffer[9];
volatile byte len = 1;
#define DIGITAL_READ(b, pin, mask) \
if (digitalRead(pin)) \
buffer[b] |= mask;
void readDigital()
{
len = 9;
buffer[0] = 0;
buffer[1] = 0;
buffer[2] = 0;
buffer[3] = 0;
buffer[4] = 0;
buffer[5] = 0;
buffer[6] = 0;
buffer[7] = 0;
buffer[8] = 0;
DIGITAL_READ(0, 0, 1); //0
DIGITAL_READ(0, 1, 2); //1
DIGITAL_READ(0, 2, 4); //2
DIGITAL_READ(0, 3, 8); //3
DIGITAL_READ(0, 4, 16); //4
DIGITAL_READ(0, 5, 32); //5
DIGITAL_READ(0, 6, 64); //6
DIGITAL_READ(0, 7, 128); //7
DIGITAL_READ(1, 8, 1); //8
DIGITAL_READ(1, 9, 2); //9
DIGITAL_READ(1, 10, 4); //10
DIGITAL_READ(1, 11, 8); //11
DIGITAL_READ(1, 12, 16); //12
DIGITAL_READ(1, 13, 32); //13
//Arduino Mega Boards
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
DIGITAL_READ(1, 14, 64); //14
DIGITAL_READ(1, 15, 128); //15
DIGITAL_READ(2, 16, 1); //16
DIGITAL_READ(2, 17, 2); //17
DIGITAL_READ(2, 18, 4); //18
DIGITAL_READ(2, 19, 8); //19
DIGITAL_READ(2, 19, 16); //20 Not avaliable on Arduino Mega, i2c pin.
DIGITAL_READ(2, 19, 32); //21 Not avaliable on Arduino Mega, i2c pin.
DIGITAL_READ(2, 22, 64); //22
DIGITAL_READ(2, 23, 128); //23
DIGITAL_READ(3, 24, 1); //24
DIGITAL_READ(3, 25, 2); //25
DIGITAL_READ(3, 26, 4); //26
DIGITAL_READ(3, 27, 8); //27
DIGITAL_READ(3, 28, 16); //28
DIGITAL_READ(3, 29, 32); //29
DIGITAL_READ(3, 30, 64); //30
DIGITAL_READ(3, 31, 128); //31
DIGITAL_READ(4, 32, 1); //32
DIGITAL_READ(4, 33, 2); //33
DIGITAL_READ(4, 34, 4); //34
DIGITAL_READ(4, 35, 8); //35
DIGITAL_READ(4, 36, 16); //36
DIGITAL_READ(4, 37, 32); //37
DIGITAL_READ(4, 38, 64); //38
DIGITAL_READ(4, 39, 128); //39
DIGITAL_READ(5, 40, 1); //40
DIGITAL_READ(5, 41, 2); //41
DIGITAL_READ(5, 42, 4); //42
DIGITAL_READ(5, 43, 8); //43
DIGITAL_READ(5, 44, 16); //44
DIGITAL_READ(5, 45, 32); //45
DIGITAL_READ(5, 46, 64); //46
DIGITAL_READ(5, 47, 128); //47
DIGITAL_READ(6, 48, 1); //48
DIGITAL_READ(6, 49, 2); //49
DIGITAL_READ(6, 50, 4); //50
DIGITAL_READ(6, 51, 8); //51
DIGITAL_READ(6, 52, 16); //52
DIGITAL_READ(6, 53, 32); //53
DIGITAL_READ(6, A0, 64); //54
DIGITAL_READ(6, A1, 128); //55
DIGITAL_READ(7, A2, 1); //56
DIGITAL_READ(7, A3, 2); //57
DIGITAL_READ(7, A4, 4); //58
DIGITAL_READ(7, A5, 8); //59
DIGITAL_READ(7, A6, 16); //60
DIGITAL_READ(7, A7, 32); //61
DIGITAL_READ(7, A8, 64); //62
DIGITAL_READ(7, A9, 128); //63
DIGITAL_READ(8, A10, 1); //64
DIGITAL_READ(8, A11, 2); //65
DIGITAL_READ(8, A12, 4); //66
DIGITAL_READ(8, A13, 8); //67
DIGITAL_READ(8, A14, 16); //68
DIGITAL_READ(8, A15, 32); //69
#endif
// Arduino Uno Boards
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
DIGITAL_READ(1, A0, 64); //14
DIGITAL_READ(1, A1, 128); //15
DIGITAL_READ(2, A2, 1); //16
DIGITAL_READ(2, A3, 2); //17
//DIGITAL_READ(2, A4, 4); //Not avaliable on Arduino Uno, i2c pin.
//DIGITAL_READ(2, A5, 8); //Not avaliable on Arduino Uno, i2c pin.
DIGITAL_READ(2, A6, 16); //20
DIGITAL_READ(2, A7, 32); //21
#endif
// DIGITAL READ not supports on A3 .. A7 on Arduino Uno
#ifdef DEBUG_READ
Serial.print(F("Read 9 bytes: "));
Serial.print(buffer[0]);
Serial.print(' ');
Serial.print(buffer[1]);
Serial.print(' ');
Serial.println(buffer[2]);
Serial.print(' ');
Serial.println(buffer[3]);
Serial.print(' ');
Serial.println(buffer[4]);
Serial.print(' ');
Serial.println(buffer[5]);
Serial.print(' ');
Serial.println(buffer[6]);
Serial.print(' ');
Serial.println(buffer[7]);
Serial.print(' ');
Serial.println(buffer[8]);
#endif
}
void readAnalog(int pin)
{
int val = analogRead(A0 + pin);
len = 2;
buffer[0] = val & 0xFF;
buffer[1] = (val >> 8) & 0b11;
#ifdef DEBUG_READ
Serial.print(F("Read analog pin "));
Serial.println(pin);
#endif
}
void onRequest()
{
Wire.write(const_cast<uint8_t *>(buffer), len);
}
#define CMD_DIGITAL_READ 0x0
#define CMD_WRITE_ANALOG 0x2
#define CMD_WRITE_DIGITAL_HIGH 0x3
#define CMD_WRITE_DIGITAL_LOW 0x4
#define CMD_SETUP_PIN_OUTPUT 0x5
#define CMD_SETUP_PIN_INPUT_PULLUP 0x6
#define CMD_SETUP_PIN_INPUT 0x7
// 8 analog registers.. A0 to A14
// A4 and A5 on Arduino Uno are not supported due to I2C
#define CMD_ANALOG_READ_A0 0b1000 // 0x8
// ....
#define CMD_ANALOG_READ_A14 0b10000 //16
#define CMD_SETUP_ANALOG_INTERNAL 0x10
#define CMD_SETUP_ANALOG_DEFAULT 0x12
void onReceive(int numBytes)
{
#ifdef DEBUG_READ
Serial.print("Received bytes: ");
Serial.println(numBytes);
#endif
int cmd = Wire.read();
switch (cmd)
{
case CMD_DIGITAL_READ:
readDigital();
break;
}
if (cmd >= CMD_ANALOG_READ_A0 && cmd <= CMD_ANALOG_READ_A14)
{
readAnalog(cmd & 0b1110);
return;
}
int pin = Wire.read();
switch (cmd)
{
case CMD_WRITE_DIGITAL_HIGH:
case CMD_WRITE_DIGITAL_LOW:
{
bool output = cmd == CMD_WRITE_DIGITAL_HIGH;
digitalWrite(pin, output);
#ifdef DEBUG
Serial.print(F("Pin "));
Serial.print(pin);
Serial.println(output ? F(" HIGH") : F(" LOW"));
#endif
break;
}
case CMD_WRITE_ANALOG:
{
int val = Wire.read() & (Wire.read() << 8);
analogWrite(pin, val);
#ifdef DEBUG
Serial.print(F("Pin "));
Serial.print(pin);
Serial.print(F(" Analog write "));
Serial.println(val);
#endif
break;
}
case CMD_SETUP_PIN_OUTPUT:
pinMode(pin, OUTPUT);
#ifdef DEBUG
Serial.print(F("Pin "));
Serial.print(pin);
Serial.println(F(" OUTPUT"));
#endif
break;
case CMD_SETUP_PIN_INPUT:
pinMode(pin, INPUT);
#ifdef DEBUG
Serial.print(F("Pin "));
Serial.print(pin);
Serial.println(F("INPUT"));
#endif
break;
case CMD_SETUP_PIN_INPUT_PULLUP:
pinMode(pin, INPUT_PULLUP);
#ifdef DEBUG
Serial.print(F("Pin "));
Serial.print(pin);
Serial.println(F("INPUT PULLUP"));
#endif
break;
case CMD_SETUP_ANALOG_INTERNAL:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
analogReference(INTERNAL1V1);
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
analogReference(INTERNAL);
#endif
#ifdef DEBUG
Serial.println(F("Analog reference INTERNAL"));
#endif
break;
case CMD_SETUP_ANALOG_DEFAULT:
analogReference(DEFAULT);
#ifdef DEBUG
Serial.println(F("Analog reference DEFAULT"));
#endif
break;
}
}
### The Esphome Example Config
esphome:
name: pool-management-system
friendly_name: Pool Management System
includes:
- arduino_port_expander.h
esp8266:
board: nodemcu
# Enable Home Assistant API
api:
encryption:
key: **"REMOVED"**
ota:
password: **"REMOVED"**
wifi:
ssid: **"REMOVED"**
password: **"REMOVED"**
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Pool-Management-System"
password: **"REMOVED"**
# define i2c device
# for an ESP8266 SDA is D2 and goes to Arduino's A4
# SCL is D1 and goes to Arduino's A5
i2c:
id: i2c_component
logger:
level: DEBUG
# define the port expander hub, here we define one with id 'expander1',
# but you can define many
custom_component:
- id: expander1
lambda: |-
auto expander = new ArduinoPortExpander(i2c_component, 0x08, true);
return {expander};
# define binary outputs, here we have 4, as the relays are inverse logic
# (a path to ground turns the relay ON), we defined the inverted: true
# option of ESPHome outputs.
output:
- platform: custom
type: binary
lambda: |-
return {ape_binary_output(expander1, 2),
ape_binary_output(expander1, 3),
ape_binary_output(expander1, 4),
ape_binary_output(expander1, 5)};
outputs:
- id: relay_1
inverted: true
- id: relay_2
inverted: true
- id: relay_3
inverted: true
- id: relay_4
inverted: true
# connect lights to the first 2 relays
light:
- platform: binary
id: ceiling_light
name: Ceiling light
output: relay_1
- platform: binary
id: room_light
name: Living room light
output: relay_2
# connect a fan to the third relay
fan:
- platform: binary
id: ceiling_fan
output: relay_3
name: Ceiling fan
# connect a pump to the 4th relay
switch:
- platform: output
name: Tank pump
id: tank_pump
output: relay_4
# define binary sensors, use the Arduino PIN number for digital pins and
# for analog use 14 for A0, 15 for A1 and so on...
binary_sensor:
- platform: custom
lambda: |-
return {ape_binary_sensor(expander1, 7),
ape_binary_sensor(expander1, 8),
ape_binary_sensor(expander1, 9),
ape_binary_sensor(expander1, 10),
ape_binary_sensor(expander1, 14) // 14 = A0
};
binary_sensors:
- id: push_button1
internal: true # don't show on HA
on_press:
- light.toggle: ceiling_light
- id: push_button2
internal: true # don't show on HA
on_press:
- light.toggle: room_light
- id: pir_sensor
name: Living PIR
device_class: motion
- id: window_reed_switch
name: Living Window
device_class: window
- id: garage_door
name: Garage garage
device_class: garage_door
# define analog sensors
sensor:
- platform: custom
lambda: |-
return {ape_analog_input(expander1, 1), // 1 = A1
ape_analog_input(expander1, 2)};
sensors:
- name: LM35 Living room temperature
id: lm35_temp
filters:
# update every 60s
- throttle: 60s
# LM35 outputs 0.01v per ºC, and 1023 means 3.3 volts
- lambda: return x * 330.0 / 1023.0;
- name: Analog A2
id: analog_a2
filters:
- throttle: 2s