I2C driver for New Haven LCD display

@Brett I used 0x3C for the I2C address which is the 7-bit equivalent of 0x78. I think I may be doing the addresses in this part wrong too but I am not sure:

xActions[0] = I2CDevice.CreateWriteTransaction(new byte[]{0x00,0x38});

It fails at the execution at the end of this code:

I2CConfig=new I2CDevice.Configuration(0x3C,400);
I2C = new I2CDevice(I2CConfig);
I2CDevice.I2CTransaction[] xActions = new I2CTransaction[1];
xActions[0] = I2CDevice.CreateWriteTransaction(new byte[]{0x00,0x38});
Thread.Sleep(10);
If(I2C.Execute(xActions,1000)==0){
Debug.Print("Failed Transaction");
}

As I said - the datasheet I saw said the address can be set with hardware/jumpers, so 0x3c is still a stab in the dark. Please check the hardware and validate that you’re even trying the correct address. But yes, 0x3c is the 7-bit equivalent of 0x78. But you didn’t ever have that address working, did you?

In my view, this again becomes a wiring issue unless it’s a speed issue. Try 100 or 200 instead of 400, see if that helps, but I expect 400 to work. Is there a reason you haven’t just tried GLX’s codeshare driver and see if it works?

@Brett My data sheet states the slave address is 0x78

The display only has 8 pins. Wired it just like the schematic with pull ups on SDA and SCL…it doesn’t mention what size pull ups in the data sheet so I just used 10k. The display lights up, I just can’t write to it yet. I will try a different speed (my EEPROM uses 10k ohm for 400 kHz I am pretty sure).

I am using parts of glx’s driver…his display has different features so I just drew from his.

if your hardware doesn’t have jumpers to set/change the address, then fine, 0x3c it is. Want to tell us where the datasheet is? Also, remember, you don’t need double pullups, assuming you’re using the same i2c lines.

As @Brett mentioned - you only need one set of pull ups.

2.2k is a better starting point than 10k…

I am not using the same lines, I removed the EEPROM to get this working before combining. Here is the data sheet:

I will switch to 2k

sorry, by “lines” I purely meant the i2c pins on the microcontroller - so unless you removed the pullups with the eeprom, or unless you are using a different set of i2c pins on the micro, you don’t need to add the second pullups.

I removed the EEPROM pull ups. Switched out the 10k ones on the display for 2k. No luck with 100 or 200 kHz either. Am I doing the bytes write for the CreateWriteTransaction?

The data sheet says write to address 00 for commands and 0x38 sets a few register values for functionality. Am I misunderstanding that part?

That seems to match their initialisation code they supply.

I don’t know the exact display you use, but I think the initialisation looks quite the same for all with the same controller. Just one value looks a bit short for initialisation.

On page 43 and 44 is a init-sequnce for a serial-interfaced display with that controller.

When using I2C remember, that you have to write the values to address 0x00 (in the datasheet are no registers i the sample).

I linked the display I am using above it runs ST7036i, the first line of initialization is 0x38 which sets a bunch of settings ( all 3 NH displays I have used seem to use the same initialization and character codes)…there is more initialization code but I can’t get this first I2C transaction to work so no point in adding the 10 other transactions I have written out after. I have been writing to register 0x00 as well for commands.

@Brett I found a hardware mistake…the capacitor going between VOUT and VSS pins was shorting on my breadboard. I fixed it but still failing…maybe I friend something?

Ok the transactions aren’t failing anymore after I connected my scope to it…must be a loose wire somewhere as well. Now I just need to go back and 1) verify what I am initializing and 2) Fix my driver so I can write strings.

In their initialization code they send 0x38 then 0x39 - this is just two different versions of the same settings right? So i just need to do one version of function settings. They then send 0x14 which configures the cursor/display shift. Next they send 0x78 which corresponds to setting the CGRAM. WHAT THE HELL IS CGRAM?And why do they have AC2 AC1 and AC0 set as 0? They then send 0x5E which appears to be a different version of the previous CGRAM settings. I really need someone to explain the differences here. The next coommand is 0x6D which appears to be yet another CGRAM configuration, only one of these is needed correct? But what does each do? 0x0C is sent next which turns the display on and cursor off followed by 0x01 which is another version of the display settings. The final command is 0x06 which does “Entry Mode Set,”

@Brett You helped me redo my other I2C driver but not the Write(string) method of it. Can you take a look at it please?

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

namespace DisplayTest
{

public class Display
{
    public  I2CDevice.Configuration I2CConfig;
    public I2CDevice I2C;

    /// <summary>
    /// Initializes a new instance of the <see cref="EEPROM"/> class.
    /// </summary>
    public Display()
    {
        I2CConfig = new I2CDevice.Configuration(0x3C, 400);  
        I2C = new I2CDevice(I2CConfig);
        Thread.Sleep(100);
        I2CDevice.I2CTransaction[] transaction = new I2CDevice.I2CTransaction[1];
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x38});
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
      //  I2C.Execute(transaction, 500);
        Thread.Sleep(10);
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x39 });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        Thread.Sleep(10);
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x14 });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x78 });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x5E });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x6D });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x0C });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x01});
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        transaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, 0x06 });
        Thread.Sleep(10);
        if (I2C.Execute(transaction, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        Thread.Sleep(10);
        
    }
  
    /// <summary>
    /// Writes a one byte data at the specified address.
    /// </summary>
    /// <param name="Address">The address to write to.</param>
    /// <param name="data">The byte to write</param>
    public void Write(int Address, byte[] data)
    {
        byte[] byte1 = new byte[2];
        byte1 = new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) };
        int length = byte1.Length + data.Length;
        byte[] payload = new byte[length];
        byte1.CopyTo(payload, 0);
        data.CopyTo(payload, byte1.Length);
        var xActions = new I2CDevice.I2CTransaction[1];
        //    byte1=[(byte)(Address>>8),(byte)(Address&0xFF)];
        xActions[0] = I2CDevice.CreateWriteTransaction(payload);
        Thread.Sleep(5);
        if (I2C.Execute(xActions, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }


    }

    /// <summary>
    /// Writes the string Text at the specified address.
    /// </summary>
    /// <param name="Address">The starting address to write to</param>
    /// <param name="Text">The text to write to EEprom</param>
    public void Write(int Address, string Text)
    {
        var xActions = new I2CDevice.I2CTransaction[1];
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes("00" + Text);  // the "00" string reserves the room for the 2 bytes address that follows
        buffer[0] = (byte)(Address >> 8);
        buffer[1] = (byte)(Address & 0xFF);
        xActions[0] = I2CDevice.CreateWriteTransaction(buffer);
        Thread.Sleep(5);
        if (I2C.Execute(xActions, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }

    }
    /// <summary>
    /// Reads the specified address.
    /// </summary>
    /// <param name="Address">The address to be read</param>
    /// <returns>One byte from the EEprom</returns>
    public byte Read(int Address)
    {
        var Data = new byte[1];
        var xActions = new I2CDevice.I2CTransaction[1];
        xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) });
        Thread.Sleep(5);
        if (I2C.Execute(xActions, 1000) == 0)
        {
            Debug.Print("Failed to perform I2C transaction");
        }
        else
        {
            xActions[0] = I2CDevice.CreateReadTransaction(Data);
            Thread.Sleep(5);   // Mandatory after each Write transaction !!!
            if (I2C.Execute(xActions, 1000) == 0)
            {
                Debug.Print("Failed to perform I2C transaction");
            }
            else
            {
                Debug.Print("Register value: " + Data[0].ToString());
                return Data[0];
            }

        }
        return 0;
    }

}
}

CGRAM - stands for “Character Graphics Random Access Memory” allows the user to define special supplementary non-standard character types that are not in the CGROM. You can load your own dot pattern shapes e.g. a rectangle into CGRAM and using certain reserved codes in DDRAM, call these up for display.

DDRAM - stands for “Data Display Random Access Memory” and is the working data buffer of the display. Each character on the display has a corresponding DDRAM location and the byte loaded in DDRAM controls which character is displayed.

ohhhh so they are just showing me examples of pre loaded dot patterns in that part of the initialization

The example codeshare driver has great abstraction of the primitives. I’d use that driver, and change the initialisation to reflect what you need (but honestly, they are probably compatible and you only need change the number of lines and characters in the macro definitions). Sure, while you’re testing it’s good to write your own simple code…

The example init does a number of transactions at once (no call to delay between) so why don’t you create a single transaction for them: I2C_out(0x14); I2C_out(0x78); I2C_out(0x5E); I2C_out(0x6D); I2C_out(0x0C); I2C_out(0x01); I2C_out(0x06);

I actually think you need to go back to the fundamentals - if your first transaction fails, that’s a sign of wrong address (no response from device) or a wiring issue. Yes, that could be caused by a short and failure.

I helped with the testing of the eeprom since I had one - send me a display and I’ll test it for you, as I don’t have anything that’s even similar.

@Brett I have the display working now, most of those transactions are unnecessary as half were just showing the other variation of each setting but they are all working now, it was a short. I just need to get my buffer for strings working properly.

awesome…

@Brett Thanks for the help!