Software ADC Comparator?


Closed Thread
Results 1 to 14 of 14
  1. #1
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72

    Default Software ADC Comparator?

    I don't know if comparator is the proper term, but I need some direction here!
    I need to measure a voltage on a ADC input and then set an output high when the input voltage goes higher than the original reading, no matter what the original reading was (not exceeding 5 volts or full scale of the ADC of course). sort of like an autogain of some type. I'd like to be able to adjust the gain (or level of difference) of the readings with another ADC input and pot. so:

    if the original reading on AN0 was 2.33 volts
    and then right after that the next reading on AN0 exceeds 2.33 volts by 1 volt (3.33)
    High myOutput once, for one second.

    so then if the next reading is 3.33 it does nothing, because there was no positive change

    but, if the next reading is 4.33 then the output goes high again because there was a positive change.

    and so on

    the difference being 1 volt, which i would also like to have control of with another ADC..

    the voltage on my ADC input is going to vary between 1 - 4 (thereabouts!) slowly, with only sudden bursts of a higher voltage for a short pulse (a few mS?) but i think my PIC (F684, 20 MHz) will be able to capture it.

    I already know how to set up ADCs, and do my Defines and all of that, I just need some workable code here. Thanks in advance for any help!

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    IF ADCVAR <= to x THEN
    DO SOMETHING
    ELSE
    IF ADCVAR >= to x THEN
    DO SOMETING ELSE
    ELSE
    ENDIF
    EDNIF
    ????????????????????????

    Is that what you are looking for ?
    ......................
    Dave
    Always wear safety glasses while programming.

  3. #3
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Might help to know the end application...

  4. #4
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default No..

    the first suggestion by mackrackit doesn't take into account the level of "difference"
    i.e. setting the output high based on the amount of change of a varible number, not just by the fact that it changed for one.
    and its classified skimask! but, heres an example:

    say my input is a light dependent resistor, or solar cell, whatever, and its sitting in a dark room, doing nothing, no output. then someone turns on a dim light, the pic would detect the change in light level in the span of one loop, and toggle an output on and off one time because it saw a positve change in voltage on the ADC.
    Then it readjusts for the new light level in the room and sits there, doing nothing, but someone makes the light a bit brighter, and again the output toggles because there is a positve change in light. so therefore, it only toggles the output because there is a positve change in light, it would ignore someone turning the light off, or dimming it. I also need control of how much of a positive change it responds to, like the amount that the voltage level is increased, so if its a very slight change, nothing happens, but if there is a large change, it will respond..
    this is really messing with my poor ol' brain! but i seem to end up asking more questions on here than answering anyway!

    Also, when i say "readjusts" i mean the circuit automatically readjusts its self, like autogain, or something!

    thanks again for your help!
    Last edited by Ryan7777; - 13th February 2008 at 03:17.

  5. #5
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Ryan7777 View Post
    and its classified skimask! but, heres an example:
    I've seen classified (or have I?)...this isn't classified (or is it?)...

    say my input is a light dependent resistor, or solar cell, whatever, and its sitting in a dark room, doing nothing, no output. then someone turns on a dim light, the pic would detect the change in light level in the span of one loop, and toggle an output on and off one time because it saw a positve change in voltage on the ADC. Then it readjusts for the new light level in the room and sits there, doing nothing, but someone makes the light a bit brighter, and again the output toggles because there is a positve change in light. so therefore, it only toggles the output because there is a positve change in light, it would ignore someone turning the light off, or dimming it. I also need control of how much of a positive change it responds to, like the amount that the voltage level is increased, so if its a very slight change, nothing happens, but if there is a large change, it will respond..
    this is really messing with my poor ol' brain! but i seem to end up asking more questions on here than answering anyway!
    Also, when i say "readjusts" i mean the circuit automatically readjusts its self, like autogain, or something!
    If you read thru what you wrote carefully enough...you've just wrote the program that you want....no, really. I was writing it as I was reading it.
    Now my question is, the input can only go so high. Once it gets up to a maximum value, what's going to bring it back down to a nominal nothing?

  6. #6
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    Ryan

    What you're looking for is a derivative function. What you can do is something like this

    Code:
    LastADC  var   word    ' previous error
    CurrADC  var   word    ' current error
    Threshold con  1        ' can be more if you want
    
    loop:
      gosub ReadADC
      Error = CurrADC-LastADC
      if Error < 0 then Error = -Error ' make absolute error
      if Error > Threshold then
        High Output
        pause 1000    ' wait 1 second
        Low Output
      endif
      LastAdc = CurrAdc
      goto loop
    This will more or less achieve what you want to. However, this is pure untested code. Use at your own risk.

    Jerson

  7. #7
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default still not it..

    I tired your code, Jerson, and it didn't seem to work right, say the ADC had 2.5 volts applied, and then i turned the voltage up to 3 volts, the output would turn on and off, over and over, rather than toggle once, to show a change happened, and then stop. i changed the threshold value to account for any instabilty in my input voltage, and still no dice. and like a i said before, i need the circuit to "readjust automatically" so that it only cares that there is a positive increase in voltage by a certain value and reacts once and then resets, it shouldn't care what the original ADC value was, only that the value increased. so it would have to "dynamically" adjust itself. you would figure that you would take a reading, and then some miliseconds later, take another reading, subtract the first value from the second and that number would show a difference (if there is any), which would mean a positive change. if that value was over that of the threshold, then react. you would have to clamp that value to a number between 0 and 1023, so there wouldn't be a negative value and a roll over (or under, in this case) which i think is what Jerson's code showed, and i already tried the same thing, in a slightly different way, and neither work... but i could be, and probably am missing something! i really don't understand absolute values (only their vodka!) and how it applies here, all your saying is that the number can only have a certain maximum value right? so couldn't i use MAX?
    Last edited by Ryan7777; - 13th February 2008 at 05:00.

  8. #8
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Like skimask said, you have the code in you explanation of the project.
    Jerson gave an "untested" example to get you started.

    Think about this:
    Code:
    Two VAR : read ADC first : write that value to VAR1 : start LOOP : read ADC :_
    write ADC value to VAR2 : IF VAR2 > VAR1 THEN ? : Now make VAR1 = VAR2_
    GOTO LOOP
    Dave
    Always wear safety glasses while programming.

  9. #9
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default This is what i have.

    This is what i got so far, and im not seeing why it doesn't work.
    please excuse the formatting and what not!

    @ DEVICE pic16F684, HS_OSC, WDT_OFF, PWRT_OFF, MCLR_ON, BOD_OFF, IESO_OFF, FCMEN_OFF

    DEFINE OSC 20
    DEFINE ADC_BITS 10
    DEFINE ADC_CLOCK 2
    DEFINE ADC_SAMPLEUS 11

    CMCON0 = %00000111
    VRCON = %00000000

    ANSEL = %00110100

    ADCON0.6 = 0
    ADCON0.7 = 0

    voltLevBf VAR WORD
    voltLevAf VAR WORD
    voltLevCk VAR WORD
    threshHold VAR WORD
    timOut VAR WORD

    prgSel VAR PORTC.2
    swtOut VAR PORTC.3

    CLEAR

    PAUSE 1000


    autoGainPrg:

    ADCIN 2, voltLevBf

    PAUSEUS 12

    ADCIN 4, threshHold

    PAUSEUS 12

    ADCIN 2, voltLevAf

    PAUSEUS 12

    voltLevCk = voltLevAf - voltLevBf

    IF voltLevCk > threshHold THEN

    HIGH swtOut

    PAUSE 60

    LOW swtOut

    ADCIN 5, timOut

    PAUSEUS 12

    PAUSE timOut

    ENDIF

    GOTO autoGainPrg:

    the ADC acts as if there are two seperate voltage values present at the pin even if the voltage is the same and doesnt change. like on the first reading it should read 3 volts, and the second reading should be 3 volts or close enough! it shouldn't flash the LED sitting on the output, but its does, over and over like a blinky circuit, like the two readings are never close to equal, no matter what threshold is set at! so that would make me think that the difference between the two readings is somehow always larger than threshold.. what i'd like to know is, what did Jerson mean by "if Error < 0 then Error = -Error ' make absolute error" ?

    IF Error < 0 THEN
    Error = Error - Error
    ENDIF
    ??? if so, i tried that version of it, and it didn't work either..

  10. #10
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    Ryan

    You seem to be reading 3 diff adc ports. First of all, you have to tell us what is each one for any of the code I gave to make sense.

    The code I gave wants only 1 adc port to sense the light intensity. So, the other 2 are redundant. And the code I gave should do exactly what you asked for.

    Check your code. You seem to have got it diff from what I have given you.

    in Pseudo code what I have sent you does this

    if CurrentADC != PreviousADC
    Output = high
    Wait 1 second
    Output = Low
    PreviousADC = CurrentADC
    endif

    Jerson

  11. #11
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default ok

    here is where i am now, and it still doesn't work, no matter.. also, if I were to set my current reading and previous readings equal, the next loop through would set them to what ever the ADC says at sample time anyway.. so it would be pointless wouldn't it?
    PreviousADC = CurrentADC ?

    @ DEVICE pic16F684, HS_OSC, WDT_OFF, PWRT_OFF, MCLR_ON, BOD_OFF, IESO_OFF, FCMEN_OFF

    DEFINE OSC 20
    DEFINE ADC_BITS 10
    DEFINE ADC_CLOCK 2
    DEFINE ADC_SAMPLEUS 11

    CMCON0 = %00000111
    VRCON = %00000000

    ANSEL = %00110100

    ADCON0.6 = 0
    ADCON0.7 = 0

    voltLevBf VAR WORD ' variable for first reading or "previous"
    voltLevAf VAR WORD ' variable for second reading "current"
    voltLevCk VAR WORD ' variable for holding the difference
    threshHold VAR WORD ' variable for the threshold
    timOut VAR WORD ' variable for holding the timeout

    prgSel VAR PORTC.2 ' not in use yet
    swtOut VAR PORTC.3 ' output to LED

    CLEAR

    PAUSE 1000


    autoGainPrg:

    ADCIN 2, voltLevBf ' sample voltage on ADC 2

    PAUSEUS 12

    ADCIN 4, threshHold ' get threshold from pot set up as volt. divider on ADC 4

    PAUSEUS 12

    ADCIN 2, voltLevAf ' sample voltage on ADC 2 again, to check for difference

    PAUSEUS 12

    IF lghtlevAf > lghtlevbf THEN ' IF the second reading is higher than the first,

    voltLevCk = voltLevAf - voltLevBf ' subtract the first reading from the second to get the Dif.

    IF voltLevCk > threshHold THEN ' IF there is a difference, and it is greater then threshold

    HIGH swtOut ' set the LED high

    PAUSE 60 ' pause for 60 mS

    LOW swtOut

    ADCIN 5, timOut ' check volt. div pot on ADC 5, use number as time out - 0 to 1023

    PAUSEUS 12

    PAUSE timOut ' Pause for the time out setting, determined by ADC 5

    ENDIF

    ENDIF

    GOTO autoGainPrg:

  12. #12
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default Hope this doesn't make anyones head explode!

    just to make sure the problem i need to solve is clear, i will explain what i want yet again.
    I will not be monitoring a sine wave, the signal will not vary that often actually and will never go negative in relation to ground. but for the sake of an example, I will use sinewave.

    Say that there is a sine wave, the frequency of which does not matter, that is 2 Vp-p.
    This Sine wave is "floating" with its zero point at 2 volts above ground, making the lowest peak 1 volt, and the highest peak 3 volts. then we'll say my threshold is set at 1.5V.
    When the sine wave reaches 1.5V above the 1 volt line (not ground!), it triggers a response from my circuit, or flashes the LED once, and then waits.
    Where the sine wave is "floating" (again, floating, not peaking) doesn't matter, it will be anywhere between 0 and 5 volts and is out of my control, it is an independent circuit.
    The PIC circuit only needs to trigger when there is a positive going change in voltage that exceeds a threshold that i will need to have control of. so therefore, the threshold has to follow the 1 volt ( or 2V or whatever!) line automatically, while i can vary the threshold level, it will always be in reference to the 1 volt line! not ground. please see my example.bmp
    (and yes i know that if my threshold is 1.5 volts, and the signal zero reference exceeds 3.5, the threshold will be out of range, and that is fine because 1.5V is only an example.)
    Attached Images Attached Images  

  13. #13
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    Ryan

    Now, I understand what you're trying to do. However, reading the adc like this hardly gives you anything worthwhile.

    Code:
    ADCIN 2, voltLevBf ' sample voltage on ADC 2
    PAUSEUS 12
    ADCIN 4, threshHold ' get threshold from pot set up as volt. divider on ADC 4
    PAUSEUS 12
    ADCIN 2, voltLevAf ' sample voltage on ADC 2 again, to check for difference
    PAUSEUS 12
    Why? The difference between the 2 samples on ADC 2 is just around 25uS. Is this what you really want??

    On reading closely, I think you need to do this
    Code:
    'Find the minimum value
    MinAdc var word         'I'm assuming the ADC to be 10bit or more
    CurrAdc var word
    Threshold var word
    DelayVal  var word
    
    while 1                                     ' loop forever
        ADCIN 2, CurrAdc                    ' current ADC reading
        ADCIN 4, Threshold                 ' threshold setting
        ADCIN 5, DelayVal                   ' delay setting
        if CurrAdc > MinAdc + Threshold then
               High Output
               pause DelayVal
               Low Output
               if CurrAdc <> MinAdc then  ' check if the current ADC value < Min ADC
                 MinAdc = CurrAdc          ' and correct the MinADC value
               endif
        endif
    wend
    Does this do what you want?
    Jerson

  14. #14
    Join Date
    Sep 2006
    Location
    Indiana, USA
    Posts
    72


    Did you find this post helpful? Yes | No

    Default Thanks

    I don't know yet, i'll have to give that code a shot, one thing i did figure out tho is that my justification was wrong, i should have had it set to right justify, and I should have saw that earlier! I used serout to spit out the ADC values and now everything looks like it should, but i'll have to do further testing.

    Thanks again!

Similar Threads

  1. Stable Adc Reading Routine
    By gebillpap in forum General
    Replies: 27
    Last Post: - 13th May 2015, 02:18
  2. Comparator circuit thoughts....
    By kevlar129bp in forum mel PIC BASIC Pro
    Replies: 15
    Last Post: - 24th October 2009, 06:04
  3. Software Stack
    By yasser hassani in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 18th December 2007, 10:04
  4. ADC value with 2 decimals on an LCD
    By Squibcakes in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 2nd December 2005, 15:54
  5. 12F675 ADC 'Issues'
    By harrisondp in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 31st March 2005, 01:55

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts