Cannot drive I2C Oled :(


+ Reply to Thread
Results 1 to 22 of 22
  1. #1
    Join Date
    Apr 2013
    Posts
    32

    Default Cannot drive I2C Oled :(

    Hello guys, I tried to drive a 0.96" 128x64 I2C oled screen whole week and I'm about to go crazy because of this... I'm able to run the screen with arduino but I want to do it with a 877f (well I'm stubborn...)
    My oled screen using ssd1306 driver and I read it's datasheet, I examined all lines of arduino codes and PICC codes (I didn't try PICC codes just viewed) But I wasn't able to run the screen :\ I can't see if I'm missing something or there is something I don't know about. Is there anyone who used these oled screens with PIC ? Or any hint what might I'd be missing.

    I worked on CircuitDomain's codes and tried many changes on it but none work in the end... I started with this topic : http://www.picbasic.co.uk/forum/showthread.php?t=17973

    N
    ow I'm just trying to see a working pixel on screen, and these are my codes;
    Code:
    '==========================MCU SETUP============================================  
    Include "modedefs.bas"
    DEFINE OSC 16
    DEFINE I2C_SLOW 1 'to use 100kHz device over 4MHz oscillator
    DEFINE I2C_HOLD 1
    
    
    OPTION_REG=0
    ADCON0=0
    ADCON1=7
    TRISA=%00111111
    TRISB=%00000001
    TRISC=0
    
    
    
    
    
    
    '================================usuart========================================
    
    
    '==============================BAUD SETUP=======================================
    
    
    I2CDevice var byte
    SCL var PortC.3         ' I2C Clock  PortC.3
    SDA var PortC.4         ' I2C Data   PortC.4
    DC VAR byte' "DATA OR COMMAND", $40=DATA; $80=COMMAND 
    LCD_DATA VAR BYTE
    COM VAR BYTE'COMMAND
    
    
    
    
    I VAR BYTE
    J VAR BYTE
    X VAR BYTE' LCD POSITION X(0 TO 127)
    Y VAR BYTE'LCD POSITION Y(0 TO 7)
    CLEAR
    '=============================================================================
    'PAGE = $B0
    
    
    I2CDevice = $78      'Display Address = $78,
    
    
    PAUSE 20
    
    
    GOSUB INIT
    
    
    
    
    MAIN:
    
    
    gosub FILL
    pause 1000
    gosub CLEAR_LCD
    pause 1000
    
    
    GOTO MAIN
    
    
    
    
    '=========================lcd initialization====================================
    INIT:
    
    
    COM=$AE:GOSUB SEND_COMMAND' DISPLAY OFF
    pause 10
    COM=$20:GOSUB SEND_COMMAND' ADRESSING MODE
    COM=$02:GOSUB SEND_COMMAND' Page adressing mode
    COM=$81:GOSUB SEND_COMMAND' Send contrast
    COM=$FF:GOSUB SEND_COMMAND'
    COM=$A4:GOSUB SEND_COMMAND' display on continue 
    COM=$A6:GOSUB SEND_COMMAND' $A6=NORMAL MODE;$A7=INVERSE MODE
    COM=$AF:GOSUB SEND_COMMAND' DISPLAY ON
    pause 10
     gosub CLEAR_LCD
     return
    '===============================================================================
    '==============================clear lcd========================================
    CLEAR_LCD:
    
    
    
    
       FOR J=0 TO 7 
        FOR I=0 TO 127
            LCD_DATA=$00:GOSUB SEND_DATA  
        NEXT I
       NEXT J                             
    
    
    RETURN 
    
    
    '****************SEND COMMAND************************************************
    
    
    SEND_COMMAND:
    dc=$80
    
    
    I2CWrite SDA,SCL,I2CDevice,DC,[COM]
    
    
    RETURN 
    '*****************************************************************************
    
    
    '======================Send data===============================================
    SEND_DATA:
    DC=$40
    
    
    I2CWrite SDA,SCL,I2CDevice,DC,[LCD_DATA]
    
    
    RETURN
    '===============================================================================
    '=============================FILL=============================================
    FILL:
    FOR J=0 TO 7
    FOR I=0 TO 127
    LCD_DATA=$FF:GOSUB SEND_DATA
    NEXT I
    NEXT J
    RETURN
    '===============================================================================
    
    
    '===========================================SET X AND Y=========================
    SET_XY:
    COM=$21:GOSUB SEND_COMMAND
    COM=X:GOSUB SEND_COMMAND
    COM=127:GOSUB SEND_COMMAND
    COM=$22:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    RETURN
    '===============================================================================
    END

  2. #2
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,256

    Default Re: Cannot drive I2C Oled :(

    Until someone has something useful, I'd embed INIT instead of using GOSUB; just to simplify code.

    (Gosubs are used when code is executed in more than one place)

    Robert

  3. #3
    Join Date
    Oct 2011
    Posts
    50

    Default Re: Cannot drive I2C Oled :(

    Is it the CRIUS display you have? If it is then I have some code that works. I did it a long time ago so it may take a while to find it.

    Phil

  4. #4
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Quote Originally Posted by Demon View Post
    Until someone has something useful, I'd embed INIT instead of using GOSUB; just to simplify code.

    (Gosubs are used when code is executed in more than one place)

    Robert
    Thanks Demon, you are right about it

  5. #5
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Quote Originally Posted by Sherbrook View Post
    Is it the CRIUS display you have? If it is then I have some code that works. I did it a long time ago so it may take a while to find it.

    Phil
    Thanks Sherbrook,
    It's label is not CRIUS but I checked CRIUS, they are same displays. I would be really greateful if you can find those codes so I can crosscheck my codes with yours to find what I'm missing.

  6. #6
    Join Date
    Oct 2011
    Posts
    50

    Default Re: Cannot drive I2C Oled :(

    Here is some code. It fills the screen with 8 lines of vertical bars then clears it.
    If the screen does not start up correctly dissconnect and wait or discharge with a resistor and try again. Apparently this is normal.
    The 'INIT' routine was arrived at by trial and error, if you can improve on it let me know.
    The 'RESET' routine makes no difference and is included for you to experiment.
    Not an easy display to work with.

    Phil

    Code:
    '****************************************************************
    '*  Name    : CRIUS_OLED_Test.pbp                               *
    '*  Author  : Philtronix                                        *
    '*  Notice  : Copyright (c) 2015 Philtronix                     *
    '*          : All Rights Reserved                               *
    '*  Date    : 15/06/2015                                        *
    '*  Version : 1.0                                               *
    '*  Notes   : PIC18F2550 int osc @ 4mHz   3.3v                  *
    '*          : CRIUS OLED display   3.3v                         *
    '****************************************************************
    osccon = %01100010          'Int OSC @ 4mHz
    adcon1 = %00001111          'All ports digital
    ucon.3 = 0                  'Disable USB port
    ucfg.3 = 1                  'Digital in RC4 & RC5
    cmcon  = 7                  'Comparators off
    
    led     var LatC.0
    scl     var PortC.1
    sda     var PortC.2
    dat     var byte
    counter var word
    
    control con %01111000       'I2C slave address (write mode)
    
    trisb = %11000000
    PortB = %00000000
    pause 500
    
    trisc = %11111000           'PortC 0, 1, 2 outputs
    PortC = %00000110           'scl & sda high to start
    
        pause 2000
    '    gosub RESET:
        gosub init_oled:
        i2cwrite sda,scl,control,[$80,$AF]  'Display ON
        pause 10
    
    Start:
        led = 1                             'Code running
        i2cwrite sda,scl,control,[$80,$A7]  'Inverse Display 
        pause 500
        i2cwrite sda,scl,control,[$80,$A6]  'Normal Display
        pause 20
    '    i2cwrite sda,scl,control,[$80,$21,$00,$40] 'Set columns
        pause 20
    '    i2cwrite sda,scl,control,[$80,$22,$00,$04]  'Set pages
        pause 500     
        for counter = 0 to 1023
        i2cwrite sda,scl,control,[$40,$FF]
        next
        led = 0                             'Code running
        for counter = 0 to 1023
        i2cwrite sda,scl,control,[$40,$00]
        next
    GOTO Start:
    
    INIT_OLED:
        i2cwrite sda,scl,control,[$80,$AE]          'Display OFF               ****
        pause 1
        i2cwrite sda,scl,control,[$80,$2E]          'Deactivate scrolling
        pause 1
        i2cwrite sda,scl,control,[$80,$20,$10]      'Page addressing mode      ****
        pause 1
        i2cwrite sda,scl,control,[$80,$A0]          '                          ****
    '    i2cwrite sda,scl,control,[$80,$A1]          '                          ****
        pause 1
        i2cwrite sda,scl,control,[$80,$A6]          'WHITE chars BLACK backround
    '    i2cwrite sda,scl,control,[$80,$A7]         'BLACK chars WHITE backround
        pause 1
        i2cwrite sda,scl,control,[$80,$81,$7F]      'Setup contrast            XXXX
        pause 1
        i2cwrite sda,scl,control,[$80,$AF]          'Display on                **** 
        pause 1
        i2cwrite sda,scl,control,[$80,$40]
        pause 1
    '    i2cwrite sda,scl,control,[$80,$C0]          'Flip display vertically   ****
        i2cwrite sda,scl,control,[$80,$C8]          'Flip display vertically   ****
        pause 1
    '    i2cwrite sda,scl,control,[$80,$A0]          '                          ****
        i2cwrite sda,scl,control,[$80,$A1]          '                          ****
        pause 1
        i2cwrite sda,scl,control,[$80,$00,$80,$10]  'Set column start address  ****
        pause 1
        i2cwrite sda,scl,control,[$80,$B0]          'Set page start address    ****
        pause 1
        return
        
    RESET:
        i2cwrite sda,scl,control,[$80,$AE]          'Display OFF
        pause 10
        I2Cwrite sda,scl,control,[$80,$20,$02]      'Page addressing mode
        pause 10
        i2cwrite sda,scl,control,[$80,$B0]          'Page start address
        pause 10
        i2cwrite sda,scl,control,[$80,$00,$80,$10]  'Set column start address
        pause 10
        i2cwrite sda,scl,control,[$80,$A0]          'Address 0 mapped to SEG 0
        pause 10
     '   i2cwrite sda,scl,control,[$80,$A1]          'Address 0 mapped to SEG 127
        pause 10
        i2cwrite sda,scl,control,[$80,$D3,$00]      'Display offset
        pause 10
    
        pause 10
        i2cwrite sda,scl,control,[$80,$40]          'Display start line
        Pause 10
        i2cwrite sda,scl,control,[$80,$C0]          'Output scan direction
        pause 10
        i2cwrite sda,scl,control,[$80,$A6]          'WHITE chars BLACK backround
        pause 10
        i2cwrite sda,scl,control,[$80,$81,$7F]      'Contrast control
        pause 10
        i2cwrite sda,scl,control,[$80,$A4]          'Entire display OFF
        pause 10
        i2cwrite sda,scl,control,[$80,$A6]          'Normal display
        pause 10
        i2cwrite sda,scl,control,[$80,$A3,$00,$40]  'Set vertical scroll
        pause 10
        i2cwrite sda,scl,control,[$80,$20,$00]      'Horizontal addressing mode
    '    i2cwrite sda,scl,control,[$80,$20,$01]      'Vertical addressing mode
        RETURN
    Last edited by Demon; - 15th June 2015 at 13:13. Reason: Fixed tags

  7. #7
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Thank you so much, I'm able to drive the screen and light up any pixel I want on screen. I think I was misusing i2cwrite command on my code. Now its ok.
    Here is my trial code for blinking any line on the screen.
    Code:
       
    '==========================MCU SETUP============================================  
    Include "modedefs.bas"
    DEFINE OSC 16
    DEFINE I2C_SLOW 1 'Used to work with 100KHz devicez when using over 4MHz (my screen working without this too)
    DEFINE I2C_HOLD 1 'Holding Lines low when not sending data (not necessary)
    
    OPTION_REG=0
    ADCON0=0
    ADCON1=7
    TRISA=%00111111
    TRISB=%00000001
    TRISC=0
    PORTC=$FF
    
    '==============================Variables=======================================
    
    I2CDevice var byte
    SCL var PortC.3         ' I2C Clock  PortC.3
    SDA var PortC.4         ' I2C Data   PortC.4
    DC VAR byte' "DATA OR COMMAND", $40=DATA; $80=COMMAND
    LCD_DATA VAR BYTE
    COM VAR BYTE' COMMAND
    
    
    I VAR BYTE
    J VAR BYTE
    X VAR BYTE' LCD Column POSITION (0 TO 127)
    Y VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    CLEAR
    '=============================================================================
    I2CDevice = $78      ' Display = $78,
    PAUSE 20
    '=========================lcd initialization====================================
    INIT:
    I2CWrite SDA,SCL,I2CDevice,[DC,$AE]'Display Off
    pause 10
    I2CWrite SDA,SCL,I2CDevice,[DC,$20,$10]' Page adressing mode
    I2CWrite SDA,SCL,I2CDevice,[DC,$D3,$00]' Set offset to 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$40]' Set display start line 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$81,$FF]' Set contrast to full
    I2CWrite SDA,SCL,I2CDevice,[DC,$A4]' display on continue 
    I2CWrite SDA,SCL,I2CDevice,[DC,$A6]' $A6=NORMAL MODE;$A7=INVERSE MODE
    I2CWrite SDA,SCL,I2CDevice,[DC,$A1]' set column 127 as start
    i2cwrite sda,scl,I2CDevice,[DC,$C8]'Flip display vertically ****
    'above 2 lines for arranging screen direction, deleting them will
    'turn the display direction 180 degree
    I2CWrite SDA,SCL,I2CDevice,[DC,$AF]'Display On
    pause 10
    '===============================================================================
    GOSUB CLEAR_LCD
    pause 500
    GOSUB TITLE
    
    
    MAIN:
    
    'gosub FILL_LINE
    'pause 1000
    'gosub CLEAR_LCD
    'pause 1000
    
    GOTO MAIN
    
    '======================Send data===============================================
    SEND_DATA:
    DC=$40
    I2CWrite SDA,SCL,I2CDevice,[DC,LCD_DATA]
    RETURN
    '===============================================================================
    '======================Send Command=============================================
    SEND_COMMAND:
    DC=$80
    I2CWrite SDA,SCL,I2CDevice,[DC,COM]
    RETURN
    '===============================================================================
    
    '==============================clear lcd========================================
    CLEAR_LCD:
    X=0
    Y=0
    LCD_DATA=$00
    'Send 0 to every column in every line
    FOR Y=0 TO 7
        gosub SET_XY
        FOR I=0 TO 127
            GOSUB SEND_DATA
        NEXT I
    NEXT Y                             
    RETURN 
    
    '=============================FILL_LINE=========================================
    FILL_LINE:
    X=0
    Y=4  'I choose 4.th line to blink
    LCD_DATA=$FF ' Every line contains pixels $01 is bottom pixel, $80 is top pixel
        gosub SET_XY
        FOR I=0 TO 127
            GOSUB SEND_DATA
        NEXT I                         
    RETURN
    '===============================================================================
    
    '===========================================SET X AND Y=========================
    SET_XY:
    COM=$21:GOSUB SEND_COMMAND
    COM=X:GOSUB SEND_COMMAND
    COM=127:GOSUB SEND_COMMAND
    'Above 3 lines means; Column starts at X and End at 127
    COM=$22:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    'Above 3 lines means; Line starts at Y and end at Y, 
    'which means ; Only work on specified line!
    RETURN
    '===============================================================================
    END

  8. #8
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Hi guys, I again thank you for your code examples Sherbrook. Now I completed my codes and I think they can be helpful.
    Anyway I wanted to share my codes for others too. Maybe someone can improve and chage them into a include file.

    By the way, is it possible to use a variable's content in a lookup table? I'll try to print out variable contents on screen but I'm not sure the way right now. I think I'll open a new thread for this =)

    Code:
    'This code is for driving an OLED screen
    'My screen was 0.96" 128x64 B/W SSD1306 chip with I2C protocol
    'I used a 16f877a, you must change definitions and register settings due to 
    'your hardware.
    'This code have a large char library in it, so it takes some memory, you may
    'delete some of chars you won't use if you need some space for your program
    'My codes don't include bitmap drawing I only intended to write texts on screen
    'So if you want to draw bitmap, you must alter printing codes.
    'Now
    'Screen contains 8 lines (which are 8 pixel height) and 128 columns
    'there are 1 printout subroutine for each Line, Simply change the X value on
    'that line's subroutine and your text will start from that column.
    'There also 8 text sobroutines which are contains text for each line, you can 
    'write your text on these subroutines, but !!!REMEMBER!!! to change the first
    'value of lookup table to number of chars u used in your text.
    
       
    '==========================MCU SETUP============================================  
    DEFINE OSC 16
    OPTION_REG=0
    ADCON0=0
    ADCON1=7
    TRISA=%00111111
    TRISB=%00000001
    TRISC=0
    PORTC=$FF
    
    '==============================BAUD SETUP=======================================
    
    I2CDevice var byte
    SCL var PortC.3         ' I2C Clock  PortC.3
    SDA var PortC.4         ' I2C Data   PortC.4
    DC VAR byte' "DATA OR COMMAND", $40=DATA; $80=COMMAND
    LCD_DATA VAR BYTE
    COM VAR BYTE'COMMAND
    X VAR BYTE' LCD Column POSITION (0 TO 127)
    Y VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    I var byte
    charset var byte 'Char codes index
    say var byte     'counter 
    text_reg var byte 'index for text
    letter_reg var byte 'data carrier for text chars
    letter_count var byte 'count of letters in your text
    CLEAR
    '=============================================================================
    I2CDevice = $78      ' Display = $78,
    PAUSE 20
    '=========================lcd initialization====================================
    INIT:
    I2CWrite SDA,SCL,I2CDevice,[DC,$AE]'Display Off
    pause 10
    I2CWrite SDA,SCL,I2CDevice,[DC,$20,$10]' Page adressing mode
    I2CWrite SDA,SCL,I2CDevice,[DC,$D3,$00]' Set offset to 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$40]' Set display start line 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$81,$FF]' Set contrast to full
    I2CWrite SDA,SCL,I2CDevice,[DC,$A4]' display on continue 
    I2CWrite SDA,SCL,I2CDevice,[DC,$A6]' $A6=NORMAL MODE;$A7=INVERSE MODE
    I2CWrite SDA,SCL,I2CDevice,[DC,$A1]' set column 127 as start
    i2cwrite sda,scl,I2CDevice,[DC,$C8]'Flip display vertically ****
    'above 2 lines for arranging screen direction, deleting them will
    'turn the display direction 180 degree
    I2CWrite SDA,SCL,I2CDevice,[DC,$AF]'Display On
    pause 10
    '===============================================================================
    GOSUB CLEAR_LCD
    pause 500
    
    MAIN:
    
    gosub Print_Line_0
    gosub Print_Line_1
    gosub Print_Line_2
    gosub Print_Line_3
    gosub Print_Line_4
    'gosub Print_Line_5 'You can comment out the lines you don't want to use
    'gosub Print_Line_6
    'gosub Print_Line_7
    
    sleep 5
    
    GOTO MAIN
    
    '=============================Text to Write=====================================
    Line_0:
    lookup text_reg,[4,"Test"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_1:
    lookup text_reg,[9,"Test teST"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_2:
    lookup text_reg,[7,"T e s t"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_3:
    lookup text_reg,[8,"%]Test{-"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_4:
    lookup text_reg,[7,"Hop Hop"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_5:
    lookup text_reg,[4,"Test"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_6:
    lookup text_reg,[4,"Test"],letter_reg' first data is number of chars in your
    'text
    return
    
    Line_7:
    lookup text_reg,[4,"Test"],letter_reg' first data is number of chars in your
    'text
    return
    
    '======================Print Lines==============================================
    Print_Line_0:
    X=0 'You can change this value to set starting column
    Y=0 'Don't change this line
    gosub SET_XY
    gosub Line_0
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_0
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_1:
    X=10 'You can change this value to set starting column
    Y=1  'Don't change this line
    gosub SET_XY
    gosub Line_1
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_1
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_2:
    X=20 'You can change this value to set starting column
    Y=2  'Don't change this line
    gosub SET_XY
    gosub Line_2
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_2
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_3:
    X=30 'You can change this value to set starting column
    Y=3  'Don't change this line
    gosub SET_XY
    gosub Line_3
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_3
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_4:
    X=40  'You can change this value to set starting column
    Y=4   'Don't change this line
    gosub SET_XY
    gosub Line_4
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_4
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_5:
    X=50  'You can change this value to set starting column
    Y=5   'Don't change this line
    gosub SET_XY
    gosub Line_5
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_5
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_6:
    X=60  'You can change this value to set starting column
    Y=6   'Don't change this line
    gosub SET_XY
    gosub Line_6
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_6
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    
    Print_Line_7:
    X=55  'You can change this value to set starting column
    Y=7   'Don't change this line
    gosub SET_XY
    gosub Line_7
    letter_count=letter_reg
    text_reg=text_reg+1
    for say=1 to letter_count
        gosub Line_7
        gosub Find_Char
        text_reg=text_reg+1
    next say
    text_reg=0
    return
    '===============================================================================
    
    '=======================Send data===============================================
    SEND_DATA:
    DC=$40
    I2CWrite SDA,SCL,I2CDevice,[DC,LCD_DATA]
    RETURN
    '===============================================================================
    '======================Send Command=============================================
    SEND_COMMAND:
    DC=$80
    I2CWrite SDA,SCL,I2CDevice,[DC,COM]
    RETURN
    '===============================================================================
    
    '==============================clear lcd========================================
    CLEAR_LCD:
    X=0
    Y=0
    LCD_DATA=$00
    'Send 0 to every column in every line
    FOR Y=0 TO 7
        gosub SET_XY
        FOR I=0 TO 127
            GOSUB SEND_DATA
        NEXT I
    NEXT Y
    X=0
    Y=0 
    gosub SET_XY                            
    RETURN 
    '=============================Find Char=========================================
    Find_Char:
    select case letter_reg
        case " "
        for charset=0 to 5
        lookup charset,[$00,$00,$00,$00,$00,$00],LCD_DATA
        gosub SEND_DATA 
        next charset
        return
    case "!"
      	for charset=0 to 5
      	lookup charset,[$00,$00,$5F,$00,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "#"
      	for charset=0 to 5
      	lookup charset,[$14,$7F,$14,$7F,$14,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "$"
      	for charset=0 to 5
      	lookup charset,[$24,$2A,$7F,$2A,$12,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "%"
      	for charset=0 to 5
      	lookup charset,[$23,$13,$08,$64,$62,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "&"
      	for charset=0 to 5
      	lookup charset,[$36,$49,$56,$20,$50,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "'"
      	for charset=0 to 5
      	lookup charset,[$00,$08,$07,$03,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "("
      	for charset=0 to 5
      	lookup charset,[$00,$1C,$22,$41,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case ")"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$22,$1C,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "*"
      	for charset=0 to 5
      	lookup charset,[$2A,$1C,$7F,$1C,$2A,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "+"
      	for charset=0 to 5
      	lookup charset,[$08,$08,$3E,$08,$08,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case ","
      	for charset=0 to 5
      	lookup charset,[$00,$00,$70,$30,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "-"
      	for charset=0 to 5
      	lookup charset,[$08,$08,$08,$08,$08,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "."
      	for charset=0 to 5
      	lookup charset,[$00,$00,$60,$60,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "/"
      	for charset=0 to 5
      	lookup charset,[$20,$10,$08,$04,$02,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "0"
      	for charset=0 to 5
      	lookup charset,[$3E,$51,$49,$45,$3E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "1"
      	for charset=0 to 5
      	lookup charset,[$00,$42,$7F,$40,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "2"
      	for charset=0 to 5
      	lookup charset,[$72,$49,$49,$49,$46,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "3"
      	for charset=0 to 5
      	lookup charset,[$21,$41,$49,$4D,$33,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "4"
      	for charset=0 to 5
      	lookup charset,[$18,$14,$12,$7F,$10,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "5"
      	for charset=0 to 5
      	lookup charset,[$27,$45,$45,$45,$39,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "6"
      	for charset=0 to 5
      	lookup charset,[$3C,$4A,$49,$49,$31,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "7"
      	for charset=0 to 5
      	lookup charset,[$41,$21,$11,$09,$07,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "8"
      	for charset=0 to 5
      	lookup charset,[$36,$49,$49,$49,$36,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "9"
      	for charset=0 to 5
      	lookup charset,[$46,$49,$49,$29,$1E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case ":"
      	for charset=0 to 5
      	lookup charset,[$00,$00,$14,$00,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case ";"
      	for charset=0 to 5
      	lookup charset,[$00,$40,$34,$00,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "<"
      	for charset=0 to 5
      	lookup charset,[$00,$08,$14,$22,$41,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "="
      	for charset=0 to 5
      	lookup charset,[$14,$14,$14,$14,$14,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case ">"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$22,$14,$08,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "?"
      	for charset=0 to 5
      	lookup charset,[$02,$01,$59,$09,$06,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "@"
      	for charset=0 to 5
      	lookup charset,[$3E,$41,$5D,$59,$4E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "A"
      	for charset=0 to 5
      	lookup charset,[$7C,$12,$11,$12,$7C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "B"
      	for charset=0 to 5
      	lookup charset,[$7F,$49,$49,$49,$36,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "C"
      	for charset=0 to 5
      	lookup charset,[$3E,$41,$41,$41,$22,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "D"
      	for charset=0 to 5
      	lookup charset,[$7F,$41,$41,$41,$3E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "E"
      	for charset=0 to 5
      	lookup charset,[$7F,$49,$49,$49,$41,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "F"
      	for charset=0 to 5
      	lookup charset,[$7F,$09,$09,$09,$01,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "G"
      	for charset=0 to 5
      	lookup charset,[$3E,$41,$41,$51,$73,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "H"
      	for charset=0 to 5
      	lookup charset,[$7F,$08,$08,$08,$7F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "I"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$7F,$41,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "J"
      	for charset=0 to 5
      	lookup charset,[$20,$40,$41,$3F,$01,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "K"
      	for charset=0 to 5
      	lookup charset,[$7F,$08,$14,$22,$41,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "L"
      	for charset=0 to 5
      	lookup charset,[$7F,$40,$40,$40,$40,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "M"
      	for charset=0 to 5
      	lookup charset,[$7F,$02,$1C,$02,$7F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "N"
      	for charset=0 to 5
      	lookup charset,[$7F,$04,$08,$10,$7F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "O"
      	for charset=0 to 5
      	lookup charset,[$3E,$41,$41,$41,$3E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "P"
      	for charset=0 to 5
      	lookup charset,[$7F,$09,$09,$09,$06,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "Q"
      	for charset=0 to 5
      	lookup charset,[$3E,$41,$51,$21,$5E,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "R"
      	for charset=0 to 5
      	lookup charset,[$7F,$09,$19,$29,$46,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "S"
      	for charset=0 to 5
      	lookup charset,[$26,$49,$49,$49,$32,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "T"
      	for charset=0 to 5
      	lookup charset,[$03,$01,$7F,$01,$03,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "U"
      	for charset=0 to 5
      	lookup charset,[$3F,$40,$40,$40,$3F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "V"
      	for charset=0 to 5
      	lookup charset,[$1F,$20,$40,$20,$1F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "W"
      	for charset=0 to 5
      	lookup charset,[$3F,$40,$38,$40,$3F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "X"
      	for charset=0 to 5
      	lookup charset,[$63,$14,$08,$14,$63,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "Y"
      	for charset=0 to 5
      	lookup charset,[$03,$04,$78,$04,$03,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "Z"
      	for charset=0 to 5
      	lookup charset,[$61,$59,$49,$4D,$43,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "["
      	for charset=0 to 5
      	lookup charset,[$00,$7F,$41,$41,$41,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "\"
      	for charset=0 to 5
      	lookup charset,[$02,$04,$08,$10,$20,$00	 ],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "]"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$41,$41,$7F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "^"
      	for charset=0 to 5
      	lookup charset,[$04,$02,$01,$02,$04,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "_"
      	for charset=0 to 5
      	lookup charset,[$40,$40,$40,$40,$40,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "`"
      	for charset=0 to 5
      	lookup charset,[$00,$03,$07,$08,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "a"
      	for charset=0 to 5
      	lookup charset,[$20,$54,$54,$38,$40,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "b"
      	for charset=0 to 5
      	lookup charset,[$7F,$28,$44,$44,$38,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "c"
      	for charset=0 to 5
      	lookup charset,[$38,$44,$44,$44,$28,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "d"
      	for charset=0 to 5
      	lookup charset,[$38,$44,$44,$28,$7F,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "e"
      	for charset=0 to 5
      	lookup charset,[$38,$54,$54,$54,$18,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "f"
      	for charset=0 to 5
      	lookup charset,[$00,$08,$7E,$09,$02,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "g"
      	for charset=0 to 5
      	lookup charset,[$0C,$52,$52,$4A,$3C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "h"
      	for charset=0 to 5
      	lookup charset,[$7F,$08,$04,$04,$78,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "i"
      	for charset=0 to 5
      	lookup charset,[$00,$44,$7D,$40,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "j"
      	for charset=0 to 5
      	lookup charset,[$20,$40,$40,$3D,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "k"
      	for charset=0 to 5
      	lookup charset,[$7F,$10,$28,$44,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "l"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$7F,$40,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "m"
      	for charset=0 to 5
      	lookup charset,[$7C,$04,$78,$04,$78,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "n"
      	for charset=0 to 5
      	lookup charset,[$7C,$08,$04,$04,$78,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "o"
      	for charset=0 to 5
      	lookup charset,[$38,$44,$44,$44,$38,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "p"
      	for charset=0 to 5
      	lookup charset,[$7C,$18,$24,$24,$18,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "q"
      	for charset=0 to 5
      	lookup charset,[$18,$24,$24,$18,$7C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "r"
      	for charset=0 to 5
      	lookup charset,[$7C,$08,$04,$04,$08,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "s"
      	for charset=0 to 5
      	lookup charset,[$48,$54,$54,$54,$24,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "t"
      	for charset=0 to 5
      	lookup charset,[$04,$04,$3F,$44,$24,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "u"
      	for charset=0 to 5
      	lookup charset,[$3C,$40,$40,$20,$7C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "v"
      	for charset=0 to 5
      	lookup charset,[$1C,$20,$40,$20,$1C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "w"
      	for charset=0 to 5
      	lookup charset,[$3C,$40,$30,$40,$3C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "x"
      	for charset=0 to 5
      	lookup charset,[$44,$28,$10,$28,$44,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "y"
      	for charset=0 to 5
      	lookup charset,[$4C,$50,$50,$50,$3C,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "z"
      	for charset=0 to 5
      	lookup charset,[$44,$64,$54,$4C,$44,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "{"
      	for charset=0 to 5
      	lookup charset,[$00,$08,$36,$41,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "|"
      	for charset=0 to 5
      	lookup charset,[$00,$00,$77,$00,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "}"
      	for charset=0 to 5
      	lookup charset,[$00,$41,$36,$08,$00,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    case "~"
      	for charset=0 to 5
      	lookup charset,[$02,$01,$02,$04,$02,$00],LCD_DATA
      	gosub SEND_DATA
      	next charset
      	return
    end select
    return
    '===============================================================================
    '=========================CHAR_SET==============================================
    
    '===========================================SET X AND Y=========================
    SET_XY:
    COM=$21:GOSUB SEND_COMMAND
    COM=X:GOSUB SEND_COMMAND
    COM=127:GOSUB SEND_COMMAND
    'Above 3 lines means; Column starts at X and End at 127
    COM=$22:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    COM=Y:GOSUB SEND_COMMAND
    'Above 3 lines means; Line starts at Y and end at Y, 
    'which means ; Only work on specified line!
    RETURN
    '===============================================================================
    END

  9. #9
    Join Date
    Feb 2013
    Posts
    723

    Default Re: Cannot drive I2C Oled :(

    Using above code, I've tried to use this display with 16F870:

    http://www.ebay.com/itm/221727746237...%3AMEBIDX%3AIT

    But it does not works:

    Code:
    '****************************************************************
    '*  Name    : UNTITLED.BAS                                      *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 07.02.2014                                        *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    '****************************************************************
    
    Include "modedefs.bas"  ' Include serial modes
       TRISA = %11111111       ' Set PORTA to all input
       TRISC = %00000000	    ' Sets all PortB pins to output
       ADCON1 = %10001001      ' Set PORTA analog and right justify result
       ADCON0=%00000000
       low portc.4
       low portc.5
    
    DEFINE LCD_DREG PORTB
    DEFINE LCD_DBIT 4
    DEFINE LCD_RSREG PORTB
    DEFINE LCD_RSBIT 0
    DEFINE LCD_EREG PORTB
    DEFINE LCD_EBIT 1
    DEFINE LCD_BITS 4 
    DEFINE LCD_LINES 2
    DEFINE LCD_COMMANDUS 1500
    DEFINE LCD_DATAUS 44
    DEFINE OSC 4
    
    '==========================MCU SETUP============================================  
    
    
    'DEFINE I2C_SLOW 1 'Used to work with 100KHz devicez when using over 4MHz (my screen working without this too)
    'DEFINE I2C_HOLD 1 'Holding Lines low when not sending data (not necessary)
    
    OPTION_REG=0
    ADCON0=0
    ADCON1=7
    TRISB=%00000001
    trisc = %11111111           'PortC 0, 1, 2 outputs
    PortC = %00110000           'scl & sda high to start
    
    
    led     var portC.0
    scl     var PortC.4
    sda     var PortC.5
    dat     var byte
    counter var word
    
    control con %01111000       'I2C slave address (write mode)
    
    pause 500
    
    
    
        pause 2000
        gosub RESET:
        gosub init_oled:
        i2cwrite sda,scl,control,[$78,$AF]  'Display ON
        pause 10
    
    Start:
    
        led = 1                             'Code running
        i2cwrite sda,scl,control,[$78,$A7]  'Inverse Display 
        pause 500
        i2cwrite sda,scl,control,[$78,$A6]  'Normal Display
        pause 20
    '    i2cwrite sda,scl,control,[$78,$21,$00,$40] 'Set columns
        pause 20
    '    i2cwrite sda,scl,control,[$78,$22,$00,$04]  'Set pages
        pause 500     
        for counter = 0 to 1023
        i2cwrite sda,scl,control,[$40,$FF]
        next
        led = 0                             'Code running
        for counter = 0 to 1023
    lcdout $fe,$C0, #counter, " main   "
        i2cwrite sda,scl,control,[$40,$00]
        next
    GOTO Start:
    
    INIT_OLED:
    lcdout $fe,$C0, "init   "
        i2cwrite sda,scl,control,[$78,$AE]          'Display OFF               ****
        pause 1
        i2cwrite sda,scl,control,[$78,$2E]          'Deactivate scrolling
        pause 1
        i2cwrite sda,scl,control,[$78,$20,$10]      'Page addressing mode      ****
        pause 1
        i2cwrite sda,scl,control,[$78,$A0]          '                          ****
    '    i2cwrite sda,scl,control,[$78,$A1]          '                          ****
        pause 1
        i2cwrite sda,scl,control,[$78,$A6]          'WHITE chars BLACK backround
    '    i2cwrite sda,scl,control,[$78,$A7]         'BLACK chars WHITE backround
        pause 1
        i2cwrite sda,scl,control,[$78,$81,$7F]      'Setup contrast            XXXX
        pause 1
        i2cwrite sda,scl,control,[$78,$AF]          'Display on                **** 
        pause 1
        i2cwrite sda,scl,control,[$78,$40]
        pause 1
    '    i2cwrite sda,scl,control,[$78,$C0]          'Flip display vertically   ****
        i2cwrite sda,scl,control,[$78,$C8]          'Flip display vertically   ****
        pause 1
    '    i2cwrite sda,scl,control,[$78,$A0]          '                          ****
        i2cwrite sda,scl,control,[$78,$A1]          '                          ****
        pause 1
        i2cwrite sda,scl,control,[$78,$00,$78,$10]  'Set column start address  ****
        pause 1
        i2cwrite sda,scl,control,[$78,$B0]          'Set page start address    ****
        pause 1
        return
        
    RESET:
        i2cwrite sda,scl,control,[$78,$AE]          'Display OFF
        pause 10
        I2Cwrite sda,scl,control,[$78,$20,$02]      'Page addressing mode
        pause 10
        i2cwrite sda,scl,control,[$78,$B0]          'Page start address
        pause 10
        i2cwrite sda,scl,control,[$78,$00,$78,$10]  'Set column start address
        pause 10
        i2cwrite sda,scl,control,[$78,$A0]          'Address 0 mapped to SEG 0
        pause 10
     '   i2cwrite sda,scl,control,[$78,$A1]          'Address 0 mapped to SEG 127
        pause 10
        i2cwrite sda,scl,control,[$78,$D3,$00]      'Display offset
        pause 10
    
        pause 10
        i2cwrite sda,scl,control,[$78,$40]          'Display start line
        Pause 10
        i2cwrite sda,scl,control,[$78,$C0]          'Output scan direction
        pause 10
        i2cwrite sda,scl,control,[$78,$A6]          'WHITE chars BLACK backround
        pause 10
        i2cwrite sda,scl,control,[$78,$81,$7F]      'Contrast control
        pause 10
        i2cwrite sda,scl,control,[$78,$A4]          'Entire display OFF
        pause 10
        i2cwrite sda,scl,control,[$78,$A6]          'Normal display
        pause 10
        i2cwrite sda,scl,control,[$78,$A3,$00,$40]  'Set vertical scroll
        pause 10
        i2cwrite sda,scl,control,[$78,$20,$00]      'Horizontal addressing mode
    '    i2cwrite sda,scl,control,[$78,$20,$01]      'Vertical addressing mode
        RETURN
    The initial address was $80, so I've changed it to $78, as shown on picture of the OLED itself.

  10. #10
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    It is same oled I used. First of all, sending 00 and FF for seeing empty and full screen won't work try 00 and 0F. I think ssd1306 outputs are not able to drive all leds at same time. Secondly, your mcu setup is in a mess, you are setting trises and adcons 2 times and differently. Plus, you should set portc.4 and 5 as outputs since PIC is master here, you are setting them inputs in these codes. Both your RESET and INIT subroutines are actually INIT routunies, Sending wrong commands may interrupt oled's working, keep them simple and use only 1 INIT routine(you can use same routine as reset) You may use these codes as init.
    Code:
    '=========================lcd initialization====================================
    INIT:
    I2CWrite SDA,SCL,I2CDevice,[DC,$AE]'Display Off
    pause 10
    I2CWrite SDA,SCL,I2CDevice,[DC,$20,$10]' Page adressing mode
    I2CWrite SDA,SCL,I2CDevice,[DC,$D3,$00]' Set offset to 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$40]' Set display start line 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$81,$FF]' Set contrast to full
    I2CWrite SDA,SCL,I2CDevice,[DC,$A4]' display on continue 
    I2CWrite SDA,SCL,I2CDevice,[DC,$A6]' $A6=NORMAL MODE;$A7=INVERSE MODE
    I2CWrite SDA,SCL,I2CDevice,[DC,$A1]' set column 127 as start
    i2cwrite sda,scl,I2CDevice,[DC,$C8]'Flip display vertically ****
    'above 2 lines for arranging screen direction, deleting them will
    'turn the display direction 180 degree
    I2CWrite SDA,SCL,I2CDevice,[DC,$AF]'Display On
    pause 10
    '===============================================================================
    You don't need to send control commands in your main routine unless you want to really control the screen, delete them. Put some delay after sending 00 / 0f to screen,

    Aaannnd last of all, before entering my comment, I checked 16f870's datasheet for SDA SCL pins but I couldn't see I2C support in device specs. I don't know if you can use I2CWrite command with that model.

  11. #11
    Join Date
    Feb 2013
    Posts
    723

    Default Re: Cannot drive I2C Oled :(

    Thanks, I will try with PIC16F876A, which has hardware I2C capabilities.

  12. #12
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: Cannot drive I2C Oled :(

    Been working on a new char table for the OLED. Problem is the LOOKUP command can only take 255 bytes. This new routine can replace the one from elcrcp above. I have added a few new variables:

    Code:
    'charset var byte 'Char codes index
    charset var word 'Char codes index
    chartmp var byte 'char codes index temp
    letter_temp var byte	' working copy
    Just change Find_Char to Find_Char2
    Code:
    '=============================Find Char  2=======================================
    Find_Char2:
    ' Enter this Subroutine with printable character: letter_reg
    ' letter_reg is subtracted from " " (space char) and * by 5 to be able to index into one table
    ' One table is broken into 3 to avoid the 255 max.  Index into table must be a byte variable.
    
    	letter_temp = letter_reg - 32	' Space is now at index 0 all other characters are 32 less into index
    	letter_temp = letter_temp * 5	' Every character is made of 5 bytes
        for charset=letter_temp to letter_temp+4
    	IF letter_reg < "A" then
    	chartmp = charset - 0 	' lookup variable must be 8 bits 
        lookup chartmp,[$00,$00,$00,$00,$00,$00,$00,$5F,$00,$00,$14,$7F,$14,$7F,$14,$00,$08,$07,$03,$00,_	'sp,!,#,"
    					$24,$2A,$7F,$2A,$12,$23,$13,$08,$64,$62,$36,$49,$56,$20,$50,_	'$,%,&
    					$00,$08,$07,$03,$00,$00,$1C,$22,$41,$00,$00,$41,$22,$1C,$00,_	'',(,)
    					$2A,$1C,$7F,$1C,$2A,$08,$08,$3E,$08,$08,$00,$00,$70,$30,$00,_	'*,+,,
    					$08,$08,$08,$08,$08,$00,$00,$60,$60,$00,$20,$10,$08,$04,$02,_	'-,.,/
    					$3E,$51,$49,$45,$3E,$00,$42,$7F,$40,$00,$72,$49,$49,$49,$46,_	'0,1,2
    					$21,$41,$49,$4D,$33,$18,$14,$12,$7F,$10,$27,$45,$45,$45,$39,_	'3,4,5
    					$3C,$4A,$49,$49,$31,$41,$21,$11,$09,$07,$36,$49,$49,$49,$36,_	'6,7,8
    					$46,$49,$49,$29,$1E,$00,$00,$14,$00,$00,$00,$40,$34,$00,$00,_	'9,:,;
    					$00,$08,$14,$22,$41,$14,$14,$14,$14,$14,$00,$41,$22,$14,$08,_	'<,=,>
    					$02,$01,$59,$09,$06,$3E,$41,$5D,$59,$4E],LCD_DATA	'?,@
    	elseif  (letter_reg < "[") then 
    	chartmp = charset - 165		' subtract previous table length so "A" = zero 					
    	lookup chartmp,[$7C,$12,$11,$12,$7C,_	'A
    					$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,_	'B,C,D
    					$7F,$49,$49,$49,$41,$7F,$09,$09,$09,$01,$3E,$41,$41,$51,$73,_	'E,F,G
    					$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$20,$40,$41,$3F,$01,_	'H,I,J
    					$7F,$08,$14,$22,$41,$7F,$40,$40,$40,$40,$7F,$02,$1C,$02,$7F,_	'K,L,M
    					$7F,$04,$08,$10,$7F,$3E,$41,$41,$41,$3E,$7F,$09,$09,$09,$06,_	'N,O,P
    					$3E,$41,$51,$21,$5E,$7F,$09,$19,$29,$46,$26,$49,$49,$49,$32,_	'Q,R,S
    					$03,$01,$7F,$01,$03,$3F,$40,$40,$40,$3F,$1F,$20,$40,$20,$1F,_	'T,U,V
    					$3F,$40,$38,$40,$3F,$63,$14,$08,$14,$63,$03,$04,$78,$04,$03,_	'W,X,Y
    					$61,$59,$49,$4D,$43],LCD_DATA	'Z
    	else  
    	chartmp = charset - 295		' subtract previous tables length so "[" = zero
    	lookup chartmp,[$00,$7F,$41,$41,$41,$02,$04,$08,$10,$20,_	'[,\
    					$00,$41,$41,$41,$7F,$04,$02,$01,$02,$04,$40,$40,$40,$40,$40,_	'],^,_
    					$00,$03,$07,$08,$00,$20,$54,$54,$38,$40,$7F,$28,$44,$44,$38,_	'`,a,b
    					$38,$44,$44,$44,$28,$38,$44,$44,$28,$7F,$38,$54,$54,$54,$18,_	'c,d,e
    					$00,$08,$7E,$09,$02,$0C,$52,$52,$4A,$3C,$7F,$08,$04,$04,$78,_	'f,g,h
    					$00,$44,$7D,$40,$00,$20,$40,$40,$3D,$00,$7F,$10,$28,$44,$00,_	'i,j,k
    					$00,$41,$7F,$40,$00,$7C,$04,$78,$04,$78,$7C,$08,$04,$04,$78,_	'l,m,n
    					$38,$44,$44,$44,$38,$7C,$18,$24,$24,$18,$18,$24,$24,$18,$7C,_	'o,p,q
    					$7C,$08,$04,$04,$08,$48,$54,$54,$54,$24,$04,$04,$3F,$44,$24,_	'r,s,t
    					$3C,$40,$40,$20,$7C,$1C,$20,$40,$20,$1C,$3C,$40,$30,$40,$3C,_	'u,v,w
    					$44,$28,$10,$28,$44,$4C,$50,$50,$50,$3C,$44,$64,$54,$4C,$44,_	'x,y,z
    					$00,$08,$36,$41,$00,$00,$00,$77,$00,$00,$00,$41,$36,$08,$00,_	'{,|,}
    					$02,$01,$02,$04,$02],LCD_DATA	'~
    	endif
        gosub SEND_DATA
        next charset
    	LCD_DATA = $00		' space between characters always $00 
        gosub SEND_DATA
    	return
    
    '===============================================================================

    IDE says this compiles in less than 4K so I tried the 16F877 and that compiles as well.
    Regards
    TimC
    Last edited by timc; - 17th July 2015 at 04:06. Reason: added the user name elcrcp

  13. #13
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: Cannot drive I2C Oled :(

    The INIT routine is critical and no single INIT routine will work for all SSD1306 displays. If you get your display to work in under an hour consider yourself lucky. This INIT routine can replace the one from elcrcp above if your display did not work. I have tried this same "routine" for both PIC's, AVR's and in Basic and C.
    Regards
    TimC



    Code:
    '==================    SSD1306 I2C OLED initialization   ======================
    INIT:
    I2CWrite SDA,SCL,I2CDevice,[DC,$AE]'Display OFF
    I2CWrite SDA,SCL,I2CDevice,[DC,$D3,$00]' Set offset to 0
    'I2CWrite SDA,SCL,I2CDevice,[DC,$40]' Set display start line 0, usually not needed
    I2CWrite SDA,SCL,I2CDevice,[DC,$8D,$14]' Set Charge Pump Internal, USUALLY needed
    I2CWrite SDA,SCL,I2CDevice,[DC,$20,$10]' Adressing mode $10=Page, $00=Horizontal
    I2CWrite SDA,SCL,I2CDevice,[DC,$A1]' set segment remap column 127 as start
    i2cwrite sda,scl,I2CDevice,[DC,$C8]' Com Scan Direction, Flip display vertically
    i2cwrite sda,scl,I2CDevice,[DC,$DA,$12]' set COM pins = 128x64=$12   128x32=$02
    I2CWrite SDA,SCL,I2CDevice,[DC,$81,$7F]' Set contrast to $01 to $FF  ($7F is default, $01 is faint)
    I2CWrite SDA,SCL,I2CDevice,[DC,$A4]' display ON continue
    I2CWrite SDA,SCL,I2CDevice,[DC,$A6]' $A6=NORMAL MODE;  $A7=INVERSE MODE
    I2CWrite SDA,SCL,I2CDevice,[DC,$AF]'Display ON
    ' longer delay here because we need to see if display shows random bytes.
    ' If you see random bytes - your display and INIT are probably working!
    pause 500	' remove when you like
    Wait what's DC? Well it should be $00 but I have read it might be $80. Is this why they are only $4 on EBAY?

  14. #14
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Good question there timc
    I realised that I forgot setting DC in init after some time.
    Funny Fact: After I set DC to $80 for INIT routine, oled not worked properly (or maybe not worked at all, can't remember right now) while SET_XY routine working fine with DC $80. So actually I'm not sure if command mode is 00 or 80 but it's working this way

  15. #15
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    By the way TimC, your character table is clearly more efficient and Flash friendly. I will try it too when I have opportunity.
    But I want to ask something first; I'm not sure how LOOKUP and LOOKUP2 commands treats different data types, so that is why I'm asking this, lets say I wrote;
    "lookup2 variable,['string',variable2],variable3"
    And variable 2 contains 7 as data.
    Now, since string and variable2 are different data types, will this char table be able to recognize them both? I mean, is it working for both of '7' and 7 ?
    I'm just asking because I really don't know the behavior of lookup commands for different data types.

  16. #16
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: Cannot drive I2C Oled :(

    Personally I would not alternate different data types in a big character table because you want to make it as simple and small as possible. From the PBP manual it says: "Lookup2 generates code that is about 3 times larger then Lookup."
    So I went back to Lookup. The only other reason that you might use Lookup2 is because it can address 1024 values. The new manual for V3 says Lookup can address 1024 values but it failed after "S" and before it reached "T" which is exactly 256 values.

    Me thinks the V3.0.8 compiler has a bug!

  17. #17
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: Cannot drive I2C Oled :(

    I posted a full demo of a SSD1306 add-in over on the code example forum. elcrcp I think this is what you were asking for earlier.
    Best part is you can start to use it like a regular LCD with data from other devices and formatted output.

    http://www.picbasic.co.uk/forum/showthread.php?t=20179

    TimC

  18. #18
    Join Date
    Apr 2013
    Posts
    32

    Default Re: Cannot drive I2C Oled :(

    Yes TimC that is my answer =)
    By the way, I tried your init suggestion and it's fine (I didn't know that upper limit of contrast was 7F) then I wanted to see your include file and sample code (good job you did there ) but I couldn't make it work don't know why, I'll examine them detailed later but they are definetly very useful and easy to work with.

  19. #19
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Re: Cannot drive I2C Oled :(

    The Contrast Init line should read
    Set contrast FROM $01 to $FF NOT Set contrast to $01 to $FF.
    Therefore $FF is the upper limit.

    Good luck

  20. #20
    Join Date
    Jun 2016
    Posts
    60

    Default Re: Cannot drive I2C Oled :(

    Hi all, I did use the Timc code to drive a 0.96 '' oled display and it works fine (thank you Timc)
    The only doubt now I have is the warning message I get compiling the code:

    "ASM WARNING Argument out of range. Last significant bits used. (0) : Warninig [202]"

    What does it mean?
    How can I remove it?

    Alberto

  21. #21
    Join Date
    Feb 2007
    Posts
    55

    Default Re: Cannot drive I2C Oled :(

    I bought a OLED display on ebay saying it had a SSD1306 chip, trying running some code from here and I got a display full of noise

    Turns out it has SH1106 driver

    I modified the code here to work with it on 18F877
    this draws a box around the display


    <code>

    'OLED driver 16F877
    'SH1106 driver
    'NOT SSD1306

    '==========================MCU SETUP============================================
    Include "modedefs.bas"

    DEFINE OSC 8


    ADCON0=0
    ADCON1=7
    TRISA=%00111111
    TRISB=%00000001
    TRISC=0
    TRISD=0
    TRISE=0
    PORTC=$FF

    '==============================Variables========== =============================

    I2CDevice var byte
    SCL var PortC.3 ' I2C Clock PortC.3
    SDA var PortC.4 ' I2C Data PortC.4
    DC VAR byte' "DATA OR COMMAND", $40=DATA; $0=COMMAND
    LCD_DATA VAR BYTE
    COM VAR BYTE' COMMAND


    I VAR BYTE
    J VAR BYTE
    X VAR BYTE' LCD Column POSITION (0 TO 127)
    Y VAR BYTE'LCD Line POSITION FOR PAGE MODE(0 TO 7)
    Xlow VAR BYTE 'Low 4 bits of X
    Xhigh VAR BYTE 'High 4 bits of X
    CLEAR
    '================================================= ============================
    I2CDevice = $78 ' Display = $78,
    PAUSE 500
    '=========================lcd initialization====================================
    DC = 0
    INIT:
    I2CWrite SDA,SCL,I2CDevice,[DC,$AE]'Display Off
    pause 10
    I2CWrite SDA,SCL,I2CDevice,[DC,$D3,$00]' Set offset to 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$40]' Set display start line 0
    I2CWrite SDA,SCL,I2CDevice,[DC,$8D,$14]' Set Charge Pump Internal, usually needed
    'I2CWrite SDA,SCL,I2CDevice,[DC,$20,$10]' Page adressing mode
    I2CWrite SDA,SCL,I2CDevice,[DC,$A1]' set column 0 as start
    i2cwrite sda,scl,I2CDevice,[DC,$C8]'
    I2CWrite SDA,SCL,I2CDevice,[DC,$DA,$12]' set COM pins = 128x64=$12 128x32=$02'
    I2CWrite SDA,SCL,I2CDevice,[DC,$81,$01]' Set contrast to low
    I2CWrite SDA,SCL,I2CDevice,[DC,$A4]' display on continue
    I2CWrite SDA,SCL,I2CDevice,[DC,$A6]' $A6=NORMAL MODE;$A7=INVERSE MODE

    I2CWrite SDA,SCL,I2CDevice,[DC,$AF]'Display On
    pause 500




    '================================================= ==============================
    GOSUB CLEAR_LCD
    pause 500



    MAIN:

    gosub CLEAR_LCD
    pause 1000
    gosub BOX1
    pause 1000

    GOTO MAIN

    '======================Send data============================================== =
    SEND_DATA:
    DC=$40
    I2CWrite SDA,SCL,I2CDevice,[DC,LCD_DATA]
    RETURN
    '================================================= ==============================
    '======================Send Command=========================================== ==
    SEND_COMMAND:
    DC=0
    I2CWrite SDA,SCL,I2CDevice,[DC,COM]
    RETURN
    '================================================= ==============================

    '==============================clear lcd========================================
    CLEAR_LCD:
    X=2
    Y=0
    LCD_DATA=$00
    'Send 0 to every column in every line
    FOR Y=0 TO 7
    gosub SET_XY
    FOR I=0 TO 127
    GOSUB SEND_DATA
    NEXT I
    NEXT Y
    RETURN

    '================================================= ==============================
    BOX1:
    FOR Y = 0 TO 7
    X=2
    GOSUB SET_XY
    LCD_DATA=%11111111
    GOSUB SEND_DATA
    X=129
    GOSUB SET_XY
    GOSUB SEND_DATA
    NEXT Y
    FOR X = 3 TO 128
    Y=0
    GOSUB SET_XY
    LCD_DATA=%00000001
    GOSUB SEND_DATA
    Y=7
    GOSUB SET_XY
    LCD_DATA=%10000000
    GOSUB SEND_DATA
    NEXT


    RETURN

    '===========================================SET X AND Y=========================
    SET_XY:
    COM = $B0
    COM = COM + Y '<<<--- SET PAGE ADDRESS %1011DDDD
    GOSUB SEND_COMMAND

    Xhigh = X >> 4
    Xlow = X &$0F
    COM=Xlow '<<<--- SET COL ADDRESS LOW bits %0000DDDD
    GOSUB SEND_COMMAND
    Xhigh.4 = 1
    COM = Xhigh '<<<--- SET COL ADDRESS HIGH bits %0001DDDD
    GOSUB SEND_COMMAND

    RETURN
    '================================================= ==============================


    END

    </code>

  22. #22
    Join Date
    Aug 2003
    Location
    Australia
    Posts
    984

    Default Re: Cannot drive I2C Oled :(

    Probably this:
    Code:
    chartmp = charset - 295
    char temp is a byte who’s maximum value is 255.
    It will probably also break it if it was working, to fix it,
    you’d probably have to rotate the values in the lookup table by some amount.


    Quote Originally Posted by Alberto View Post
    Hi all, I did use the Timc code to drive a 0.96 '' oled display and it works fine (thank you Timc)
    The only doubt now I have is the warning message I get compiling the code:

    "ASM WARNING Argument out of range. Last significant bits used. (0) : Warninig [202]"

    What does it mean?
    How can I remove it?

    Alberto

Similar Threads

  1. OLED 128X96 cheap china lcd
    By starwick in forum Code Examples
    Replies: 10
    Last Post: - 19th June 2017, 05:23
  2. Help With OLED Display / 128X64 SSD1306
    By Denner in forum General
    Replies: 6
    Last Post: - 25th May 2013, 15:40
  3. SEROUT + SERIN, OLED + PICAXE coding help required
    By SeanHowson in forum mel PIC BASIC
    Replies: 4
    Last Post: - 15th October 2012, 16:11
  4. Master SPI interface to LCD/OLED??
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 19th September 2009, 23:44
  5. OLED 128x128 color display
    By Ron Marcus in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 21st May 2007, 01:45

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts