Menu

ReadAD10 Error?

Help
Tam Do
2007-06-11
2013-05-30
  • Tam Do

    Tam Do - 2007-06-11

    Hugh,

    I am having problems with the ReadAD10 function, currently it is outputting 8-bit range values (0-255) instead of the proper 10-bit range (0-1023). I have a 100k pot wired up to AN0 and I am periodically polling the values of the 10bit output, displaying them on an attached LCD. The LCDWord function is working fine so that can be ruled out. I suspected a problem with the data formatting but the code seems fine to me. Also another suspect area is the chip definition file, as in the following sniplet. However I was able to confirm that ADRESL is defined, so it should output the 10 bit value properly. I'm a little stumped at what's happening.

    PIC16F876A

    'Write output
    #IFDEF Var(ADRESL)
    ReadAD10_H = ADRESH
    ReadAD10 = ADRESL
    #ENDIF
    #IFDEF NoVar(ADRESL)
    ReadAD10 = ADRES
    #ENDIF

    I remember this function working properly before (I am running the version you have updated) and I am not sure what is broken.

    My code is similar to the following:

    Loopy:
    Dim Temperature As Word
    Temperature = ReadAD10(AN0)
    LCDWord(Temperature)
    Wait 500 ms
    Goto Loopy

    Is there anything I should be doing that I may be forgetting? Thanks!

     
    • Nobody/Anonymous

      I think you just need to switch your high and low bytes of the ReadAD10.  So instead of:
      ReadAD10_H = ADRESH
      ReadAD10 = ADRESL
      use;
      ReadAD10 = ADRESL
      ReadAD10_H = ADRESH

      Quote from Hugh: "When copying two bytes into a word, it is important to copy the low byte first. This is because the high byte of the word var is cleared when the word var is set to a byte value or variable."

      Kent

       
    • Tam Do

      Tam Do - 2007-06-12

      Oops, no that wasn't it Kent. I had switched them to test if changing the order would make any difference. I just tried switching them back and it makes no difference.

      I believe I have narrowed down the problem though. I suspected there may be a problem with using functions and words (it may have been broken in Hugh's new updates) and I wrote some code to test it.

      sub test_function_word #nr
      Dim test_var As word
      test_var = test_word
      cls
      LCDWord(test_var)
      SerialTXWord(test_var)
      end sub

      word function test_word
      test_word = 9999
      end function

      The function is expected to display 9999 on the LCD and the terminal but interestingly enough it displays 15. If I have some free time later i'm going to go compare the two source codes to see whats up.

       
    • Hugh Considine

      Hugh Considine - 2007-06-13

      Tam and Kent, you're both right. The bytes were being set the wrong way around, and there was also a problem with the passing of parameters.

      I'm pretty sure I've been able to fix this bug - I've just successfully run this program on an 18F4550:

      #include "mytest.h"

      Print "A/D Test"
      Wait 1 sec

      Do
      CLS
      LCDWord ReadAD10(AN0)
      Wait 100 ms
      loop

      (mytest.h has LCD port settings, #chip and #config directives)

      Fixed files are in the usual place - http://gcbasic.sourceforge.net/newfiles/update.zip

       
    • Nobody/Anonymous

      Sorry to drag this out some more.  But just some observations, since going back to the 4bit LCD routines.  Downloaded latest zip, and still had the problem with LCDWord.

      Back when I was re-inventing the wheel,(i.e. an ascii LCD function for my serial LCD), I forgot to extend Hugh's routine to include 1,000's an 10,000' divisions.  Also noted at the time that "dim LCDTempValue as word" was needed to make my seperate header file work.  So if you put the above statement in the old lcd.h file, everything seems to work fine for me (using a 16f88).  This might also work for the new lcd.h but did not try.

      Kent

      Find this line in old lcd.h:

      sub LCDWord(LCDValue as word) #NR
      dim LCDValueTemp as word  'this makes everything o.k.

      '******************************
      'Test 4 bit LCDWord routine
      '******************************

      'Chip model
      #chip 16f88,20
      #config     _CP_OFF & CPD_OFF  &_WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF & _MCLR_ON

      'Setup 4 bit LCD
      #define LCD_IO 4
      #define LCD_DB4 PORTB.5
      #define LCD_DB5 PORTB.6
      #define LCD_DB6 PORTB.7
      #define LCD_DB7 PORTB.0
      #define LCD_RS PORTA.4
      #define LCD_RW PORTA.3
      #define LCD_Enable PORTA.2

      #define Switch PORTB.2   
      dim testx as word
      dim T1 as word

      dir Switch In
      InitTimer1 Osc, PS1_1/8
      Print "Hello World"
      wait 1 s

      Start:
      ClearTimer 1
      Wait until Switch Off
      wait 10 ms
      StartTimer 1
      Wait until Switch On
      StopTimer 1
      T1 = TMR1L
      T1_H = TMR1H
      cls
      LCDWord (T1)
      locate 1,0
      testx = 59999
      LCDWord (testx)
      wait 1 s
      Goto Start

       
    • Tam Do

      Tam Do - 2007-06-16

      Hugh,

      I tried your test code out with the new files and indeed they work. However the following program as I mentioned in my other thread still produces errors.

      #chip 16F876A, 20
      #config HS_OSC, WDT_OFF, LVP_OFF

      sub test_function_t #nr
      Dim test_var As Word
      test_var = test_function
      end sub

      word function test_function
      test_function = 9999
      end function

      Main:
      Dim test_var As Word
      test_var = test_function
      end

      I suppose there must be some incorrect type detection going on here, particularly if the subroutine is compiled before the function, as the same code will compile fine without the included subroutine.  The asm output is below.

      ;Program compiled by Great Cow BASIC (0.9 12/6/2007)
      ;Need help? See the GCBASIC forums at http://sourceforge.net/forum/?group_id=169286,
      ;check the documentation or email hconsidine@bigpond.com.

      ;********************************************************************************

      ;Set up the assembler options (Chip type, clock source, other bits and pieces)
      LIST p=16F876A, r=DEC
      #include <P16F876A.inc>
      __CONFIG _HS_OSC & _WDT_OFF & _LVP_OFF

      ;********************************************************************************

      ;Set aside memory locations for variables
      TEST_FUNCTION    equ    32
      TEST_FUNCTION_H    equ    33
      TEST_VAR    equ    34
      TEST_VAR_H    equ    35

      ;********************************************************************************

      ;Jump to initialisation code when PIC is reset
          ORG    0
          call    INITSYS
          goto    SystemInitialise

      ;********************************************************************************

      ;Interrupt vector
          ORG    4
          retfie

      ;********************************************************************************

      ;Various initialisation routines, automatically called by GCBASIC
      SystemInitialise

      ;********************************************************************************

      ;Start of the main program
      MAIN
          call    FN_TEST_FUNCTION
          movf    TEST_FUNCTION,W
          movwf    TEST_VAR
          clrw
          movwf    TEST_VAR_H
          goto    BASPROGRAMEND
      BASPROGRAMEND
          sleep
          goto    $

      ;********************************************************************************
      ;Subroutines included in program
      ;********************************************************************************

      FN_TEST_FUNCTION
          movlw    39
          movwf    TEST_FUNCTION_H
          movlw    15
          movwf    TEST_FUNCTION
          return

      ;********************************************************************************

      INITSYS
          clrf    PORTA
          clrf    PORTB
          clrf    PORTC
          movlw    7
          banksel    CMCON
          movwf    CMCON
          banksel    ADCON0
          bcf    ADCON0,ADON
          banksel    ADCON1
          bcf    ADCON1,ADFM
          bcf    ADCON1,PCFG3
          bsf    ADCON1,PCFG2
          bsf    ADCON1,PCFG1
          bcf    ADCON1,PCFG0
          banksel    STATUS
          return

      ;********************************************************************************

      END

      The only workaround right now is to add some inline asm after the call.

      Main:
      Dim test_var As Word
      test_var = test_function
      movf test_function_h,W ***
      movwf test_var  ***
      end

       
    • Nobody/Anonymous

      Tam and Hugh,
      Tried the READAD10 for the first time, very nice!  I was able to compile the short code below for a 16f88 at 20mhz, and a 4 bit LCD.  Hooked up  a 50K pot to +5V, AN0 on the wiper, and GND.  O.K., NOW there is a current limiting 330ohm resistor in series with AN0.  The results were from 0 to 1023, which I believe is your 10 bits.

      The function works also as expected.  Have not looked into the specific A2D registers of your device and how GCBasic a-d.h handles them.  So, there still could be a problem for you?

      If questions remain about calling a function or sub from within a sub or function, then you should start a new thread.  Your construction of the example is at fault, as opposed to GCBasic. 

      Kent

      '.......
      word function test_function 
      test_function = 9999 
      end function 

      Main: 
      cls
        LCDWord test_function
        locate 1,0
        LCDWord ReadAD10(A0)
      wait 2 s
      goto Main

      this is a test:

      [html]Main: 
      cls
         LCDWord test_function
         locate 1,0
         LCDWord ReadAD10(A0)
      wait 2 s
      goto Main[html]

       
    • Tam Do

      Tam Do - 2007-06-16

      Kent,

      I can't see what is wrong in my example. I declared a Word value and I am assigning the value from the function test_function to the word. However this code works if the above subroutine is not included, or the function is in code before the subroutine, which I find to be very odd. As for a-d.h, the variable ADRESL is defined therefore the code should work and does work fine whenever there is NOT a subroutine declared.

      However once a subroutine is declared in code, the function breaks.

      For example the following code using your code with the 877 and an added subroutine produces the following code.

      ;Start of the main program
      MAIN
          call    NO_USE
          call    CLS
          call    FN_TEST_FUNCTION
          movf    TEST_FUNCTION,W
          movwf    LCDVALUE
          clrw
          movwf    LCDVALUE_H
          call    LCDWORD
          movlw    1
          movwf    LCDLINE
          clrf    LCDCOLUMN
          call    LOCATE
          movf    A0,W
          movwf    ADREADPORT
          call    FN_READAD10
          movf    READAD10,W
          movwf    LCDVALUE
          clrw
          movwf    LCDVALUE_H
          call    LCDWORD
          movlw    2
          movwf    SysWaitTempS
          call    Delay_S
          goto    MAIN
      BASPROGRAMEND
          sleep
          goto    $

      Note in particular the call to the function:

          call    FN_TEST_FUNCTION
          movf    TEST_FUNCTION,W
          movwf    LCDVALUE
          clrw
          movwf    LCDVALUE_H

      It in fact clears the upper nibble thus only producing 0-255. In the sourcecode there is a section dealing with type detection, and if the function is not detected as a word function, then the code is produced. Therefore I reason that there is a problem with type detection.

       
    • Tam Do

      Tam Do - 2007-06-16

      Forgot the subroutine:

      sub no_use #nr
      nop
      end sub

       
    • Hugh Considine

      Hugh Considine - 2007-06-16

      Tam, there was a problem with the type detection caused by a bug in the TypeOfVar function. I've just fixed this, and the code you posted in the other thread now compiles fine.

      Also, #nr is only needed where there are parameters that you do not want copied back - if there are no parameters, you can leave it out.

       
    • Nobody/Anonymous

      Tam, sorry for my mis-understanding, I just saw a subroutine that was not called from main (which normally isn't an issue).  But I also noticed that there might be some contention between the subroutine and main over who owned the duplicate statement of test_var = test_function.  So on the surface, it looked to be a hypothetical case, that un-nessarily caused the problem.

      Woke up and plugged in the board this morning and no go on READAD10, so couldn't try your no_use sub.  Looks like more troubleshooting, oh joy.

      Kent

       

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.