Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Plz help building a voltmeter on PIC12F683

Status
Not open for further replies.
As you are left justifying and you only read ADRESH, you are effectively using the ADC as an 8 bit device and your conversion should be,
Code:
    Vin = sample * 5 / 255
You may want to change the variable Vin to an int (or word) instead of a byte as the compiler may do 8 bit arithmetic and loose bits.

If you want to use the full 10 bit then change to right justification and change your code to fetch the result to,
Code:
    sample = ADRESH * 256 + ADRESL        'Write conversion result

HTH

Mike.
 
Spock, I feel like I am in a Star Trek movie.

Mike (Pommie) is telling you that you are reading into a byte, Biggest number you will get is 256 (0-255). Make it a word (integer;two bytes). Also he is telling you go from 8bits to 10bits on the ADC.

What HTH is.. I have no idea. Mike?
 
mramos1 said:
Spock, I feel like I am in a Star Trek movie.

Mike (Pommie) is telling you that you are reading into a byte, Biggest number you will get is 256 (0-255). Make it a word (integer;two bytes). Also he is telling you go from 8bits to 10bits on the ADC.

What HTH is.. I have no idea. Mike?

The code will still work with Vin as a byte, he just needs to change the conversion maths. However, it would be better to go to 10 bits as I assume he has other plans for this code down the line. I now see you suggested this may be the problem earlier. Good call.

HTH = Hope that helped.

HTH:D

Mike.
 
jankop said:
MrSpock, can you give me a hex file from your BASIC please?

Jankop, unfortunatelly I'm away from the computer where everything is set up. I'll post the whole project sometime this week. It works just fine now. Thank's to everybody's replies.
 
Pommie said:
The code will still work with Vin as a byte, he just needs to change the conversion maths. However, it would be better to go to 10 bits as I assume he has other plans for this code down the line. I now see you suggested this may be the problem earlier. Good call.

HTH = Hope that helped.

HTH:D

Mike.

Thanks, Mike. That's exactly how I'm doing it im my final version:
Code:
Vin VAR BYTE 
Sample VAR WORD

Sample.highbyte = ADRESH
Sample.lowbyte = ADRESL

LET Vin = sample * 5 / 1023

Although since PICBASIC PRO lacks operations with decimal values (everything here is integers :confused: ) I'm using the "Sample" variable directly, without converting it to voltage.
 
MrSpock

Good job.

Maybe I will make onr for my sons golf cart. He is always worried about the battery then he leave the lights and radio on.

Post the .HEX as well and I do not have pic basic pro. Or I can flip it to MikroBASIC.
 
Final Version

Here is the final version as promissed. I used a serial LCD for debugging in my simulator. In "real life" just leave pin 2 disconnected.

Red LED steady lit: < 12V
Steady yellow (both read and green ON): 12V to 12.6V
Steady Green: 12.6V to 14.6V
Blinking red: > 14.6V

I used dual color LED, which produces yellow when both red and green are ON.

I quite not figure out how to read Vint as decimal. Apparently in Pic Basic Pro everything is integer or byte, no variable takes the decimal point value. I'd appreciate if anybody modified the code to display the actual voltage value on LCD.

Code:
@ DEVICE PIC12F683,MCLR_OFF,INTRC_OSC_NOCLKOUT,WDT_OFF,BOD_OFF
@ DEVICE PWRT_ON,FCMEN_OFF,IESO_OFF,PROTECT_ON

GrnLED  CON    0        ' Green LED
RedLED  CON    1        ' Red LED
Sample  VAR    WORD
Vin     VAR    WORD     ' Input voltage on Pin 3
LCD     CON    5        ' 4-Line serial LCD on pin 2 for debugging
pause 300               ' Let LCD initialize

DEFINE OSC 8
DEFINE ADC_BITS 10      ' Use 10-bit A/D
Define ADC_CLOCK 3      ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50  ' Set sampling time in uS
DISABLE INTERRUPT       ' Disable interrupts

ADCON0.0 = 1            ' Turn On A/D
ADCON0.2 = 1            ' A/D channel 3
ADCON0.3 = 1            ' ?
ADCON0.6 = 0            ' VDD is voltage reference
ADCON0.7 = 1            ' Right Justify result

ANSEL = %00111000       ' Set AN3 analog, rest digital
CMCON0 = 7              ' Analog comparators off

'GPIO port pins 0, 1 as outputs
TRISIO.0 = 0
TRISIO.1 = 0
TRISIO.5 = 0            ' LCD
                                                            
SEROUT LCD, 2400, [$FE, 1]  ' Clear LCD
pause 100 

start:
    ADCON0.1 = 1        ' Start conversion
    while ADCON0.1 = 1  ' Wait for conversion           
        Pauseus 100
    wend
    sample.highbyte = ADRESH        'Write conversion result
    Sample.lowbyte = ADRESL 
    PAUSE 10 
    
    'Display results
    if sample < 573 then ' < 12v
        LOW GrnLED                   
        HIGH RedLED
    endif
    if sample > 572 AND sample < 600 then    ' 12V TO 12.6V
        HIGH GrnLED
        HIGH RedLED
    endif
    if sample > 599 AND sample < 695 then  ' 12.6 TO 14.6
        HIGH GrnLED
        LOW RedLED
    endif
    if sample > 694 then ' > 14.6v
        LOW GrnLED
        TOGGLE RedLED
    endif
    Pause 100   
    
    LET Vin = sample * 5 / 1023 
    
display:
    SEROUT LCD, 2400, [$FE, 2]  
    serout LCD, 2400, ["Sample = "]
    serout LCD, 2400, [#Sample]
    SEROUT LCD, 2400, [$FE, $C0]
    serout LCD, 2400, ["Vin = "]
    serout LCD, 2400, [#Vin]
    Pause 100    
goto start
 

Attachments

  • Schema_final.JPG
    Schema_final.JPG
    104.7 KB · Views: 810
  • VMON_final.asm
    3.9 KB · Views: 209
  • VMON_final.zip
    1.1 KB · Views: 240
Last edited:
1) i'll suggest you to use DEBUG instead of SEROUT, it's actually more code efficient and have more useful features
2) have a look for DEC modifier in DEBUG section, and DIG modifier in section 4.17.7 of your manual.

Maybe the following link could give you some tips.
http://rentron.com/AD_LOG.htm

HTH
 
Adc

Your LED's is blinking because you are switching it on and off in jour last routine you have to use WHILE/WEND or IF/THEN your code
Code:
start:        
    
        HIGH GrnLED
        PauseUs(10)
        HIGH RedLED
        PauseUs(500)
        
goto start
Here is my code for a 16F818 but it will be easy to change to 12F683 If you have any problems with that contact me
Code:
Main:
       ADCON0 = %11000101                                'start ADC  PORTA.0
       gosub notdone
        IF adres < 127 then 
        High RedLED
        LOw GrnLED
        Else
        High GrnLED
        Low  RedLED
ENDIF
GOTO Main

notdone: Pause 5 
       If ADCON0.2 = 1 Then notdone                    ' Wait for low on bit-2 of ADCON0, conversion finished 
       return
End
And here is the complete program
Code:
'****************************************************************
'*  Name    : CarMonitor.PBP                                     *
'*  Author  : Chris Bezuidenhout                                *
'*  Notice  : Copyright (c) 2007 Micro Developments             *
'*          : All Rights Reserved                               *
'*  Date    : 2007/10/23                                        *
'*  Version : 1.1.1                                             *
'*  Notes   :                                                   *
'*          :                                                   *
'*  Website : http://www.patenttrade.net
'****************************************************************
INCLUDE "Modedefs.Bas"

       OSCCON = %01100000                  'set the intrc osc change bit 4 to logic  1 for 8 MHz
       OSCTUNE = %000000
       
DEFINE  OSC  4     ' Set IRC Frequency
DEFINE ADC_BITS 10       ' Set number of bits in result
DEFINE ADC_CLOCK 1    ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds
          
IgnIn    var     word
Altin    var     word
Oilin    var     word
TempIn   var     word
ResIn    var     word               'Reserve input
IgnOut   var     portb.0
AltOut   var     portb.1
OilOut   var     portb.2
TempOut  var     portb.3
Buzzer   var     portb.4
ComO     var     portb.5
SigOut   var     portb.6
sp2      var     portb.7
Spin1    var     porta.6
Spin2    var     porta.7
X        var     byte
Y        var     byte


TRISA = %11111111          'Porta 0-4 all analog 5 input only pull high
TRISB = %00000000
ADCON0 = %11000001
Pause 2000 ' Wait .5 second 
ADCON1 = %10000010 ' Set PORTA analog and RIGHT justify result



OPTION_REG = $7f        ' Enable PORTB pullups

pause 500
portb = 0
low Buzzer
    
       
       
Main:       
       gosub CIgn
       gosub CAlt
       gosub COil
       gosub CTemp
       gosub Send
       
       
Ignition:
       if ignin = 0 then 
       high Ignout
       gosub Send
       goto main
       endif
       if ignin > 300 then 
       low ignout
       goto Alternator
       endif
'       if ignin > 0 and ignin < 300 then
       for y = 1 to 3
       gosub CIgn
       gosub Send
       if ignin > 300 then  Alternator
       
       for x = 1 to 2
       high Ignout
       high buzzer
       pause 200
       low buzzer
       pause 200
       next x
       pause 1000
       next y    
       
'       endif
Alternator:
           if ignin = 0 then goto main
       low ignout       
       if Altin > 1020 then 
       high altout  '?????????Kalibreer
       for y = 1 to 3
       gosub CAlt
       gosub Send
       if altin < 1020 then Oil
       for x = 1 to 4
       high buzzer
       pause 200
       low buzzer 
       pause 200
       next x
       pause 1000
       next y
       endif
        
Oil:   
       if ignin = 0 then goto main
       low altout           
       if Oilin > 10 then    'This variable have to be calibrated to sensor unit
       high Oilout           'for a plain on/of it must be set to 0, the pot at minimum 
       for y = 1 to 3        'if there is some contact resistance it can be calibrated acordingly
       gosub COil            'For a analog (resistive) sensor it have to be calibrated to 
       gosub Send            'the sensor
       if oilin < 10 then Temperature    'So is this one
       for x = 1 to 6
       high buzzer
       pause 200
       low buzzer
       pause 200      
       next x
       pause 1000
       next y
       endif
       
Temperature:
            if ignin = 0 then goto main
       low Oilout
       if tempin < 85 then 
       high tempout
       for y = 1 to 3
       gosub CTemp
       gosub Send
       if tempin > 85 then main
       for x = 1 to 8
       high buzzer
       pause 200
       low buzzer
       pause 200 
       next x
       pause 1000  
       next y
       endif
       low tempout
   goto main         
CIgn:
       ADCON0 = %11000101             'start ADC  A0
       gosub notdone
       IgnIn.highbyte = ADRESH
       IgnIn.Lowbyte = ADRESL
       write 0,ignin.highbyte
       write 1,ignin.lowbyte
       return
CAlt:       
       ADCON0 = %11001101             'start ADC A1
       gosub notdone
       altin.highbyte = ADRESH
       altin.Lowbyte = ADRESL
       write 2,Altin.highbyte
       write 3,Altin.lowbyte
       return
COil:       
       ADCON0 = %11010101             'start ADC A2
       gosub notdone
       oilin.highbyte = ADRESH
       oilin.Lowbyte = ADRESL
       write 4,oilin.highbyte
       write 5,oilin.lowbyte
       return
CTemp:       
       ADCON0 = %11011101             'start ADC A3
       gosub notdone
       TempIn.highbyte = ADRESH
       TempIn.Lowbyte = ADRESL
       write 6,tempin.highbyte
       write 7,tempin.lowbyte
       return
CRes:       
       ADCON0 = %11100101             'start ADC A4
       gosub notdone
       resin.highbyte = ADRESH
       resin.Lowbyte = ADRESL
       Return        
Send:
       serout SigOut, N2400,["A",IgnIn.highbyte,IgnIn.lowbyte,altin.highbyte,altin.lowbyte,Oilin.highbyte,Oilin.lowbyte,Tempin.highbyte,Tempin.lowbyte,resin.highbyte,resin.lowbyte]
       return
notdone: Pause 5 
       If ADCON0.2 = 1 Then notdone' Wait for low on bit-2 of ADCON0, conversion finished 
       return
end
 
Last edited:
chrismicro, thank you for the feedback. It's interesting. As fior the blinking red LED, I used TOGGLE here on purpose. It blinks about 3 times per second if input voltage exceeds 14.6V.
 
Pleasure hope you get some use for the program and your on the right track with PICBasic, but be careful with to high a voltage on your AD channels, you can damage a good micro, use a zener to protect it
 
MrSpock.

What is the part number and maker for LCD1 also the price. If cheap enough for serial LCDs now, I might get me a couple for Chrismas.

I normally use MPLABS debugger and LED for debugging. But that is nice if the cost is not too high.
 
mramos1 said:
MrSpock.

What is the part number and maker for LCD1 also the price. If cheap enough for serial LCDs now, I might get me a couple for Chrismas.

mramos1, I used a generic serial LCD for debugging in my simulator program - Proteus, where it called "MILFORD-4X20-BKP" I have no idea if it's real and how much it cost.

This one: https://www.mouser.com/search/ProductDetail.aspx?R=27979virtualkey61900000virtualkey619-27979 is $35, but I don't know if it's gonna work - there is no datasheet on the website.
 
Status
Not open for further replies.

Latest threads

Back
Top