Skip to content
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

I2C not working correctly on ESP8266 since 1v92 #1311

Closed
SpenceKonde opened this issue Jan 17, 2018 · 33 comments
Closed

I2C not working correctly on ESP8266 since 1v92 #1311

SpenceKonde opened this issue Jan 17, 2018 · 33 comments
Labels
ESP8266 This is only a problem on ESP8266 devices

Comments

@SpenceKonde
Copy link

This can be efficiently demonstrated using an AT24 EEPROM - one of the simplest I2C devices there is. The only thing I can come up with that is consistent with the evidence is that only the first two bytes are getting though:

.read() works fine - it reports correct values. This means the first two data bytes are making it through, since they are used to set the address.
.write() however doesn't work. It doesn't error, it just doesn't write to the EEPROM.

The same EEPROM module works on a Pico running 1v95 and on an ESP8266 running 1v91.

I suspect the change that caused the problem is: ESP8266: Add i2c clock stretch (#1097)

See this forum thread for more information: http://forum.espruino.com/conversations/315565

@gfwilliams gfwilliams added the ESP8266 This is only a problem on ESP8266 devices label Jan 17, 2018
@gfwilliams
Copy link
Member

Wow, interesting - and does software I2C work?

@SpenceKonde
Copy link
Author

Will test tonight - I feel like I tried that, but I don't see any record of it in my posts, so will retest.

@MaBecker
Copy link
Contributor

Not sure what's not working on your side .....

firmware

 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v95 Copyright 2017 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:1024/1024, manuf 0xe0 chip 0x4016
> 

test snippet

// test with PCA9501

function enableWrite(w) {
  if ( w) 
    i2c.writeTo(id1,255^128^2);
  else 
    i2c.writeTo(id1,255);
}

var id1 =32;
var id2 = id1^64;

var i2c = new I2C();
i2c.setup({sda:D4,scl:D5});
I2C1.setup({sda:D4,scl:D5});

// Soft
  console.log('test with i2c');
  enableWrite(i2c,true);
  i2c.writeTo(id2,[0,"1234567890"]);
  enableWrite(false);

  i2c.writeTo(id2,0); console.log(E.toString(i2c.readFrom(id2,10)));

  enableWrite(true);
  i2c.writeTo(id2,[0,"ABCDEFGHIJ"]);
  enableWrite(false);

  i2c.writeTo(id2,0); console.log(E.toString(I2C1.readFrom(id2,10)));

// Hard
  console.log('test with I2C1');
  enableWrite(i2c,true);
  I2C1.writeTo(id2,[0,"1234567890"]);
  enableWrite(false);

  I2C1.writeTo(id2,0); console.log(E.toString(I2C1.readFrom(id2,10)));

  enableWrite(true);
  I2C1.writeTo(id2,[0,"ABCDEFGHIJ"]);
  enableWrite(false);

  I2C1.writeTo(id2,0); console.log(E.toString(I2C1.readFrom(id2,10)));

output

>test with i2c
1234567890
>ABCDEFGHIJ
test with I2C1
1234567890
>ABCDEFGHIJ
=undefined
> 

should by here by tomorrow

image

@SpenceKonde
Copy link
Author

SpenceKonde commented Jan 18, 2018

The plot thickens - read is NOT working afterall - it reads values, but they're WRONG in one case. I am at my GF's and didn't bring a pico, just the ESP8266, so I can't verify which is correct.

`
I2C1.setup({scl:5,sda:4}); I2Ctouse=I2C1;
//I2Ctouse=new I2C({scl:5,sda:4});
var eeprom=require("AT24").connect(I2Ctouse, 64, 256);
function test() {
var tval=eeprom.read(0,10);
console.log(eeprom.read(0,10));
eeprom.write(0,[tval[0]+2,tval[1]+2]);
console.log(eeprom.read(0,10));

}
`

Software I2C:

` _____ _
| |_ ___ ___ _ ||___ ___
| | -| . | _| | | | | . |
|
|| || |||||_|
|
| http://espruino.com
1v95 Copyright 2017 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:1024/1024, manuf 0xe0 chip 0x4016

=undefined

test()
new Uint8Array([200, 31, 255, 63, 200, 243, 255, 63, 188, 53])
new Uint8Array([200, 31, 255, 63, 200, 243, 255, 63, 140, 53])
=undefined

`

Hardware I2C


| |_ ___ ___ _ ||___ ___
| | -| . | _| | | | | . |
|
|| || |||||_|
|
| http://espruino.com
1v95 Copyright 2017 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
http://espruino.com/Donate
Flash map 4MB:1024/1024, manuf 0xe0 chip 0x4016

=undefined

test()
new Uint8Array([3, 22, 99, 107, 32, 116, 104, 101, 32, 112])
new Uint8Array([3, 22, 99, 107, 32, 116, 104, 101, 32, 112])
=undefined

`

Edit: I can't seem to make Github display code in the expected way, sorry. Not sure quite what's wrong here.

@MaBecker
Copy link
Contributor

Another positiv test by Frida:

http://forum.espruino.com/comments/14050812/

@SpenceKonde
Copy link
Author

I've updated the thread with results of additional tests. Software I2C seems completely broken here, on all boards, while hardware I2C works on Pico and ESP32, but not ESP8266.

@gfwilliams
Copy link
Member

This seems really odd. I'd noticed something that looked wrong (!started)? in software I2C, but was loathe to change it since software I2C worked.

Thing is, I've just spent the past week writing loads of modules using software I2C stuff on a variety of devices, and it's all worked without a hitch (apart from the MPU9250 - but that's almost certainly me) - so I'm honestly not sure what's going on at your end.

Software I2C does use the chip's pullup resistors, so if you were trying to drive 5v I guess it could interfere with 5v pullup resistors, but that seems super unlikely.

@SpenceKonde
Copy link
Author

EEPROM is running at 3.3v, same as microcontroller in all cases.

The fact that even on official Pico, we get total garbage out of software serial seems to suggest something is seriously wrong. Do any of the modules you were working with require two bytes to be written at a time to set the address of a register, instead of just 1? That seems to be the only "different" thing about the AT24 vs normal I2C.

In the case of both ESP's, power came in from 2A USB power supply into a 3.3v 1117-series regulator (I think these were NCP1117's - could have been ZLDO1117's too), on pico power came from the Vcc pin.

And Frida in the forum thread has now posted claiming to get the same results with software I2C and hardware I2C. I'm starting to question my own sanity - I've reproduced this on a whole bunch of devices, so why doesn't it happen for anyone else?

@gfwilliams
Copy link
Member

No, as far as I know they were all 1 byte write, multi-byte read.

Looking at the code, you'd expect anything with a capacity of 2048 or less to work though, since that's only a single byte that gets sent? In your examples you're using the 256 one?

@SpenceKonde
Copy link
Author

But cap is leftshifted by 7 bits, see:
function AT24(i2c, pgsz, cap, i2ca) {
this.i2c = i2c;
this.i2ca = (i2ca===undefined) ? 0x50 : 0x50|(i2ca&0x07);
this.pgsz=pgsz?pgsz:0;
this.cap=cap<<7;
this.ca=0;
}
AT24.prototype.a=function(b) {return (this.cap>2048)?E.toString([b>>8,b]):E.toString(b);};

And as noted in the description, you feed the constructor the capacity in kilobits (the same thing the manufacturers state in their headline description of the product); that leftshift of 7 is the same as a multiply by 1024 (to convert kilobits to bits) followed by a division by 8 to convert bits to bytes.

So I'm using a 256 kilobit (32 kbyte) EEPROM. It's 16kbit (2048 byte) or less that you need to take the other codepath.

@gfwilliams
Copy link
Member

Do you have a 2 channel oscilloscope? You might be able to see what's going wrong... Even if it's not storage you could just do the same command over and over.

@gfwilliams
Copy link
Member

gfwilliams commented Jan 19, 2018

Actually I should add that hardware I2C on ESP8266 isn't actually hardware. It's just another software implementation (although a different one!) - so that would explain a lot.

Perhaps the EEPROMS use the clock stretching functionality and the software I2C doesn't handle it properly?

@SpenceKonde
Copy link
Author

Yeah, I probably won't be able to put the scope on it until saturday, or maybe sunday due to plans w/gf, unless she wants to get it on her way back to her place :-P

Will post data when I'm able to get it.

@SpenceKonde
Copy link
Author

The timing of the I2C signals changed between 1v91 and 1v95 (presumably 1v91 -> 1v92) - in 1v91, it pulses SCL high in the middle of the bit on SDA - but in 1v95, it pulses SCL high seemingly simultaneously as SDA goes high (if it's a 1). I suspect this is behind the differences.

It seems to be right on the edge of working - connecting the scope probe to SCL is enough to make it work!

@gfwilliams
Copy link
Member

Thanks for checking - so is that software i2c on the Pico, or ESP8266?

@MaBecker
Copy link
Contributor

MaBecker commented Jan 21, 2018

Well, I can now confirm that a AT24C256 EEPROM does not work on 1v95 ESP8266 with both software I2C implementations.

But on 1v95 with this i2_master.c version it works using I2C1 and not with i2c = new I2C().

I can also confirm that this is now the only i2c device on my desk that does not work with the clock stretch version of i2c_master.

Additionally: I never use i2c = new I2C() on any device, so no test results for any device.

@SpenceKonde
Copy link
Author

SpenceKonde commented Jan 21, 2018

My experiments with the scope were using I2C1 on ESP8266.

I suppose software I2C tests might be even more interesting, since that seems to be busted everywhere.

Strange that the EEPROMs are pickier about the signal timing than other parts.

@gfwilliams
Copy link
Member

Diffing with the old i2c_master (git difftool 6e09066c679ca62634e7d9f732c8ff8e93b29cdc -- targets/esp8266/i2c_master.c) it seems that the clock-stretch checks actually replace the delay - it'd be pretty easy to just re-add a delay as well as the clock-stretch check, and that might fix it? I've just done this - so let me know if a new build fixes this.

It's possible the I2C EEPROMs then don't use clock-stretching, but still expect I2C to run reasonably slowly? I guess that could be the issue here.

Thanks for looking into this - if you could try and check out normal software I2C it'd be handy - I don't believe I have any I2C EEPROMs here, but I have added delays to that too now. Ideally I'd use the ESP8266 style though and use some half-delays in order to get nicely spaced clock signals - it'll be a bit miss-shapen now.

PS. While doing it I noticed that the ESP8266 impl doesn't seem to use timeouts - so if a device tried to stretch the clock forever (or there was a short) then it'd hang the call and cause a watchdog reboot!

@Frida854
Copy link

If I remember correctly, there was no timeout when i changed i2c to use clockstrecth

@MaBecker
Copy link
Contributor

MaBecker commented Jan 22, 2018

PS. While doing it I noticed that the ESP8266 impl doesn't seem to use timeouts - so if a device tried to stretch the clock forever (or there was a short) then it'd hang the call and cause a watchdog reboot!

Yes this can happen when using loops like this while (!i2c_master_getDD()) {};

i2c_master.c is taken from the ESP8266_NONOS_SDK and had no loops, so no need for timeouts.
And was modified to work with any pin for Espruino by @tve.

i2c_master_1v95_fix - read works, write not
i2c_master_1v95_fix

i2c_master_1v91 - works
i2c_master_1v91

@MaBecker
Copy link
Contributor

MaBecker commented Jan 23, 2018

Seems that AT24C256 is a special one. Got a TinyRTC module with a AT24C32 and it works perfect
i2c_master_1v95 (ae3a89f)
bildschirmfoto 2018-01-23 um 06 12 24

@SpenceKonde

  • can you replace the eeprom with a pin compatible one like 24LC256-I/P?
  • or rewrite our code and use esp8266 4MB internal flash?

@SpenceKonde
Copy link
Author

@MaBecker I have multiple other EEPROM chips. All of the others I have tried behave the same way as the AT24C256. I need the 1mbit ones, so I'm using 24FC1026's in my production modules. I tested out a number of other EEPROMs from my EEPROM drawer, and they all seem to have this problem - but as we established, it's right on the edge (it works with the scope probe attached), so I wouldn't be surprised if it appears to work with some parts and not others. I think the correct approach is to figure out what's going on here and correct Espruino's I2C implementations so that they work, rather than rummage through the EEPROM bin hoping to find some parts that work. They ALL used to work...

@gfwilliams - You can buy an AT24c256 from Mouser/Digikey/Farnell - connect WP and the address pins to ground, 0.1uF cap between Vcc and Gnd, and pullups on I2C lines - they're straightforward to work with. They're cheap - if getting the EEPROMs to test with is a problem, PM me on forums, I'll buy you the EEPROMs; this is a very serious issue to me - I've used an AT24 eeprom in virtually every project I have built, and have just finished building a bunch of ESP8266-based controller boards for the lighting in my room (remember that old Animate code for the pingpong lights? I finally finished that project)

@gfwilliams
Copy link
Member

@SpenceKonde thanks - I can definitely get something to test with. However have you checked the changes I made? The latest Travis builds should have them in and that might have fixed it for you.

@SpenceKonde
Copy link
Author

I got this build last night - did this one have the fix in it? http://www.espruino.com/binaries/travis/master/espruino_1v95.167_esp8266_4mb.tgz

@gfwilliams
Copy link
Member

gfwilliams commented Jan 24, 2018

Should have, yes. I'd try both software and I2C1 and see if there's any difference

@gfwilliams
Copy link
Member

Did you get a chance to try this? Specifically the normal software I2C.

@SpenceKonde
Copy link
Author

When I tried software I2C (I think on that version) on ESP8266 I saw NOTHING on the scope, whatsoever. I'd been hoping to do more tests, but this weekend wound up being really stressful, and I didn't have the mental energy for working with something as frustrating as this.

@gfwilliams
Copy link
Member

Any chance to try this yet?

@MaBecker
Copy link
Contributor

@SpenceKonde any news about that issue?

@SpenceKonde
Copy link
Author

SpenceKonde commented Dec 30, 2018 via email

@MaBecker
Copy link
Contributor

So lets close it for now

@SpenceKonde
Copy link
Author

SpenceKonde commented Apr 8, 2019 via email

@MaBecker
Copy link
Contributor

MaBecker commented Apr 8, 2019

Great, thanks for testing and sharing the result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ESP8266 This is only a problem on ESP8266 devices
Projects
None yet
Development

No branches or pull requests

4 participants