Page 1 of 1

I2C changes to get the HTU21D working.

Posted: Tue Apr 12, 2016 7:21 pm
by Frida
In the latest commit eec8a94 I have made some changes.

>>> i2c.scan()
[64]

Smallest scan freq is ca. 800 hz, or esp8266 resets.

To get the scan to work, I changed to write to address instead of read from address.

Code: Select all

STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
    machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
    mp_obj_t list = mp_obj_new_list(0, NULL);
    // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
    for (int addr = 0x08; addr < 0x78; ++addr) {
        mp_hal_i2c_start(self);
        //int ack = mp_hal_i2c_write_byte(self, (addr << 1) | 1);
        int ack = mp_hal_i2c_write_byte(self, (addr << 1)); // PB
        if (ack) {
            mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
        }
        mp_hal_i2c_stop(self);
    }
    return list;
}
i2c.writeto(0x40, '231') dosent work, but that does i2c.writeto(0x40, b'\xE7') # 231.

>>> i2c.writeto(0x40, '231')
>>> i2c.readfrom(0x40, 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: I2C bus error

>>> i2c.writeto(0x40, b'\xE7') # 231
>>> i2c.readfrom(0x40, 1)
b'\x02'


To get clock stretching to work, I made these changes.

Code: Select all

STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) {
    return mp_hal_pin_read(self->sda);
}

STATIC int mp_hal_i2c_scl_read(machine_i2c_obj_t *self) { // PB
    return mp_hal_pin_read(self->scl);
}


STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
    mp_hal_i2c_delay(self);
    mp_hal_i2c_scl_low(self);
    mp_hal_i2c_delay(self);

    uint8_t data = 0;
    for (int i = 7; i >= 0; i--) {
        mp_hal_i2c_scl_release(self);
        while (mp_hal_i2c_scl_read(self) == 0) { // PB
            // clock stretching
        }
        mp_hal_i2c_delay(self);
        data = (data << 1) | mp_hal_i2c_sda_read(self);
        mp_hal_i2c_scl_low(self);
        mp_hal_i2c_delay(self);
    }
    *val = data;

    // send ack/nack bit
    if (!nack) {
        mp_hal_i2c_sda_low(self);
    }
    mp_hal_i2c_delay(self);
    mp_hal_i2c_scl_release(self);
    mp_hal_i2c_delay(self);
    mp_hal_i2c_scl_low(self);
    mp_hal_i2c_sda_release(self);

    return 1; // success
}
All done in file machine_i2c.c in /micropython/extmod


[edit]
And now temp and humidy and dewpoint comes in.

temp: 22.08019 relH: 32.7497 dew: 5.016602
temp: 22.08019 relH: 32.7497 dew: 5.016602
temp: 22.05873 relH: 32.71918 dew: 4.984558
temp: 22.06947 relH: 32.69629 dew: 4.983948
temp: 22.08019 relH: 32.69629 dew: 4.993347

Re: I2C changes to get the HTU21D working.

Posted: Fri Apr 15, 2016 1:21 pm
by Frida
And now with timeout

Code: Select all

        uint32_t start = mp_hal_ticks_ms(); // PB
        while (mp_hal_i2c_scl_read(self) == 0) { // PB
            // clock stretching
            if(mp_hal_ticks_ms() - start > 55) { // max 50ms/14bit/temp
              mp_hal_i2c_stop(self);
              nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error clock stretching"));
            }
        }

Re: I2C changes to get the HTU21D working.

Posted: Fri Jan 06, 2017 12:10 pm
by Lornioiz
Hi there!

I was trying to make a simple HTU21D driver but I got stuck very early because it does seems that I can't find the peripheral address.
When I execute i2c.scan() this is what I get back:

[8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119]

I then found your post and I'm wondering if this is the problem that made you create the fix.
If so, can you explain me how to implement it? where should put this code?

thanks an regards

Re: I2C changes to get the HTU21D working.

Posted: Fri Jan 06, 2017 1:06 pm
by Frida
I haven't looked at it for a long time.
I put the code in: 'machine_i2c.c in /micropython/extmod'
But are you using pullup on SCL and SDA?

And the HTU21D was part of stretch goal, but I don't know of it is implementet yet?

Re: I2C changes to get the HTU21D working.

Posted: Fri Jan 06, 2017 3:52 pm
by Lornioiz
Frida wrote: But are you using pullup on SCL and SDA?

And the HTU21D was part of stretch goal, but I don't know of it is implementet yet?
The breakout I'm using as already pullups so I don't think that's the problem.
I Think I'm gonna try the fixes you wrote, thanks alot!

P.S.

I don't think the driver is implemented yet (but I'm not sure).

Re: I2C changes to get the HTU21D working.

Posted: Sat Sep 30, 2017 3:37 pm
by joeheart
in the neweast esp8266 firmware , i2c.scan() still can't found the address

>>>i2c.scan()
>>>[]

same htu21d connect in esp32 board ,use micropython,works good.

please someone help me.thanks a lot

Re: I2C changes to get the HTU21D working.

Posted: Mon Jan 14, 2019 10:02 am
by dentex
Hello,
I'm having the same problem with no results from I2C scan. Do you have now a solution? Thanks.

Running esp8266-20190113-v1.9.4-779-g5064df207

EDIT: Changing pins to D5 and D6 makes `i2c.scan()` to work: I have the right address [64], which is 0x40.
Now the error is `OSError: [Errno 19] ENODEV` ...
Other I2C peripherals on the same pins work (a BMP280 barometer and a SSD1306 oled).

Re: I2C changes to get the HTU21D working.

Posted: Mon Jan 21, 2019 10:58 am
by dentex
Preceding post edited...
Any hints?

Thanks.

Re: I2C changes to get the HTU21D working.

Posted: Fri Jan 10, 2020 3:12 pm
by raulmazda
dentex wrote:
Mon Jan 21, 2019 10:58 am
Any hints?
I found this post as I was trying to get the htu21d working on my board. I now have a working recipe on a d1 mini.

The code in main is:

Code: Select all

scl = machine.Pin(5, machine.Pin.OPEN_DRAIN, machine.Pin.PULL_UP)
sda = machine.Pin(4, machine.Pin.OPEN_DRAIN, machine.Pin.PULL_UP)
htu = htu21d.HTU21D(scl, sda)
while True:
    print('temp %f humid %f' % (htu.temperature, htu.humidity))
    time.sleep(2)
I had to slightly modify an old htu21d.py found on github. See https://github.com/laz-/htu21d-esp8266 for the working version.

Maybe some of this will help?

Re: I2C changes to get the HTU21D working.

Posted: Fri Jan 10, 2020 5:17 pm
by kevinkk525
There are actually quite a few HTU21D libraries and they work fine with ESP8266.
This is the one I use on my esp8266: https://github.com/kevinkk525/htu21d-esp8266


There's also one from Peter Hinch that works slightly different: https://github.com/peterhinch/micropyth ... ter/htu21d