“Define a series of steps for performing automatic tests of your I2C devices using just a Raspberry Pi Pico.
While developing my latest project, I encountered the need to repeatedly test the device by transmitting several I2C commands in a specified order. In this way, I could ensure the target device would respond correctly after pushing the latest code changes. However, the transmitting microcontroller, typically an Arduino-based board, had to be programmed to send I2C data and print the results upon boot, which also meant any changes made to the controller required a reflash. My goal for this project was to build a device that could perform any kind of I2C-related task without the need for reprogramming if a change were to occur.
The most important aspect of this I2C probe is the fact that it works via a JSON file which can be dropped into the virtual storage device presented by the Raspberry Pi Pico’s CircuitPython firmware. Once this happens, the file is read and parsed to extract configuration options along with the series of steps. Think of a step as a command, and the configuration information as settings regarding the bus, a default address, and a default delay between steps.
Found here on GitHub, the I2C implementation is not platform-specific, as every command call is simply an abstraction. Currently, the base class requires implementations for scan, checkAddress, write, read, and writeThenRead. The I2CSim class prints plausible data that could be reasonably expected from a real device, and its purpose is to check if the steps being run are the desired ones. Meanwhile, the I2CPico class configures the I2C0 bus on pins 4 and 5 to perform real operations and print the results via USB serial.
Each step in the steps array is a JSON object containing certain keys that convey the action being taken and any other data that is required to carry it out. For instance, the WRITE action type needs a key called data which is an array of bytes to be transmitted. Meanwhile, the REPEAT action performs a series of steps a certain number of times. If overridden default values do not appear in the individual action, the default from the config object is used instead. This is especially useful when working with only a single device, as its address can be used for every action.”