Menu

Need some help regarding AD and float number

Help
2010-04-29
2013-05-30
  • Paulo Marcio Silva

    Hi everyone,

    I didn't find this topic on the forum. I want to read an analogic value and make some maths with it and show the value in the LCD.
    I have the 10 bit AD I want it to show the 0 - 5V value and not 0-1023. Do you know how should I do this? Heres the program I've made but it didn't work.

    #chip 16F688, 4
    #config WDT=off
    #config MCLR=on
    #config osc = INTRC_OSC_NOCLKOUT

    #define LCD_IO 4
    #define LCD_DB4 PORTA.2
    #define LCD_DB5 PORTC.5
    #define LCD_DB6 PORTA.4
    #define LCD_DB7 PORTA.5
    #define LCD_Enable PORTA.0
    #define LCD_RS PORTA.1
    #define LCD_NO_RW

    #define ad AN7

    dim advalue as word

    PRINT "Hello World"

    wait 1 s
    main:
    CLS
    advalue=ReadAd10(ad)
    advalue=5*avalue/1024
    locate 1,0
    LCDWord(avalue)

    goto main

     
  • Paulo Marcio Silva

    avalue is wrong. The right variable is advalue. I changed for it and I get just 0 in my LCD.

     
  • mmotte

    mmotte - 2010-04-29

    Looks very close!

    You need to define the port direction for the a/d

    dir PORTC.3  in

    only thing isee besides the "advalue" problem you found

    GL

     
  • Paulo Marcio Silva

    Really? I could get the 0-1023  A/D data before without using the port direction. But,  I'll try this tomorrow.
    Thanks for the tip!

     
  • gcha44

    gcha44 - 2010-04-29

    Hi,
    I think your program is correct but the precision is not good because you only obtain the entire value of advalue  .
    You'l have a better precision if you multiply advalue by 10000 and then you could divide it by 10000 to display the remainder .
    advalue=(50000/1024)*advalue   'The advalue never exceeds 50000  ( Word  )
    50000/1024=48.828 . The entire value is 48 but you must multiply by 49 to have a better  result

    You can call your subroutine Printdec like this
    advalue=49*advalue                                                        'instead of advalue=5*advalue/1024
    printdec advalue , 10000
    print "V"

    Sub PrintDec (number as word , factordiv as word )
    dim entire , remainder as word
    select case factordiv 'to avoid values that are different of 10,100,1000,10000
    case 10
      nop
    case 100
    nop
    case 1000
    nop
    case 10000
    nop
    case else
    exit sub
    end select
    entire= number / factordiv
    remainder=number %factordiv
    print entire 'dispalys entire number
    print "."
    'you must display the number of "0" before the remainder 
    'or else the result will not be true

    select case factordiv
    case 100
      if remainder < 10 then
        print "0"
      end if
    case 1000
    if remainder <100 then
       print "0"
    end if
    if remainder < 10 then
      print "0"
    end if
    case 10000
    if remainder <1000 then
      print "0"
    end if
    if remainder <100 then
      print "0"
    end if
    if remainder < 10 then
      print "0"
    end if
    end select
    print remainder
    end sub

    'ie: if advalue= 308
    advalue=49*308
    advalue=15092
    the display will be :
    1.5092V

    Nota: the precision will still be better if your voltage reference is 2.56V because

    25600/1024 = 25 exactly !

    GC

     
  • gcha44

    gcha44 - 2010-04-29

    You can choose your voltage reference such as 1024*48=49152 =4,9152V  by adjusting voltage on Vref with a 10t potentiometer .
    But you can choose any other value , the most important is the multiplicand is a entire number and the result is not greater than 50000 !
    The PrintDec subroutine will be used to display any word value you want divide by 10 , 100 , 1000 , 10000

    GC

     
  • Nobody/Anonymous

    Hi!
    tanks for the answer. I just didn't understand the use of this subroutine PrintDec. It's not doing anything is it?
    I'll test it later but using this 2 lines should work ..
    entire= number / factordiv
    remainder=number %factordiv

     
  • gcha44

    gcha44 - 2010-04-29

    Hi,

    I volontary choose an explicit example :
    If entire =2 , remainder = 3 and factordiv=  10000 , if you don't use this subroutine (PrintDec)  you'll  display  result = 2.3  .
    But it's false ,because the result is 2.0003  !

     
  • Paulo Marcio Silva

    Understood.
    Thank you very much for the support!

     
  • gcha44

    gcha44 - 2010-04-30

    I often use this subroutine ,and I added it to my included files .
    To do that , you write your "Printdec" subroutine , you save it as "Printdec.h" in  "gcbacic / include / lowlevel"  directory .
    Then you open the file named "lowlevel.dat" in "gcbasic / include " directory and you add "printdec.h"  at the end of list .
    Each time you'l want to display a precise value of AD converting you'l call that subroutine
    Example: if you want to convert 24017( mV)  in V  ,you'll write
    PrintDec 24017 , 1000 :Print "V"
    That's very easy to use , and the result will be  true and perfect !
    Have a nice day
    GC

     
  • gcha44

    gcha44 - 2010-05-06

    Hi again,

    I think your program doesn't work for the same reason as in your last post "LCD 4 bits mode help me"
    Before <goto main>  you must write  <wait 1 s>  to display the result ,or else it will be continuously erased
    GC

     
  • Tom Poulton

    Tom Poulton - 2013-02-11

    Hi there.

    How could this be adapted to work in the range of 0-25V? as Im using a potential divider on AN0 to give me 5V at 25V. I've tried altering GCHA44's code all ways i can think of, but all i seem to get is just 'V' on the LCD with nothing else but works fantastic to read 0-5V. I've tried altering the factor variable to be 4x greater, also tried modifying the AN0 figure before its put into the sub but to no avail

    any advice would be greatly appreciated

    Thanks

     
  • gcha44

    gcha44 - 2013-02-12

    Hi Tomlo,

    The principle is the same but in this case  you work with a long word
    If I muliply 25*10000 I obtain 250000 for a 25V potential
    So, to find the entire value you must do (250000/1024)*Advalue = 244.14*advalue
    You can work with 244*1024 to have a good result

    I think you have just to dim entire as long , not word  ( see in GCBASIC.chm / syntax / variables). I have not tried this but I think it does work.
    Regards

     
  • gcha44

    gcha44 - 2013-02-12

    Sorry not entire but advalue

     
  • Tom Poulton

    Tom Poulton - 2013-02-12

    Hi GC, thanks for the reply, I'll try it in a few minutes

     
  • Tom Poulton

    Tom Poulton - 2013-02-12

    I get an Invalid variable type: LONG when I try to compile :(

     
  • gcha44

    gcha44 - 2013-02-12

    Have you the last updated GCBASIC compiler?  See http://gcbasic.sourceforge.net/download.html (update.zip)

     
  • Tom Poulton

    Tom Poulton - 2013-02-12

    Cheers, that was what was stopping it compiling as I tend to use GCGB evvironment but in text mode

    I've compiled it but still getting some odd actions, figure before the decimal point is all over the place, the 4 digits after the decimal point do seem correct though. Heres the code I am using now:

    Dim Number As word
    Dim entire , remainder As word
    Dim advalue As long
    Wait 1 s
    loop:
    advalue=ReadAD10(AN0)
    advalue=(244*advalue)
    'instead of advalue=5*advalue/1024
    printdec advalue , 10000
    locate 0, 2
    print "V"
    Wait 1 s
    CLS
    Goto loop
    Sub PrintDec (number As word, factordiv As word)
        select case factordiv
        'to avoid values that are different of 10,100,1000,10000
        case 10
        nop
        case 100
        nop
        case 1000
        nop
        case 10000
        nop
        case else
        exit sub
        end select
        entire= number / factordiv
        remainder=number %factordiv
        locate 0, 4
        print entire
        'dispalys entire number
        print "."
        'you must display the number of "0" before the remainder 'or else the result will not be true
        select case factordiv
        case 100
        if remainder < 10 then
            print "0"
        end if
        case 1000
        if remainder <100 then
            print "0"
        end if
        if remainder < 10 then
            print "0"
        end if
        case 10000
        if remainder <1000 then
            print "0"
        end if
        if remainder <100 then
            print "0"
        end if
        if remainder < 10 then
            print "0"
        end if
        end select
        print remainder
    End Sub
    

    Snipped all the includes and irrelevant stuff out

     
  • Tom Poulton

    Tom Poulton - 2013-02-12

    Doh! just realised also that PrintDec I should have changed it to 'number as long' instead of word

    Works great now, checked LCD alongside an DVM and its very accurate, its for use in a bench PSU im building for myself.

    Thanks for all your help GCHA :)

     
  • Tom Poulton

    Tom Poulton - 2013-02-12

    Oops, forgot to ask, is there a way i can trim the figure after the DP to 2 decimal places?

     
  • gcha44

    gcha44 - 2013-02-14

    if you divide number by 10000 and to obtain 2 decimals after DP you just have to do

    remainder= remainder /100

    but for a better result  you must do :
    dim remainder1 as word
    remainder1= remainder % 100

    remainder= remainder/100
    if remainder1>50 then remainder=remainder+1

    Regards

     
  • Tom Poulton

    Tom Poulton - 2013-02-18

    Thanks for the help, working perfectly now

     

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.