1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

How to translate wire.requestfrom (arduino) to c?

Discussion in 'Arduino' started by electroRF, Oct 10, 2013.

  1. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi,

    I have a problem - my PIC18F fails reading bytes from I2C GLCD Slave (GLCD-FLEXEL).

    I found an Arduino code, which uses the following function to read 1 byte from the GLCD.

    I think that the reason for which I don't manage to read from the GLCD, using C Code that runs on my PIC, is that I don't know how to translate the Wire.requestFrom to C Code.

    How do you do that?

    I don't have HW problem as I do manage to write data to the LCD.

    Reading is the problem.

    Thanks!

    unsigned int GLCDI2C::getColor(void){

    unsigned int data = 0;
    unsigned char number = 1;

    Wire.beginTransmission(g_i2caddress);
    Wire.write(GLCDI2C_COMMAND);
    Wire.write(GLCDI2C_GET_COLOR);
    Wire.endTransmission();

    //delay(GLCDI2C_CMDDELAY);
    // Connect to device and request byte

    Wire.beginTransmission(g_i2caddress);
    Wire.requestFrom(g_i2caddress, number);

    if (Wire.available()) {
    data = Wire.read();
    }
    return data;
    }
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,306
    Likes:
    914
    Location:
    Rochdale UK
    ONLINE
  3. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Ian
    Thanks a lot!

    I tried playing with it, sending different combination of bytes in order to read the Cursor value.
    However, no luck :(

    I believe it is because I don't implement correctly the wire.requestFrom in C.

    BTW,
    I took yesterday I2C EEPROM, soldered it to the board, read its datasheet, and manage to read and write to it.
    This I2C EEPROM is connected in parallel to the GLCD, same SCK and SDA.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland

    Is this your code? I don't think there is supposed to be "Wire.beginTransmission(g_i2caddress);" before the "Wire.requestFrom(g_i2caddress, number);"
    Try removing it.

    Also I think that you are supposed to wait until data is available, so it should be:
    while(Wire.available() <number); // wait for data

    // read data
    data = Wire.read();
     
    Last edited: Oct 10, 2013
  6. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T
    Thanks a lot for your help.

    This code was taken from the link that Ian found in internet - http://www.picaxeforum.co.uk/archive/index.php/t-22945.html

    The guy there said it worked for him.

    My project is in C, PIC18F <--I2C--> GLCD.

    I'm trying to implement the code from the link in C, but struggle with the Wire.requestFrom function.

    I succeed writing to the GLCD well, but I fail reading - I read always zero.

    This is my code for writing cursor value (which works great) and reading the cursor value (which fails).

    I can see in Scope that the GLCD returns ACK to every byte sent to it.
    But when the RCEN is set and the Master generates 8 clock pulses, the SDA line remains LOW, and therefore I read Zero.

    Code (text):
    // Set Cursor position (Write)
    StartI2C();
    putcI2C(GLCD_WRITE);
    putcI2C(0xFE);
    putcI2C(0x04);
    putcI2C(0x15); //x cursor
    putcI2C(0x15); //y cursor
    StopI2C();

    //Read 'y' Cursor Position from Slave
    StartI2C();
    putcI2C(GLCD_WRITE); //0x8C = GLCD Address (R/W cleared)
    putcI2C(0xFE);
    putcI2C(0x07);
    RestartI2C();
    putcI2C(GLCD_READ); //0x8D = GLCD Address with R/W set
    IdleI2C();
    unsigned char i2cReadData;
    i2cReadData = SSPBUF;
    StopI2C();
     
     
    Last edited: Oct 11, 2013
  7. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Maybe it does not like the "repeated start" between the command and the actual reading. Try replacing that with "stop" and "start". Some I2C devices are picky about the details.
     
  8. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T!
    I've tried also replacing Repeated Start with Stop -> Start, but with no luck.

    I think that translating the "Wire" code to C code might solve the problem of reading.
     
  9. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    I don't know... i2c can be tricky without seeing the actual signal. With logick analyzer image or oscilloscope image we could pinpoint the problem.

    Why do you have "RestartI2C();" after the "IdleI2C();". That looks strange.
     
  10. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T,
    Thank you for assisting.

    This is the Scope image after sending "GLCD_READ" (= Slave Address with R/W bit set) from PIC to Slave.
    As you can see, the Slave Acks (SDA LOW) at the 9th pulse.
    [​IMG]

    This is the Scope image after PIC set "RCEN=1" (I2CRead).
    As you can see, SDA remains LOW, therefore PIC reads SSPBUF=0.
    [​IMG]


    Per your question,
    You're right, I mis-copied the code, there was no RestartI2C there after the IdleI2C.
    I edited the post and removed it.
     
  11. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Did you remove the RestartI2C before you took those pictures?
    Is there really only 8 clock cycles in the last picture? I think during every transaction there should be 9 clock cycles. 9th cycle is the ACK bit. Well.. if there was a ninth clock, the result would be NACK (no-ack). Maybe PIC omits the ninth clock in case of NACK?

    I noticed that now you have replaced the "repeatedStart" with "restart".. that is wrong.
    Check your code sequence carefully now...

    I think it should be

    Code (C):

    //Read 'y' Cursor Position from Slave
    StartI2C();
    putcI2C(GLCD_WRITE); //0x8C = GLCD Address (R/W cleared)
    putcI2C(0xFE);
    putcI2C(0x07);
    RepeatedStartI2C();
    putcI2C(GLCD_READ); //0x8D = GLCD Address with R/W set
    IdleI2C();
    unsigned char i2cReadData;
    i2cReadData = SSPBUF;
    StopI2C();
     
    Also, the original blue code in the first post uses "stop" and "start" instead of "repeatedstart". Try that also, now that you have removed the "restart" from the end.
     
  12. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T,
    Thanks again!

    The Code from which I took the 2 scope pictures is just the code you posted now.

    I also tried your code with Stop -> Start instead of Restart, but again I read 0x00 (no difference).

    Yes, there're just 8 clocks in the last picture.
    When RCEN is set, the Master sends 8 clock pulses, not 9.

     
  13. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Ok.. this is getting messy. I am confused what is the last code you have tried. Could you copy paste it here straight from your code? Don't edit the codes in old posts.
     
  14. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T.

    This is the code I last tried, copied from MPLAB:
    Code (text):
       
    // Set x,y Cursors position
          IdleI2C();
          StartI2C();
          IdleI2C();
          WriteI2C(GLCD_WRITE); //GLCD_WRITE = 0x8C - GLCD Address (0x46) with R/W bit clear
          IdleI2C();
          WriteI2C(0xFE);
          IdleI2C();
          WriteI2C(0x04); //Set Cursor potition Opcode
          IdleI2C();
          WriteI2C(0x33); //x cursor
          IdleI2C();
          WriteI2C(0x33); //y cursor
          IdleI2C();
          StopI2C();
         
         
        // READ y Cursor Position from Slave
           unsigned char i2cReadData;
           IdleI2C();
           StartI2C();
           IdleI2C();
           WriteI2C(GLCD_WRITE); //GLCD_WRITE = 0x8C = GLCD Address (0x46) with R/W bit clear
           IdleI2C();
           WriteI2C(0xFE);
           IdleI2C();
           WriteI2C(0x06); //Get Cursor potition Opcode
           IdleI2C();
           RestartI2C();
           IdleI2C();
           WriteI2C(GLCD_READ); //GLCD_READ = 0x8D = GLCD Address (0x46) with R/W bit set
           IdleI2C();
           i2cReadData=ReadI2C();
           IdleI2C();
           StopI2C();


     
     
  15. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Ok.. the RestartI2C() is fine.. I got confused about that. I thought you had some "repeatedStart" function, but the RestartI2C is just that.

    The code looks good. My last idea is to try to put some delay before (or after) the "RestartI2C". Maybe the GLCD needs some time to get the data ready for reading. If that does not work, I do not know what is wrong.
     
  16. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Put some delay after you have written the cursor positions also.. maybe that takes time too. (Can you see that the cursor actually moves when you tell it to move?)
     
  17. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Hi Mister T,

    I already tried placing delays between different steps, and I'll try playing with it more.
    Code (text):
    void I2C_delay()
    {
    volatile int v;
    int i;
    for (i=0; i < 500; i++) v;
    }
    I know that the cursor moves because right after the "reading" stage, I write text to the GLCD, and the text starts in an offset on the screen.

    I think that the problem might be failure to translate the Wire code to C code.
    Especially the wire.requestFrom and wire.available, which I didn't implement in my C code.
     
  18. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    No, that is not the problem. Your i2c code looks good and the scope images look good too. The problem is that there is no proper documentation for the GLCD. For example, if you look at any i2c EEPROM datasheet, they have a detailed description of the communication... with timing diagrams and all.

    Try reading some other register. The firmware version is at 0xFE 0x30. (Try this before you write cursor positions, or do any other i2c communication.)
     
  19. electroRF

    electroRF Member

    Joined:
    Jun 23, 2012
    Messages:
    689
    Likes:
    9
    Location:
    Portugal
    Thanks Mister T.

    Two days ago I took I2C EEPROM sample, and a day later it was already soldered to my PIC (in parallel to the GLCD, same SDA and SCL lines) and I managed to read data from it.
    However! at first I always read 0xFF from the EEPROM, but after I added delay between each step, I managed to read correctly.

    I see why you think it's timing issue, but I added so many delays that I don't know what else to do to solve a timing issue.
    Additionally, they say in the GLCD Datasheet that :
    The delay between any two bytes of data coming
    from Master should be less than 255 ms. If this condition is not met, the module will time-out and
    clear the receive buffer.

    I tried reading the color, with same failure.

    I'll try reading the FW as well and will update.
     
  20. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    Yeah.. try adding "ridiculously" long delays (10ms to 100ms). And once again try replacing the "restart" with start and stop with a long delay between.. Maybe write something after you set the cursor and then try to read the cursor position. I know it is shooting in dark, but I have no other ideas.

    Reading the FW should be simple.. and should not require ridiculous delays.
     
  21. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    What document is that?

    Edit: .. Found it :) the same document you linked to in the first post.
     
    Last edited: Oct 11, 2013

Share This Page