stickbreaker / arduino-esp32

Arduino core for the ESP32
38 stars 23 forks source link

ETH and I2C #36

Closed deividi21 closed 6 years ago

deividi21 commented 6 years ago

Hardware:

Board: ESP32 Dev Module Core Installation/update date: ?11/jul/2017? IDE name: Arduino IDE Flash Frequency: 80Mhz Upload Speed: 921600

Description:

I have been trying to communicate by I2C while connected through Ethernet cable. Stand alone, both communication works. Although, when I begin ETH, Wire stops working. ETH seems to work properly.

Sketch:

#include <ETH.h>
#include <Wire.h>

static bool eth_connected = false;

void WiFiEvent(WiFiEvent_t event)
{
    switch (event) {
        case SYSTEM_EVENT_ETH_START:
        Serial.println("ETH Started");
        //set eth hostname here
        ETH.setHostname("esp32-ethernet");
        break;
        case SYSTEM_EVENT_ETH_CONNECTED:
        Serial.println("ETH Connected");
        break;
        case SYSTEM_EVENT_ETH_GOT_IP:
        Serial.print("ETH MAC: ");
        Serial.print(ETH.macAddress());
        Serial.print(", IPv4: ");
        Serial.print(ETH.localIP());
        if (ETH.fullDuplex()) {
            Serial.print(", FULL_DUPLEX");
        }
        Serial.print(", ");
        Serial.print(ETH.linkSpeed());
        Serial.println("Mbps");
        eth_connected = true;
        break;
        case SYSTEM_EVENT_ETH_DISCONNECTED:
        Serial.println("ETH Disconnected");
        eth_connected = false;
        break;
        case SYSTEM_EVENT_ETH_STOP:
        Serial.println("ETH Stopped");
        eth_connected = false;
        break;
        default:
        break;
    }
}

void testClient(const char * host, uint16_t port)
{
    Serial.print("\nconnecting to ");
    Serial.println(host);

    WiFiClient client;
    if (!client.connect(host, port)) {
        Serial.println("connection failed");
        return;
    }
    client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
    while (client.connected() && !client.available());
    while (client.available()) {
        Serial.write(client.read());
    }
    Serial.println("closing connection\n");
    client.stop();
}

void setup()
{
    Serial.begin(115200);
    WiFi.onEvent(WiFiEvent);
    ETH.begin(1, 17, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT);

    Wire.begin(33, 32,100000);
}

void loop()
{
    if (eth_connected) {
        testClient("google.com", 80);
    }

    delay(5000);
    Wire.beginTransmission(40);
    Wire.write("test");
    Wire.endTransmission();
}

Debug Messages:

Opening port
Port open
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 19 - ETH_START
ETH Started
[W][esp32-hal-i2c.c:1094] i2cCheckLineState(): invalid state sda=0, scl=0

[E][esp32-hal-i2c.c:1110] i2cCheckLineState(): Bus Invalid State, TwoWire() Can't init
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 21 - ETH_CONNECTED
ETH Connected
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 23 - ETH_GOT_IP
ETH MAC: 30:AE:A4:19:5E:47, IPv4: 10.1.1.147, FULL_DUPLEX, 100Mbps

connecting to google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 01 Jun 2018 18:43:30 GMT
Expires: Sun, 01 Jul 2018 18:43:30 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
closing connection

connecting to google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 01 Jun 2018 18:43:35 GMT
Expires: Sun, 01 Jul 2018 18:43:35 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
closing connection

Port closed
stickbreaker commented 6 years ago

@deividi21

[W][esp32-hal-i2c.c:1094] i2cCheckLineState(): invalid state sda=0, scl=0 [E][esp32-hal-i2c.c:1110] i2cCheckLineState(): Bus Invalid State, TwoWire() Can't init

These messages are telling you that the Defined SCL and SDA pins are not in the 'idle' state when Wire.begin() was called, the init section tried to recover the buss to their idle state by manually driving the pins through a High/Low sequence that preforms an i2c Reset. But, it was unsuccessful.

What is your electrical circuit? The esp32 needs pullup resistors on the I2c buss I recommend 2.4k ohm to 3.3v.

Reviewing Eth.h, it seems that the Ethernet controller chips use an i2c bus for configuration, but I can't find what calls it actually makes. Eth.h is buried in esp-idf, so I cant see the source. I suspect that the idf is commandeering i2c0, try using i2c1.

Change your code to release Wire(), and assign it to i2c1:

void setup(){
Serial.begin(115200);
 ~Wire();
Wire = TwoWire(1);
Serial.println("initializing i2c1 using pins 33 and 32");
Wire.begin(33,32,100000);

WiFi.onEvent(WiFiEvent);
ETH.begin(1, 17, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT);
Serial.println("Re-Initing Wire, testing to make sure it still works after ETH start");
Wire.begin(33,32,100000);
}

Chuck.

deividi21 commented 6 years ago

@stickbreaker Thanks for the quick response.

This is the schematic of the i2c bus:

image

"Reviewing Eth.h, it seems that the Ethernet controller chips use an i2c bus for configuration, but I can't find what calls it actually makes. Eth.h is buried in esp-idf, so I cant see the source. I suspect that the idf is commandeering i2c0, try using i2c1." I have the same thought. I'm still looking for clues on this subject.

I've made the modifications, but I had to comment "~Wire();". I was getting this error:

Error compiling project sources
Teste_i2c_eth.ino: 70:8: error: no match for call to '(TwoWire) ()
Build failed for project 'Teste_i2c_eth'
   ~Wire()

After commenting "~Wire();", I got:

Opening port
Port open
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
initializing i2c1 using pins 32 and 32
Re-Initing Wire, testing to make sure it still works after ETH start
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 19 - ETH_START
ETH Started
[W][esp32-hal-i2c.c:1094] i2cCheckLineState(): invalid state sda=0, scl=0

[E][esp32-hal-i2c.c:1110] i2cCheckLineState(): Bus Invalid State, TwoWire() Can't init
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 21 - ETH_CONNECTED
ETH Connected
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 23 - ETH_GOT_IP
ETH MAC: 30:AE:A4:19:5E:47, IPv4: 10.1.1.147, FULL_DUPLEX, 100Mbps

connecting to google.com
stickbreaker commented 6 years ago

what version of my code are you using? espressif/arduino-esp32/stickbreaker-i2c stickbreaker/arduino-esp32/main /v.0.2.3 stickbreaker/arduino-esp32/stickbreaker-i2c stickbreaker/arduino-esp32/release v0.2.0 // v0.2.0

~Wire(); 

should not generate a compiler error.

Chuck.

deividi21 commented 6 years ago

Hello again stickbreaker, sorry for the delay. I had to solve some troubles at my work before going through this subject again.

I'm using stickbreaker/arduino-esp32 , Branch: stickbreaker-i2c. Is it correct?

There is this code at the end of Wire.h: / V0.2.2 13APR2018 preserve custom SCL,SDA,Frequency when no parameters passed to begin() V0.2.1 15MAR2018 Hardware reset, Glitch prevention, adding destructor for second i2c testing /

~Wire(); Still doesn't work. I've tried to call the functions in it by creating an other public function, but it dind't wok.

I've tried different ways of calling the I2C functions by changing their position on the code, pins and address, but again, nothing worked.

stickbreaker commented 6 years ago

@deividi21 you are one version behind, grab the current files in my repo, libraries/Wire/src/Wire.h libraries/Wire/src/Wire.cpp cores/esp32/esp32-hal-i2c.h cores/esp32/esp32-hal-i2c.c cores/esp32/esp32-hal-log.h

Version V0.2.3 is where I first supported destructors.

You are currently on stickbreaker/arduino-esp32 V0.2.2 which did not support ~Wire().

Chuck.

deividi21 commented 6 years ago

@stickbreaker , I've downloaded the V0.2.3 version and fixed the destructor problem. I think calling the destructor by ~Wire() is wrong. A book that my friend recommended to me states Wire.~TwoWire(). Book: Beginning C for Arduino, Second Edition: Learn C Programming for the Arduino, page 336 Jack Purdum, ISBN-13 (pbk): 978-1-4842-0941-7 ISBN-13 (electronic): 978-1-4842-0940-0 DOI 10.1007/978-1-4842-0940-0

However, I'm still geting the same error:

Opening port
Port open
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
initializing i2c1 using pins 33 and 32
Re-Initing Wire, testing to make sure it still works after ETH start
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 19 - ETH_START
ETH Started
[E][Wire.cpp:141] initHardware(): invalid state sda=0, scl=0

[E][Wire.cpp:159] initHardware(): Bus Invalid State, TwoWire() Can't init
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 21 - ETH_CONNECTED
ETH Connected
[D][WiFiGeneric.cpp:293] _eventCallback(): Event: 23 - ETH_GOT_IP
ETH MAC: 30:AE:A4:19:5E:47, IPv4: 10.1.1.147, FULL_DUPLEX, 100Mbps
[E][esp32-hal-i2c.c:1202] i2cProcQueue():  Busy Timeout start=0x13bf, end=0x13f1, =50, max=50 error=0
[E][esp32-hal-i2c.c:630] i2cDumpI2c(): i2c=0x3ffc1148
[E][esp32-hal-i2c.c:641] i2cDumpI2c(): dev=0x60027000 date=0x16042000 level=DEBUG
[E][esp32-hal-i2c.c:643] i2cDumpI2c(): lock=0x3ffd43e0
[E][esp32-hal-i2c.c:645] i2cDumpI2c(): num=1
[E][esp32-hal-i2c.c:646] i2cDumpI2c(): mode=1
[E][esp32-hal-i2c.c:647] i2cDumpI2c(): stage=3
[E][esp32-hal-i2c.c:648] i2cDumpI2c(): error=0
[E][esp32-hal-i2c.c:649] i2cDumpI2c(): event=0x3ffdcde4 bits=0
[E][esp32-hal-i2c.c:650] i2cDumpI2c(): intr_handle=0x3ffdce14
[E][esp32-hal-i2c.c:651] i2cDumpI2c(): dq=0x3ffdcdc0
[E][esp32-hal-i2c.c:652] i2cDumpI2c(): queueCount=1
[E][esp32-hal-i2c.c:653] i2cDumpI2c(): queuePos=0
[E][esp32-hal-i2c.c:654] i2cDumpI2c(): byteCnt=0
[E][esp32-hal-i2c.c:604] i2cDumpDqData(): [0] 50 W STOP buf@=0x3ffc3416, len=4, pos=4, eventH=0x0 bits=0
[E][esp32-hal-i2c.c:620] i2cDumpDqData(): 0x0000: test                             74 65 73 74 
[E][esp32-hal-i2c.c:968] i2cDumpInts(): 1 row  count   INTR    TX     RX
[E][esp32-hal-i2c.c:971] i2cDumpInts(): [01] 0x0001 0x0002 0x0005 0x0000 0x000013bf
[E][esp32-hal-i2c.c:971] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x000013bf
[E][Wire.cpp:141] initHardware(): invalid state sda=0, scl=0

[E][Wire.cpp:159] initHardware(): Bus Invalid State, TwoWire() Can't init

connecting to google.com

Port closed
stickbreaker commented 6 years ago

@deividi21 I don't have a solution for you. These errors:

initializing i2c1 using pins 33 and 32 Re-Initing Wire, testing to make sure it still works after ETH start [D][WiFiGeneric.cpp:293] _eventCallback(): Event: 19 - ETH_START ETH Started [E][Wire.cpp:141] initHardware(): invalid state sda=0, scl=0 [E][Wire.cpp:159] initHardware(): Bus Invalid State, TwoWire() Can't init

are stating fact. If SCL and SDA are not idle(high) the i2c bus cannot be initialized. Either you have a hardware fault or as you suspect, the Ethernet library/hardware is stomping on pins 32,33.

[E][esp32-hal-i2c.c:1202] i2cProcQueue(): Busy Timeout start=0x13bf, end=0x13f1, =50, max=50 error=0

If the I2c bus (SCL,SDA) is not idle(high) when a transaction starts, a Busy Timeout will always occur. There is nothing in software I can do to fix a hardware reality.

I would recommend you post this issue on the main Espressif repo: espressif/arduino-esp32. I would title it: Ethernet causing GPIO32,33 to always read LOW.

Chuck.

stickbreaker commented 6 years ago

@deividi21 What happens when you use different GPIO pins?

Chuck.

deividi21 commented 6 years ago

@stickbreaker I've tried the GPIOs 16 and 4 (SDA ans SCL), but it presents the same error.

stickbreaker commented 6 years ago

@deividi21 i don't have any experience with ethernet on Esp32, this article mentions that it uses i2c for control. It uses SMI_MDC and SMI_MDIO. Perhaps the ethernet library is redirecting/reconfiguring the second i2c peripheral.

Chuck.

deividi21 commented 6 years ago

Thank you Chuck, I'll keep trying. If I got any news, I'll post it here.