0

I am working on a project which requires communication from an Arduino Due (Master) and an FDC2214Q1 C to D IC (Slave), but there is some variability as to whether the code works or not depending on seemingly random variables.

I have narrowed the issue to the function I am using to read 2 bytes from the slave. The code is pretty standard, and is as follows:

// Read 2 byte from the FDC at 'address'
uint16_t FDC2214::read16FDC(uint16_t address) {

    uint16_t data;

    Wire.beginTransmission(_i2caddr);
    Wire.write(address);
    Wire.endTransmission(false); //restart
    Wire.requestFrom(_i2caddr, (uint8_t) 2);

    while (!Wire.available());
    data = Wire.read();
    data <<= 8;

    while (!Wire.available());
    data |= Wire.read();
    Wire.endTransmission(true); //end

    return data;
}

The code seems to get hung up sometimes on while (!Wire.available()) and if I simply remove that step, I never get the correct Device ID.

However, if I simply unplug the DUE and close the Serial Monitor and replug in and upload, it works. I just kind of upload and disconnect a few times and open and close the Serial Monitor and sometimes it works great, other times it gets hung up?

Any ideas what could be causing such and issue?

Code based on this library: https://github.com/zharijs/FDC2214/blob/master/src/FDC2214.cpp


Final code that has been working, removes need for While loop:

uint16_t FDC2214::read16FDC(uint16_t address) {

    uint16_t data;
        Wire.beginTransmission(_i2caddr); //queuing the slave address
        Wire.write(address); //queuing the register address/pointing regsiter
        byte busStatus = Wire.endTransmission(); //transmit all queued data and bring STOP condition on I2C Bus
        if(busStatus != 0x00)
        {
           Serial.print("Transmission Error....!");//transmissiion error wait here for ever
           while(1);
        }

        Wire.requestFrom(_i2caddr, (uint8_t) 2);     //this is looping code; when 2-byte has arrived, the loop terminates
        data = Wire.read();   //read the first byte from FIFO Buffer
        data = (data <<8)| Wire.read();   //16-bit data is formed
        Wire.endTransmission(true); //end
        return data;
}
  • how long are the wires? what value pullups are you using? – dandavis Feb 13 at 19:21
  • Currently do not have pull-ups as there is only one master/slave, but I realize maybe I should as a precaution. Will add some now, and let you know if that fixes anything. Thank you @dandavis – Jonathan A Feb 13 at 19:35
  • Hey @dandavis so I just added the pull-ups (1k) and it seemed they worked. But, sure enough, after a few sessions of opening and closing the Serial Monitor and unplugging/plugging the Arduino, I was able to reproduce the problem once again. – Jonathan A Feb 13 at 19:42
  • your code is not formatted properly ..... the two command lines after the while commands should not be indented ... the indentation implies that the two commands are inside the while loop .... they are not part of the while loop – jsotola Feb 13 at 21:44
  • @jsotola, this comment in no way helps me out, I understand how to format code, just thought it might be easier to emphasize the while loops I was referring to by tabing out the underlying code. – Jonathan A Feb 13 at 22:06
2

Adafruit tells to avoid the Arduino Due. One of the reasons is the I2C bus. Can you use an other Arduino board? For example one of the MKR boards with a SAMD21 processor.

The Due has pullup resistors on the board for SDA and SCL which are too low in value. Sometimes the I2C bus with SDA and SCL works, but sometimes it does not work at all. Perhaps you are able to remove the pullup resistors at SDA and SCL from the board.

If possible use Wire1 with SDA1 and SCL1. Those have no pullup resistors at all, so you need to add 4k7 pullup resistors to 3.3V. When you use a library, you might have to change the library to use "Wire1" instead of "Wire".

You need to remove these, they are not doing something:

while (!Wire.available());    <- not doing something

Remove the Wire.endTransmission at the end.

Wire.endTransmission(true);   <- remove this
return data;

That library does not use the Wire library in a proper way.


The pullup resistors are 1k5 or sometimes 1k and are located in the upper-right corner, near pin 20 and 21. A value of 1k5 should be okay, when there are no other pullup resistors. When you board has 1k resistors, then I suggest to remove them.

photo of pullup resistors the pullup resistors in the schematic

Removing them is possible with a soldering iron and a big blob of solder. Check if the board is clean afterwards, for example with a magnifier. Avoid overheating your expensive Arduino Due board.

The I2C bus needs pullup resistors to work. A normal value is 4k7. Sometimes there are already 10k pullup resistors on a sensor module.

If the I2C has problems, start by using short seperate wires for SDA and SCL. When a cable is used for the I2C bus, then the cable is probably the problem and not the pullup resistors.

  • Thanks for the note, unfortunately I don't have any MKR boards, but I have some nanos that I can try out. I will swap to 4k7 pull ups as well, and remove the parts you have mentioned and give it a shot. I have read that the while(!Wire.available) is not necessary but figured it couldn't hurt (apparently it can). Will update either today or tomorrow the result of this! Thanks @Jot – Jonathan A Feb 13 at 19:47
  • Do not add extra 4k7 to SDA and SCL. There are already pullup resistors on the Due, which are too low in value. Adding 4k7 makes it worse. Only when using SDA1 and SCL1 requires to add (normal) pullup resistors. – Jot Feb 13 at 19:49
  • Gotcha, I will remove them for the Due, but for testing on the Nano should I remove them as well? @Jot (also i have to run, but will update this ASAP tomorrow morning.) – Jonathan A Feb 13 at 19:52
  • The sensor is for 3.3v and the nano runs at 5v. I don't like that combination, unless you use a level shifter for sda and scl. – Jot Feb 13 at 19:57
  • it was my understanding that the i2c on the Nano was 3.3V, but if it is not as you say, would it be possible to disable the internal pull ups and then simply use a 2k7 or 4k7 to 3.3V? – Jonathan A Feb 13 at 22:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.