Menu

10 bit A/D Again

Help
George
2011-02-15
2013-05-30
  • George

    George - 2011-02-15

    I've been reading 2009 and older on-line help with 10 bit A/D, but in 2011, I am too new to understand the syntax etc.   I too determined that ReadAD produces an 8 bit result, which isn't precise enough.  GCGB is great but it does hot have intrinsic capability to employ all micro controller capabilities. "Help" on 10 big A/D in the thread has ques but I don't have the expertise to put it together. I cut and pasted some code that simply did not work (but I'm a newby too). I hope someone will be so kind as to provide a complete code example that fits into the code below of reading LM35 with 10 bit resolution.  Sure appreciate it….thanks!

    ;Chip Settings
    #chip 16F877,6

    Dir PORTA.0 In ; LM35

    Start:

    Volt = ReadAD(AN0) ; how to read 10 bit instead of 8 bit??
    ; Convert to deg C
    ; Turn LED on when the result (converted to C) exceeds a value

    GOTO Start

     
  • gcha44

    gcha44 - 2011-02-15

    To have a 10 bits result you must use ReadAD10(AN0)

     
  • Nobody/Anonymous

    So do I simply swap ReadAD(AN0) in my code with "ReadAD10(AN0)?  Seems pretty simple.  Does that mean that my variable "Volt" will now be a word? or do I need to Dim Volt as Word above?

    THanks!

     
  • Nobody/Anonymous

    Well, I answered that question myself; I just rewrote the code and replaced my ReadAD with your function ReadAD10 and voila.  Major thanks to you.

    But this leads to another question.  How do I find and print the fractional result:  My calculations show temp = 20.509 degC.  How can I display the rounded result, 20.5?  THanks again!!
     

     
  • gcha44

    gcha44 - 2011-02-17

    Microgeo ,

    I'm sorry , I did'not notice your another question !

    LM35 has a linear 10mV/°C scale factor with a 0,5°C accuracy
    For 100°C , max voltage is 10mV*100=1000 mV=1V !
    So , for 20°C , voltage is 10mV*20=200mV !

    I presume you have a 5V supply (5000mV).
    So , 5000mV is theorically the maximum you can reach (500°C) for ReadAD10(AN0)=1024

    Thus , for 20°C , ReaAD10(AN0) will be : 200*1024 / 5000=40,96    (40 or 41)

    To display the temperature with a decimal you can try this :
    temp= readAD10(AN0) *5000 /1024      '  for 20°C you will find 40*5000/1024=195
    decimal= temp % 10                                 '=5
    temp=temp / 10                                          '=19
    print temp
    print ","
    print decimal
    print "°C"                                                     '=19,5°C

    ie: for ReadADC10(AN0)=40 , you obtain 19,5°C
    for 41 >>    20,0°C
    for 42 >>    20,5°C …….and so on

    Regards

     
  • George

    George - 2011-02-20

    Very nice!  Thanks.  I will try your plan.

     
  • George

    George - 2011-02-20

    Thanks again.  Happy with decimal trick but have another problem that I've noticed before and here too: My LCD displays values accordingly:  41 on AN0 converts to 20.5 C and 42 to 21.0 C. Strange, my calculations match yours but my GCBB results are 0.5 deg off.

    Here's another strange issue:
    I happen to have written my math code differently from you but should be the same.  It is,

    Dim Temp as word
    Dim Volt as word
    Dim TempScaler as word
    Dim DegC as word

    PreScaler = 4.883

    Volt = ReadAD10(AN0)  ; raw value at AN0
    Temp = Volt*PreScaler  ;
    decimal = Temp%10
    DegC = Temp/10           ; temperature degC

    I then Print Volt (raw value), DegC (C), and Temp(value used to calculate F).  Results look like:
    40  20.0C  200, OK

    Now, if I operate on Temp (200) to convert it to degF,
    Temp = Temp/10*9/5+32, I get Temp = 51 which should be 68 using excel (which uses "my" sense of math operation protocol)
    So I broke the conversion down.
    Temp = Temp*9 and I get 1800, perfect, so I revised that line, added math to read,
    Temp = Temp*9/5, which is the same as 1800/5 but the result printed is 200 instead of 360??   Like multiplying Temp by 1/1 instead of 9/5??
    I could only get the correct results by breaking the math into discrete parts:
    Temp = Temp*9
    Temp = Temp/5
    Temp = Temp/10
    Temp = Temp+32

    Any ideas?  Sure appreciate it!

     
  • Nobody/Anonymous

    Hi,
    1)  You must verify if your supply voltage (ie:4997mV) and enter its value in your code instead of 5000mV
        So presaler wiln't have the same value ( 4.880 in this case)
    2) you can write      temp=((temp*9) / 50)+ 32
        You must see chapter on "Setting Variables" in GCBasic help :

    "GCBASIC understands order of operations. If multiple operands are present, they will be processed in this order:
    1.    Brackets
    2.    Unary operations (not and negate)
    3.    Multiply/Divide/Modulo
    4.    Add/Subtract
    5.    Conditional operators
    6.    And/Or/Xor   "

    It's the reason I always use brackets in my mutiple calculations to avoid many mistakes

    For instance in your operation : temp=temp*9/5 , GCBasic will calculate 9/5 before temp*9
    9/5 is 1 , not  1,8 because GCBasic doesn't know decimal numbers . That is why you find temp*1=200 , not 360

    in my case : temp=(temp*9)/50) +32

     
  • Nobody/Anonymous

    sorry , continuation :

    in my case : temp=(temp*9)/50) +32
    GCBasic calculate first temp*9 ( first brackets)  =1800
    then 1800/50 (second brackets = 36
    then 36+32 = 68 !!

    Regards
    GC

     
  • George

    George - 2011-02-21

    Hey, nobody, you're somebody!  Thanks for explaining.

     
  • gcha44

    gcha44 - 2011-02-21

    Hi,  
    Thanks  microgeo . OOps , sorry , I forgot to Log in !
    GCBasic is  very easy to use and it's free !!
    I often use it for PIcs and even AVr's and the results are perfect .
    When you catch the "programming viruse"  of GCBasic you can't cure !  lol
    Last year I translated GCbsasic.chm in french language . You can find it in downloads .
    Regards
    GC

     
  • George

    George - 2011-02-23

    Oh I've got the pic bug alright.  The problem is that I'm quite used to Visual Basic and such with excess examples and explanations.  GCBasic is great but I have to use trial and error a lot or great help from this forum.  THere are great examples in MicroBasic but then I'd have to translate them to GCBasic to use (easier than to French!!).  Like using an internal clock to measure how many seconds pass between events.  I can't find examples in GCBasic and the index examples are brief and not explained…any ideas on this topic?

     
  • gcha44

    gcha44 - 2011-02-23

    Hi,
    Some time ago , I compiled a program I named "chronometer" .

    I simplified it to be more comprehensive ,.
    I Used a 16F628 with a 4Mhz quartz but you can adapt it for any other PIC with TMR1 timer . Calculations are made with a
    4 Mhz quartz , but I give you the procedure to calculate preselection TMR1 and number of overflows .

    'quartz frequency is 4Mhz
    'internal clock is 4Mhz/4=1Mhz
    'with a 1/8 prescaler for TMR1 , the frequency becomes : 1000000/8=125000Hz
    'period is 1/125000=0,000008 s = 8µs
    'TMR1 is a 16 bits timer . It overflow after 65536 impulses
    'So , if we use entire TMR1 , we have every overflow at 65536 * 0,000008=0,524288 s
    'but that value isn't very easy to use . O,5s Will be better !
    'To obtain 0,5s , TMR1 will overflow after   0,5 / 0,000008=62500  impulses
    'so , to obtain an overflow after 62500 impulses , we must preselect TMR1 at  65536-62500=3036
    'TMR1 is a 16 bits timer , so TMR1H=3036/256=11 and TMR1L=3036 mod 256=220
    'Then , with these values TMR1 will overflow every 0,5s
    'After 2 overflows , the time will be exactly  1 Second  !!

    This is the simplified program :

    #chip 16F628 , 4
    #define LED PortA.1
    #define sensor PortA.0
    #define LCD_IO 4
    #define LCD_DATA_PORT PortB
    #define LCD_DB4 PortB.4
    #define LCD_DB5 PortB.5
    #define LCD_DB6 PortB.6
    #define LCD_DB7 PortB.7
    #define LCD_RS PortB.0
    #define LCD_ENABLE PortB.1
    #define LCD_NO_RW

    dim countervalue as word
    dim seconds as word
    dir LED out
    dir sensor in

    initTimer1 Osc , PS1_8

    On interrupt Timer1Overflow call IncCounter

    beginning:

    TMR1H=11
    TMR1L=220
    countervalue=0
    counter=0

    CLS

    do
          print "Wait sensor "
    loop until sensor=1                        

    cls
    Print "Counting…"
    StartTimer 1                                    'TMR1 is started when sensor is 1

                      do
       counter=countervalue % 2       ' counter helps to blink led every second
      if counter =0 then                  
           set LED on
    else
           set LED off
    end if
    locate 0,2
    seconds=countervalue / 2      ' because TMR1 overflows 2 times per second
    print seconds                            'LCD displays seconds
                     loop until  sensor=0        

    StopTimer 1                             'if sensor is 0 , timer1 is stopped
    cls
    print "Counter = "
    locate 0,2
    print seconds
    print "s"
    wait 2 s
    goto beginning

    Sub IncCounter
          countervalue =countervalue +1           'after each interrupt countervalue increments
           TMR1H=11                                 ' preselect TMR1 at  3036
           TMR1L=220
    end sub

    I hope this program will help you
    You can read GCB help , chapters Timers , interrupt , etc….

    Regards
    GC

     
  • gcha44

    gcha44 - 2011-02-24

    If you want  a better accuracy :

    When sensor stops , TMR1 isn't =0
    So you can display mS like that :
    You simply doTMR1 * 0,008  (because each impulse=8µs or 0,008 mS)
    So you'll obtain  milliseconds= (TMR1 /1000) * 8 

    be carefull : you cannot do  (TMR1 *8) /1000  because if TMR1 is near 65535 , ie : 65532 the multiplication will exceed capacities of GCBASIC calculation (65532*8= 524256 which isn't a "word" variable) .
    Whereas 65532 /1000 gives 65
    and 65 *8 gives 520 mS !    ( in fact 524 but the accuracy is correct  )
    Regards
    GC

     
  • ajai

    ajai - 2011-03-04

    OK guys lets get back to lm35 dz(0-100degC only) coz thats where my problem is
    hey GreatCow Ha Ha 44 times(definitely not tryin to bug u) hope u throw som light on my irritating problems
    have PIC 16F676, 16x2 lcd JHD162A SERIES, lm35, 7805, 12vpower sup, every thin on breadboard.
    +12v main conected to 7805, in between capacitors- 1x470uf & 1x100uf in parallel
    7805--->2x100uf caps parallel (all electrolytic)---> powering pic16f676 & lcd( pin 1,2,3&15,16backlite2x10k pots)
    lm35 conecter to 12v.
    PIC blips a 2.5mm red led 300ms once a sec, reads lm35 as readAd10(an3) displays raw value per sec, bickers to lcd - 4bit mode and is cursed till death or power out (which eve first) but thats were simplicity ends:
    7805 output = 5.07v, lm35 = 98.7mV  i.e. yes 9.8degC but lcd erratic values 8-9-14-15-10-11so on within secs
    so raw_temp*0.488= 3.9--7.3degC no stable reading. reading other thermometers, actual temp in room is 9.9-9.8deg(dont ask, at 8500 ft hapens )
    also lcd fades on every refresh of screen - adjusting pots no cure, riping out backlit n blinker led has minimalistic effect, maybe room temp has smthin to do with this odd behaviour? 
    noticed wen moving pots towards or away from sensor readings change even to 3-4 raw, but checked with multimeter no flaw with lm35 guess its the MCU.
    so how to capture ADC readings for a longer period any commandso coz tutorial only have 3 adc commands
    any sugestions on circuitry

     
  • ajai

    ajai - 2011-03-04

    oh i added those capacitors hopin to solve those pulses but nothin substantial happened
    may be those voltage or current fluctuations r changing the Vref for adc at reading time as they more or less coincide
    but that alone dont explain everythin.

     
  • gcha44

    gcha44 - 2011-03-05

    Ajai711,
    Lcd fading every second seems to be a "cls" command and a wait … ms   in your main loop .
    Erratic values are due to calculation . GCBasic doesn't accept decimal variables , only byte and word .
    Can you post your code to see where his the problem ?
    GC

     
  • ajai

    ajai - 2011-03-06

    ;Chip Settings
    #chip 16F676,4
    #config OSC=INTRC_OSC_NOCLKOUT

    ;Defines (Constants)
    #define LCD_IO 4
    #define LCD_RW PORTA.0
    #define LCD_RS PORTA.1
    #define LCD_Enable PORTA.2
    #define LCD_DB4 PORTC.0
    #define LCD_DB5 PORTC.1
    #define LCD_DB6 PORTC.2
    #define LCD_DB7 PORTC.3

    'lcd_no_rw comand not realy working showing black out,pixl blotches
    Dir PORTC.4 Out
    Dir PORTA.4 In
    Wait 3 s

    'last min modificaton
    set portc.4 on
    Print "This is a TEST"
    Wait 3 s
    cls
    print "Hellow Everyone"
    Wait 3 s
    cls
    Print " LM 35dz : "
    Do Forever
    cls
    Print ReadAD10(AN3)
    Set PORTC.4 On
    Wait 350 ms
    Set PORTC.4 Off
    Wait 650 ms
    Loop

    hi again
    so
    Q1. for adc port do we have to define direction as in or not (as done above portA.4=AN3 on chip)?
    Q2. how to increase ADCs capture time so it takes a longer n more accurate reading, will add tiny caps to line n see.
    ' lm35dz does not print coz no wait after that, initially had more line in prog but removed(before makin 1st post here)coz too much math for humble chip
    PIC doc says about takin multiple readins n averagin them out for accurate readins

    read somewhere …… better to stay quiet n be assumed dumb than to open ur mouth n conform all doubts
    couple of days later readin paper n ther it said ……….beter to ask dumb questions n be chided than to pretend smart n actually stay dumb. the world indeed is very confusing , so
    D Q1 in definig variable types options= bit, byte, word, integr, string, array. bit= 1 or 0, ON or OFF but confused whats the diff btwn bit byte n word (if u could kindly explain)
    D Q2 in a variable (string or integr ) how to read a particular Nth character or column in that line e.g. name$ = ajai ,
              if i ask whats the 3rd char. ans='a' . or number= 12357 again whats the 4th char. ans= '5'.

    Sorry, you mus think i am some sort of question bank

     
  • gcha44

    gcha44 - 2011-03-10

    Hi ajai711,

    It will better to do a special post in Forum help because initial 10 bits A/D again was by  microgeo .
    However , I'll try to respond you .

    Q1)  Yes , when you have an anolog entry you must do Dir PortA.4 In 
    Q2)  LM35 has a very shot response to temperature . A/D conversion is calculated for an optimum value by GCBasic , depending of internal clock ( here it's 4Mhz) . But conversion is also very short ( if you read PIC16F676 datasheet it's value is between 2 to 4 µs !)
    So, to define time between two readings you must do Wait …s . In your case time is about 350+650ms=1s + some µs to execute differents instructions
    Q3) Byte is a 8 bits variable : it's maximum value is 255
           Word is a 16 bits variable : it'smaximum value is 65535
           In a byte , first bit value is 1 ,second 2 , third 4  , fourth 8 , fith is 16 , sixth is 32 ,seventh is 64 and eighth is 128
           If you add all these bits , you obtain 1+2+4+8+16+32+64+128=255
           All values are possible between 0 and 255  . For instance , if Bit 4 =0 and bit 7=0 , you'll have
              1+2+4+0+16+32+0+128 =183
    Q4) You can read : https://sourceforge.net/projects/gcbasic/forums/forum/579126/topic/3738060  if you want to find a ..Xth char. in a string . The "instr"  instruction not referenced in GCBasic help but that you can find it in GCBasic\include\lowlel\sting.h   .It's very usefull to find what you are searching for !

    regards
    GC

     

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.