I2C on Spark core (noob question)

@chasc , @ScruffR, @bko,

Looking at wiring_i2c.cpp in the Spark github, I suspect @chasc , you have uncovered a bug: The following code:

    while(NumByteToWrite--) {
.
.
}

with NumByteToWrite defined as uint8_t, will loop and send junk for 255 bytes (0 - 1). The device, which is expecting a stop and only a stop, probably gives up responding at all with ACKS and a timeout results.

@chase, try with doing a single byte write() before the endTransmission() as you did before and see whether that works. It is still not correct, as the device only expects the Start, which it ACKs, followed by a Stop.

@bko, @ScruffR - Iā€™m not a github user, so maybe one of you can fix this and submit a pull request. The while statement should simply test the current state of NumByteToWrite, with the decrement occurring after the byte has been sent further down the while loop.

Thanks @pra. Thatā€™s the setup I was using.

WHOA, okay. So I pulled out my breadboard just now to re-measure some suspicious D0/1 pin voltages and today after powering on itā€™s miraculously working as soon as I plug it into USB for power.

I guess Iā€™ll have to do some more testing and return if it stops working again. I honestly did nothing except unplug it from USB and put it in the other room last night. It also seems to be racing through the power-on phases and reaching the pulsing cyan state much faster; before it would often blink green for 30+ seconds. Does that mean anything?

Assuming NumByteToWrite is 0, since the ā€˜ā€“ā€™ follows NumByteToWrite wonā€™t it be decremented after the while loop has already evaluated to 0 and stopped? The good news is it looks like the TwoWire library should correctly send the slave address and close the connection even when there are zero bytes in the TX buffer.

I went back and tried my own HIH6130 library and itā€™s working now too. I tried it both with the single byte transmission and with zero byte transmission and it still works either way. Iā€™m still at a loss for why: Iā€™ve spent hours over at least 4 other days in the last couple weeks and only ever got code = 4.

I feel a little dirty suggesting it, but is it possible thereā€™s a date bug that could have somehow affected I2C operation? Thatā€™s the only thing that I can imagine changed between last night and this morning.

[wiring_i2c.cpp][1]
[1]: https://github.com/spark/firmware/blob/master/src/spark_wiring_i2c.cpp

You may be right as itā€™s NumByteToWrite-- rather than --NumBytesToWrite. Still pretty ambiguous though. I think the blinking green means trying to connect to your access point, so probably means weaker signal thru more walls etc in other room. If it works when you plugged it into USB for power, what were you using for power when it wasnā€™t working?

@chasc, Iā€™m absolutely positive that there is no date/time issue in spark_wiring_i2c.
There are other posibilities thoā€™.
It has happened before that OTA flashing did not always replace the old firmware. In cases where I just canā€™t find an error I just make sure that OTA works by flashing some obviously different firmware (e.g. blink LED).
Another thing might be, when you do so much testing it wouldnā€™t surprise me if some test cases were on the ToDos but were not actually performed or analysed as thoroughly as you remembered :wink: Happened to me before :blush:

Anyway, now it works - something you did must have helped :+1:

1 Like

@pra ā€” All test cases were using USB power.

@ScruffR ā€” Iā€™ll have to keep an eye out for the OTA not updating the firmware. During my testing I rarely unplugged the Spark Core from USB power, but I did unplug it overnight. Does power cycling sometimes help the OTA take hold? That could have invalidated some of my tests, but I definitely had sketches with different Serial messages showing so it canā€™t explain all scenarios.

I agree thereā€™s no date/time issue with spark_wiring_i2c but I know just enough to understand I2C is supported at the hardware level and perhaps shares some hardware with another date-aware component that maybe(?) could interfere. I just canā€™t get over that I tried the same exact things days in a row and then on 1/1/15 it just works.

Well now Iā€™ll get back to trying to make progress on the original project and cross my fingers I donā€™t end up back at this thread!

I appreciate the help though, guys.

1 Like

Good page! Thanks!

This fixed my problem! Thanks!

Chasc could you please send me a code fragment for how you send the empty transmission to HIH3160? I have a new Photon with HIH6130 that takes one measurement at power up then stops updating. The I2C status bits are 0. I suspect itā€™s just one of the lousy sensors others complain about that stop updating but before I yank it I thought Iā€™d try your fix. Does that make sense? Hereā€™s my code fyi. Both humidity and temp seem to freeze. Thanks for looking.

   if ( read )
    {
        delay(40);
        Wire.requestFrom(TEMP_SENSOR, 4, true); // request 4 bytes information
        uint8_t b       = Wire.read();
        uint8_t bend    = Wire.endTransmission();
        I2C_Status      = bend;
        //
        int rawHum      = (b << 8) & 0x3f00;
        rawHum          |=Wire.read();
        hum             = roundf(rawHum / 163.83);
        //
        int rawTemp     = (Wire.read() << 6) & 0x3fc0;
        rawTemp         |=Wire.read() >> 2;
        temp            = (float(rawTemp)*165.0/16383.0 - 40.0)*1.8 + 32.0 + TEMPCAL; // convert to fahrenheit and calibrate
        tempInt         = roundf(temp);
    }

Hereā€™s what I was referring to with the 1 or 0 byte transmission. I think in the spec doc for the HIH sensor it says to send zero bytes, which is just a beginTransmission followed by an endTransmission, but when I was working with another board, RFduino, the Wire library wouldnā€™t do anything unless you enqueued some bytes to pass, thus the .write(0). Not sure that it was ever necessary for Photon, but it was in my bag of tricks to try.

Wire.beginTransmission(_slaveAddress);
Wire.write(0);
TXstatusCode = Wire.endTransmission();

Thanks. In the end it was not necessary for the Photon. I discovered that I was missing a ā€œbeginTransmission()ā€ statement. Duh, the mistakes we make.