Interfacing NHD-0420CW-AY3 to PIC controller via I2C

Comments

2 comments

  • Saurabh_B
    Hello,

    This OLED display does have a rather lengthy command input process. Unfortunately it is one of the few available controllers for OLED displays of this type. I can help guide you to get the display working.

    I will be referring to the controller datasheet as well, this can be found here: https://newhavendisplay.com/content/app_notes/US2066.pdf 

    In your examples below, I don't see you sending the control byte after sending the I2C address. (Page 11, controller datasheet)
    After sending the I2C address, you would need to send the Control Byte, this will let the display know that the following incoming information is either Data or a Command. The Control Byte will also be needed between each byte of data.

    For the contrast setting, you would first need to activate the RE Flag, then the SD flag.
    For this you would send the function SET command (0x2A), then the OLED Characterization command (0x79), this will allow you to modify the contrast.

    For the set cursor command I am not sure what the 0x45 is, however you would need to send the Set DDRAM Address command.

    The Set SEG pins & hardware configuration command will allow you to rotate the display, or have text coming in from a different location rather than the top left. The entry mode command determines whether you want to enable the shift on the display, or if you would like the Address counter to auto increment or decrement after receiving a character.

    I would also recommend looking at the example code here: https://github.com/NewhavenDisplay/NHD_US2066

    Could you also provide your I2C1_Wr function?
    0
  • cbrun17

    Hello Saurabh_B,

    Thank you so much for the quick response. Unfortunately the I2C_WRITE function is part of the built I2C library within MikroC for PIC based controllers.

    The code attached is what I have so far. It is comprised of bits and pieces of several sources. I'm attempting to build a library for use within MikroC to use for several projects. Also, my hope is to be able to share the final result to other users of this compiler. These are wonderful displays, however, very little support by the MikroC community.

    //***************************************************************
    //
    // I2C functions for NHD-0420CW-AY3
    // and other serial LCDs with US2066 controller
    // made by Newhaven Display
    //
    // Compiler: MikroC Pro For PIC 7.1
    //
    // MikroC Libraries used: I2C  C_String
    //
    // Controller for this project: PIC18F4520
    //***************************************************************
    #include "I2C_LCD_functions.h"    // Header file
    #include <stdint.h>
    #define DC LATC.F0      // define D/C control pin connected to PORTC.0
    #define DataS 1         // Make pin high for data mode
    #define CommandS 0    // make pin low for command mode


    // !!!These constants must be declared in the project source code.!!!
    // I2C Address for LCD
    extern const unsigned short _I2C_ADDRESS; //With SA0 tied to VSS address will be 0x3C. When SA0 is tied to VDD, address will be 0x3D
    // Column width of LCD
    extern const unsigned short _LCD_WIDTH;

    //****************************************************************
    //
    //  Function: StringSize
    //
    //  Action: Returns the length (in characters) of a string
    //
    //  Parameters: 1
    //          InString = String whose length will be returned
    //
    //
    //  Returns: The size of the string
    //
    //****************************************************************

    unsigned int StringSize(char* InString)
    {
        unsigned int StrSize;
        char StrByte;

        StrSize = 0;
        StrByte = InString[StrSize];
        while( StrByte != '\0' )
        {
            StrSize++;
            StrByte = InString[StrSize];

        }
        return StrSize;

    }


    //****************************************************************
    //
    //  Function: LCD_Init
    //
    //  Action: LCD Initialization sequence:
    //
    //  Parameters: 0
    //
    //
    //  Returns: Nothing
    //
    //****************************************************************
    void LCD_Init()
    {
    unsigned short rows = 0x08;

    //______________________________________________________________________________________________________________________________________
            uint8_t ack;
            I2C_Write(_I2C_ADDRESS); // Configured for 0x3C in main program       
            I2C1_Init(100000);   // initialize I2C (module 1  - change this if using a different module
           
            I2C_Start();
           

            I2C_Write(0x2A); //function set (extended command set)
            I2C_Write(0x71); //function selection A
            DC = DataS // Bring D/C high
            delay_us(50);  //delay
            I2C_Write(0x00);  // **** disable internal VDD regulator
            delay_us(50);  //delay
            DC = CommandS // Bring D/C low
            I2C_Write(0x28); //function set (fundamental command set)
            I2C_Write(0x08); //display off, cursor off, blink off
            I2C_Write(0x2A); //function set (extended command set)
            I2C_Write(0x79); //OLED command set enabled
            I2C_Write(0xD5); //set display clock divide ratio/osc freq
            I2C_Write(0x70); //set display clock divide ratio/osc freq
            I2C_Write(0x78); //OLED command set disabled
            I2C_Write(0x09); //extended function set (4-lines)
            I2C_Write(0x06); //COM SEG direction
            I2C_Write(0x72); //function selection B. Choose ROM set & CGRAM
            DC = DataS // Bring D/C high
            delay_us(50);  //delay
            I2C_Write(0x00); //Select CGRAM & character ROM 0
            delay_us(50);  //delay
            DC = CommandS // Bring D/C low
            I2C_Write(0x2A); //function set (extended command set)
            I2C_Write(0x79); //OLED command set enabled
            I2C_Write(0xDA); //set SEG pins hardware configuration
            I2C_Write(0x10); //set SEG pins hardware configuration
            I2C_Write(0xDC); //function selection C
            I2C_Write(0x00); //function selection C
            I2C_Write(0x81); //set contrast control
            I2C_Write(0x02); //set contrast control 0x7F default
            I2C_Write(0xD9); //set phase length
            I2C_Write(0xF1); //set phase length
            I2C_Write(0xDB); //set VCOMH deselect level
            I2C_Write(0x40); //set VCOMH deselect level
            I2C_Write(0x78); //OLED command set disabled
            I2C_Write(0x28); //function set (fundamental command set)
            I2C_Write(0x01); //clear display
            I2C_Write(0x80); //set DDRAM address to 0x00
            I2C_Write(0x0C); //display ON
            I2C_Stop();
            delay_ms(100);  //delay

    }
    //______________________________________________________________________________________________________________________________________

    //***************************************************************
    //
    //  Function: LCD_Line_Out
    //
    //  Action: Send a string of characters to the LCD
    //          String will be displayed at given position
    //
    //  Parameters: 3
    //          line = line on which text will display (1-4)
    //          col = column at which text will display (1-20)
    //          info = string which will be sent to LCD
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Line_Out(short line, short col, char* info)
    {
        short size;
        short ccount;
        //default to line 1 if value passed is out of range
        if (line < 1 || line > 4) line = 1;
        //default to column 1  if value passed is out of range
        if (col < 1 || col > _LCD_WIDTH ) col = 0;
        size =  StringSize(info);
        LCD_Set_Pos(line, col);
        for (ccount = 0; ccount < size; ccount++)
            LCD_Chr_Out_CP(info[ccount]);
    }

    //****************************************************************
    //
    //  Function: LCD_Line_Out_CP
    //
    //  Action: Send a string of characters to the LCD
    //          String will be displayed at cursor position
    //
    //  Parameters: 1
    //          info = string which will be sent to LCD
    //
    //  Returns: Nothing
    //
    //****************************************************************

    void LCD_Line_Out_CP(char* info)
    {
        short size;
        short ccount;
        size =  StringSize(info);
        for (ccount = 0; ccount < size; ccount++)
            LCD_Chr_Out_CP(info[ccount]);

    }

    //***************************************************************
    //
    //  Function: LCD_Line_Out_Centered
    //
    //  Action: Send a string of characters to the LCD
    //          String will displayed horizontally centered
    //          on the given line
    //
    //  Parameters: 2
    //          line = line where string will be displayed
    //          info = string which will be sent to LCD
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Line_Out_Centered(short line, char* info)
    {
            //char len,col;
            //default to line 1 if value passed is out of range
           if (line < 1 || line > 4) line = 1;

            //len = StrLen(info);
            //col = ((_LCD_WIDTH - len)/2) + 1;
            LCD_Set_Pos(line,( (_LCD_WIDTH - StringSize(info)) / 2) + 1);
            LCD_Line_Out_CP(info);
    }

    //***************************************************************
    //
    //  Function: LCD_Chr_Out
    //
    //  Action: Send a single character to the LCD
    //          Character will be displayed at a given position
    //
    //  Parameters: 3
    //          row = line on which text will display (1-4)
    //          col = column at which character will be displayed (1-20)
    //          chr = character to send
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Chr_Out(short line, short col, char chr)
    {
        //default to line 1 if value passed is out of range
        if (line < 1 || line > 4) line = 1;

        //default to column 0  if value passed is out of range
        if (col < 1 || col > _LCD_WIDTH ) col = 0;

        LCD_Set_Pos(line,col);
        I2C1_Start();
        I2C1_Wr(_I2C_ADDRESS);
        I2C1_Wr(chr);
        Delay_us(100);
        I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Chr_Out_CP
    //
    //  Action: Send a single character to the LCD
    //          Character will be displayed at cursor position
    //
    //  Parameters: 1
    //          chr = character to send
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Chr_Out_CP(char chr)
    {
        I2C1_Start();
        I2C1_Wr(_I2C_ADDRESS);
        I2C1_Wr(chr);
        Delay_us(100);
        I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Set_Pos
    //
    //  Action: Set cursor position
    //
    //  Parameters: 2
    //           line = Cursor line (1-4)
    //           col = Cursor column (1-20)
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Set_Pos(short line, short col)
    {
            short ln;

          //default to line 1 if value passed is out of range

          if (line < 1 || line > 4) line = 1;

          //default to column 0  if value passed is out of range

          if (col < 1 || col > _LCD_WIDTH ) col = 0;

            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x45); //Set cursor
            switch (line)
            {
                    case 1:
                        ln = 0x80;
                        break;
                    case 2:
                        ln = 0xA0;
                         break;
                    case 3:
                        ln = 0xC0;
                        break;
                    case 4:
                        ln = 0xE0;

            }
            I2C1_Wr(ln + (col-1));
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Clear
    //
    //  Action: Clear LCD display
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Clear() //Done
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x20);
            Delay_us(1500);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_ClearToHome
    //
    //  Action: Clear LCD display and place cursor to home position
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************
    void LCD_ClearToHome() //Done
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x01);
            Delay_us(1500);
            I2C1_Stop();
    }


    //***************************************************************
    //
    //  Function: LCD_Contrast
    //
    //  Action: Set display contrast level
    //
    //  Parameters: 1
    //          level = Contrast level ( 1 low - 50 high )
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Contrast(short level)
    {
            if (level < 1 || level > 255) level = 127;  //default to 127 if out of range
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0x81);
            I2C1_Wr(0x28);
            I2C1_Wr(level);
            Delay_us(500);
            I2C1_Stop();
            Delay_ms(5);
    }

    //***************************************************************
    //
    //  Function: LCD_Blink_On
    //
    //  Action: Turn on blinking cursor
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Blink_On()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0x28);
            I2C1_Wr(0x09);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Blink_Off
    //
    //  Action: Turn off blinking cursor
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Blink_Off() //Done
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x0C);
            Delay_us(100);
            I2C1_Stop();
    }



    //***************************************************************
    //
    //  Function: LCD_Underline_On
    //
    //  Action: Turn on the underline cursor
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Underline_On()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x47);
            Delay_us(1500);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Underline_Off
    //
    //  Action: Turn off the underline cursor
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Underline_Off()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x48);
            Delay_us(1500);
            I2C1_Stop();
    }


    //***************************************************************
    //
    //  Function: LCD_Cursors_Off
    //
    //  Action: Turns off blinking & underline cursors
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Cursors_Off()
    {
            LCD_Blink_Off();
            LCD_Underline_Off();
    }


    //***************************************************************
    //
    //  Function: LCD_Cursor_Right
    //
    //  Action: Move cursor one position right (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Cursor_Right()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x4A);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Cursor_Left
    //
    //  Action: Move cursor one position left (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Cursor_Left()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x49);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Cursor_Home
    //
    //  Action: Move cursor to Line 1, Column 1 (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Cursor_Home()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x00);
            Delay_us(1500);
            I2C1_Stop();
    }


    //***************************************************************
    //
    //  Function: LCD_Backspace
    //
    //  Action: Move cursor one position left (character deleted)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Backspace()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x4E);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Display_Right
    //
    //  Action: Shift display one position right (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Display_Right()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            I2C1_Wr(0xFE);
            I2C1_Wr(0x56);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Display_Left
    //
    //  Action: Shift display one position left (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Display_Left()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x55);
            Delay_us(100);
            I2C1_Stop();
    }


    //***************************************************************
    //
    //  Function: LCD_Display_on
    //
    //  Action: Turns on LCD screeen (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Display_On()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x0C);
            Delay_us(100);
            I2C1_Stop();
    }

    //***************************************************************
    //
    //  Function: LCD_Display_Off
    //
    //  Action: Turns off LCD screen (display unchanged)
    //
    //  Parameters: 0
    //
    //  Returns: Nothing
    //
    //***************************************************************

    void LCD_Display_Off()
    {
            I2C1_Start();
            I2C1_Wr(_I2C_ADDRESS);
            //I2C1_Wr(0xFE);
            I2C1_Wr(0x08);
            Delay_us(100);
            I2C1_Stop();

    }
    Also attached a schematic of my connections for reference.

    I look forward to any advice you can provide.
    Chris

    [attachment deleted by admin]
    « Last Edit: May 05, 2017, 03:48:15 PM by cbrun17 »
    0

Please sign in to leave a comment.