I2c-slave stopped working

Hi, I want to build a large display with 4 7-segment digits. A master-ESP32 gets the data to display via MQTT and sends them via an i2c-bus to the digits, which each have a ESP32-slave. The slaves shall compile their i2c-address from 3 jumpers according to their position in the display. So I only have one type of spare and can configure it via jumpers.

From ESP32 I2C Slave - Arduino Reference I found a library at github
GitHub - gutierrezps/ESP32_I2C_Slave: I2C slave library for ESP32
and copied the examples for testing with minor changes. This worked as expected.

When I added the code for reading the jumpers and changed
bool success = WireSlave.begin(SDA_PIN, SCL_PIN, I2C_SLAVE_ADDR);
to
bool success = WireSlave.begin(SDA_PIN, SCL_PIN, position);
where position is an int, it gave me

E (25) i2c: i2c_param_config(671): i2c clock choice is invalid, please check flag and frequency
[ 29][E][WireSlave.cpp:53] begin(): invalid I2C parameters

I changed back, but the error remains :-((

I can't find any infos about Flags and frequency for this library. Since it is a slave, it should adjust to the frequency of the master? Or should frequency set equal on the master and the slaves? But where?

Any ideas what goes wrong here?
TIA, Karl

A slave does not generate clock pulses on SCL.

Hi Doc,
that's what I was thinking, but what does this error mean and what can I do?

I changed back to the constant, but the error stays here.

Show the code around the line in error.

Hi again, here's part of the code:

#include "Arduino.h"
#include <Wire.h>
#include <WireSlave.h> 

#define SDA_PIN 21 
#define SCL_PIN 22 
#define I2C_SLAVE_ADDR 0x02 

void setup() {
int position = get_position();
  Serial.print("L114 position= ");
  Serial.println(position);  

  bool success = WireSlave.begin(SDA_PIN, SCL_PIN, position); 
	if (!success) { 
		Serial.println("I2C slave init failed"); 
		while(1) delay(100); 
	} 
  else {
	Serial.printf("Slave joined I2C bus with addr #%d\n", I2C_SLAVE_ADDR); 
  }

  WireSlave.onReceive(receiveEvent);
	//WireSlave.onRequest(requestEvent); 
}

Can you see what I did wrong?

Is it possible to use Serial2 and connect all of them via a daisy chain ?

The I2C bus was not designed to go into a cable to go somewhere else. It is not that kind of bus. It is also a bad idea to use the I2C bus for communication between processors. The Wire library is blocking, the Master waits until the I2C session has finished.

The ESP32 has been updated for Slave mode with the Arduino IDE. I think there was a update a month ago, or maybe that was just the documentation. You don't have to install a library. Please uninstall that library and update your boards.

The Master-Slave examples from Espressif are pretty terrible [EDIT] They made it less ugly 15 days ago.
They are still not compatible with the Arduino Wire library.
There is no proof yet that the ESP32 works reliable in Slave mode. You can try it for a experiment. I suggest to use something else for a real project.

It took many years to make the Arduino Uno work reliable in Slave mode. There seems to be problems with the Arduino Zero (ATSAMD21 processors) with the I2C. The Arduino Due has troubles with the I2C bus. Projects with motors and a I2C bus between a Master and a Slave often fail.
If you do everything wrong, then the length of a I2C bus can be 20cm. If you follow the standards, then 2 meters is possible. Some can even go further.

Yes, I know that it is a short haul bus - my bus is 0,2m long, so I am inside specification.
Searching on www.arduino.cc for "ESP32 i2c slave" gives a link to the library I try to use.

I forgot to mention that I use platform.io as IDE, not Arduino.

What do you suggest? rs485, CAN-bus for a bus of a few cm? Is it easier with SPI, or do I get the same problems?

Just normal RX TX. The ESP32 has a spare Serial2. You have to find a way to connect all of them.
Search for "serial daisy-chain".
If you need only communication one way, then you could connect all the RX to the single TX of the Master.
If that is too hard, then you could add RS-485 modules to the RX TX signals and use a RS485 library.

The SPI bus is a high speed bus, perfect for a SD memory card, but not to communicate between modules.

You should not add things to your project that don't belong there. Please remove that library from your computer. There is even a note that it should no longer be used.

The Espressif Slave example: WireSlave.ino.
The Espressif documentation about I2C in Arduino mode: https://docs.espressif.com/projects/arduino-esp32/en/latest/api/i2c.html

I followed your advice and used the Wire-library and followed the examples.
Now it works in one direction. I will test the other direction sometime this week.

Thank you, Karl

PS: Don't you think there should be a remark on
ESP32 I2C Slave - Arduino Reference
that that library is obsolete? Who is able to do this?

You have a dual core, 64-bit, 240MHz processor controlling each digit? That's world-record level of overkill!

2 Likes

You are right - nearly. I think you will admit, that I save myself a lot of wiring compared to a conventional design. Additionally I have 6 large and a few small displays and so I can keep the count of spares low, since they all are identical. Furthermore I can implement actions for different failures. Considering all this and design time for the PCBs, I think it is a financially good solution - by transistor count it sure is overkill!

No, I don't see how using an esp32 rather than, for example a pcf8574 or tpic6b595 saves any wiring. In fact tpic6b595 might save some wiring compared to esp32. The esp32's pins can only supply 12mA at 5V and I suspect more is needed for your digits, so I imagine you are using transistors or ULN chips also. Depending on their requirements, tpic6b595 might replace both the esp32 and the transistors/ULN.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.