This is on a cactus micro board I got from Tindie that is a 3.3v 8mhz atmega32u4 coupled with an ESP-11 module. I had to wire the GPIO0 and GPIO1 to the SCL and SDA lines and I switched the default jumpers from using SoftwareSerial on pins 11 and 12 to hardware serial. Max serial pass-through is 57600 because of known timing issues with the atmega32u4 running at 8mhz.
The code is a basic example showing how to set a digital pin state or the analogWrite value of a pwm pin. Should be easy to build on and add commands to get input pin values, analog sensor values, etc... Right now the arduino methods return the pin and value that was set as there's no way to get the value of an output pin. This is mainly to show how to get a multi-byte value back from the slave.
Arduino Sketch
#include <Wire.h>
#define ESP_CH_EN 13
#define SLAVE_ADDRESS 0x29
#define TWI_FREQ_SETTING 400000L // 400KHz for I2C
#define CPU_FREQ 8000000L // 8MHz
uint8_t command; // which command was requested (if any)
uint8_t pin;
uint8_t value;
enum {
I2C_CMD_SET_DIGITAL_PIN = 1,
I2C_CMD_SET_PWM_PIN = 2
};
void requestEvent(){
if (command > 0) {
uint8_t response[2];
response[0] = pin;
response[1] = value;
pinMode(pin, INPUT);
pinMode(pin, OUTPUT);
switch (command) {
case I2C_CMD_SET_DIGITAL_PIN:
digitalWrite(pin, (value) ? HIGH : LOW);
break;
case I2C_CMD_SET_PWM_PIN:
analogWrite(pin, value);
break;
}
Wire.write(response, sizeof response);
command = 0;
}
}
void receiveEvent(int bytesReceived) {
if (bytesReceived == 3) {
command = Wire.read();
pin = Wire.read();
value = Wire.read();
}
}
void setup() {
command = 0;
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect
}
Serial1.begin(57600);
// Enable esp8266
pinMode(ESP_CH_EN, OUTPUT);
digitalWrite(ESP_CH_EN, HIGH);
Wire.begin(SLAVE_ADDRESS);
// TWBR = ((CPU_FREQ / TWI_FREQ_SETTING) - 16) / 2;
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
}
void loop() {
while (Serial.available()) {
Serial1.write(Serial.read());
}
while (Serial1.available()) {
Serial.write(Serial1.read());
}
}
nodemcu code
function write_pin(dev_addr, command, pin, value)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, command)
i2c.write(id, pin)
i2c.write(id, value)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr,i2c.RECEIVER)
result=i2c.read(id,2)
i2c.stop(id)
--print("Pin " .. string.byte(result,1) .. " value is " .. string.byte(result,2) )
end
id = 0
sda = 4 -- GPIO2
scl = 3 -- GPIO0
slaveAddr = 0x29
digitalPinCommand = 1
pwmPinCommand = 2
digitalPin = 8
pwmPin = 9
state = 0
brightness = 0
fadeAmount = 5
i2c.setup(id,sda,scl,i2c.SLOW)
tmr.alarm(0, 1000, 1,
function()
state = not state
write_pin(slaveAddr, digitalPinCommand, digitalPin, (state and 1 or 0))
end
)
tmr.alarm(1, 30, 1,
function()
write_pin(slaveAddr, pwmPinCommand, pwmPin, brightness)
brightness = brightness + fadeAmount
if brightness == 0 or brightness == 255 then
fadeAmount = -fadeAmount
end
end
)