Menu

18F2455 LCD problem

Help
2009-05-01
2013-05-30
  • Edward LaBudde

    Edward LaBudde - 2009-05-01

    Hi all, newbie here is having trouble with the LCD’s again.  I have a test program for the display in a 16F88 and 18F2455.  The LCD works OK with the F88, but not with the F2455.  The programs are identical except for the chip.  Both chips are using crystal oscillators and have measured frequencies on the money. 

    The 2455 chip has a total time to transmit the data (K) that is 80 us longer than the F88. 

    I think that is why the printout on the display on the F24565 looks like: tKKtKKKKttKK….  Alternating between t and K in random fashion.

    I need help!  I think there may be a problem with GCBasic in here somewhere!

    Why might this be happening and is there a work around or fix?
    Regards, and thanks, Ed.

    Here is the sample program, the F88 is Identical except for Chip, Also included are pieces of assembler code that relate to the display.
    ‘A LCD test for 18F2455

    'Chip model
    #chip 18F2455, 20 'Measured clock = 20.0015 .0075%

    'Set the pin Directions
    Dir portA.4 Out    'LCD output pin 6

    'set defines
    #define SendAHigh Set PORTA.4 on
    #define SendALow Set PORTA.4  off

    'Set initial parameters
    InitSer 1, r2400, 1, 8, 1, none, invert 'Positive going start bit
    main:
    call display
    wait 10 ms
    goto main

    Sub Display
        wait 1 s
        serprint 1, "K"
        Return

    F88 display Results
    DISPLAY
        movlw    1
        movwf    SysWaitTempS
        call    Delay_S
        movlw    1
        movwf    SER_SELECT
        movlw    low SYSSTRINGPARAM1
        movwf    SysStringB
        movlw    high SYSSTRINGPARAM1
        movwf    SysStringB_H
        movlw    low StringTable1
        movwf    SysStringA
        movlw    high StringTable1
        movwf    SysStringA_H
        call    SysReadString
        movlw    low SYSSTRINGPARAM1
        movwf    SysPRINTDATAHandler
        movlw    high SYSSTRINGPARAM1
        movwf    SysPRINTDATAHandler_H
        call    SERPRINT14
        return
        return
    ;SERPRINT (BYTE,STRING)
    SERPRINT14
        movf    SysPRINTDATAHandler,W
        movwf    FSR
        bcf    STATUS, IRP
        btfsc    SysPRINTDATAHandler_H,0
        bsf    STATUS, IRP
        movf    INDF,W
        movwf    PRINTLEN
        movlw    0
        subwf    PRINTLEN,W
        btfsc    STATUS, Z
        return
        clrf    SYSPRINTTEMP
    SysForLoop2
        incf    SYSPRINTTEMP,F
        movf    SER_SELECT,W
        movwf    SER_SELECT
        movf    SYSPRINTTEMP,W
        addwf    SysPRINTDATAHandler,W
        movwf    FSR
        bcf    STATUS, IRP
        btfsc    SysPRINTDATAHandler_H,0
        bsf    STATUS, IRP
        movf    INDF,W
        movwf    SER_BYTE
        call    SERSEND
        movf    PRINTLEN,W
        subwf    SYSPRINTTEMP,W
        btfss    STATUS, C
        goto    SysForLoop2
        return

    F2455 Display results
    DISPLAY
        movlw    1
        movwf    SysWaitTempS,BANKED
        call    Delay_S
        movlw    1
        movwf    SER_SELECT,BANKED
        lfsr    1,SYSSTRINGPARAM1
        movlw    low StringTable1
        movwf    TBLPTRL,ACCESS
        movlw    high StringTable1
        movwf    TBLPTRH,ACCESS
        call    SysReadString
        movlw    low SYSSTRINGPARAM1
        movwf    SysPRINTDATAHandler,BANKED
        movlw    high SYSSTRINGPARAM1
        movwf    SysPRINTDATAHandler_H,BANKED
        call    SERPRINT14
        return
        return
    ;SERPRINT (BYTE,STRING)
    SERPRINT14
        movff    SysPRINTDATAHandler_H,AFSR0_H
        movff    SysPRINTDATAHandler,AFSR0
        movff    INDF0,PRINTLEN
        movlw    0
        subwf    PRINTLEN,W,BANKED
        btfsc    STATUS, Z,ACCESS
        return
        clrf    SYSPRINTTEMP,BANKED
    SysForLoop2
        incf    SYSPRINTTEMP,F,BANKED
        movff    SER_SELECT,SER_SELECT
        movf    SYSPRINTTEMP,W,BANKED
        addwf    SysPRINTDATAHandler,W,BANKED
        movwf    AFSR0,ACCESS
        clrf    WREG,ACCESS
        addwfc    SysPRINTDATAHandler_H,W,BANKED
        movwf    AFSR0_H,ACCESS
        movff    INDF0,SER_BYTE
        call    SERSEND
        movf    PRINTLEN,W,BANKED
        subwf    SYSPRINTTEMP,W,BANKED
        btfss    STATUS, C,ACCESS
        goto    SysForLoop2
        return

     
    • Edward LaBudde

      Edward LaBudde - 2009-05-04

      Well thanks guys for jumping right in there! 

      Upon further testing I find the total time to transmit one frame of data on the F88 to be 3.832 ms not the 3.75 ms (9/2400) it is supposed to be.  That is 2.2% to long.  The time for the F2455 is 3.912 ms.  That is 4.3% too long, and marginal at reception.  Most feel that 2% is necessary for reilable communications.

      Why is GCB producing such large timing error?  Why is the error chip dependent?

      Kent?   Regards, Ed.

       
    • Hugh Considine

      Hugh Considine - 2009-05-04

      Ed, I dealt with the delay code a while back, and have just uploaded the fixed version of the compiler. Please download the update from http://gcbasic.sourceforge.net/newfiles/update.zip and see if it's any better.

      Sorry about the time it's taken me to post the fixed code! There are a lot of things changed inside GCBASIC since the last release, and I'm only now confident to post the latest version. (A full list of changes is at http://gcbasic.sourceforge.net/newfiles/update.zip\)

       
    • Hugh Considine

      Hugh Considine - 2009-05-04

      Oops, managed to get that link completely wrong! The list of changes is at:

      http://gcbasic.sourceforge.net/update.html

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-06

      Hugh, I am having big problems with the new code.  I can not get the serial to function at all.  It also messes up pulse tests.  The asm code double calls the sub-routines.

      Help! Ed.

      'A LCD test for 18F2455

      'Chip model
      #chip 18F2455, 20 'Measured clock = 20.0015 .0075%

      'Set the pin Directions
      Dir portA.4 Out    'LCD output pin 9

      'set defines
      #define SendAHigh Set PORTA.4 on
      #define SendALow Set PORTA.4  off
      #define PulseT PORTA.4

      'Set initial parameters
      InitSer 1, r2400, 1, 8, 1, none, invert 'Positive going start bit
      main:
      call pulse
      wait 10 ms
      goto main

      Sub Display
          wait 1 s
          serprint 1, "K"
          Return

      Sub Pulse
          set pulseT on
          wait 100 us
          set pulseT off
      return

      ASM file
      MAIN
          call    PULSE
          call    PULSE
          movlw    10
          movwf    SysWaitTempMS,BANKED
          clrf    SysWaitTempMS_H,BANKED
          call    Delay_MS
          goto    MAIN

      with display
      MAIN
          call    DISPLAY
          call    DISPLAY
          movlw    10
          movwf    SysWaitTempMS,BANKED
          clrf    SysWaitTempMS_H,BANKED
          call    Delay_MS
          goto    MAIN

      16F88 ASM
      MAIN
          call    TEST
          call    TEST
          movlw    10
          movwf    SysWaitTempMS
          clrf    SysWaitTempMS_H
          call    Delay_MS
          goto    MAIN

      With 2 calls
      MAIN
          call    TEST
          call    TEST
          call    DISPLAY
          call    DISPLAY
          movlw    10
          movwf    SysWaitTempMS
          clrf    SysWaitTempMS_H
          call    Delay_MS
          goto    MAIN

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-08

      Hugh, I was able to resolve my the problem by using the new rs232.h file and the previous release GCB.  By changing line 347 to 38.  the frame time for the 18F2455 is 3.736 ms.  Using 39 for the 16F88 it is 3.756 ms.  Should be 3.75 ms. Both work fine now.  Still not sure why it is chip dependent!

      BTW, the new rs232.h file is in update.zip.  update-nochipdata has the old version.

      I think you should warn folks not to downloads the lastest update, that will save a lot of questions.

      Best regards, Ed.

      P.S. GCBasic is an awesome piece of work.  I love it.

       
    • Hugh Considine

      Hugh Considine - 2009-05-08

      I've put a warning on the update.html page, hopefully that combined with the posts on the forum will be enough!

      The delay is chip dependent because of the delay calculating code in GCBASIC - it wasn't very accurate! The delays in GCBASIC work by using loops inside of loops, with a varying level of nesting depending on how long the delay needs to be.

      In the 10us delays, the older version didn't take into account the time taken by the outer loops when deciding how much time to waste in the inner loops, and also didn't add any extra single instruction cycle delays - it tried to get the best time possibly by adjusting the inner loop - which would be up to 2 cycles out depending on the clock speed of the PIC, an error increased by the outer loops. The new version does take into account the outer loops, and will add single cycle delays to the inner loop where needed.

      This gives quite a major improvement, I can't remember the exact figures now but on a 4 MHz chip in MPLAB, a 2.5 ms delay using 10us (Wait 250 10us) was around 3 ms with the old code, and 2.506 ms with the new code.

      In the ms delays, there are an inner loop (that loops D1 times) and and outer loop (that loops D2 times), which combined give a delay of 1 ms. These are then repeated by more outer loops to give the required number of milliseconds delay. In the old version of GCBASIC, D2 would be set to 10, and D1 to 100 * ChipMhz / 12. In the new version, GCBASIC uses trial and error (brute force) to find the values of D1 and D2 so that:

      5 + D2 * (3 * D1 + 4) ≈ 1000 * ChipMhz / 4

      The improvement in the ms delays isn't quite as major as the improvement in the 10us delays, but still better!

      I don't know what's causing the double calls, but will investigate this weekend. Thanks for the compliment!

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-10

      Hi all newbie still having serial LCD problems.  I fixed the timing problems by modifying the rs232.h file and using the old release of GCB.  The LCD works fine as long as the data is hard coded into the serprint command.  I need to display the contents of a word variable, so I am trying to use the serprint command to print out the data in the high and low Bytes.  If I type in vales for these it works fine and the transmission takes about 65 ms for the screen.  If I try to print the high and low Bytes from a variable, it takes about 187 ms of mostly grabbled up stuff.  I do not understand why it is sending so many characters. 

      Some please help!   Regards, Ed.

      Code:
      'A LCD test for 18F2455

      'Chip model
      #chip 18F2455, 20 'Measured clock = 20.0015 .0075%

      'Set the pin Directions
      Dir portA.4 Out    'LCD output pin 6

      'set defines
      #define SendAHigh Set PORTA.4 on
      #define SendALow Set PORTA.4  off
      Dim test as word
      wait 100 ms    'start up delay

      test = 20000

      'Set initial parameters
      InitSer 1, r2400, 1, 8, 1, none, invert 'Positive going start bit
      main:
      call display
      wait 5 s
      goto main

      Sub Display
          wait 1 s
          call Clear
          serprint 1, "TH "
          serprint 1, 200        'test_h  If I use this it does not work!
          serprint 1, " TL "
          serprint 1, 125        'test   If I use this it does not work!
      Return

      Sub Clear
          sersend 1, 254    'start
          sersend 1, 1    'clear screen
          sersend 1, 254    'Start
          sersend 1, 128    'first line
      Return

       
    • kent_twt4

      kent_twt4 - 2009-05-10

      From the beginning, or reiteration, SerSend and SerPrint are very fragile.  Only a select combination of oscillator and device  seem to work.  Much of this is due to GCBasic internal wait state algorithm being off, as stated by Hugh, not the accuracy of the external crystal. When using an internal oscillator, things could get even worse.  Using slow baud rates also affects accuracy by using more wait state loops, and thus compounding the error.  So until a stable update is instituted, with improved wait routines, stop any expectations from SerSend and SerPrint.

      The previously discussed hardware uart routine works well, and have never heard of any problems.  This is because the hardware uart runs off the Pics clock (which we know is accurate), and not dependent on software wait states.  Also, flags are set and cleared in hardware, so the timing of operations don't get ahead of themselves.  So unless the uart is taken up by some other operation, use the hardware uart routines.

      The alternate software routine works.  The loops don't take into account the fixed call and return overhead.  So one may have to substitute a slightly smaller wait state figure, from the ideal, to make up for that.

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-10

      Kent, thanks for the reply.  I know about the delay problem.  I changed the rs232.h file for the 2400 baude to:

      Sendr2400 = 40-40/ChipMHz    'use 40 for 2455, 41 for 88.

      This makes the timing well within 1% and rock steady and it works just fime as long as the lines are hard coded.  When reading the high and low data Bytes it goes nuts and sends out lots of extra charaters.  And it is very uniform. They are identical each transmission, not random.  So my question is directed to why it only does this only when reading data Bytes?  There must be a reason why this is going on.

      My test curcit board does not make it easy to use the hardware usart, as the display will require a data inversion to work, so that is why I am using the software serial.

      Best regards, Ed. 

       
    • kent_twt4

      kent_twt4 - 2009-05-10

      Ed,
      O.K. second look, try sersend 1, 200, not serprint, as that is for string values only.  Or, I have missed the boat again!

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-11

      Kent, thanks.  I want to send the value of the Byte as a string.  If I use sersend it sends a number, which I use in the clear subroutine, this sends  a number to the display which cause mode changes.  These work well to clear the screen etc. (see sub clear).  I need to see the byte value on the display so I can read the values stored in the data variables.

      I will investigate the hardware as an option, but how do I know GCB won't do the same thing on when reading a data Byte on it as well?

      There seems to be a fundemental problem with GCB when transfering Bytes from varibles to serprint.

      Best regards, Ed.

       
    • kent_twt4

      kent_twt4 - 2009-05-11

      Not aware of how you are going to do what you say.  Thats what the SerSend does, it descontructs the variable byte or word into ascii characters that a terminal or serial device understands.

      Why wouldn't you send a byte  as a number using SerSend?

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-11

      Kent, thanks for the suggestion.  I need to explain my display.  It uses numbers for commands.  For Example this subroutine clears the display and sets the cursor on the first line (address 128).  The number 254 precede commands.

      Sub Clear
          sersend 1, 254    'start of command
          sersend 1, 1        'clear screen
          sersend 1, 254    'Start of command
          sersend 1, 128    'first line
      Return

      This one sets the cursor to the second line (address 192).

      Sub second
          sersend 1, 254    'start of command
          sersend 1, 192    'second line
      Return

      To see an ASCII character on the screen I need to use serprint, not sersend.  As in

      serprint 1, "EH "

      This will print EH on the display followed by a blank space.

      So you see I need to use the print command to see the values of numbers on the display.   If a Byte has the value of 200 and I use
      Serprint 1, Byte it gets grabbled up. If I use
      Serprint1, 200 it works fine

      I am out most of today, So I will try some other things tomorrow.
      Regards, Ed.

       
    • kent_twt4

      kent_twt4 - 2009-05-11

      Ed, is this the parallax unit that you had troubles with before?  Maybe the answer is to use a select case statement and send out SerPrint that way?

      #chip 18f4620,20

      #define SendALow Set PORTB.7 OFF
      #define SendAHigh Set PORTB.7 ON
      dir PortB.7 out
      InitSer (1, r9600, 1, 8, 1, none, normal)

      Main:
      ByteVar = ReadAD(AN0)
        Temp = ByteVar /100 'hundreds
        GetCase
        Temp = (ByteVar % 100)/10 'tens
        GetCase
        Temp = ByteVar % 10 'ones
        GetCase
      wait 2 sec
      goto Main

      sub GetCase
      select case Temp
             
              case 0
                   SerPrint 1, "0"
              case 1
                   SerPrint 1, "1"
              case 2
                   SerPrint 1, "2"
              case 3
                   SerPrint 1, "3"
              case 4
                   SerPrint 1, "4"
              case 5
                   SerPrint 1, "5"
              case 6
                   SerPrint 1, "6"
              case 7
                   SerPrint 1, "7"
              case 8
                   SerPrint 1, "8"
              case 9
                   SerPrint 1, "9"
      end select
      end sub

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-12

      Kent, the display I am using is a Scott Edwards BPI-216.  I could not get the parallax unit to work.  However I think the problem with that unit was the timing error in GCB.  With the old GCB timing the delay time was in error by about 2.2%.  I corrected this by changing the calculation in rs232.h.  The SE unit seems more tolerant.  With the new settings the frame time at 2400 b is 3.76 ms or .27% error.

      Anyway I think I found a work around.  It seems that if I dim variable as word, when reading the high and low bytes, GCB goes nuts and sends out way too many characters when reading the high and low bytes directly.  I am reading the timer 1 and timer 3 bytes as follows:

      Elev = TMR1L
      Elev_h = TMR1H
      Azth = TMR3L
      Azth_h = TMR3H

      If I do
      serprint 1, Elev_h 
      It does not work

      If I do
      Elev_dummy_l = elev
      Elev_dummy_h = elev_h
      serprint 1, Elev_dummy_h 
      It works.

      Seems there is a problem in GCB somewhere in the word mode

      I will have to do more testing to see if this will do the job.

      Regards, Ed.

       
    • Edward LaBudde

      Edward LaBudde - 2009-05-13

      Hi all, After further testing I have verified the problem and that the work around does indeed solve the problem. 

      The problem is that GCB gets confused when issuing a serprint command from a Byte dimensioned as word.  GCB sends out what appears to be about 16 characters instead of 1.  I can not tell exactly as it overflows my screen.  It will do this only when printing Bytes from a word variable.  The pattern appears as gibberish, but is repeatable.

      The solution is to transfer the word Bytes to an intermediate variable that is dimensioned as Byte.  In my cause I have “dim Elev as word.”  I can not print either of the Bytes to the screen using serprint.  If I do Elev_dummy_h = Elev_h, it works fine. I did not try sersend.

      I confirmed that what is seen on the display agrees with what is stored in EProm for all variables concerned.

      I cannot tell you the hours I have spent getting the LCD to do what I want!@#$%

      Hugh, could you conjuror up an explanation for this behavior?

      Regards, Ed.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.