Continue to Site

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.

  • 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.

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

Status
Not open for further replies.

electroRF

Member
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;
}
 
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.
 
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;
}

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:
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:
// 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:
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.
 
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.
 
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.
 
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.
**broken link removed**

This is the Scope image after PIC set "RCEN=1" (I2CRead).
As you can see, SDA remains LOW, therefore PIC reads SSPBUF=0.
**broken link removed**


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.
 
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

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.
 
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.

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

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.
 
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.
 
Hi Mister T.

This is the code I last tried, copied from MPLAB:
Code:
// 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();
 
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.
 
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?)
 
Hi Mister T,

I already tried placing delays between different steps, and I'll try playing with it more.
Code:
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.
 
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.

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.)
 
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.
 
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.

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.
 
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.

What document is that?

Edit: .. Found it :) the same document you linked to in the first post.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top