Skip to content

Confusing overload of Wire::begin #6616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Equidamoid opened this issue Apr 23, 2022 · 9 comments · Fixed by #7000
Closed

Confusing overload of Wire::begin #6616

Equidamoid opened this issue Apr 23, 2022 · 9 comments · Fixed by #7000
Assignees
Milestone

Comments

@Equidamoid
Copy link

Board

Any

Device Description

Not specific to a device.

Hardware Configuration

Any I2C device connected

Version

v2.0.2

IDE Name

CLion + platformio

Operating System

Linux

Flash frequency

N/A

PSRAM enabled

no

Upload speed

N/A

Description

The Wire::begin method has confusing overload:

    bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
    bool begin(uint8_t slaveAddr, int sda=-1, int scl=-1, uint32_t frequency=0);

The sda and scl arguments are of type int, while the SDA and SCL constants from d32_core.h have type uint8_t. A "naive" user might try to call begin(SDA, SCL) and get mysterious "could not acquire lock" error on first attempt to use the bus.

To make the problem worse, this code worked fine before the "slave" overload was introduced.

As a solution I want to propose renaming the "slave" function to something like begin_slave.

Sketch

int setup(){
    // have to explicitly specify the pins to provide the frequency
    Wire.begin(SDA, SCL, 4000);
    Wire.beginTransmission();
}

Debug Message

[   238][E][Wire.cpp:319] beginTransmission(): could not acquire lock
[   239][E][esp32-hal-i2c.c:142] i2cWrite(): could not acquire lock


### Other Steps to Reproduce

_No response_

### I have checked existing issues, online documentation and the Troubleshooting Guide

- [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@Equidamoid Equidamoid added the Status: Awaiting triage Issue is waiting for triage label Apr 23, 2022
@me-no-dev
Copy link
Member

You can also:

Wire.begin();
Wire.setClock(frequency);

@StickStackxD
Copy link

You can also:

Wire.begin();
Wire.setClock(frequency);

I can confirm that the workaround is working for now.

@Equidamoid
Copy link
Author

@me-no-dev
I came up with this (I know, ugly, but at least straightforward):

Wire.begin(static_cast<int>(SDA), static_cast<int>(SCL), static_cast<uint32_t>(4000));

@me-no-dev
Copy link
Member

casting also works, but I do see this as a kind of issue :) we will have to "fix" this somehow

@VojtechBartoska VojtechBartoska added Status: Needs investigation We need to do some research before taking next steps on this issue and removed Status: Awaiting triage Issue is waiting for triage labels Apr 26, 2022
@mymy-dot
Copy link

mymy-dot commented May 25, 2022

This issue ended up taking me several hours to solve, until by chance I came across this post. Granted, I don't know what I'm doing. But I do know that adding:

Wire.begin(static_cast<int>(SDA), static_cast<int>(SCL), static_cast<uint32_t>(4000));

Made the beginTransmission(): could not acquire lock error go away on my ESP-WROOM-32 and I was able to access my I2C device.

@bato3
Copy link

bato3 commented Jul 14, 2022

This is because SDA and SCL are defined as

static const uint8_t SDA = 21;
static const uint8_t SCL = 22;

and Wire.begin() can be:

    bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); 
    bool begin(uint8_t slaveAddr, int sda=-1, int scl=-1, uint32_t frequency=0);

And some libriares defines it initializations as:

   bool     begin(uint8_t sda = SDA, uint8_t scl = SCL, uint32_t speed = AHTXX_I2C_SPEED_100KHZ, uint32_t stretch = AHTXX_I2C_STRETCH_USEC);

Working solutions

  Wire.begin((int) SDA , (int) SCL);
  Wire.begin(21, 22);
  Wire.begin();

Not working solutions:

Wire.begin(0x38, (int) SDA, (int) SCL);
Wire.begin((uint8_t) -1, (uint8_t) -1); // display error:
//i2cSlaveInit(): invalid pins sda=-1, scl=22

Another affected: esphome/esphome#2978

@SuGlider
Copy link
Collaborator

I see some other conflict with overload of Wire::begin():

Wire.begin(SDA, SCL, 40000) will end up in I2C Slave initalization... This is a Regression Issue!

[   102][E][esp32-hal-i2c-slave.c:224] i2cSlaveInit(): invalid pins sda=9, scl=-128
[   109][E][Wire.cpp:168] begin(): Slave Init ERROR

I also noticed that it is necessay to force the right overload by using something like:

Wire.begin(SDA, SCL, (uint32_t)40000);   //  casting forces it to be MASTER

By other hand, a typical Arduino Slave initialization such as
Wirebegin(0x34);
will end up in a I2C MASTER initialization - also confusing because this is the Arduino I2C Slave deafult setup.

In order to force Slave setup, it is necessary to use a type casting again...

Wire.begin((uint8_t)0x34);   //  casting forces it to be SLAVE

@me-no-dev - would you consider changing all of it to the default Arduino way Wire::begin()/Wire::begin(uint8_t) and only expose Wire::setClock() and Wire::setPins() for an Arduino Core 2.1.0, for instance?

I think it may be a good way to "start over" and solve it for good.

@SuGlider
Copy link
Collaborator

@me-no-dev - Please evaluate the proposed solution in #7000

@SuGlider
Copy link
Collaborator

SuGlider commented Jul 16, 2022

#7000 makes all those cases to work fine:

  // I2C MASTER Test Cases
  Serial.println("\nUC 1.1 - Master - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin();

  Serial.println("\nUC 1.2 - Master - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin(-1, -1);
  
  Serial.println("\nUC 1.3 - Master - default SDA/SCL pins, 1KHz bus");
  Wire.end(); Wire.begin(-1, -1, 1000);
  
  Serial.println("\nUC 1.4 - Master - default SDA, SCL pin 2, 2KHz bus");
  Wire.end(); Wire.begin(-1, 2, 2000);
  
  Serial.println("\nUC 1.5 - Master - default SDA/SCL pins, 400KHz bus");
  Wire.end(); Wire.begin(SDA, SCL, 400000);
  
  Serial.println("\nUC 1.6 - Master default SDA pin 8, SCL pin 9, 800KHz bus");
  Wire.end(); Wire.begin(8, 9, 800000);
  
  Serial.println("\nUC 1.7 - Master - SDA pin 8, SCL pin 9, default 100KHz bus");
  Wire.end(); Wire.begin(8,9);
  
  Serial.println("\nUC 1.8 - Master - SDA pin 10, SCL pin 11, 200KHz bus");
  Wire.end(); Wire.begin(SDA_1, SCL_1, 200000);
  
  Serial.println("\nUC 1.9 - Master - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin(SDA, SCL);
  
  Serial.println("\nUC 1.10 - Master - default SDA/SCL pins, 4KHz bus");
  Wire.end(); Wire.begin(-1, -1, 4000);
  
  Serial.println("\nUC 1.11 - Master - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin((int) SDA , (int) SCL);

  // I2C SLAVE Test Cases
  Serial.println("\nUC 2.1 - Slave - ADDR 0x28 - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin(0x28);
  
  Serial.println("\nUC 2.2 - Slave - ADDR 0x21 - default SDA/SCL pins, default 100KHz bus");
  Wire.end(); Wire.begin(SLV_ADDR);
  
  Serial.println("\nUC 2.3 - Slave - ADDR 0x21 - default SDA/SCL pins, 4KHz bus");
  Wire.end(); Wire.begin(SLV_ADDR, -1, -1, 4000);
  
  Serial.println("\nUC 2.4 - Slave - ADDR 0x38 - SDA 10, SCL 11, default 100KHz bus");
  Wire.end(); Wire.begin(0x38, SDA_1, SCL_1, 0);
  
  Serial.println("\nUC 2.5 - Slave - ADDR 0x38 - default SDA/SCL pins, 4KHz bus");
  Wire.end(); Wire.begin(0x38, -1, SCL, 4000);

@SuGlider SuGlider self-assigned this Jul 16, 2022
@SuGlider SuGlider added this to the 2.0.5 milestone Jul 16, 2022
@SuGlider SuGlider moved this from Todo to In Progress in Arduino ESP32 Core Project Roadmap Jul 16, 2022
@SuGlider SuGlider moved this from In Progress to In Review in Arduino ESP32 Core Project Roadmap Jul 16, 2022
@SuGlider SuGlider moved this from In Review to In Progress in Arduino ESP32 Core Project Roadmap Jul 16, 2022
@SuGlider SuGlider moved this from In Progress to In Review in Arduino ESP32 Core Project Roadmap Jul 20, 2022
Repository owner moved this from In Review to Done in Arduino ESP32 Core Project Roadmap Jul 26, 2022
@VojtechBartoska VojtechBartoska removed the Status: In Progress ⚠️ Issue is in progress label Jul 26, 2022
dasdgw added a commit to dasdgw/yoradio that referenced this issue Apr 14, 2024
this fixes the touch sensor for cyd esp32-3248S035C.

error msg: beginTransmission(): "Bus is in Slave Mode"

possibly related:
espressif/arduino-esp32#6616
dasdgw added a commit to dasdgw/gt911-arduino that referenced this issue Apr 20, 2024
    this fixes the touch sensor for cyd esp32-3248S035C.
    
    error msg: beginTransmission(): "Bus is in Slave Mode"
    
    possibly related:
    espressif/arduino-esp32#6616
dasdgw added a commit to dasdgw/gt911-arduino that referenced this issue Apr 20, 2024
    this fixes the touch sensor for cyd esp32-3248S035C.
    
    error msg: beginTransmission(): "Bus is in Slave Mode"
    
    possibly related:
    espressif/arduino-esp32#6616
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
7 participants