Shop OBEX P1 Docs P2 Docs Learn Events
Another LCD driver (HD44780) — Parallax Forums

Another LCD driver (HD44780)

MagIO2MagIO2 Posts: 2,243
edited 2011-02-16 11:33 in Propeller 1
I had a look into two LCD drivers I found in the object exchange. Of course they work ...
(more or less - initialization of one driver is weird as you can not restart the code without restarting the display)

But both are objects that run in the SPIN interpreter, steeling runtime from that COG ;o) I like a TV-driver approach, where the LCD communication is done in a dedicated COG. That's because code running in the COG is no longer needed in HUB-RAM.

The current version is simply a LCD driver without any extras. As you can read in the drivers comment-section I already have plans to improve that driver.

What do you think? Is there a need for an additional LCD driver in the ObEx? What features do you have in mind?


PS: The drivers first usage will be a intelligent DCC booster. That explains the text and user defined characters in the test-code.
One or two years ago I started the iBooster project on an AVR - in between I build our house. But now I want to redo the project with a prop.

Added new archive .. please find some words about the changes in the todays post further down (01-24-2010)
Replaced archive with the next iteration ... find some words about the change in my post (01-26-2010)

And here is the list of current features and what you can do with it:
- CMD_INSTR: of course you can send any LCD instruction like "Clear display", "Home", "Set cursor"·.....
- CMD_PRINT: print a string
- CMD_WRITE: write one byte (character or data-value)
- CMD_SETCHAR: write 8 bytes, which can be used to transfer the definition of a user defined·character
-·CMD_SETBLINK: set's one of eight blinking characters - or better alternating characters, because·you can define both. Using " " and "*" would give·you a blinking star, "a" and "A" would give a letter periodically·switching from upper to lower-case
- CMD_SETRATE: allows to alter the speed of blinking·AND scrolling
- CMD_SHIFT:·With this you can move the address with which the upper left corner of the display starts. So you can do horizontal scrolling with this without·moving the whole content. In 2 line displays you can use that for·a second screen.
- CMD_SETLINE:·here you address a screen position and a string which is bigger than the screen. The driver then takes care of scrolling the·string from right to left. It also allows to use a subsection of a row instead.
- CMD_SETLEN: This was the old instruction to choose a subsection for SETLINE. Now you can choose the incrementor for the scrolling. For example an incrementor of 0 will stop scrolling. This is cool, as now you can use the string-buffer as a screen buffer. Whatever you write in that buffer will appear on the display according to the refresh-rate.
You can set it to 2 to scroll in steps of 2 characters.
You can set it to the width of your display and you have an alternating row.
### update on 02-07-2010 ###
- CMD_SATOMIC: Don't interrupt the subsequent LCD.execute instructions by blinking character and/or scrolling lines
- CMD_EATOMIC: End atomic-state
- CMD_OTSCROLL: If you switched off automatic scrolling for a scrolling line, you can scroll it manually with this instruction. This has been introduced for menu-support.

LCD_test_2 contains a demo for a 2 lines display.
LCD_test_4 contains a demo for a 4 lines display.

Please note: I put the driver to the object exchange, so please find the latest version there


SSteve reported a problem in post #26 (-THANKS FOR THAT-):
The output of the driver contained garbage. The problem most propably is the wiring in combination with the high frequency of the signals. It can be fixed easily by opening the BenkyLCDdriver.spin, searching for
w500ns long 25
and replace the 25 with 200. This will change the clock-timing.

Post Edited (MagIO2) : 3/4/2010 4:43:46 AM GMT
«1

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-10-27 07:24
    10 downloads up to now - any feedback?
  • JonnyMacJonnyMac Posts: 8,912
    edited 2009-10-27 16:53
    Suggesting that there are too many of a given device object available is like suggesting there are too many Mexican restaurants in a given city (I love Mexican food); programmers, like other artists, each have their own take and I find it valuable to examine the different strategies used by various programmers.

    I may just port my own Spin driver for the HD44780 to PASM -- will be a good exercise and provide a different take for those like me who enjoy differing viewpoints.
  • jazzedjazzed Posts: 11,803
    edited 2009-10-27 18:32
    I agree with Jon. Every Mexican (or Thai ... whatever) restaurant I've been to was different and intriguing (excluding franchised chain store junk of course). Just knowing one way lends to mediocrity.
  • BradCBradC Posts: 2,601
    edited 2009-10-28 03:31
    Yeah, I third that. Reading other peoples code that does exactly the same thing as the code I just spent X hours creating is very often a great way to learn alternative methods (often better) of skinning the cat.

    By writing the first object yourself you ensure your understanding of the basic concepts is sound, which makes it that much easier when you are scratching your head wondering "why the heck did he write it like that?!?".

    Often it's a tradeoff of size vs speed or the ease of adding new features. In any case, you can never have too many examples to learn from, particularly in diverse languages.

    I recently got back into the PIC's with a dsPIC, and went in search of a flashy led hello world example in asm. Do you think I could find one? 50 examples in C (and one in Pascal) but none in asm. Plenty of forum posts asking for one and lots of replies saying "nobody uses asm on those chips". You are never short of an example in Spin or PASM [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lt's not particularly silly, is it?
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-10-29 07:51
    Thanks for your encouragement ... but it seems to be valuable as a programming lesson only ;o) ... hopefully more in a way "oh .. nicely done" than in "uh .. here you can see how you should not do it" ;o)

    Current status is that blinking characters work ... currently I support 8 blinking characters
    I added a shift instruction ... with this you can shift the start adress to be displayed to the left or to the right by as many steps as you want ... so you can switch between 2 screens for example

    With the next "milestone" (the scrolling text) I will provide the sources again.

    Post Edited (MagIO2) : 10/29/2009 10:03:17 AM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-24 21:27
    As I got my gadgetgangster board running a short while ago, I'm now able to continue with that driver. (My first prop is occupied with a graphical display).

    Things changed:
    CMD_SETRATE => the general rate used for blinking and scrolling can be changed
    CMD_SHIFT => if you have a 1 or 2 lines display you have unused display RAM. With shift you can have independent screens or shift the content of the display n characters to the left/right
    CMD_SETLINE => here you can point to a string which can be much longer than the screen. The driver will then take care of scrolling this string in one line. It can even be a subsection of this line.
    Other usage is, to define a screen-buffer for a line. So you don't have to use 'set cursor', print or write to update the screen. Just write what you want to display into the screen buffer and the driver takes care of sending it to the display.
    CMD_SETLEN => this is for setting the number of characters to print by the SETLINE. This will most likely be changed in next step, so you can have one line which scrolls across the whole screen while another one only scrolls 10 chars.


    Nice feature in the LCD test is the progress bar.

    Cleanup still needed. So it's just another iteration to a version that I could put into the Ob-Ex. Is someone using the driver? Feedback welcome!

    Added the current archive to the top post.

    Post Edited (MagIO2) : 1/25/2010 8:57:06 AM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-26 20:48
    Just added support for 4 scrolling lines. That's maybe a not needed feature as such, but if you create strings having the size of your display and when you set the string incrementor to 0, you have a screen-buffer for displays with up to 4 rows. Just put your changes into the strings and the driver will take care to send it to the screen. No need to call any function.

    Another usage came into my mind. If you have a string of n*16 characters and you set string incrementor to 16 it will show the first string ... then the second .... up to n and start from beginning again. I don't have a demo for that yet ... maybe later.

    Another improvement:
    I found a small ... well ... it's not really a bug. But the code that generates the signals was waiting far to long. Instead setting E to high, wait ~250ns and set E to low for at least ~250ns, I did not change the setting from init-phase. It was 500ns, 500us ... Changed that to ~300ns for both. Now compare the progress bar with the old version ;o)))

    Still no feedback? Then I'll propably put the next version into ObEx.

    Have fun!






    PS: added the following code as demo for the alternating text:
      printTestTitle( string("Alter text   ") )
      LCD.exec( LCD#CMD_SETRATE, 10_000_000 )    ' set the rate higher, so text is displayed long
                                                 ' enough
      LCD.exec( LCD#CMD_SETLEN, 16<<16 + 16 )    ' set the incrementor to 16 (the first 16 ;o)
      LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE1 + @alt )
      waitcnt( clkfreq*50+cnt )
      LCD.exec( LCD#CMD_SETRATE, 1000000 ) 
     
    dat
    alt   byte "This is a demo  for alternating text, which is  pretty cool, as the function wasbuild for someth different ;o)  ",0
    
    
    

    And I also have some code for a 4 row display:

    Post Edited (MagIO2) : 1/26/2010 9:25:19 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-28 17:45
    It looks like everybody is using TV or VGA instead of text LCDs ;o)

    Please have a look at the feature list I've added to the first post. I still have ~200 longs free in the LCD COG.

    Current planning is to include menu support.
    But I could also think of a PWM for fading the backlights of the LCD.

    any other ideas?
  • Don MDon M Posts: 1,647
    edited 2010-01-28 18:07
    I am interested in using 4x20 LCD. Menu functions and yes, controlled backlighting would be wonderful. Even better would be adjustable contrast.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-28 19:29
    Hmmm ... 4x20 is already running, as it's no difference for the driver in general. (That's the reason why I added 2 more scrolling lines - so it's possible to have a screen-buffer mode for 4 row displays). Maybe there is a default value left for the line-size of the CMD_SETLINE, but that can be changed during runtime. Have a look into the LCD_test_4.spin 3 posts above, that contains a test modified for 4x20 displays.

    I'm not sure if adjustable contrast is that useful. My current feeling is that a adjustable resistor gives a constant contrast, as I never changed it after initial setup. But on the other hand, having both is a good use for the 2 counters and not to much code is needed for that.


    PS: I checked that
    MagIO said...
    Maybe there is a default value left for the line-size
    There is no PASM code which uses a fixed line-length - just set your display size in the constant
    STG_LINE_WIDTH

    Post Edited (MagIO2) : 1/28/2010 9:25:53 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-30 21:38
    Played a bit with my LCD driver, as I found a question in another forum where a member wanted to use a text LCD display (2x8) upside down·but having·the letters readable. As the text LCDs don't support to mirror the characters idea was to use the 8 user definable characters.

    What shall I say: IT WORKS!

    Well ... it depends on the display. First I used a 2x16 blue/white display and it did not work. Then I used a 4x16 green/black display and here it works.

    So, if you want to display a little splash-screen when starting the application ...
    ... or you want to show a temperature curve ....
    ... or you want to show a frequency spectrum ...
    ... or you simply want to double the available user defined characters ...

    no need to spend extra $ for a graphical display if the graphics can be simple.

    Enjoy
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-02-07 21:27
    Ok, here's a little bugfix and·small iteration·release.

    The bug I found·was related to the graphics output·introduced with the·previous post. I played a bit with it for a temperature logger. It measures the temperature periodically and displays the actual value in degree Celsius and plots the value in a curve showing the last 40 measurements. So it was using the screen-buffer-mode for the line containing the temperature together with the graphics output. This combination does not work correctly and leads to trash-output.
    Problem is, that both outputs (the line containing the temperature and the graphics) need to send LCD instructions. (Set CRAM or set cursor). But the screenbuffer-output is done periodically and can·be processed in the middle of the·SPIN code·sending the new graphics data.

    Solution: I introduced 2 new instructions for setting a bunch of LCD commands·to being atomic. So, neither blinking characters nor a scrolling line will be executed unless the atomic operation is finished.
    CMD_SATOMIC
    CMD_EATOMIC

    The next instruction is for supporting menus - but can be usefull for other things as well. This is possibly the first step in menu support ... maybe the only one ... don't know yet ... depends on how much need is out there for menu support ? ;o)
    CMD_OTSCROLL
    (for one time scroll)
    will scroll the text in a line by the given number of characters. You can see how·to create scrolling menus with that in the demo. (The demo has been written for a 4x16 LCD, should also work with other 4 line displays, but needs changes for 2 line displays)






    Post Edited (MagIO2) : 2/7/2010 9:45:17 PM GMT
  • wb7076wb7076 Posts: 29
    edited 2010-03-04 02:19
    I am trying to use a 20x4 lcd i changed the line in the driver but it displays the messages in the wrong places.
    1600 x 1200 - 599K
    1600 x 1200 - 637K
    1600 x 1200 - 645K
  • wb7076wb7076 Posts: 29
    edited 2010-03-04 03:22
    and how about a pub like move (3,2)
    just for us newbbbb's
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-04 05:50
    Thank you for your feedback! Especially because I didn't have the chance to test my driver with a 20x display yet, as I don't have one.

    What you found is not a problem in the driver itself. But changing the constant in the driver is only half of the truth. The demos themself are written for 16x displays. To make them work you have to check the function calls which contain cursor positioning. And as the CMD_SETLINE also set's the cursor the 16x4 demo won't work properly for your 20x4 display (.... maybe I should add constants to the demo-code as well ...)
    [noparse][[/noparse]code]
    · LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE1 +·········· @scrbuf1 )
    · LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE2 + $40<<16 + @scrbuf2 )
    · LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE3 + $10<<16 + @scrbuf3 )
    · LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE4 + $50<<16 + @scrbuf4 )
    [noparse][[/noparse]/code]
    The part which sets the cursor is the xx<<16. Rather than working with x any y coordinates, this instruction works with display RAM addresses.
    The first line starts at address $00, the second at $40 (that's true for 16x and 20x displays) But the 3rd and 4th start at $10 and $50 for 16x and at $14 and $54 for 20x displays.

    By the way ... the function that sets the cursor looks like that:
    [noparse][[/noparse]code]
    ··· LCD.exec( LCD#CMD_INSTR, ( %10000000 + $45 ) )
    [noparse][[/noparse]/code]
    This one would set the cursor to 2nd line 6th character.

    I see that it would be easier for newbies to have comfort-functions. But I'm not sure if this is a good service in the end. We talk about programming a microcontroller. In my opinion comfort is only good where it does not cost RAM or runtime.
    As a newbie you not only learn how to program, you also learn habits. If you get used to comfort functions at this time, you will also use them when you're more experienced - and possibly forget about the fact that you could do it wasting less RAM when you'd need it.
    Of course there are drivers which really do hardcore stuff and need to be translated to easier functions. But I think an LCD-driver is not that difficult to understand.

    ... and hey ... if you really want those functions, then write a wrapper for the driver like in TV and TV_Text.
  • wb7076wb7076 Posts: 29
    edited 2010-03-04 19:20
    you know any good reading. so i can learn functions and tips for programing
    like how to solve problems with programs. My school days are long behind me.
    anyway as soon as i hit send on the keyboard. i saw what was going on with the code.
    I figured it out. I am going to port the driver to my timer project.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-04 20:39
    Sorry ... the days that I learned programming are long behind me. But I think it would be best to search for books about data structures and algorithms rather than for books that teach a programming language.

    Another good source of wisdom is code .... search for well documented source-code in the object exchange and not only have a look at how to use it correctly, but also look how the things are solved. If you can not figure out why things are done in that particular way, simply ask here in the forum.

    Experience it worth a thousand books.
  • lardomlardom Posts: 1,659
    edited 2010-03-07 17:28
    · I'm late to this thread but I could scroll text in a Pbasic program I wrote. It·is tedious for me to do the same thing in Spin. I can't be the only 'propellerhead' that·benefits from what you·add to the knowledge base.·I will download your object, obex or not.

    ··I have a satisfactory collection of reworked unipolar stepper methods·but there is nothing in the obex the last time I looked. I know there is better code...somewhere. Because I·think unipolar stepper code should be·in that basic building block list of objects I may submit my own code.

    · I, for one, have to study seasoned programmers to get up to speed. MagIO2 is one of the classes I attend.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    PropellerHead

  • JonnyMacJonnyMac Posts: 8,912
    edited 2010-03-07 23:16
    My LCD object (in ObEx) has window scrolling methods -- you could lift those and add them to MaIO's object.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-08 08:10
    Hi lardom, Hi Jonny,

    after a first glance into jm_lcd4_demo.zip, I'd say that your scrolling is doing nearly the same thing as my LCD#CMD_SETLINE instruction in default mode. I think the difference is that you scroll through the text and return, while SETLINE will start from the beginning again.

    @lardom:
    I see some flowers in your post -thanks for that-, but I'm not sure whether there is a question or a request for changes in the driver?

    When putting the driver into the object-exchange, I also switched to maintenance mode - as I have other things to code ;o)
    So, even if I have some more ideas for that driver - especially when reading such feedback - I will only update the driver on request by others (new functions, bugfix), or when I come back to a project that uses a text display and find out that there is something missing.
  • lardomlardom Posts: 1,659
    edited 2010-03-08 16:07
    MagIO2, I tried to say if a driver adds a new feature or·just a different approach to a similar problem I think it should be in the obex. Variety..yes. Rehash..no. I have flowers for everybody who·have reached out to me in this forum. I never thought I could program anything until·recently when I wanted to build a digital machine for my wife and daughters. That's the machine in the Youtube video but I built my first machine with a 555 timer chip and a modified servo. I surprised myself and I haven't hit my ceiling·yet.·My excitement may die down over time but for now I am enjoying the rush.
  • SSteveSSteve Posts: 808
    edited 2011-02-13 21:07
    I just downloaded the object and I'm running into a problem. I can't seem to get text to display on the second line. I'm using a Parallax 2x16 parallel LCD. Here's the test program I'm running:
    con
        _CLKMODE      = XTAL1 + PLL16X
        _XINFREQ      = 5_000_000
    
        LCDBasePin    = 0
        LEDOnPin      = 255
    
        lineLen       = 8
    
    obj
        LCD: "BenkyLCDdriver"
    
    pub main | i, inx, let
      LCD.start( LCDBasePin,0 )
    
    '  LCD.exec(LCD#CMD_INSTR, %00000001) ' clear screen
      LCD.exec(LCD#CMD_INSTR, %01000000 + $40) ' set the character RAM address to $40
      LCD.exec(LCD#CMD_PRINT, @text1)
      waitcnt(clkfreq << 1 + cnt)
    
      repeat
        repeat let from "!" to "~"
          repeat inx from 0 to lineLen - 1
            scrbuf[inx] := let
          LCD.exec(LCD#CMD_INSTR, %01000000 + $40) ' set the character RAM address to $40
          waitcnt(clkfreq >> 2 + cnt)
          LCD.exec(LCD#CMD_PRINT, @scrbuf)
          waitcnt(clkfreq >> 2 + cnt)
          LCD.exec(LCD#CMD_INSTR, %01000000 + $00) ' set the character RAM address to $00
          waitcnt(clkfreq >> 2 + cnt)
          LCD.exec(LCD#CMD_PRINT, @scrbuf)
          waitcnt(clkfreq >> 2 + cnt)
    
    
    dat
    text1   byte  "First Message", 0
    
    scrbuf  byte  " "[lineLen],0
    

    What I expect to happen is that "First Message" shows up on line 2. After that, it should cycle through ASCII characters first on line 2 then on line 1. But what I see is "First Message" on line 1, then cycling through ASCII characters on the first half on line 1 then the second half of line 1. I've attached a movie to illustrate.

    Am I doing something wrong?
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-13 21:15
    From a quick glance, your commands are slightly off.
    LCD.exec(LCD#CMD_INSTR, %0100_0000 + $40)
    
    should probably read
    LCD.exec(LCD#CMD_INSTR, %[COLOR="red"]10[/COLOR]00_0000 + $40)
    
    I'm aware that there is a %0100_0000 command but given that the offset is $40 I figured one of them is wrong ($40 == %0100_0000). Meaning either change the command or adjust the offset.
  • SSteveSSteve Posts: 808
    edited 2011-02-13 22:18
    Thanks. I copied a line of code from the demo program, but I obviously copied the incorrect line. I'll give that a try.
  • SSteveSSteve Posts: 808
    edited 2011-02-14 09:11
    I fixed the error in my code, but I'm still having trouble with BenkyLCDdriver. I'm getting a lot of garbled characters. At first I thought the LCD was broken, but then I tried another LCD driver from the Object Exchange and it works fine. I haven't had time to try to step through the BenkyLCDdriver code yet.

    If someone can give the attached program a try and let me know if they see the same thing that would be a big help. I have a switch attached to pin 14 to choose which driver to use, but you can also get rid of the if statement and comment out the call the the driver you don't want to use.

    I normally use bst under OS X but I also tried this with Propeller Tool to rule out any bst-related issue.

    IMG_3893.JPG
    IMG_3894.JPG
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-14 11:27
    I tried it ... both drivers run on my LCD.
  • SSteveSSteve Posts: 808
    edited 2011-02-14 11:34
    Interesting. I wonder what the difference is. I'm using a Propeller Professional Development Board with jumper wires between the LCD's connector and the PPDB's breadboard. I'm guessing the connections are ok since one of the drivers works. Maybe the PASM is too fast for my particular LCD.
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-14 11:36
    My guess is that the PASM is to fast for the wires, not for the LCD, because in my code I check the busy-flag of the LCD.

    You could also make sure that there is no solder flux between the pads of the LCD. At higher frequencies solder flux can cause problems.
  • SSteveSSteve Posts: 808
    edited 2011-02-14 11:46
    Well, my application is not high-speed so I think I will use the SPIN-based driver since it works without hardware troubleshooting. I know next to nothing about electronics so I avoid hardware issues whenever possible. :-)
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-14 11:56
    Thank you for sharing your experience! Even if the outcome is sad for me ;o)
Sign In or Register to comment.