stevemarple / SoftWire

Software I2C implementation for Arduino and other Wiring-type environments
GNU Lesser General Public License v2.1
144 stars 30 forks source link

Fix no data transmitted issue because `_txBufferIndex` always zero #26

Closed ming-chu closed 2 years ago

ming-chu commented 3 years ago

Problem:

The data line wasn't sending any data after the address was sent. If I got any mistaken for the usage, please guide me.

Thanks for the library and appreciated.😊

Before fix:

The data line keeps sending the address + write mode with no data afterward. [0x64:W, nothings ... ]

After fix:

The data line has data following the first clock, excepted [0x64:W, 00000001, 00000010, 00000011] in this case.

Simple code to reproduce the problem:

#include <Arduino.h>
#include <SoftWire.h>

uint8_t sdaPin = A2;
uint8_t sclPin = A3;
SoftWire i2c(sdaPin, sclPin);

void setup()
{
  i2c.setDelay_us(5);
  i2c.begin();
  delay(300);
}

void loop()
{
  uint8_t data[3] = {1, 2, 3};
  i2c.beginTransmission(0x64);
  i2c.setTxBuffer(data, 3);
  // workaround to increase the _txBufferIndex by calling `write(data, size)`  but waste CPU time. 
  // also the `write(data, size)` must need to call after `setTxBuffer` since `_txBufferIndex >= _txBufferSize` always true
  // i2c.write(data, 3); 
  i2c.endTransmission();
  delay(100);
}

_txBufferIndex >= _txBufferSize is always true and return for the first write, so _txBuffer seems never write.

size_t SoftWire::write(uint8_t data)
{
    if (_txBufferIndex >= _txBufferSize) {
        setWriteError();
        return 0;
    }

    _txBuffer[_txBufferIndex++] = data;
    return 1;
}

Screenshots from oscilloscope

before fix: image

after fix: image

stevemarple commented 2 years ago

You should set the TX buffer once in setup() using setTxBuffer(), then you use write() to put the data into the buffer. Please see the ReadDS1307 example for the correct usage.

ming-chu commented 2 years ago

Thanks for the advice. Sorry for any inconvenience caused 🙇‍♂️