Parallel LCD with 20M2 C.x pins

Bryang

Member
Hi all,
I've got a 20x4 LCD running parallel with a 20M2. I've done a few 40X2's & 18X's parallel before, without too many issues, using B.4=DB4, B.5=DB5, B.6=DB6, & B.7=DB7 of the 40X2 so works basically as per the Picaxe Manual-3 as is, but this time I needed to configure the LCD to the LHS of the 20M2 pic, whereby C.4=DB4, C.3=DB5, C.2=DB6, & C.1=DB7.

So, I figured that to match the nibble pulseouts to the correct LCD pins, I had to reverse the binary number and then shift it one up on the pic...
eg: the letter "T" is %01010100, so this becomes %00101010 but pulsing it as is, it wont align to C1-C4, so shifting it up (*2) will align it (now high nibble is 01010 & low nibble is 01000) and then I use a mask %00011110.

It might make more sense if you look at the code?

... but, I just get the infamous 1st & 3rd lines showing blocks! I've tried hard coding a few binary numbers for the characters instead of calculating, and sometimes I get lines 2 & 4 as 1/2 blocks (as well as lines 1 & 3 full blocks!) So I'm sure it's something in the code & not the wiring, but probably not seeing the forest for the trees!

It's annoying me, so am determined to not re-wire it to the RHS of the PIC or to use serial, as no doubt it's something simple!
Does anybody spot anything obvious?
 

Attachments

PhilHornby

Senior Member
I'm not very good at debugging in my head, but is this the culprit?
Rich (BB code):
spin:    (abbreviated)
      Hinib = w3 / 8 & %00011110    'high nibble 
return

      gosub spin
      high C.7          'C.7=RS RS on the LCD sets it to "instruction" when low & "character" when high
      let pinsC = Hinib
i.e high C.7 is immediately overridden by the let PinsC = Hinib
 

Bryang

Member
Thanks Phil, You might be right, plus I think I've made a mess of the LCD Reset (initialise) subroutine!
Needing matchsticks to hold open my eyes at present, so will tackle them tomorrow & report back :)
 

westaust55

Moderator
Since you are seeing blocks are the characters on the first (and 3rd) lines the usual culprit is incorrect initialisation code.
 

hippy

Technical Support
Staff member
I would remove the 'spin:' routine and completely write 'wrins:' and 'wrchr:' from scratch, and also use 'b0' to hold the charcater byte value to output. Then you can use something like -

Code:
pinC.1 = bit7 ; Put out high nibble
pinC.2 = bit6
pinC.3 = bit5
pinC.4 = bit4
Code:
pinC.1 = bit3 ; Put out low nibble
pinC.2 = bit2
pinC.3 = bit1
pinC.4 = bit0
 

Bryang

Member
lol... I think what you're saying throw away my code attempt is start again from scratch with the basics! & you are probably right ;-)
Question on the basics though...
going back to the example in manual-3, for example the line let pins = 48, then pulsout... so this is the equivalent on the PortB as let pinsB=%00110000 : ... means that B.7 & B.6 are low, B.5 & B.4 are high, then B.3-B.0 are low.
So this means per the manual-3, what we are doing is pulsing to the LCD DB4 & DB5. yes?
So later in the initialise code it has let b1=14 : gosub wrins
14 is %00001110, So this is then pulsing low (0000) to DB7-DB4, the pulsing high to DB7-DB5 & low to DB4. Correct?.

Have I got this worked out in my head correct? Maybe I'm just missing something really basic!
 

inglewoodpete

Senior Member
So this means per the manual-3, what we are doing is pulsing to the LCD DB4 & DB5. yes?
So later in the initialise code it has let b1=14 : gosub wrins
14 is %00001110, So this is then pulsing low (0000) to DB7-DB4, the pulsing high to DB7-DB5 & low to DB4. Correct?.
Basically, when using either 4- or 8-bit data transfers to the LCD, you:
(1) Apply the required data to the LCD data pins (DB7-DB4 for 4-bit or DB7-DB0 for 8-bit) and then
(2) Apply a brief pulse to the LCD's enable pin.
Preceding those two steps, you need to set or clear the command/data input pin on the LCD to steer the 4 or 8 bits of data to (a) the LCD command register (configuration of the LCD and placing the cursor) or (b) the data register to display a byte.

Your problem appears to be that you are not using the so-called 'standard' PICAXE pins for connecting to the data pins of the LCD.

A few years ago I posted Universal Test Code for all Parallel Bus Alphanumeric LCD Configurations, which is ideally suited to your situation. hippy's suggestion in post #5 mirrors the method I used in that code example. I suggest that my code would provide an ideal software solution for your hardware.

Basically, all you have to do is take a copy of my code, change the #PICAXE definition to your 20M2 and then change the 6 "Symbol" definitions near the top of the code to suit your hardware interconnect and download it to your hardware. It will work!
 

hippy

Technical Support
Staff member
A few years ago I posted Universal Test Code for all Parallel Bus Alphanumeric LCD Configurations

Basically, all you have to do is take a copy of my code, change the #PICAXE definition to your 20M2 and then change the 6 "Symbol" definitions near the top of the code to suit your hardware interconnect and download it to your hardware. It will work!
I would recommend following that path.

I had overlooked that the example code in Manual 3 initialises the LCD by writing directly to the 'pins' variables so that must change as well as the 'wrins' and 'wrchr' routines.

That example code is how it is because it is optimised for the wiring shown in Manual 3 To change wiring to something else; you need to de-optimise the code, then make the changes you need, which is what inglewoodpete's code does for his alternative wiring.

Having dome that you can re-optimise but it is not really worth doing that these days because current PICAXE chips have more memory and support more GOSUB commands than the PICAXE's for which that Manual 3 example code was written.

Inglewoodpete's code has the de-optimisation already done so the only thing more which needs to be done is to change the SYMBOL definitions which define which PICAXE pins are used for each LCD signal.
 

Bryang

Member
...and it worked straight out of the box ;-) Thanks InglewoodPete.
I've thrown my code into the bin as Hippy suggested, and very comfortable developing Pete's code from his baseline :) Much appreciated.
 

Bryang

Member
I spoke to soon and tripped almost at the first hurdle... I cannot get text on the 2nd & 4th lines!

I use the same screen wired to a 40X2 picaxe, and the 2nd line works when I address it to 192, so it's not the screen.
In InglewoodPete's initialise code it has....

'Send a series of 8-bit commands to configure the LCD
b0 = %00110010 '$32 3rd Function Set, then 4-bit data, 2-line display
Gosub Cmd2LCD ' Send the command

... so by understanding the 20x4 LCD is in effect a 40x2 LCD, hence why using 128+20 takes me to the 3rd line, but just nothing with 192!

I've had a play changing the numbers it the init lines after going through a datasheet for HD447780 (I must admit, it was pushing the grey cells a bit!) and I also tried the numbers from the 40X2 code that works.
Curiously though, the 40X2 works with 4 lines with just %00110000, %00100000, %10000000 and %00001110 in the init section but when I just put these only into InglewoodPete's code, still no 2nd line!

Any suggestions?
 

lbenson

Senior Member
When you write 20 characters to line one, immediately write another 20 and see if they appear on the screen. Try that also for line 3. If nothing appears, write more than another 20--maybe it will show up somewhere.

Different LCDs have different layouts, but for a number I have seen, this has given me clues.
 

Bryang

Member
I tried that, incrimenting a number on the next location, but after filling lines 1 then 3, then a brief pause it went back to over-writing onto lines 1 then 3 again! That's when I went hunting for the HD44780 datasheet in case it was set to one line.... pretty sure it's not, but could still be wrong.
 

inglewoodpete

Senior Member
Firstly, I'm glad you managed to get your LCD to work. Unfortunately, I've never used anything but a 2 x 16 LCD (actually, several different types, including Rev-Ed's OLED).

It is quite some time since I played with LCDs. Comparing my demo code with the 2 or 3 data sheets that I have, it appears to be configured for a 1-row display. The way I read it today, bit 3 of the Function Set configuration command should be set for 2 line working, not clear.

At this point, my suggestion is to change the first command in the block of configuration commands as follows:

Code:
         'Send a series of 8-bit commands to configure the LCD
         b0 = %00111010               '$32 3rd Function Set, then 4-bit data, 2-line display
         Gosub Cmd2LCD                '    Send the command
Please report back. (I'm ready to have egg on my face :))
 

Bryang

Member
No egg.... with %00111010 I get a blank screen, no characters at all, not responding to 128 or 192 addresses! I'll keep trying :)
 

marks

Senior Member
Hi Bryang,
you are probably not allowing enough time for a previous command especially if your clearing a screen
here's another example to try.(quick edit from code snippet I posted)
Code:
#picaxe 20m2  '  4Bit Using Alternative pins marks
 SYMBOL DB7  = outpinC.1
 SYMBOL DB6  = outpinC.2
 SYMBOL DB5  = outpinC.3
 SYMBOL DB4  = outpinC.4
 SYMBOL E    = C.5  
 SYMBOL RS   = C.7  
 SYMBOL senddata  = b0
 SYMBOL index     = b1
      'value of count    = W1    ' b3,b2
      'display  count    = b4,b5,b6,b7,b8
     
      EEPROM 25,("Picaxe20M2")
      SETFREQ M32
  dirsB = %11111111
  dirsC = %10111111
 
Initialise:  
 FOR  index = 0 to 6
          LOOKUP index, ($33,$32,$28,$0C,$01,$02,$06),senddata : GOSUB Send    ' Initialise LCD/OLED
                       '(WakeUp)*3(Set4Bit)(4Bit/2Line)(DisplayOn)(Clear Display)(Return Home)(Entry Mode Set)
  NEXT index : PAUSE 10
 
      DisplayHello:
            LOW  RS                                                                      ' commandmode
            senddata = 132 :                                     GOSUB Send              ' (128-147) Line 1 Cursor Position
           HIGH RS                                                                       ' charactermode
            senddata = "H" :                                     GOSUB Send
            senddata = "e" :                                     GOSUB Send
            senddata = "l" :                                     GOSUB Send
            senddata = "l" :                                     GOSUB Send
            senddata = "o" :                                     GOSUB Send
pause 10000
            LOW  RS                                                                      ' commandmode
            senddata = $01 :                                     GOSUB Send : PAUSE 10   ' Clear Display
            senddata = 192 :                                     GOSUB Send              ' (192-211) Line 2 Cursor Position
           HIGH RS                                                                       ' charactermode
           FOR  index = 25 to 34
           READ index, senddata :                                GOSUB Send              ' sending character    
       NEXT index
pause 4000
      Count1:
            LOW  RS                                                                      ' commandmode
            senddata = 202 :                                     GOSUB Send              ' (192-211) Line 2 Cursor Position
      HIGH RS                                                                            ' charactermode
      INC W1                                                                             ' add to W1
           BinToAscii W1,b8,b7,b6,b5,b4
           FOR  index = 0 TO 5                                                           ' sending characters
       LOOKUP index,(" ",b8,b7,b6,b5,b4),senddata :          GOSUB Send                
           NEXT index
      PAUSE 8000                                                                         ' 1 second (M32)  
           
goto count1
       Send:
         DB7 =   bit7    
         DB6 =   bit6    
         DB5 =   bit5    
         DB4 =   bit4    
        PULSOUT E,1
         DB7 =   bit3    
         DB6 =   bit2    
         DB5 =   bit1    
         DB4 =   bit0    
        PULSOUT E,1        :                                     RETURN
 

Bryang

Member
Thx Marks, tried your code as-is, but still no go! Just a blank screen. I double checked the pin assignments, & no issues there. I'll have another look tonight - no doubt it is something simple, but still cannot see it!
 

Aries

New Member
These are extracts from my code for a 20x4 HD44780. To save Picaxe pins, it uses an 8-bit shift register to hold the 8 bits for the LCD display.
The first bit is initialisation ...
Code:
LCDInitialise:
    pause 1000                    ' wait for display to initialise

    low UI_LCD_E
    
    low UI_LCD_RS
    low UI_LCD_RW

#rem
    b0 = %00000001        ' clear display
    b0 = %00000110        ' cursor move / display shift
    b0 = %00001100        ' display on, cursor off, no blink
    b0 = %00111000        ' 8 bit, 2 line, 5x8 font
#endrem
    for b10 = 0 to 3
        lookup b10,(%00000001,%00000110,%00001100,%00111000),b0
        gosub SendLCDcommand
        pause 1000
    next b10
The second bit sets the DDRAM address for lines 1,2,3,4 (line number in b4, address goes into b0)
Code:
        low UI_LCD_RS
        low UI_LCD_RW
        lookup b4,($00,$40,$14,$54),b0
        b0 = b0 | %10000000                            ' set DDRAM address
        inc b4                                                    ' set up for next line
     
        gosub LoadLCDRegister
So the DDRAM addresses I use are 128, 192, 148, 212 in that order.
Essentially, lines 3 and 4 are the second 20 characters of lines 1 and 2 (hence the setting to a 2-line display in the initialisation)
 

marks

Senior Member
Hi Bryang,
looks like your still having initialisation problems.
the good thing I like about the 40x2 and the 18m2 they don't remap the port pins unlike the 20m2,
I'm sure I've tried the code posted #15 before on a 20m2 perhaps the B port which maybe faster.

I have a new bling 16x2 OLED I thought i'd try with the code #15 with your pin layout and this works fine.

I then dug up an olde 20x4 LCD and occasionally this would also have a initialisation problems
and also worst on a old 16x2 LCD which was surprising perhaps the old stuff like me is a bit more fussy.

Assuming pin2 of your lcd is connected to 5v+ and your B.0 output is just for the lcd led light.
some extra pauses have been added to the code below which seems to fix the problem for the 20m2.

The lcd needs a stable supply to start if attempting to actually power the controllers also from the B.0 pin(not recommended)
this would require a bit of extra R&D work perhaps you are switching ground through a FET with adequate decoupling capacitors .
a pause at the start of program and some extra code tweaking maybe needed.

Code:
#picaxe 20m2  ' 20m2 v8.A  4Bit Using Alternative pins marks
 SYMBOL DB7  = outpinC.1
 SYMBOL DB6  = outpinC.2
 SYMBOL DB5  = outpinC.3
 SYMBOL DB4  = outpinC.4
 SYMBOL E    = C.5  
 SYMBOL RS   = C.7  
 SYMBOL senddata  = b0
 SYMBOL index     = b1
      'value of count    = W1    ' b3,b2
      'display  count    = b4,b5,b6,b7,b8
       high B.0
      EEPROM 25,("Picaxe20M2")
      SETFREQ M32
  dirsB = %11111111
  dirsC = %10111111
Initialise:  
 FOR  index = 0 to 6
          LOOKUP index, ($33,$32,$28,$0C,$01,$02,$06),senddata:pause 1: GOSUB Send    ' Initialise LCD/OLED
                       '(WakeUp)*3(Set4Bit)(4Bit/2Line)(DisplayOn)(Clear Display)(Return Home)(Entry Mode Set)
  NEXT index : PAUSE 11
 
      DisplayHello:
            LOW  RS                                                                      ' commandmode
            senddata = 132 :                                     GOSUB Send              ' (128-147) Line 1 Cursor Position
           HIGH RS                                                                       ' charactermode
            senddata = "H" :                                     GOSUB Send
            senddata = "e" :                                     GOSUB Send
            senddata = "l" :                                     GOSUB Send
            senddata = "l" :                                     GOSUB Send
            senddata = "o" :                                     GOSUB Send
pause 10000
            LOW  RS                                                                      ' commandmode
            senddata = $01 :                                     GOSUB Send : PAUSE 10   ' Clear Display
            senddata = 192 :                                     GOSUB Send              ' (192-211) Line 2 Cursor Position
           HIGH RS                                                                       ' charactermode
           FOR  index = 25 to 34
           READ index, senddata :                                GOSUB Send              ' sending character    
       NEXT index
pause 4000
      Count1:
            LOW  RS                                                                      ' commandmode
            senddata = 202 :                                     GOSUB Send              ' (192-211) Line 2 Cursor Position
      HIGH RS                                                                            ' charactermode
      INC W1                                                                             ' add to W1
           BinToAscii W1,b8,b7,b6,b5,b4
           FOR  index = 0 TO 5                                                           ' sending characters
       LOOKUP index,(" ",b8,b7,b6,b5,b4),senddata :          GOSUB Send                
           NEXT index
      PAUSE 8000                                                                         ' 1 second (M32)  
           
goto count1
       Send:
         DB7 =   bit7    
         DB6 =   bit6    
         DB5 =   bit5    
         DB4 =   bit4
   
        PULSOUT E,1 :pause 1
         DB7 =   bit3    
         DB6 =   bit2    
         DB5 =   bit1    
         DB4 =   bit0
   
        PULSOUT E,1  :pause 1      :                                     RETURN
 

Bryang

Member
Reporting back.... ok, so I've re-run the codes from marks & inglewoodpete, then after re-reading marks #19 post with the comment about the power supply I re-powerd the LCD direct from the power bus instead of providing power via the picaxe B.0 pin... and the code from marks #15 post gave me text on the 2nd line, but strangely neither the code in post #19 (nor inglewoodpete's) gave me text on the second line.

So after all that it appears it is having a stable power source NOT via the pic that is the answer!

Next step is to better understand what is happening with the different codes (always more to learn). Not tried integrating Aries code yet, nor hippy's which sounds interesting, but will do so :)

and I am guessing for the stable power supply I could use B.0 to turn on a transistor? and a cap to smooth it? will try that soon to :)
20M2 & LCD schem.png
 

inglewoodpete

Senior Member
Reporting back.... ok, so I've re-run the codes from marks & inglewoodpete, then after re-reading marks #19 post with the comment about the power supply I re-powerd the LCD direct from the power bus instead of providing power via the picaxe B.0 pin... and the code from marks #15 post gave me text on the 2nd line, but strangely neither the code in post #19 (nor inglewoodpete's) gave me text on the second line.

and I am guessing for the stable power supply I could use B.0 to turn on a transistor? and a cap to smooth it? will try that soon to :)
First, did you re-test my code with the 2-line modification in post #13?

Hmm. In your circuit diagram, you have the 2N3904 short circuiting the 5v supply (briefly, before the smoke escapes :)). I suspect you meant it to connect to LCD pin 2 (LCD +5v supply-in).
 

Bryang

Member
Yes, I tried the change per post#3, and it didn't work at the time, but now I've changed the LCD to be powered direct from the 5V bus, your code works fine:).
Also, per marks code with post#15 working but post#19 not, with the only differences being pauses.... I tracked down what was stopping it working - it was in the Send: sub-routine. where it had the first PULSOUT, ie:
DB4 = bit4
PULSOUT E,1 : pause 1
DB7 = bit3
it didn't like the pause!!! removed the pause, and it worked.

and yes, I'll re-visit my schematic ;-)
 
Top