LCD 20x4 and AXE134(18M2) driver 20X2 based for serial / i2c.

Haroen

Member
Hi, I've a chinese 20x4 lcd display with same pin-layout as PICAXE axe134(18M2 lcd driver).
I don't have a 18M2 to drive this display but wondered if 20X2 could do the job and browsed this forum...

  • http://www.picaxeforum.co.uk/showthread.php?27556-AXE132-Predef
    * Assembled his code with the missing "Pause 20", but think it's incomplete though...
    Code:
    ; AXE134 Serial 20x4 OLED using PICAXE-18M2
    ; Emulates basic serial operation of the popular AXE033 module
    
    #picaxe 20x2
    setfreq m8
    
    pause 1000              												;Wait for LCD to initialise
    
    symbol LCDSerial = c.7
    symbol LCDBacklight = c.5
    
    SYMBOL lcdcommand = $FE             								;= 254 - send this before following commands
    symbol lcdmessage = 253             								;Display message stored on AXE133
    SYMBOL lcdclear = $01              									;clear screen and cursor to home position
    SYMBOL lcdline1 = 128              									;move to 1st line 1st character
    SYMBOL lcdline2 = 192               								;move to 2nd line 1st character
    SYMBOL lcdline3 = 148               								;move to start of 3rd line
    SYMBOL lcdline4 = 212               								;move to start of 4th line
    
    symbol baudmode = n2400             								;Serial speed for LCD
    
    symbol Brightness = w4              								;Define symbol to control PWM Duty
    
    ;Setup input and Outpit pins
    let dirsb = %11111111               								;Set Input or Output on B (All Outputs)
    let dirsc = %10100001               								;Set Input or Output on C (All I/P except)
                                        								;C.5 O/P (Backlight PWM)
                                        								;C.7 O/P (Serial to LCD)
    
    Brightness = 500                   									;Set PWM Duty initial value (500 = 50%
                                        								;1000 = 100%)
    
    ;PWM Backlight
    pwmout LCDBacklight,249,brightness                    		;Turn on LCD Backlight
    ;Amend this to allow saving to EEPROM
    
    EEPROM  00, ("Message 0 1234567890")      						;store msg 0 in the EEPROM memory
    EEPROM  20, ("Message 1 1234567890")      						;store msg 1 in the EEPROM memory
    EEPROM  40, ("Message 2 1234567890")      						;store msg 2 in the EEPROM memory
    EEPROM  60, ("Message 3 1234567890")      						;store msg 3 in the EEPROM memory
    
    serout LCDSerial, baudmode, (lcdcommand,lcdclear)           ;Clear display
    Pause 20
    serout LCDSerial, baudmode, (lcdcommand,lcdline1)           ;Position set to LCD Line 1
    Pause 20
    serout LCDSerial, baudmode, (lcdmessage,0)                  ;Displayed saved message 0
    Pause 20
    serout LCDSerial, baudmode, (lcdcommand,lcdline2)           ;Position set to LCD Line 2
    Pause 20
    serout LCDSerial, baudmode, (lcdmessage,1)                  ;Displayed saved message 1
    Pause 20
    serout LCDSerial, baudmode, (lcdcommand,lcdline3)           ;Position set to LCD Line 3
    Pause 20
    serout LCDSerial, baudmode, (lcdmessage,2)                  ;Displayed saved message 2
    Pause 20
    serout LCDSerial, baudmode, (lcdcommand,lcdline4)           ;Position set to LCD Line 4
    Pause 20
    serout LCDSerial, baudmode, (lcdmessage,3)                  ;Displayed saved message 3
    Pause 20
    
    main:
    Goto main

Is there any working 20x4 lcd driver code based on the picaxe 20x2 for serial(optionally i2c) available?
 
Last edited:

hippy

Technical Support
Staff member
A PICAXE 20X2 is able to drive a 20 x 4 display directly in 4-bit or 8-bit mode. Code for initialising and driving a 20 x 4 display would usually be the same as code for 20 x 2 and 16 x 2 displays.

It is not clear if you simply want the 20X2 to be able to put data up on a 20 x 4 display attached to it, or want the 20X2 to replicate what the AXE134Y product does, which is to receive data from another PICAXE which the 20X2 puts on the display.
 

Haroen

Member
Thanks for the fast reply,
I want the 20X2 to replicate what the AXE134Y product does, which is to receive data from another PICAXE which the 20X2 puts on the display.
So the second forum solution from Inglewoodpete who uses 4-bit mode could work for the 20 x 4 display, but what to change?
It is also much faster than the 18M2 in display handling with SetFreq M64 for High Speeds switching text.
Could be a nice upgrade when making projects where real-time-visualisation of data is wanted for fast personal interaction.

This is the case for my current project building a 3Dprinter filastruder controller.
 

hippy

Technical Support
Staff member
I want the 20X2 to replicate what the AXE134Y product does
Thanks for the clarification.

So the second forum solution from Inglewoodpete who uses 4-bit mode could work for the 20 x 4 display, but what to change?
That code should work with a 20 x 4 display connected as it would with a 20 x 2 display connected.

I am not sure what would be required to tailor it for a 20 x 4 display. Inglewoodpete I believe still visits the forum and may be able to advise but otherwise it would require analysing the code to work out what it does and what needs to change.
 

inglewoodpete

Senior Member
I don't have a 20x4 display, so have never tested the code on one. Having said that, it should not be too hard to adapt the code to work on a 20x4 just as well as the 16x2 display.

It's been a couple of years since I touched the code, so I've just done a quick refresher.

The i2c method of driving the display uses an area of the scratchpad RAM mapped character-for-character with the locations on the LCD/OLED screen. So the i2c master must write to the 20x2 i2c slave's mapped area and the 20x2 will then pass the character/s on to the screen. The 16x2 LCD has 32 bytes of scratchpad dedicated to the mapped display. A 20x4 display needs 80 bytes of the scratchpad mapped to the LCD/OLED - significantly more.

Looking at the code, I think only the following definitions will need changing:

1. Replace the scratchpad definitions with:
Code:
[color=Green]'
' **** Scratchpad (20X2 - Bytes 0 to 127d)
'[/color]
[color=Blue]Symbol [/color][color=Black]sSerInBuffStart  [/color][color=DarkCyan]= [/color][color=Navy]0          [/color][color=Green]'Also used for i2c command mode.[/color]
[color=Blue]Symbol [/color][color=Black]sSerInBuffSecond [/color][color=DarkCyan]= [/color][color=Navy]1          [/color][color=Green]'Second byte of serial input (or i2c command) buffer[/color]
[color=Blue]Symbol [/color][color=Black]sSerInBuffEnd    [/color][color=DarkCyan]= [/color][color=Navy]47         [/color][color=Green]'64-byte Serial Input buffer has been reduced for larger LCD/OLED[/color]
[color=Blue]Symbol [/color][color=Black]sDisplayMapStart [/color][color=DarkCyan]= [/color][color=Navy]48         [/color][color=Green]'This 80-byte buffer is for a 20 x 4 OLED/LCD[/color]
[color=Blue]Symbol [/color][color=Black]sDisplayMapEnd   [/color][color=DarkCyan]= [/color][color=Navy]127        [/color][color=Green]' For a 20 x 4 display, the size of the SerInBuff has been reduced[/color]
2. Replace these definitions for the changed size of the display:
Code:
[color=Blue]Symbol [/color][color=Black]cLineCount       [/color][color=DarkCyan]= [/color][color=Navy]4           [/color][color=Green]' Change from 2 for displays with 4 lines[/color]
[color=Blue]Symbol [/color][color=Black]cLineLen         [/color][color=DarkCyan]= [/color][color=Navy]20          [/color][color=Green]' Change from 16 for displays with 16-character lines[/color]
[color=Blue]Symbol [/color][color=Black]cFirstCol        [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]Symbol [/color][color=Black]cLastCol         [/color][color=DarkCyan]= [/color][color=Navy]19          [/color][color=Green]' Change from 15 for displays with 16-character lines[/color]
3. Change these locations in EEPROM (a 4-row display will need 4 bytes defined here). You will need to determine the start address of each row of your OLED/LCD and replace the values <Row1> to <Row4>
Code:
[color=Green]' Locations $F0 - $FF (240d to 255d) miscellaneous use[/color]
[color=Blue]Symbol [/color][color=Black]eOLEDFirstRowAddr [/color][color=DarkCyan]= [/color][color=Navy]$F0      [/color][color=Green]'Start of OLED Screen RAM Pointer Lookup table[/color]
[color=Blue]EEPROM [/color][color=Black]eOLEDFirstRowAddr, [/color][color=Blue]([/color][color=Navy]<Row1>[/color][color=Black], [/color][color=Navy]<Row2>[/color][color=Black], [/color][color=Navy]<Row3>[/color][color=Black], [/color][color=Navy]<Row4>[/color][color=Blue])[/color][color=Green]' Start position of each OLED/LCD row[/color]
It's nearly 11:00pm here, so I can't do much in-depth help beyond this until later in the weekend.
 

Haroen

Member
The help here in this forum is amazing!

Just like the 18M2 solution is a multipurpose solution it would be nice to have this 20X2 driver do the same to work with some popular lcd's.
Maybe a POTmeter on a free ADC-pin to select the right LCD choice 16x2, 16x4, 20x2, 20x4 to work with the code.

I had already planned to make a LCD driver-pcb layout for such a solution for my controller.
Just a picture from the project. By-The-Way, it will also be a used for injection molding purposes.
Filastruder Project.jpg
 
Last edited:

Haroen

Member
The modified part of the code for 20x4 so far,
Code:
#PICAXE 20X2
#Terminal 76800            'SerTxd default at 64MHz
#No_Table
'
' ********************************************
' Note you must uncomment just one of these two options
'#define use_OLED														; OLED
#Define use_LCD   'Note that this program does not contain code for 4-bit LCD initialisation	; LCD
' ********************************************
#Define use_welcome      ' display the welcome message upon power up
'
' **** Hardware Connections to 20X2
'
Symbol oReadNotWrite    = A.0         ' Read/Write control (Note: also used as SerOut)
'
Symbol oData4           = B.0         ' to LCD/OLED Data Line 4
Symbol oData5           = B.1         ' to LCD/OLED Data Line 5
Symbol oData6           = B.2         ' to LCD/OLED Data Line 6
Symbol oData7           = B.3         ' to LCD/OLED Data Line 7
Symbol oRSel            = B.4         ' LCD/OLED Register Select
Symbol i2cSDA           = B.5         ' hi2c Serial Data
Symbol ihSerIn          = B.6         ' Background Serial Async In
Symbol i2cSCL           = B.7         ' hi2c Serial Clock
'
Symbol Spare0           = C.0         ' Spare (hSerOut) Input/Output 0
Symbol oHWOut1          = C.1         ' Aux Output pin 1
Symbol oHWOutPin1       = outpinC.1   ' C.1 for writing to Aux Output pin 1 directly 
Symbol oHWOut2          = C.2         ' Aux Output pin 2
Symbol oHWOutPin2       = outpinC.2   ' C.2 for writing to Aux Output pin 2 directly 
Symbol oHWOut3          = C.3         ' Aux Output pin 3
Symbol oHWOutPin3       = outpinC.3   ' C.3 for writing to Aux Output pin 3 directly 
Symbol oLED             = C.4         ' Indicator LED
Symbol Spare5           = C.5         ' Spare (PWM) Input/Output 5
Symbol Spare6           = C.6         ' Spare (Input only)
Symbol oEnable          = C.7         ' LCD/OLED Enable 
'
' **** Register definitions ********************************
'
Symbol bDataStatus      = b0   '<<<b0 is reserved for bit flags
Symbol tCmdMode         = Bit0
Symbol tMsgMode         = Bit1
Symbol tExtCmdMode      = Bit2   'Extended commands: Eg. Specify new character
Symbol tOPMode          = Bit3   'Set Output pins
Symbol tDataAvail       = Bit4
'
Symbol bCommsStatus     = b1   '<<<b1 is reserved for bit flags
Symbol ti2cDataMode     = Bit8   'Commands and data received in start of Scratchpad
Symbol ti2cMappedMode   = Bit9   'Data received in map area of Scratchpad
Symbol ti2cInMode       = Bit10  'Data received via i2c
Symbol tSerInMode       = Bit11  'Data received via the Serial port
'
Symbol bOutputStatus    = b2   '<<<b2 is reserved for setting/clearing 3 output pins
Symbol bPin1Status      = bit24   'Value from incoming "set output pins" command bit0
Symbol bPin2Status      = bit25   'Value from incoming "set output pins" command bit1
Symbol bPin3Status      = bit26   'Value from incoming "set output pins" command bit2
'
Symbol bi2cAddress      = b16
Symbol bi2cCheckM       = b17     'Used for i2cTest (Used in Main loop)
Symbol bRegSelect       = b18     'w9   Bit pattern for selecting OLED registers
Symbol bDataLen         = b19     'w9   Length of command's payload data   
Symbol bInCmd           = b20     'w10
Symbol bInChar          = b21     'w10
Symbol bMsgPtr          = b21     'w10
Symbol bOutByte         = b21     'w10
Symbol bStartAddr       = b22     'w11
Symbol bEndAddr         = b23     'w11
'
Symbol bColPtr          = b24     'w12 OLED/LCD Column Pointer
Symbol bCursorPtr       = b25     'w12 record of next input position of OLED (Actual Cursor posn)
Symbol bReqCursorPtr    = b26     'w13 Required position on current character (if to be displayed)
'
Symbol bEEPROMPtr       = b54     'w27
Symbol bCounter         = b54     'w27
Symbol bOLEDChar        = b55     'w27   Character for display in OLED
'
' **** Constants
'
Symbol False            = 0
Symbol True             = 1
Symbol cSpace           = 32          'Space (blank) character
Symbol cEmpty           = 250         'Indicates empty location. A selected character that will not be needed
'                                     'cEmpty can be changed to any character between 128 and 250 (user choice)
'      OLED Commands
Symbol cOLEDDisplayClear= %00000001   ' 1 Clear Display   (takes 1.7mS)
Symbol cOLEDCursorHome  = %00000010   ' 2 Home            (takes 1.7mS)
Symbol cOLEDEntryModeSet= %00000110   ' 6 Entry Mode Set b2:1 b1:1 move char position forward (b1:0 for backwards)
Symbol cOLEDDisplayOff  = %00001000   ' 8 Display Off b3:1, b2:0(display off), b1:0(csr off), b0:0(csr flash off)
Symbol cOLEDDispCurOff  = %00001100   '12 Display On  b3:1, b2:1(display on),  b1:1(csr on),  b0:1(csr flash)
Symbol cOLEDDispCurOn   = %00001110   '14 Display On  b3:1, b2:1(display on),  b1:1(csr on),  b0:1(csr flash)
Symbol cOLEDCursorShift = %00010000   '16 b4:1, b3:0 (move cursor)/1(move display), b2:0 (sh left)/1(sh right)
Symbol cOLEDFunctionSet = %00110010   '50 b5:1, b4:1(8-bit data), b3:1(2 line LCD) b2:0 (5x7 dots)/1 (5 x 10 dots)
'Symbol cOLEDCharGenAddr= %01cccrrr   'ccc: 8 CG chars; rrr: 8 rows of 5 bits (CG data byte follows: ...xxxxx)
Symbol cOLEDPosnRow0    = %10000000   '128 Position cursor to first row  (b3-b0 = Column 0 to 15) %1000xxxx $8x
Symbol cOLEDPosnRow1    = %11000000   '192 Position cursor to second row (b3-b0 = Column 0 to 15) %1100xxxx $Cx
'
Symbol cLineCount       = 4           ' Change to 4 for displays with 4 lines				: 4 lines
Symbol cLineLen         = 20          ' Change to 20 for displays with 20-character lines		: 20 chars
Symbol cFirstCol        = 0
Symbol cLastCol         = 19          ' Change to 19 for displays with 20-character lines		: 20 chars
'      Miscellaneous masks
Symbol mskHiNibble      = %11110000
Symbol mskLoNibble      = %00001111
Symbol mskSetCmdReg     = %00000000         
Symbol mskSetChrReg     = %00010000
'
'      Comms Constants (hSerial and hi2c)         
Symbol mskSerialOnly    = %00100000   '
Symbol flgSerialOnly    = %00100000   '
Symbol mskHi2cOnly      = %01000000   '
Symbol flgHi2cOnly      = %01000000   '
Symbol mskHi2cAndSerial = %01100000   '
Symbol flgHi2cAndSerial = %01100000   '
Symbol ci2cSlaveAddress = 5
'       Images of Status Byte
Symbol cCharacterOnly   = %00010000   'Assumed to be printable character
Symbol cCmdWithData     = %00010001   'One-byte command for OLED
Symbol cOutputMode      = %00011000   'One-byte command for 20X2's 3 x output pins
'
' **** RAM Pointers (56 to 127d) Not used
'
' **** Scratchpad (20X2 - Bytes 0 to 127d)
'
Symbol sSerInBuffStart  = 0          'Also used for i2c command mode.
Symbol sSerInBuffSecond = 1          'Second byte of serial input (or i2c command) buffer
Symbol sSerInBuffEnd    = 47         '64-byte Serial Input buffer can be reduced if required	: 20x4
Symbol sDebugBuffStart  = 64
Symbol sDebugBuffEnd    = 71
Symbol sDisplayMapStart = 48         'This 32-byte buffer is for a 16 x 2 OLED/LCD: 20x4
Symbol sDisplayMapEnd   = 127        ' For a 20 x 4 display, reduce the size of the SerInBuff	: 20x4
'
' **** EEPROM 256 Bytes
'
' Store the 16 character user defined messages in EEPROM data memory
' First two messages are optionally used as welcome message

' If using a display with 20 characters you will need to edit 
'   the start addresses to be multiples of 20 (currently at 16) 
'   and add 4 characters to each message.
' 4 line displays always use the strange 1-3-2-4 layout.
'
#IfDef use_OLED      
EEPROM $00, ("  Serial OLED   ")    ' store msg in the EEPROM memory
#Else
EEPROM $00, ("  Serial  LCD   ")    ' store msg in the EEPROM memory
#EndIf
EEPROM $10, ("with HSS&i2c I/F")    ' store msg in the EEPROM memory
'
EEPROM $20, ("This is msg 2   ")    ' store msg in the EEPROM memory
EEPROM $30, ("This is msg 3   ")    ' store msg in the EEPROM memory
EEPROM $40, ("This is msg 4   ")    ' store msg in the EEPROM memory
EEPROM $50, ("This is msg 5   ")    ' store msg in the EEPROM memory
EEPROM $60, ("This is msg 6   ")    ' store msg in the EEPROM memory
EEPROM $70, ("This is msg 7   ")    ' store msg in the EEPROM memory
EEPROM $80, ("This is msg 8   ")    ' store msg in the EEPROM memory
EEPROM $90, ("This is msg 9   ")    ' store msg in the EEPROM memory
EEPROM $A0, ("This is msg 10  ")    ' store msg in the EEPROM memory
EEPROM $B0, ("This is msg 11  ")    ' store msg in the EEPROM memory
EEPROM $C0, ("This is msg 12  ")    ' store msg in the EEPROM memory
EEPROM $D0, ("This is msg 13  ")    ' store msg in the EEPROM memory
EEPROM $E0, ("This is msg 14  ")    ' store msg in the EEPROM memory
' Locations $F0 - $FF (240d to 255d) miscellaneous use
Symbol eOLEDFirstRowAddr = $F0      'Start of OLED Screen RAM Pointer Lookup table
'Zie spreadsheet EEPROM eOLEDFirstRowAddr, Start position of each LCD row.xls:
EEPROM eOLEDFirstRowAddr, ($80, $94, $A8, $BC)' Start position of each OLED/LCD row	: 20x4
"#Define use_LCD 'Note that this program does not contain code for 4-bit LCD initialisation."

I've a 20x4 LCD, how to modify code and what schematic connection have to be made?
 
Last edited:

hippy

Technical Support
Staff member
Another approach is to take some existing generic code such as LCD4_A below for an 18M2 ( which should work on an actual AXE133 ) and convert it for use with a 20X2 and the hardware interface which is going to be used with that LCD4_B ( which should match Inglewoodepete's hardware ).

That's Step 1, getting the 20X2 to control your hardware. It should work with anything from 16 x 2 displays up to 20 x 4 displays though it will not be using all characters or all four lines.

Step 2 in the next post.
 

Attachments

hippy

Technical Support
Staff member
Now Step 2. Update LCD4_B to LCD4_C which can work with SERIN data. It won't be great if you try running it, you can only send one byte at a time and will need delays between the bytes because it's slow to be ready for the next SERIN but it should work, though I haven't tested it.

Unnecessary code has been removed, and it only supports sending a character to display or a byte command prefixed by 254.

Then update LCD_C to LCD_D which uses background receive rather than SERIN.

Then you can add another other functionality you might need.
 

Attachments

Haroen

Member
Sorry, none of the above code worked :(

Couldn't find what the solution was, so I worked out my own code based on the 18M2 lcd driver.
Code:
; AXE134 Serial 20x4 OLED using PICAXE-20X2 instead of 18M2!
; .---------------------------------------------.
; |    Hardware connection definition           |
; `---------------------------------------------'
;                20X2
;            .----__----.
;            | V+    0V |
;            | SI    SO |
;  LCD RS -->| C.7  B.0 |--> LCD D0
;   SERIN -->| C.6  B.1 |--> LCD D1
;   LCD E <--| C.5  B.2 |--> LCD D2
;            | C.4  B.3 |--> LCD D3
;            | C.3  B.4 |--> LCD D4
;            | C.2  B.5 |--> LCD D5
;            | C.1  B.6 |--> LCD D6
;            | C.0  B.7 |--> LCD D7
;            `----------'

#picaxe 20X2
SetFreq m16

; Supported Commands
; 0-7, 8-15	CGRAM characters
; 16-252	normal ASCII characters, according to selected character map table
; 253, X	display 12 character pre-saved message from EEPROM memory, X can be 0-11
; 254, X	OLED command, X can be 0 to 255 
; 255, X	control outputs C.2, C.1, C.0 (via lower 3 bits of X)

#define use_welcome							; display the welcome message upon power up

symbol baud = N2400_16						; Serial baud rate 2400,N,8,1. Note main program runs at 16MHz otherwise Pause-command will shorten pause for LCD processing!

let dirsC = %10111111						; PortC 0,1,2,3,4,5,7 all outputs
symbol spare0 	= C.0 						; spare output 0
symbol spare1 	= C.1 						; spare output 1
symbol spare2 	= C.2 						; spare output 2
symbol RX		= C.6							; serial receive pin
symbol enable 	= C.5							; OLED enable
symbol rs 		= C.7							; OLED RS 

; OLED data pins are on B.0 to B.7

; Store the 20 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; Please remember 4 line displays always use the strange 1-3-2-4 line layout.

EEPROM  00, ("  Serial 20x4 OLED  ") 	; store msg 0 in the EEPROM memory
EEPROM  20, ("   www.picaxe.com   ") 	; store msg 1 in the EEPROM memory
EEPROM  40, ("This is msg 2       ") 	; store msg 2 in the EEPROM memory
EEPROM  60, ("This is msg 3       ") 	; store msg 3 in the EEPROM memory
EEPROM  80, ("This is msg 4       ") 	; store msg 4 in the EEPROM memory
EEPROM 100, ("This is msg 5       ") 	; store msg 5 in the EEPROM memory
EEPROM 120, ("This is msg 6       ") 	; store msg 6 in the EEPROM memory
EEPROM 140, ("This is msg 7       ") 	; store msg 7 in the EEPROM memory
EEPROM 160, ("This is msg 8       ") 	; store msg 8 in the EEPROM memory
EEPROM 180, ("This is msg 9       ") 	; store msg 9 in the EEPROM memory
EEPROM 200, ("This is msg 10      ") 	; store msg 10 in the EEPROM memory
EEPROM 220, ("This is msg 11      ") 	; store msg 11 in the EEPROM memory

;initialise OLED
init:
	gosub OLED_init							; initialise OLED

; display welcome message if desired
#ifdef use_welcome	
	let b1 = 0									; message 0 on top line
	gosub msg									; do it
	low rs										; command mode
	let pinsB = 192							; move to line 2, instruction 192
	pulsout enable,1  						; pulse the enable pin to send data.
	high rs										; character mode again
	let b1 = 1 									; message 1 on bottom line
	gosub msg									; do it
#endif


; main program loop, runs at 16MHz
main:
	serin RX,baud,b1							; wait for the next byte
	; NB keep character mode test as first item in this list to optimise speed
	if b1 < 253 then
		let pinsB = b1 						; output the data
		pulsout enable,1  					; pulse the enable pin to send data.
		goto main								; quickly loop back to top
	else if b1 = 254 then
		low rs 	     							; change to command mode for next character
		serin RX,baud,b1						; wait for the command byte
		let pinsB = b1 						; output the data
		pulsout enable,1  					; pulse the enable pin to send data.
		high rs									; back to character mode
		goto main								; quickly loop back to top
	else if b1 = 253 then
		serin RX,baud,b1						; wait for the next byte
		gosub msg								; do the 16 character message
		goto main								; back to top
	else ; must be 255
		serin RX,baud,b1						; wait for the next byte
		let pinsC = b1 & %00000111 | %10000000	; output the data on C.0 to C.1, keep RS high
		goto main								; back to top
	end if


; power on OLED initialisation sub routine
OLED_init:
	let dirsB = %11111111					; PortB all outputs
	; Winstar OLED Module Initialisation
	; according to WS0010 datasheet (8 bit mode)
	pause 500 									; Power stabilistation = 500ms
	; Function set - select only one of these 4 character table modes
	;let pinsB = %00111000 	; 8 bit, 2 line, 5x8 , English_Japanese table
	let pinsB = %00111001 	; 8 bit, 2 line, 5x8 , Western_European table1
	;let pinsB = %00111010 	; 8 bit, 2 line, 5x8 , English_Russian  table
	let pinsB = %00111011 	; 8 bit, 2 line, 5x8 , Western_European table2
	pulsout enable,1  	; 
	let pinsB = %00001100					; Display on, no cursor, no blink
	pulsout enable,1 	
	let pinsB = %00000001 					; Display Clear
	pulsout enable,1
	pause 7										; Allow 6.2ms to clear display
	setfreq m16									; now change to 16Mhz
	let pinsB = %00000010 					; Return Home
	pulsout enable,1
	let pinsB = %00000110 					; Entry Mode, ID=1, SH=0
	pulsout enable, 1
	high rs										; Leave in character mode
Return


; display message from EEPROM sub routine
; message number 0-11 must be in b1 when called
; uses (alters) b1, b2, b3, b4
msg:
	let b2 = b1 // 12 * 20					; EEPROM start address is 0 to 11 multiplied by 20
	let b3 = b2 + 20 - 1 					; end address is start address + (20 - 1)
	for b4 = b2 to b3							; for 20 times
		read b4,b1								; read next character from EEPROM data memory into b1
		let pinsB = b1 						; output the data
		pulsout enable,1  					; pulse the enable pin to send data.
	next b4										; next loop
Return
Now it almost looks like the intro text but scrambled,

"Serial 20x4 OLED" -> ""Sgrkcn"22z6"ONGF""
"www.picaxe.com" -> """www.rkcczg.coo"

see picture.
ScrambledText.jpg

Display speeds are insufficiently slow!
The use of Serin makes massage more scrambled.

What's wrong here?
 

hippy

Technical Support
Staff member
Display speeds are insufficiently slow!
The use of Serin makes massage more scrambled.

What's wrong here?
It could be that the code is using 2400 baud, a faster buad rate will speed things up.

The display will be getting scrambled if you are sending data quicker than the PICAXE can keep up.

The original AXE133 code was written to work with an 18M2 and there may be differences in execution timing when using another PICAXE. In particular there is output pin mapping which needs to be done on the 20X2 to place all B.x pins on one side of the chip and this can take longer than it does on the 18M2. It's not a massive difference but could be enough to affect the timing.

Don't worry about speed to start with. Get it working when data is sent to it a byte at a time; that will prove the code works and the hardware is correct. Then you can set about improving the speed, moving to using background serial.

If wanting to use background serial, the first step after proving the hardware works would be to modify the hardware and code so the 'hserin' pin is available for input.
 

marks

Senior Member
Hi Haroen,
after another quick look at displayed characters on your lcd
it would seem like DB1 on the lcd is remaining high causing your problem !
so check for a hardware or wiring problem.
 

Haroen

Member
I will certainly try using the 20x2 9600Bps/Hi2C link later to speed things up, thanks for that link Marks ;)

I've tried baud 1200 and even SetFreq m8 to slow things down and reduce timing difference, NO result.
I've tried OLED_init with English_Japanese, English_Russian, Western_European table, NO result.

As Hippy sugested I've stripped the code to analysed the problem and found that Marks was right about pin DB1 remaining high but turns out also DB2!
There was no wiring problem and than tested the pins I/O's with some demo code and was ok.
So 20X2 chip seems to be ok.

Looks like my code conversion from 18M2 to 20X2 has a bug?!
So where in the code are DB1 and DB2 pulled high?
 

hippy

Technical Support
Staff member
Looks like my code conversion from 18M2 to 20X2 has a bug?!
So where in the code are DB1 and DB2 pulled high?
I hadn't fully appreciated that the scrambled data was in the showing of the default messages, but marks noted that and identified the problem.

There does not appear to be a bug in your code; it simulates fine and does not set DB1 or DB2 high other than where it seems it is meant to during initialisation.

The "let pinsB = b1" in the 'msg' routine shows the correct character data is being output to the LCD so it would seem that DB1 and DB2 being high and corrupting those characters is a hardware or wiring issue.

It could however be a timing issue when controlling the LCD so it would be worth commenting out the two SETFREQ commands ( at the start of the code and towards the end of OLED_Init ) to see if that improves the display and removes corruption.

It might also be worth replacing that OLED_Init code with the initialisation sequence which would be used with an LCD as that may be causing issues when initialising your LCD.
 

marks

Senior Member
Hi Haroen,
I've seem to recall there being a problem with early firmware C0 on the 20x2picaxe.

try changing
let pinsb = b1

too
outpinsb = b1
 

hippy

Technical Support
Staff member
As Hippy sugested I've stripped the code to analysed the problem and found that Marks was right about pin DB1 remaining high but turns out also DB2!
There was no wiring problem and than tested the pins I/O's with some demo code and was ok.
I double-checked and compared what should have been shown with what was shown and the problem appears to be that DB1 to the LCD is permanently high as marks noted in post #13, all other DB pins seem to be what they should be.

That would seem to confirm there is no issue with using "pinsB=" on your chip, and that the problem is external to the PICAXE.

Check the wire from LCD DB1 does go to B.1 on the 20X2 hasn't got connected to something else.

If there is a short, solder splash or some hardware issue, it may be at the LCD end rather than at the PICAXE end. It might be worth checking the wire for DB1 is not broken, is securely soldered on the LCD, as that might cause it to float and be seen as 1.

Code:
Should be        Shown      .---- Always 1
     76543210         76543210
' ' %00100000    '"' %001000[b]1[/b]0
' ' %00100000    '"' %001000[b]1[/b]0
's' %01110011    's' %011100[b]1[/b]1
'e' %01100101    'g' %011001[b]1[/b]1
'r' %01110010    'r' %011100[b]1[/b]0
'i' %01101001    'k' %011010[b]1[/b]1
'a' %01100001    'c' %011000[b]1[/b]1
'l' %01101100    'n' %011011[b]1[/b]0
' ' %00100000    '"' %001000[b]1[/b]0
'2' %00110010    '2' %001100[b]1[/b]0
'0' %00110000    '2' %001100[b]1[/b]0
'x' %01111000    'z' %011110[b]1[/b]0
'4' %00110100    '6' %001101[b]1[/b]0
' ' %00100000    '"' %001000[b]1[/b]0
'O' %01001111    'O' %010011[b]1[/b]1
'L' %01001100    'N' %010011[b]1[/b]0
'E' %01000101    'G' %010001[b]1[/b]1
'D' %01000100    'F' %010001[b]1[/b]0
' ' %00100000    '"' %001000[b]1[/b]0
 

Haroen

Member
Commenting out the two SETFREQ commands, no result.

These 20X2 of mine are from around 2011, don't know if firmware bug is present.
Tried "outpinsb = b1", no result.

Where to find the proper LCD_Init code to replace OLED_Init?
 

hippy

Technical Support
Staff member
As the issue is the LCD always seeing DB1 as high it is definitely a hardware issue.

As everything seems to be working apart from that from looking at what is on the display (albeit corrupted), it means you can forget SETFREQ, not worry about PICAXE firmware version, not worry about the initialisation.
 

Haroen

Member
Sorry Hippy, I've overlooked your post #17.
Ok, hardware it is!

I tested that LCDpin D1...
Without wires connected to it gives 5V.
I've tied only that LCDpin D1 HIGH and display message was the same as previous picture.
Then I tied only the LCDpin D1 LOW and display message was different...

mma,exaaip,uuu
DELM 4x00 laipeQ

The LCDdisplay seems to react on High and Low signals with this changed massage?
Call me stuborn but I hoocked up my osciloscope to LCDpin D1 and ground and saw pulses, BUT then when switching power ON and OFF voila:

"Serial 20x4 OLED"
"www.picaxe.com"

It works BUT WHY?
Now I turned OFF the power of my osciloscope and booted the project STILL it displays correctly!?
Removing the osciloscope clamps and the display is scrambled again!?
Magic? How can I create my PICAXE LCD project without the need to have my osciloscope connected to pinB.1-D1?
 

rossko57

Senior Member
That's exactly the kind of effect you get with bad connections when they are disturbed (by probing around). Look for dry solder joints, spread connector or IC socket pinholders, or (much less likely) flying wires broken within the PVC sleeves.
 

inglewoodpete

Senior Member
The fault suggests that the 0v ground connection is not complete between the OLED and the controller board. The signal return path is relying on the oscilloscope's ground connection.
 

Haroen

Member
The harder the battle the sweeter the victory!

After careful examination of my "Picaxe development board axe091" there were no malfunctions.
I really really really can't find bad connections, connector or IC socket pinholders, or wires broken within the PVC sleeves, dry solder joints :eek:

Came to the idea to try this code on a picaxe 28X2 and it worked!
And without oscilloscope hooked to it!
I think that this way I can exclude the LCD+header and wires out of the equation.
I don't want to lose so many LCD driver pins when I would use a 28X2 though, so really want to know what I do wrong.

I don't have any spare thd picaxe 20X2 to see if I blew up that B.1 pin somehow for this kind of code?
So, left me one other hard choice to desolder an existing working picaxe CNC unipolar driver project.:eek:
Tested this replacement 20X2 chip in my LCDdriver project and a few characters of rubish appeared?!:confused:

It's time for advise from George Michael "A different Corner": marks his previous post,...
http://www.picaxeforum.co.uk/showthr...-DISPLAY/page2, post#20!
* In the first 20X2 chip his code displays nothing, there is something wrong with that chip!
* In the desoldered 20X2 chip his code worked to display correct welcome text: "marks......"! :D

Now the serialOut or Hi2cOut from a 28X2 (converted code instead of a 18M2 from marks) has to send to the 20X2 display driver.
Changed code lines for serialOut or Hi2cOut ...
Code:
#picaxe 28X2
SETFREQ EM32
But the display stays on welcome message after sending?
Why doesn't it receive serin or i2c?
 
Last edited:

hippy

Technical Support
Staff member
Why doesn't it receive serin or i2c?
Hard to say without seeing your full program code and knowing exactly how you have wired things.

You could have things wired wrongly, connections to the wrong pins, crossed over bus lines for I2C or missing pull-ups, baud rate or polarity wrong or sending too quickly for serial.

It would also help to clarify if your LCD code is running on a 20X2 or 28X2, and confirm that displays data without corruption now, as it's not clear to me what you finally settled on.
 

Haroen

Member
I made the schematic of my test board:
Schematic tbv marks.jpg

*** Send chip ***
28X Serial out code:
Code:
#picaxe 28X2  											'Version 2.A * Testdrive  4bit/2X2 Serial driver * marks
SETFREQ EM32

#No_Table

main:
	serout B.5,N9600_32,(254,192)   				'Command Line 2 Cursor Position

	serout B.5,N9600_32,("* *   9600 bps..")

	serout B.5,N9600_32,(254,$21) 				'Control A0 high
	pause 4000

	serout B.5,N9600_32,(254,192)   				'Command Line 2 Cursor Position

	serout B.5,N9600_32,(" * *  9600 bps..") 

	serout B.5,N9600_32,(254,$20) 				'Control A0 low  
	pause 4000
goto main
OR

28X2 i2c out code:
Code:
#picaxe 28X2  								'Version 2.A * Testdrive  4bit/20x2 Hi2C driver * marks
SETFREQ EM32

HI2CSETUP I2CMASTER,%10100000,I2Cfast_32,I2Cbyte
pause 4000

main:
	HI2COUT 0,(254,192) 					'Command Line 2 Cursor Position
	pause 10
	HI2COUT 0,("*    Hi2C ABCDEF")
	pause 40
	HI2COUT 0,(254,$21) 					'Control A0 high
	pause 4000 								'15 minimum
	HI2COUT 0,(254,192)
	pause 10
	HI2COUT 0,(" *   Hi2C ABCDEF")
	pause 40
	HI2COUT 0,(254,$20) 					'Control A0 low
	pause 4000 								'15 minimum

	HI2COUT 0,(254,192) 					'Command Line 2 Cursor Position
	pause 10
	HI2COUT 0,("  *  Hi2C ABCDEF")
	pause 40
	HI2COUT 0,(254,$21) 					'Control A0 high
	pause 4000 								'15 minimum 
	HI2COUT 0,(254,192)
	pause 10
	HI2COUT 0,("   * Hi2C ABCDEF")
	pause 40
	HI2COUT 0,(254,$20) 					'Control A0 low
	pause 4000 								'15 minimum
goto main
*** Receive chip LCD driver ***
20X2 Serialin & i2c code:
Code:
'Default is 9600 serial mode.
'If we want Hi2C then power off and power on both boards together so it can catch the interupt before it gets into 9600 serial mode.

#picaxe 20X2 																												'Version C.0 * 20x2 LCD/OLED driver 4Bit (9600Bps or Hi2C fast/slow )* Written by marks!						
	#no_data
	#terminal off

'            SCK	   = B.7
'            SDA     = B.5
'            DB7     = B.3
'            DB6     = B.2
'            DB5     = B.1
'            DB4     = B.0

	SYMBOL E       = C.3
   SYMBOL RS      = C.2
   SYMBOL Rx      = C.7
	SYMBOL senddata = b0 : SYMBOL sentdata = b0
	SYMBOL index    = b1
	
	TABLE   0, ($3,$3,$3,$2,$2,$8,$0,$C,$0,$1,$0,$2,$0,$6)  													'(4Bit)(2line/5x8)(Display On)(Clear Display)(Return Home)(Entry Mode Set)
	TABLE  40, ("Display OK!")																							'Welcome message.
	
	SETFREQ M64
	HI2CSETUP I2CSLAVE, %10100000
 	dirsB = %00001111
 	dirsC = %10111111
 	SETINTFLAGS %01000000 , %01000000

IntialiseDisplay: 
   FOR index = 0 to 13
		READTABLE index, senddata : outpinsB = senddata : PULSOUT E,1 										'Initialise LCD/OLED 
	NEXT index  :  PAUSE 10
 	 	
Display:
   LOW RS                                                                                                                              
   senddata = 128 : outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1	'(128-147) Line 1 Cursor Position
   HIGH RS                                                                                                                              
               
   FOR index = 40 TO 50
		READTABLE index, senddata
 	   outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1						'sending characters to line one
 	   Pause 500
 	NEXT index



 Main:
	SERIN Rx,N9600_64,sentdata
   IF sentdata = 254 THEN Commands
   outpinsB = sentdata >> 4 : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1
 GOTO main



 Commands:
   SERIN Rx,N9600_64,sentdata
   outpinsB = sentdata >> 4
   IF outpinsB = $2 then Control
   LOW RS : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1 : HIGH RS
   GOTO Main

 Control:																													'Control with serial an output pin.
   SELECT CASE sentdata
	   Case  $20  Low A.0
	   Case  $21 High A.0
   END SELECT
   GOTO Main

 Hi2C:
	ptr = 0
	hi2cflag = 0
	HI2CSETUP I2CSLAVE , %10100000
	SETINTFLAGS %01000000 , %01000000

Interrupt:
	PAUSE 1000
	ptr = 0
	IF @ptrinc = 254 THEN CommandsHi2c
	FOR  ptr = 0 TO hi2clast
		outpinsB = @ptr >> 4  PULSOUT E,1 : outpinsB = @ptr  PULSOUT E,1
	NEXT ptr
	GOTO Hi2C

 CommandsHi2c:
	outpinsB = @ptr >> 4
	IF outpinsB = $2 THEN ControlHi2c
	LOW RS : PULSOUT E,1 : outpinsB = @ptr : PULSOUT E,1 : HIGH RS
	GOTO Hi2C

 ControlHi2c:																												'Control with Hi2c an output pin.
   SELECT CASE @ptr
	   Case  $20  Low A.0
	   Case  $21 High A.0
   END SELECT
   GOTO Hi2C
 

hippy

Technical Support
Staff member
Nothing jumps out as being particularly wrong to me. It would probably be best to get SERIN working before adding I2C. I would remove the interrupt routine, SETINTFLAGS, HI2CSETUP and I2C routines. I would also drop down to default operating speed and 2400 baud; get it working before trying to make it run faster.

As mentioned previously, if you send data to the 20X2 faster than it is ready to receive data you will get corruption or data might not display. Start with slower output in your sending program. For example, instead of -

serout B.5,N9600_32,(254,192)

Use ( at default speed, slower baud rate ) -

serout B.5, N2400, (254) : pause 10
serout B.5, N2400, (192) : pause 10
 

Haroen

Member
Send code sofar in the 28X2,
Code:
#picaxe 28X2  											'Version 2.A * Testdrive  4bit/2X2 Serial driver * marks
SETFREQ EM32

#No_Table

main:
 'Command Line 2 Cursor Position
 serout B.5, N2400, (254) : pause 10
 serout B.5, N2400, (192) : pause 10 
 serout B.5,N2400,("* *   2400 bps.."): pause 10

 'Control A0 high
 serout B.5, N2400, (254) : pause 10
 serout B.5, N2400, ($21):	pause 4000

 'Command Line 2 Cursor Position
 serout B.5, N2400, (254) : pause 10
 serout B.5, N2400, (192) : pause 10 
 serout B.5,N2400,(" * *  2400 bps.."):	pause 10

 'Control A0 low  
 serout B.5, N2400, (254) : pause 10
 serout B.5, N2400, ($20):	pause 4000
goto main
LCDdriver code without i2c,
Code:
#picaxe 20X2 																												'Version C.0 * 20x2 LCD/OLED driver 4Bit (9600Bps or Hi2C fast/slow )* Written by marks!						
	#no_data
	#terminal off

'            SCK	   = B.7
'            SDA     = B.5
'            DB7     = B.3
'            DB6     = B.2
'            DB5     = B.1
'            DB4     = B.0

	SYMBOL E       = C.3
   SYMBOL RS      = C.2
   SYMBOL Rx      = C.7
	SYMBOL senddata = b0 : SYMBOL sentdata = b0
	SYMBOL index    = b1
	
	TABLE   0, ($3,$3,$3,$2,$2,$8,$0,$C,$0,$1,$0,$2,$0,$6)  													'(4Bit)(2line/5x8)(Display On)(Clear Display)(Return Home)(Entry Mode Set)
	TABLE  40, ("Display OK!")																							'Welcome message.
	
	SETFREQ M64
;	HI2CSETUP I2CSLAVE, %10100000
 	dirsB = %00001111
 	dirsC = %10111111
; 	SETINTFLAGS %01000000 , %01000000

IntialiseDisplay: 
   FOR index = 0 to 13
		READTABLE index, senddata : outpinsB = senddata : PULSOUT E,1 										'Initialise LCD/OLED 
	NEXT index  :  PAUSE 10
 	 	
Display:
   LOW RS                                                                                                                              
   senddata = 128 : outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1	'(128-147) Line 1 Cursor Position
   HIGH RS                                                                                                                              
               
   FOR index = 40 TO 50
		READTABLE index, senddata
 	   outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1						'sending characters to line one
 	   Pause 500
 	NEXT index



 Main:
	SERIN Rx,N2400,sentdata
   IF sentdata = 254 THEN Commands
   outpinsB = sentdata >> 4 : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1
 GOTO main



 Commands:
   SERIN Rx,N2400,sentdata
   outpinsB = sentdata >> 4
   IF outpinsB = $2 then Control
   LOW RS : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1 : HIGH RS
   GOTO Main

 Control:																													'Control with serial an output pin.
   SELECT CASE sentdata
	   Case  $20  Low A.0
	   Case  $21 High A.0
   END SELECT
   GOTO Main

; Hi2C:
;	ptr = 0
;	hi2cflag = 0
;	HI2CSETUP I2CSLAVE , %10100000
;	SETINTFLAGS %01000000 , %01000000

;Interrupt:
;	PAUSE 1000
;	ptr = 0
;	IF @ptrinc = 254 THEN CommandsHi2c
;	FOR  ptr = 0 TO hi2clast
;		outpinsB = @ptr >> 4  PULSOUT E,1 : outpinsB = @ptr  PULSOUT E,1
;	NEXT ptr
;	GOTO Hi2C

; CommandsHi2c:
;	outpinsB = @ptr >> 4
;	IF outpinsB = $2 THEN ControlHi2c
;	LOW RS : PULSOUT E,1 : outpinsB = @ptr : PULSOUT E,1 : HIGH RS
;	GOTO Hi2C
;
; ControlHi2c:																												'Control with Hi2c an output pin.
;   SELECT CASE @ptr
;	   Case  $20  Low A.0
;	   Case  $21 High A.0
;   END SELECT
;   GOTO Hi2C
When powered the text "Display OK!" appears and then nothing!?
The transmitted text "* * 2400 bps.." doesn't appear at all...
 

marks

Senior Member
Hi Haroen,
Make use of the serial terminal to check you are using the correct baud!
if you are using a 4mhz resonator your speed is only em16

in any case start by using the internal frequency,s
here's an example to use the terminal to check.

Code:
#picaxe 28X2
#terminal 9600
SETFREQ M8

#No_Table

main:
	serout A.4,N9600_8,(254,192)   				'Command Line 2 Cursor Position

	serout A.4,N9600_8,("* *  marks bps..")

	
	pause 1000

	serout A.4,N9600_8,(254,192)   				'Command Line 2 Cursor Position

	serout A.4,N9600_8,(" * *  9600 bps..") 

	
	pause 1000
goto main
 

hippy

Technical Support
Staff member
serout B.5,N2400,(" * * 2400 bps.."): pause 10

That may be sending too fast for the LCD firmware to keep up with. You may need to send each byte with a suitable delay -

serout B.5,N2400,(" ") : pause 10
serout B.5,N2400,("*") : pause 10
serout B.5,N2400,(" ") : pause 10
serout B.5,N2400,("*") : pause 10
serout B.5,N2400,(" ") : pause 10
serout B.5,N2400,("2") : pause 10
serout B.5,N2400,("4") : pause 10
etc

Also, N2400 won't send at 2400 baud when using SETFREQ EM32, and nor will N2400 receive at 2400 when using SETFREQ M64 in the receiver.

Run the transmitter and receiver at their default operating speeds to start with. Worry about getting things faster once we have the transmitter and receiver code working.

I am not convinced your "command" / "control" handling in the receiver is correct. I would also remove that. And I would start with far simpler sending code -

Code:
#Picaxe 28X2
Pause 5000
Do
  SerOut B.5, N2400, ( "X" )
  Pause 500
Loop
That should slowly but eventually fill all character positions on the LCD with X's.
 

hippy

Technical Support
Staff member
Also, your initialisation routine seems to be potentially broken. Though it may seem to be working it may not actually be initialising properly -

Code:
TABLE  0,($3,$3,$3,$2,$2,$8,$0,$C,$0,$1,$0,$2,$0,$6) 

IntialiseDisplay: 
FOR index = 0 to 13
  READTABLE index, senddata : outpinsB = senddata : PULSOUT E,1
NEXT index  :  PAUSE 10
That's not providing any delay after sending initialisation nibbles and bytes, and for $0,$1 ( $01), screen clear, that can take a good few milliseconds to execute.
 

marks

Senior Member
Hi Haroen,
because the driver is 4 bit there is plenty of delay in the code
but hippy is correct for 8bit driver this would need to be checked.
I've added some working examples checked using a 40x2 at post #43
hopefully this will work the same on the 28x2
http://www.picaxeforum.co.uk/showthread.php?19474-Learning-to-Drive-an-LCD-DISPLAY/page5
it was a quick cut n paste but does work,I left my new w10 Pc for a few min
bugger me it rebooted and installed updates closed pe6 and didn't save what I was doing.
In future I'll save before I leave my PC lonely
your circuit could do with a bit more decoupling
hope you get thinks sorted cheers.
 

Haroen

Member
Marks post #28...
Totally forgot to check the correct baud versus SETFREQ :eek:
I tested the circuit on the "Picaxe development board axe091" where the resonator isn't a 4mhz as I incorrectly had drawn in my previous schematic :eek:
I used the terminal to check the serout and now was OK on the PE6 screen ("* * marks bps..", " * * 9600 bps..") but the LCD display was somewhat scrambled.

Hippy post #29...
Filling all character positions code on the LCD with X's worked.
Sending each byte with a suitable delay was working and now I've unscrambled text displayed, :cool:
But how to send something like:
* SerOut A.4, N9600, ( "Temperature=") ? or better
* SerOut A.4, N9600, ( "Temperature=", b1, "°C") ?

Hippy post #30...
Initialisation routine by Marks was meant for "(4Bit)(2line/5x8)(Display On)(Clear Display)(Return Home)(Entry Mode Set)" and my display should be 4 lines.
So what to change for 4 lines in "TABLE 0,($3,$3,$3,$2,$2,$8,$0,$C,$0,$1,$0,$2,$0,$6)" ?

Marks post #31...
Thanks for separating Serial and Hi2C code that I have yet to try.
(BTW, I've automatic Windows updates=Off for exactly that problem you have had. Locked out Bill Gates.)
 

marks

Senior Member
Hi Haroen ,
this is turning into a 101 workshop lol!

most lcd's have 2line controllers (40 characters a line)
the same initialization is used on 20x4 lcd's (4line)

line3 is a continuation of line1
line4 is a continuation of line2

display corruption can be caused from supply, reprogramming etc
power on again to reset initialization we can also try to code this out.
it is likely in this case caused by reusing pin a.4 which is also the serial out pin which would be better not to use.

here we will write some bad code to get around it you'll also likely have to power off and on.
usually I just rewrite locations that need changing
we can write over the corrupted characters by sending all lines again 20 +20+20+20
you can also check what version picaxe you have by selected (check picaxe type connected)
it is also quickly shown after programming a chip.(hopefully yours supports M16)
Code:
#picaxe 28x2  ' version B.3 * Testdrive  4bit/20x2 9600 driver haroen
#no_data
SETFREQ M16
PAUSE 2000

SYMBOL DS18B20 = C.0				                  
 SYMBOL senddata     = pinsb
 SYMBOL index        = b0		   
 SYMBOL Temperature  = W1  SYMBOL TempMsb   = b3  SYMBOL TempLsb  = b2
 SYMBOL T            = W2  
 SYMBOL Sign         = b9
 SYMBOL D0           = b10
 SYMBOL D1           = b11 
 SYMBOL D2           = b12 
 SYMBOL D3           = b13 
 SYMBOL D4           = b14

Main:

serout a.4,n9600_16,(254,128)   ' Command Line 1 Cursor Position (128-147)

serout a.4,n9600_16,("                    ")
              
serout a.4,n9600_16,(254,192)   ' Command Line 2 Cursor Position (192-211)

serout a.4,n9600_16,("Temperature today   ") 


ConvertTemperature:
  ReadTEMP12 DS18B20,T
  
       Temperature = T                                        
       Sign = " "                                                    ' Display +   
     IF TempMsb > 127 THEN                       
       Sign = "-"                                                    ' Display - 
       Temperature = - Temperature                                    
     ENDIF 
            Temperature = Temperature *8**51200+5                    ' Celsius(-55.0?C to 125.0?C)rounded up
                  BinTOASCII Temperature,D4,D3,D2,D1,D0 
                  IF  D4 = "0" THEN : D4 = Sign                      ' leading zero blanking 
                   IF D3 = "0" THEN : D3 = Sign : D4 = " " : ENDIF   ' leading zero blanking 
                  ENDIF 
    DisplayTemperature:
            serout a.4,n9600_16,(254,148)   ' Command Line 3 Cursor Position (148-167)
             serout a.4,n9600_16,(D4,D3,D2,".",D1,223,"C             ") 

    ConvertTemperatureF:
        Temperature = T                                    
       Sign = " "                                                    ' Display +
       Temperature = Temperature +880 *16**46080 -6700               ' Fahrenheit(-67.0?F to 257.0?F)rounded up   
     IF TempMsb > 127 THEN                       
       Sign = "-"                                                    ' Display - 
       Temperature = - Temperature                                    
     ENDIF    
       Temperature =   Temperature +5                                                   
                  BinTOASCII Temperature,D4,D3,D2,D1,D0 
                  IF  D4 = "0" THEN : D4 = Sign                       ' leading zero blanking 
                   IF D3 = "0" THEN : D3 = Sign : D4 = " " ENDIF      ' leading zero blanking 
                  ENDIF 
    DisplayTemperatureF:
            serout a.4,n9600_16,(254,212)   ' Command Line 4 Cursor Position (212-231)
             serout a.4,n9600_16,(D4,D3,D2,".",D1,223,"F             ") 
                                    
GOTO main
 

hippy

Technical Support
Staff member
But how to send something like:
* SerOut A.4, N9600, ( "Temperature=") ? or better
* SerOut A.4, N9600, ( "Temperature=", b1, "°C") ?
You can only achieve that using SERIN when the receiving code is executing fast enough to be ready for each byte sent. When driving an LCD in 4-bit mode that is going to be difficult, even if the baud rate is reduced. Even when driving the LCD in 8-bit mode it may be difficult if the DB0-DB7 pins are not on the same port.

The solution is to forget SERIN and use HSERIN background receive. That allows the PICAXE to receive at a fast rate while processing what is received at a slower rate.
 

marks

Senior Member
If your able to keep you driver code efficient enough a 20x2 @ 64mhz can easily keep up with N9600_16 baud.

SENDING PICAXE
Code:
#picaxe 40x2  ' version B.3 * Testdrive  4bit/20x2 9600 driver 
'#picaxe 18m2  ' version 2.D 
#no_data
low c.1                        ' sometimes required to prevent corruption of first serout bytes
SETFREQ M16                     ' or M8 for N9600_8 can be used
PAUSE 3000                      ' allow some time for driver to complete

Main:

serout c.1,n9600_16,(254,1)     ' Clear All
 pause 1                        ' sometimes required for clear and home to stop missing characters in next line
                                ' if other commands for outputs or messages are created you will need to work the pause required after it.
					  
serout c.1,n9600_16,(254,128)   ' Command Line 1 Cursor Position (128-147)
serout c.1,n9600_16,("Line 1    128 to 147") 

serout c.1,n9600_16,(254,192)   ' Command Line 2 Cursor Position (192-211)
serout c.1,n9600_16,("Line 2    192 to 211") 

pause 8000
serout c.1,n9600_16,(254,1)     ' Clear All
 pause 1                        ' sometimes required for clear and home to stop missing characters in next line


serout c.1,n9600_16,(254,148)   ' Command Line 3 Cursor Position (148-167)
serout c.1,n9600_16,("Line 3    148 to 167") 

serout c.1,n9600_16,(254,212)   ' Command Line 4 Cursor Position (212-231)
serout c.1,n9600_16,("Line 4    212 to 231") 

pause 8000
GOTO main
I guess what needs to be realised if we 're sending N9600_32 this may be too fast and will be likely to see problems.
and slower than N9600_8 may also not be reliable.

DRIVER 20X2 PICAXE
Code:
#picaxe 20X2   '  versions C.0 C.1 C.3    *LCD/OLED driver 4Bit (9600Bps)* marks						
#no_data       '    .-----_-----.
#terminal off  '    | V+     0V |
pause 400      ' -->| SI     SO |--> a.0 Control output
'       Rx N9600 -->| C.7   B.0 |--> LCD DB4
'  (10K pulldown)   | C.6   B.1 |--> LCD DB5
'                   | C.5   B.2 |--> LCD DB6
'                   | C.4   B.3 |--> LCD DB7
'         LCD E  <--| C.3   B.4 |
'         LCD RS <--| C.2   B.5 |
'                   | C.1   B.6 |
'                   | C.0   B.7 |
'                   '-----------'  				                  
     	SYMBOL Rx     = C.7
	SYMBOL E      = C.3
	SYMBOL RS     = C.2
	SYMBOL senddata = b0 : SYMBOL sentdata = b0 		
	SYMBOL index    = b4
	
	TABLE   0, ($3,$3,$3,$2,$2,$8,$0,$C,$0,$1,$0,$2,$0,$6)  '(4Bit)(2line/5x8)(Display On)(Clear Display)(Return Home)(Entry Mode Set)
	TABLE  40, ("marks......")
		
	SETFREQ M64	
 	dirsB = %00001111			
 	dirsC = %10111111
 								
IntialiseDisplay: 
      FOR  index = 0 to 13                                               
READTABLE index, senddata : outpinsB = senddata : PULSOUT E,1 ' Initialise LCD/OLED 
 	NEXT index  :  PAUSE 10	
 	 	
Display:
      LOW RS                                                                                                                              
      senddata = 128 : outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1'(128-147) Line 1 Cursor Position
      HIGH RS                                                                                                                              
               
      FOR index = 40 TO 50                                                   
READTABLE index, senddata 
 	   outpinsB = senddata >> 4 : PULSOUT E,1 : outpinsB = senddata : PULSOUT E,1 ' sending characters to line one
 	   pause 500     
 	NEXT index
                                   
 Main:
  SERIN Rx,N9600_64,sentdata
   IF sentdata = 254 THEN Commands
   outpinsB = sentdata >> 4 : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1
   GOTO main
   
 Commands:
   SERIN Rx,N9600_64,sentdata
    outpinsB = sentdata >> 4 
    IF outpinsB = $2 then Control 
    LOW RS : PULSOUT E,1 : outpinsB = sentdata : PULSOUT E,1 : HIGH RS
    GOTO Main
    
 Control: 
    SELECT CASE sentdata
    case  $20  low a.0
    case  $21 high a.0
    END SELECT
    GOTO Main
I have had no issues with the displays that I've used LCDs or Oled.
 
Last edited:

marks

Senior Member
Hi Hareon,
I've updated my code to use the hardware serial dedicated pins which I've posted.
I must admit even 9600 runs quicker and will probably make it easier to interface with the range of other picaxes without fine tuning lol.
its hard to reason why an lcd needs to be so quick. but am tempted to try 115200 one day to try 20x2multiplex7segment without seeing it update.
time to put my 40x2 away and do my tax .
 

Haroen

Member
Sorry all for taking so long to get it up and running in this workshop, lol.
I learn a lot that I didn't knew before!

Just to eliminate hardware connections I made a small 20X2 smd LCDdriver fan-out-board and added some caps in the posted schematic also connected new wires.
20X2 smd LCDdriver.jpg
These 20X2 smd chips where never before used or programmed (to eliminate corrupted parts) and have PICAXE version vC.2.
The thd 20X2 chips that I start using on this topic on the "Picaxe development board axe091" where versions vC.0 and vC.2!
I don't know what the newest 20X2 version is?
The result is just the same scrambled display text.

Using pin C.1 instead of A.4 or writing over the corrupted characters by sending all lines again did not help.
Code from inglewoodpete #1 and also modified later in this post doesn't work.

I upgraded my PE6 from 6.0.8.8 to 6.0.8.11, still scrambled text.

Marks #36 verified example code also scrambled display text!

I now give up Serout and switch to i2c testing...
 

hippy

Technical Support
Staff member
I now give up Serout and switch to i2c testing...
It is very hard for others to help if you do not post all the code you are using, do not show your hardware connection scheme, and do not detail how the fault manifests itself; whether the initial 'welcome' message is corrupted or only data sent from the controlling PICAXE is corrupted.
 

inglewoodpete

Senior Member
Code from inglewoodpete #1 and also modified later in this post doesn't work.

I upgraded my PE6 from 6.0.8.8 to 6.0.8.11, still scrambled text.

Marks #36 verified example code also scrambled display text!
If both marks' and my (inglewoodpete's) code don't work then it suggests you have a wiring fault (bad connection on one or more wires).

Can you post the (modified) code for my version of the driver chip (or, if already posted, indicate which post it is in), and I'll have a deeper look at over the coming weekend. I will also need a link (URL) to a copy of your 4-row, 20-column LCD's datasheet to better understand the configuration and addressing of each character position.
 
Top