Main Site Documentation

I2c Question(message lag)


#1

Hello All,

I am having a weird problem, i am writing a driver for this LCD https://www.olimex.com/Products/Duino/Shields/SHIELD-LCD16x2/open-source-hardware

and i am using the c++ classes as reference. But when testing it seems that the display is not displaying the last charecter i send. and then when i send it a new one it displays the previous one.

so if i want to display in sequence 1, 2, 3, 4 ,5 ,6 ,7 ,8, 9 i get -, 1, 2, 3, 4, 5, 6, 7, 8
I am using the i2c netmf reference code so nothing to crazy.

 lock (I2CHelper.Device)
            {
                byte len;
                byte x, y;
                x = X;
                y = Y;

            len = (byte)text.Length;

            for (int i = 0; i < len; i++)
            {
                //create transactions (we need 2 in this example)
                I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[1];

                // create write buffer (we need one byte)
                byte[] RegisterNum = new byte[4] { LCD_WR, y, x, (byte)text[i] };
                xActions[0] = I2CDevice.CreateWriteTransaction(RegisterNum);

                // Explicitly set the I2C bus to access device A by setting the I2C Config to the Device A's config.
                I2CHelper.Device.Config = LCDConnection;

                if (I2CHelper.Device.Execute(xActions, 1000) == 0)
                {
                    Debug.Print("Failed to perform I2C transaction");
                }
                else
                {
                    Debug.Print("write: " + text[i]);
                }

                // delay(20);
                Thread.Sleep(20);

                x++;
                if (x > 15)
                {
                    x = 0;
                    y++;
                    if (y > 2)
                        return;
                }
            }

Roy


#2

What can you see when you step through your code? Particularly what does RegisterNum look like? That seems like the area of your code that’s most likely to lead to the behavior that you explain.


#3

i have gone through it, and as far as i can see is it sends all 9 numbers. but after the last send it does not update the display. this is how it is done in the c lib

void LCD16x2::lcdWrite(char* string){
    uint8_t len;
    uint8_t x, y;
    x = X;
    y = Y;
    
    len = strlen(string);
    for(int i = 0; i < len; i++){
        Wire.beginTransmission(ADDRESS);
        Wire.write(LCD_WR);
        Wire.write(y);
        Wire.write(x);
        Wire.write(string[i]);
        Wire.endTransmission();
        
        delay(20);
        x++;  
        if(x > 15){
            x = 0;
            y++;
            if(y > 2)
                return;
        }   
    }
}

i am wondering coud the way it sends the data be different? its like the lcd is still expecting data and so does not update. does netmf send the data differently?

Roy


#4

No I2C expert but I did notice one thing in your code.

//create transactions (we need 2 in this example)
I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[1]; << You are using [1]

GHI sample code 

This example will read the value of the register on an I2C device with the 7-bit address of 0x38.
you first have to write the register number you want to read, two in this case, and then read the value back.

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

public class Program
{
    public static void Main()
    {
        //create I2C object
        //note that the netmf i2cdevice configuration requires a 7-bit address! It set the 8th R/W bit automatically.

        I2CDevice.Configuration con = new I2CDevice.Configuration(0x38, 400);
        I2CDevice MyI2C = new I2CDevice(con);

        // Create transactions - We need 2 in this example, we are reading from the device

        // First transaction is writing the "read command"
        // Second transaction is reading the data

        I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];

        // create write buffer (we need one byte)
        byte[] RegisterNum = new byte[1] { 2 };

        xActions[0] = I2CDevice.CreateWriteTransaction(RegisterNum);

        // create read buffer to read the register
        byte[] RegisterValue = new byte[1];
        xActions[1] = I2CDevice.CreateReadTransaction(RegisterValue);

        // Now we access the I2C bus using a timeout of one second 
        // if the execute command returns zero, the transaction failed.
	    // (this is a good check to make sure that you are communicating with the device correctly
        // and don’t have a wiring issue or other problem with the I2C device)

        if (MyI2C.Execute(xActions, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        else
        {
            Debug.Print("Register value: " + RegisterValue[0].ToString());
        }
    }
}

#5

yes doing it like this does not work.

                I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[4];

                // create write buffer (we need one byte)
                byte[] RegisterNum = new byte[1] { LCD_WR };
                xActions[0] = I2CDevice.CreateWriteTransaction(RegisterNum);

                byte[] RegisterNum2 = new byte[1] { y };
                xActions[1] = I2CDevice.CreateWriteTransaction(RegisterNum2);

                byte[] RegisterNum3 = new byte[1] { x };
                xActions[2] = I2CDevice.CreateWriteTransaction(RegisterNum3);

                byte[] RegisterNum4 = new byte[1] { (byte)text[i] };
                xActions[3] = I2CDevice.CreateWriteTransaction(RegisterNum4);

i have a feeling it might just be a bug in the lcd furmware, but i dont understand why it works fine using an arduino.


#6

How did you end up converting this section of the c++ source?

void LCD16x2::lcdWrite(int intVal){
    String Str = String (intVal);
    char charBuf[6];
    Str.toCharArray(charBuf, 6);
    lcdWrite(charBuf);
}

If you call the overloaded function with an int does it behave the same? Clip the value?


#7

Ah sorry i should of said how i caled it…

         int[] numbers = new int[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            for (int i = 0; i < numbers.Length; i++)
            {
                PrintText(numbers[i].ToString());
            }

so i am converting it to a string first so that code is not called.


#8

Oh this is different than what I was thinking. What you are saying then is that the first call to output doesn’t do anything, but subsequent calls do?

So if you were to…

PrintText(“test1”);
PrintText(“test2”);
PrintText(“test3”);

you’d end up with “test2” on the display?

Are you missing an initialization call?

In the sample code that comes with the shield

  lcd.lcdClear();
  
  lcd.lcdGoToXY(2,1);
  lcd.lcdWrite("BUT1:");
  
  lcd.lcdGoToXY(10,1);
  lcd.lcdWrite("BUT2:");
  
  lcd.lcdGoToXY(2,2);
  lcd.lcdWrite("BUT3:");
  
  lcd.lcdGoToXY(10,2);
  lcd.lcdWrite("BUT4:");

Perhaps all you need to do is implement the GoToXY call then write?


#9

No what i am getting when you print

lcd.lcdClear();
lcd.lcdWrite(“ABC:”);// -AB // - = space
lcd.lcdWrite(“DEF”);
//CAC
//CDC
//CDE
//CDF

After a restart(not restarting the lcd) i get other crap. to much to write each itteration down :}


#10

Interesting. Might want to try the GoToXY function between calls. Looks like it’s not positioning properly, at least on those latter ones. Doesn’t explain the odd behavior on the first call, though.

I might have one of those LCD shields in my stash here. I’ll take a peek today when I go in.