Dealextreme LCD i2c 20*4

Hello every one!
( please don’t look at my english, i’m french )

i bought an I2C LCD on dealextreme.com but i don’t manage to use it …

i try to make some sketch with my teacher but it don’t work very well .

i give you the link of the lcd => [quote]http://dx.com/p/arduino-iic-i2c-serial-blue-backlight-lcd-2004-module-display-138616[/quote]

i use a FEZ panda II.

I give you the sketch i try

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
namespace FEZ_Panda_II_TestI2C
{
    public class Program
    {
        static I2CDevice.Configuration config = new I2CDevice.Configuration(0x20, 10);
        static I2CDevice.I2CTransaction[] Init = new I2CDevice.I2CTransaction[1];
        static I2CDevice.I2CTransaction[] t1 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t2 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t3 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t4 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t5 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t6 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] t7 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] b4 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] b8 = new I2CDevice.I2CTransaction[2];
        static I2CDevice.I2CTransaction[] Allumer = new I2CDevice.I2CTransaction[1];
        static I2CDevice.I2CTransaction[] Donnee = new I2CDevice.I2CTransaction[4];
        static I2CDevice LEDI2C = new I2CDevice(config);

        public static void Main()
        {
           
                byte[] RegisterNum = new byte[1] { 0x08 }; 
                Init[0] = I2CDevice.CreateWriteTransaction(RegisterNum);
                Thread.Sleep(100);
                Mettre4bit();
        }

        public static void Mettre4bit()
        {
            byte[] M1 = new byte[1] { 0x00 };
            Init[0] = I2CDevice.CreateWriteTransaction(M1);

            byte[] b1 = new byte[1] { 0x03 };
            b8[0] = I2CDevice.CreateWriteTransaction(b1);
            byte[] b2 = new byte[1] { 0x13 };
            b8[1] = I2CDevice.CreateWriteTransaction(b2);

            byte[] b41 = new byte[1] { 0x08 };
            b4[0] = I2CDevice.CreateWriteTransaction(b41);
            byte[] b42 = new byte[1] { 0x18 };
            b4[1] = I2CDevice.CreateWriteTransaction(b42);

            byte[] M2 = new byte[1] { 0x02 };
            t1[0] = I2CDevice.CreateWriteTransaction(M2);
            byte[] M3 = new byte[1] { 0x12 };
            t1[1] = I2CDevice.CreateWriteTransaction(M3);

            byte[] M4 = new byte[1] { 0x02 };
            t2[0] = I2CDevice.CreateWriteTransaction(M4);
            byte[] M5 = new byte[1] { 0x12 };
            t2[1] = I2CDevice.CreateWriteTransaction(M5);

            byte[] M6 = new byte[1] { 0x08 };
            t3[0] = I2CDevice.CreateWriteTransaction(M6);
            byte[] M7 = new byte[1] { 0x18 };
            t3[1] = I2CDevice.CreateWriteTransaction(M7);

            byte[] M8 = new byte[1] { 0x00 };
            t4[0] = I2CDevice.CreateWriteTransaction(M8);
            byte[] M9 = new byte[1] { 0x10 };
            t4[1] = I2CDevice.CreateWriteTransaction(M9);

            byte[] M10 = new byte[1] { 0x0E };
            t5[0] = I2CDevice.CreateWriteTransaction(M10);
            byte[] M11 = new byte[1] { 0x1E };
            t5[1] = I2CDevice.CreateWriteTransaction(M11);

            byte[] M12 = new byte[1] { 0x00 };
            t6[0] = I2CDevice.CreateWriteTransaction(M12);
            byte[] M13 = new byte[1] { 0x10 };
            t6[1] = I2CDevice.CreateWriteTransaction(M13);

            byte[] M18 = new byte[1] { 0x01 };
            t7[0] = I2CDevice.CreateWriteTransaction(M12);
            byte[] M19 = new byte[1] { 0x11 };
            t7[1] = I2CDevice.CreateWriteTransaction(M13);

            byte[] M14 = new byte[1] { 0x08 };
            Allumer[0] = I2CDevice.CreateWriteTransaction(M14);

            byte[] D1 = new byte[1] { 0x04 };
            Donnee[0] = I2CDevice.CreateWriteTransaction(D1);
            byte[] D2 = new byte[1] { 0x14 };
            Donnee[1] = I2CDevice.CreateWriteTransaction(D2);
            byte[] D3 = new byte[1] { 0x01 };
            Donnee[2] = I2CDevice.CreateWriteTransaction(D3);
            byte[] D4 = new byte[1] { 0x11 };
            Donnee[3] = I2CDevice.CreateWriteTransaction(D4);


            LEDI2C.Execute(Init, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(b8, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(b4, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t1, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t2, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t3, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t4, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t5, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t6, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(t7, 1000);
            Thread.Sleep(1000);
            LEDI2C.Execute(Allumer, 1000);
            Thread.Sleep(500);
            LEDI2C.Execute(Donnee, 1000);

            Thread.Sleep(5000);
        }
    }
}

i found a librairy named LiquidCrystal made for arduino but i can’t use it.

So if someone find how to use it, i will be greatfull !

thanks !

Check out http://www.tinyclr.com/codeshare/entry/166 its not the same display, but you will see how i2c is done with a different LCD.

Hello… (Not English here - Czech. :slight_smile: )
Maybe problem is timing at the thread.sleep, because you have always 1s. When you google any 20x4 lcd datasheet, there will be some “Initializing the display” chapter. There is usually written these steps: Power On > write {RS, RW, DB7, DB6, DB5, DB4} = { 0, 0, 0, 0, 1, 1} > wait more than 15ms {I wait 16ms} > write { 0, 0, 0, 0, 1, 1} > wait more than 4,1ms {so 5 ms} > write { 0, 0, 0, 0, 1, 1} > wait more than 100 micros { so 1ms} > Initialize (including { 0, 0, 0, 0, 1, 0} for defining 4b interface).
As far as i understand your code, you are writing { 0, 0, 0, 0, 1, 1} in b8, but you need to write it 3x with thread.sleep(16,5 and 1) and so on. My code for my 20x4 init is:


static I2CDevice ICBus = new I2CDevice(null);
static byte[] WB1 = { 0x00 };
static I2CDevice.I2CTransaction[] ICW_Reg1 = new I2CDevice.I2CTransaction[]
            {
                I2CDevice.CreateWriteTransaction(WB1) 
            };

static void ICLCD_INIT()
    {
      WB1[0] = 0xC3; // 1100 0010 = E, LCD, /RS, /RW,    /DB7, /DB6, DB5, DB4
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x43; // 0100 0010 = /E, LCD, /RS, /RW,    /DB7, /DB6, DB5, DB4 -  /E = write instruction
      ICBus.Execute(ICW_Reg1, 100);
      Thread.Sleep(16);
      WB1[0] = 0xC3;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x43;
      ICBus.Execute(ICW_Reg1, 100);
      Thread.Sleep(5);
      WB1[0] = 0xC3;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x43;
      ICBus.Execute(ICW_Reg1, 100);
      Thread.Sleep(1);

      WB1[0] = 0xC2; //4bit 
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x42;
      ICBus.Execute(ICW_Reg1, 100);

      WB1[0] = 0xC2; //4bit + 2 line displ
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x42;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0xC8;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x48;
      ICBus.Execute(ICW_Reg1, 100);

      WB1[0] = 0xC0; // increment counter after writing character
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x40;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0xC6;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x46;
      ICBus.Execute(ICW_Reg1, 100);

      WB1[0] = 0xC0; // display on, no cursor, no blink 
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x40;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0xCC;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x4C;
      ICBus.Execute(ICW_Reg1, 100);

      WB1[0] = 0xC0; // clear display
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x40;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0xC1;
      ICBus.Execute(ICW_Reg1, 100);
      WB1[0] = 0x41;
      ICBus.Execute(ICW_Reg1, 100);
      Thread.Sleep(2); // pause required for display clearing 

    }

public static void Main()
    {
      I2CDevice.Configuration ICLCD = new I2CDevice.Configuration(0x20, 100);
      ICBus.Config = ICLCD;
      ICLCD_INIT();
// writing 'A'
        byte MyCharA = (byte)'A';
         WB1[0] = (byte)(0xD0 + MyCharA  / 16); // D = 1101 -> E, LCD, /RW, RS -> prepare character's higher 4 bits
        ICBus.Execute(ICW_Reg1, 100);
        WB1[0] = (byte)(0x50 +MyCharA / 16); // 5 = 0101 -> /E, LCD, /RW, RS -> write character's higher 4 bits
        ICBus.Execute(ICW_Reg1, 100);
        WB1[0] = (byte)(0xD0 +MyCharA  % 16); // prepare character's lower4 bits
        ICBus.Execute(ICW_Reg1, 100);
        WB1[0] = (byte)(0x50 +MyCharA  % 16); // write character's lower 4 bits
        ICBus.Execute(ICW_Reg1, 100); // after this the 'A' should be visible
...
    }

Hi!
I’ve the same LCD ( from dealextreme) but it dosen’t work.
Mike.kup with your code the LCD backlight just turn on.
Can you give me some advice ?
Or maybe give me the name of your lcd, that would be faster …
Thanks.

I have a DFRobot I2C LCD backpack (I2C LCD Backpack-DFRobot) which I think uses the same I2C Expander chip as the DealExtreme board. I had a hard time getting it to work too, so I put something together from the various code snippets I found.
I am using a Cerbuino Bee.

I want to give credit to “jabroni” for most of the code (http://www.tinyclr.com/codeshare/entry/177), I just had to make some tweaks and optimizations to the backlight function and to the I2C functions. It seems on the Cerbuino Bee you have to execute each i2C transaction separately, it did not work with the original code that put 3 transactions in an array (see here: http://www.tinyclr.com/forum/topic?id=8068&page=1#msg79215).
After I used one I2C transaction at a time it started working.

In your main file (Program.cs) you use it like this:


        public static void Main()
        {

            I2CLCD lcd = new I2CLCD();

            //RealTimeClock.SetTime(new DateTime(2011, 01, 19, 23, 27, 0, 0));
            //Utility.SetLocalTime(RealTimeClock.GetTime());

            lcd.clear();

            int i = 0;
            while (true)
            {
                //LCD.clear();
                lcd.setCursor(0, 0);
                //LCD.print(i.ToString());
                lcd.print("This is Line 1...");
                lcd.setCursor(0, 1);
                lcd.print("This is Line 2...");
                lcd.setCursor(0, 2);
                lcd.print("This is Line 3...");
                lcd.setCursor(0, 3);
                lcd.print("Line 4: " + i.ToString());
                i++;
                //Wait for a bit
                Thread.Sleep(250);
            }
            
        }


Add this file to your project: I2CLCD.cs


using Microsoft.SPOT.Hardware;
using System.Threading;

namespace DisplayLCDHD44780
{
    /// <summary>
    /// FEZ Driver for the DFRobot I2C/TWI LCD1602 Module
    /// http://www.dfrobot.com/index.php?route=product/product&path=53&product_id=135
    ///
    /// This display uses a JHD 162A LCD module with a DFRobot I2C Module
    /// The I2C module uses a PCA8574 I/O Expander at Address 0x27
    /// http://www.nxp.com/documents/data_sheet/PCA8574_PCA8574A.pdf
    ///
    /// Code is adapted from the arduino code:
    /// http://www.dfrobot.com/image/data/DFR0063/Arduino_library.zip
    ///
    /// The module should be connected to the I2C port on the FEZ - sda (Data2) and scl (Data3)
    ///
    /// Refer to documentation on the Hitachi HD44780 for more detailed operational information
    /// Eg: http://lcd-linux.sourceforge.net/pdfdocs/lcd1.pdf
    /// </summary>
    public class I2CLCD
    {
        // The following are the first 4 bits of each byte.

        const byte RS = 0x01; // Register select bit. 0=command 1=data
        const byte RW = 0x02; // Read/Write bit. We usually want to write (0).
        const byte EN = 0x04; // Enable bit. Data is set on the falling edge - see hitachi doco
        // flags for backlight control
        const byte LCD_BACKLIGHT = 0x08;
        const byte LCD_NOBACKLIGHT = 0x00;

        // The following are the high 4 bits - compounded with the flags below
        // Note that everything must be done in 4bit mode, so set 4bit mode first.

        // commands
        const byte LCD_CLEARDISPLAY = 0x01;
        const byte LCD_RETURNHOME = 0x02;
        const byte LCD_ENTRYMODESET = 0x04;
        const byte LCD_DISPLAYCONTROL = 0x08;
        const byte LCD_CURSORSHIFT = 0x10;
        const byte LCD_FUNCTIONSET = 0x20;
        const byte LCD_SETCGRAMADDR = 0x40;
        const byte LCD_SETDDRAMADDR = 0x80;

        // Flags to be used with the above commands

        // flags for display entry mode (0x04)
        const byte LCD_ENTRYRIGHT = 0x00;
        const byte LCD_ENTRYLEFT = 0x02;
        const byte LCD_ENTRYSHIFTINCREMENT = 0x01;
        const byte LCD_ENTRYSHIFTDECREMENT = 0x00;

        // flags for display on/off control (0x08)
        const byte LCD_DISPLAYON = 0x04;
        const byte LCD_DISPLAYOFF = 0x00;
        const byte LCD_CURSORON = 0x02;
        const byte LCD_CURSOROFF = 0x00;
        const byte LCD_BLINKON = 0x01;
        const byte LCD_BLINKOFF = 0x00;

        // flags for display/cursor shift (0x10)
        const byte LCD_DISPLAYMOVE = 0x08;
        const byte LCD_CURSORMOVE = 0x00;
        const byte LCD_MOVERIGHT = 0x04;
        const byte LCD_MOVELEFT = 0x00;

        // flags for function set (0x20)
        const byte LCD_8BITMODE = 0x10;
        const byte LCD_4BITMODE = 0x00;
        const byte LCD_2LINE = 0x08;
        const byte LCD_1LINE = 0x00;
        const byte LCD_5x10DOTS = 0x04;
        const byte LCD_5x8DOTS = 0x00;


        private byte _backLight = LCD_BACKLIGHT; // default to backlight on

        private byte[] _cmd_arr = new byte[1];

        private byte[] _row_offsets = { 0x00, 0x40, 0x14, 0x54 };   // this is for a 20x4 display

        private I2CDevice _myI2C;
        I2CDevice.I2CTransaction[] _i2cXA = new I2CDevice.I2CTransaction[1];

        /// <summary>
        /// Writes a byte in 4bit mode.
        /// </summary>
        /// <param name="byteOut">The byte to write</param>
        /// <param name="mode">Additional Parameters - eg RS for data mode</param>
        public void write4bit(byte byteOut, byte mode = 0)
        {
            write((byte)(byteOut & 0xF0), mode);
            write((byte)((byteOut << 4) & 0xF0), mode);
        }


        /// <summary>
        /// Writes a byte to the I2C LCD.
        /// </summary>
        /// <param name="byteOut">The byte to write</param>
        /// <param name="mode">Additional Parameters - eg RS for data mode</param>
        public void write(byte byteOut, byte mode = 0)
        {
            // Write the byte
            // Set the En bit high
            _cmd_arr[0] = (byte)(byteOut | _backLight | mode | EN);
            _i2cXA[0] = I2CDevice.CreateWriteTransaction(_cmd_arr);
            _myI2C.Execute(_i2cXA, 500);

            // Set the En bit low
            _cmd_arr[0] = (byte)(byteOut | _backLight | mode);
            _i2cXA[0] = I2CDevice.CreateWriteTransaction(_cmd_arr);
            _myI2C.Execute(_i2cXA, 500);
        }

        /// <summary>
        /// Prints text at current location
        /// </summary>
        /// <param name="text"></param>
        public void print(string text)
        {
            for (int i = 0; i < text.Length; i++)
                write4bit((byte)(text[i]), RS);
        }

        /// <summary>
        /// Clear screen and return to home
        /// </summary>
        public void clear()
        {
            write4bit(LCD_CLEARDISPLAY);
            Thread.Sleep(15);
            write4bit(LCD_RETURNHOME);
            Thread.Sleep(5);
        }

        /// <summary>
        /// Sets the cursor position. Zero based column and row.
        /// </summary>
        /// <param name="col"></param>
        /// <param name="row"></param>
        public void setCursor(byte col, byte row)
        {
            write4bit((byte)(LCD_SETDDRAMADDR | (col + _row_offsets[row])));
        }

        /// <summary>
        /// Turn the backlight off.
        /// </summary>
        public void backLightOff()
        {
            _backLight = LCD_NOBACKLIGHT;
            _cmd_arr[0] = (byte)(_backLight | EN); // do not set Enable flag to low so we don't write to the LCD
            _i2cXA[0] = I2CDevice.CreateWriteTransaction(_cmd_arr);
            _myI2C.Execute(_i2cXA, 500);
        }

        /// <summary>
        /// Turn the backlight on.
        /// </summary>
        public void backLightOn()
        {
            _backLight = LCD_BACKLIGHT;
            _cmd_arr[0] = (byte)(_backLight | EN);
            _i2cXA[0] = I2CDevice.CreateWriteTransaction(_cmd_arr);
            _myI2C.Execute(_i2cXA, 500);
        }

        public I2CLCD(ushort address = 0x20, int clockRateKhz = 400)
        {
            I2CDevice.Configuration cfg = new I2CDevice.Configuration(address, clockRateKhz);
            _myI2C = new I2CDevice(cfg);

            Thread.Sleep(15);

            // Set 4 Bit mode - copied from arduino code
            write(LCD_FUNCTIONSET | LCD_8BITMODE);
            write(LCD_FUNCTIONSET | LCD_8BITMODE);
            write(LCD_FUNCTIONSET | LCD_8BITMODE);
            write(LCD_FUNCTIONSET | LCD_4BITMODE);
            Thread.Sleep(1);
            // COMMAND | FLAG1 | FLAG2 | ...
            write4bit(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS);
            Thread.Sleep(1);
            write4bit(LCD_ENTRYMODESET | LCD_ENTRYLEFT);
            Thread.Sleep(1);
            write4bit(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON);
            Thread.Sleep(1);
            write4bit(LCD_CLEARDISPLAY);
            Thread.Sleep(15);
        }

    }
}

Hope that works for you!
Mike