Skip to content

judasgutenberg/Arduino_I2C_Slave_With_Commands

Repository files navigation

Arduino I2C Slave With Commands

This is based on the simpler Generic_Arduino_I2C_Slave and this firmware is compatible with I2C masters only expecting that firmware. An I2C Slave is a microcontroller connected to a master via I2C signals that responds to commands sent via I2C from the master. The master can use a slave to control additional GPIO pins, access its EEPROM, or even have the slave act as a watchdog to reset it should it fail to occasionally "pet" the slave. If the master is internet-capable, it can also reflash the slave's firmware entirely over I2C (no wire to reset required) if you install my version of the twiboot bootloader on the slave.

The wiring is pretty trivial, especially to anyone who had to solder all the data and address signals of a device back in the 1980s:

image

image

GPIO pins on the slave are read or controlled in the simplest way possible: a request to a single byte returns the value at the pin of that number. Any value sent that is more than one byte is considered a write, with the first byte being the GPIO pin number and everything else being the value. There is a range of pins that is so large that they do not exist (pins greater than 128) and writing to or reading from those triggers a number of additional functions.

master_slave.ino (and master_slave.h if you want master_slave.ino to instead be a .cpp file) are a library of functions for communicating with this slave from a master. This is taken directly from my ESP8266_Remote repository and will probably need tweaking to work with your code (for example, it refers to a global, config, and utility files that aren't in this repository).

This version adds the ability for an Arduino Slave to run a number of commands issued by a master. These commands are all pin actions to pins numbered between 128 and 255. On an Arduino, such actions are to pin numbers that are beyond those likely to be present (at least as of 2025), so they are available for a wide range of uses. For now the commands are:

128: reboot slave

129: return millis() value of slave

130: return millis() of last watchdog reboot from slave (0 for never rebooted)

131: return number of reboots since the slave booted

132: return millis of last time watchdog was petted (0 for never petted)

133: seconds ago that the watchdog was petted when it last bit (0 for never bit)

134: make slave reboot the master now

150: set pointer for EEPROM read/write

151: sequential EEPROM write mode

152: sequential EEPROM read mode

153: exit EEPROM mode, back to default behavior

160: get firmware version

161: get unix time of last firmware compile

162: get onboard temperature (or whatever that glitchy value is)

163: get free memory

164: get slave configuration - where in the EEPROM the slave-specific configuration is stored

165: get an int representing the processor type

166: get the size in bytes of RAM space

170: set serial baud rate and start serial port

171: retrieve data from serial buffer

172: populate serial buffer for transmission

173: get unix time of last successful serial data parse

174: get last parsed data arriving via serial

175: set parsed serial packet offset

176: get specific parsed serial datum (by ordinal)

177: get number of serial parse configurations

178: get size of parsed serial packet in bytes

179: set serial mode (0: no serial, 1: serial monitor, 2: parse serial for data using parse configuration)

180: set UNIX time

181: get UNIX time

182: get slave configuration given index

183: set slave configuration at index with value

190: jump to bootloader - useful when you want the master to reflash the slave's firmware via I2C, which is now supported. Before jumping, a magic value is set in a word beginning at location 510 (decimal) in the EEPROM, telling the bootloader to go into reflashing mode.

20X: pet hardware watchdog - if this is implemented, the slave will reboot the master if it is not petted frequently enough. This mechanism also allows the master to send the Unix timestamp so the the slave can keep track of Unix time independently. There are a range of pet-the-watchdog commands:

200: pets the watchdog, telling it that it must be petted once per second or it can bite (reset!) -- that's way too fast, don't do that.

201: pets the watchdog, telling it that it must be petted once per every ten seconds or it can bite (reset!) -- that's a bit too fast, so probably not too useful.

202: pets the watchdog, telling it that it must be petted once every 100 seconds or it can bite (reset!) -- that's a workable rate, but it's a bit too fussy.

203: pets the watchdog, telling it that it must be petted once every 1000 seconds or it can bite (reset!) -- that will keep your master alive without a lot of unneeded restarts.

204: pets the watchdog, telling it that it must be petted once every 10000 seconds or it can bite (reset!) -- only requires a pet once every 3 hours. Also a useful rate.

One particularly useful feature is the serial parser. This is a system where a slave can be configured to monitor a serial line (one that may not actually attach to the master) looking for certain passages of text to focus on. When it detects these, it can then look for data at offsets within these passages and then assemble integers from the data to place in a data packet for retrieval by the master. This completely offloads serial parsing from the master. I am using this feature to monitor serial traffic between a SolArk inverter and its WiFi dongle to capture important solar inverter data.

205: pets the watchdog, telling it that it must be petted once every 100000 seconds or it can bite (reset!) -- only requires a pet once every day. Useful, but not super responsive if the master should lock up.

Since an Atmega328 has a kilobyte of EEPROM, this can be used to store semi-volatile configuration data for a master, as EEPROM has much better wear characteristics than flash (the only storage option on a stock ESP32 or ESP8266 board). An advantage of storing configuration data on the slave is that the slave then becomes the "personality module." This means the masters can all run identical firmware, and you distinguish them by either giving them slaves containing different EEPROM configurations or you set their personalities up remotely.

About

Based on my Generic I2C Slave, this adds useful commands in place of reads to pin numbers that are too large to be found on a real device. Commands to control pins, EEPROM, and communicate via serial.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Contributors