View Full Version : Help! Help understanding PIC ADC
ejaf
Feb 08, 2007, 11:59 AM
To all experienced PIC programmers out there...
I am reading up on PIC and their functions in particular, in order to help me with my project. Downloaded MikroBasic, and have been doing a lot of self teaching.
However, I am somewhat perplexed in regards to the ADC function that some PICs support. Basically, the function takes an analog signal, and converts it to a digital value (in the case of 8bit ADC, values are 0-255, If I'm interpreting this right).
OK...that's great, but what does this value represent? What I want to do in the long run is trigger an action when my voltage goes below a certain threshold (sound familiar?), but I'm at a loss of understanding what I can do with the value returned. Do I need another ADC value (let's say, some OpAmp that gives me a constant voltage) to compare it to? Or am I missing the boat in my understanding.
TIA...Eric
mmormota
Feb 08, 2007, 12:34 PM
OK...that's great, but what does this value represent? What I want to do in the long run is trigger an action when my voltage goes below a certain threshold (sound familiar?), but I'm at a loss of understanding what I can do with the value returned. Do I need another ADC value (let's say, some OpAmp that gives me a constant voltage) to compare it to? Or am I missing the boat in my understanding.
TIA...Eric
You can choose a stabilized internal voltage or the Vdd as voltage reference.
V_input = V_ref * AD_value / 2^n
where
V_input: the input voltage on the a/d input pin
V_ref: the voltage reference of your choice
AD_value: the result of the A/D conversion
2^n: n is the bit number of the conversion, ie. 256 if it's a 8 bit a/d, 4096v if it's a 12 a/d etc.
Example1: your choice is the Vdd as reference, and the power supply voltage is is 5V.
You have a 8 bit a/d.
You get 117 from the a/d.
V_input= 5V * 117/256= 2,285V
Example2: your choice is the internal reference, in the data sheet you found it 2,5V (depends on the type)
You have a 12 a/d
you get 1177 from the a/d
V_input= 2,5V * 117/4096 = 0,718V
JimDrew
Feb 08, 2007, 12:38 PM
The value represents a voltage range. VREF is typically the high end of the range, and VREF can be set to either the input voltage to the PIC or an external reference through one of the pins assigned for this function. Every PIC is a little different on how the A/D converter works, so make sure that you consult the datasheet for the PIC you are using.
In typical applications, VREF = INPUT VOLTAGE = +5 volts. If this is the case, then the voltage (5v) is divided by your 8 bit value (256) to give you .01953125 volts for each value of the A/D conversion. For example, if the value you received was 0x5A (90 decimal), the voltage would be 90 * .01953125 = 1.7578125 volts.
If you need to extend the range of the voltage being measured so that it is higher than what the PIC's A/D converter can handle, you need to use a simple voltage divider circuit (2 resistors), taking care that the total resistance does not exceed about 20K, otherwise insufficient current will cause random fluctuations in the A/D conversion.
ejaf
Feb 08, 2007, 01:16 PM
OK...
So, if I use an internal reference, and all I have to do is find what that value is, and then I should be good to go. Interesting. I didn't find any reference to that in the data sheet I was looking at, but then again it's the first time I'm plowing through one of these, so I'm quite overwhelmed, so say the least.
Would rather use the internal ref, I think, since my Voltage input will be between 3 to 4 V. Just wanted to see how I could flash different color LEDs when my Lipo starts getting close to my predetermined voltage value (I know...this is been done before, but I'm just trying to learn).
Thanks...I think, if I find the "magic" internal reference in the datasheet, I will be good to go.
Eric
Dan Baldwin
Feb 08, 2007, 01:53 PM
The smaller PICs that I use (12F675, 12F683) do not have an internal reference. You can either use VDD, or an external reference. In your case, it sounds like VDD voltage will vary, so you would need to use an external reference. What PIC are you planning on using?
Dan
mmormota
Feb 08, 2007, 03:23 PM
If there is no internal reference, use a micropower reference, like this one:
http://rocky.digikey.com/WebLib/Texas%20Instruments/Web%20data/REF2912_20_25_30_33_40.pdf
Measure the fixed 1.25 V of the device using the Vdd as reference.
Considering a 10 bit a/d (typical in smaller PIC's)
1.25V = Vdd * AD_result / 1024
Vdd = 1,25V * 1024 / AD_result
xorcise
Feb 08, 2007, 03:56 PM
I hate to be a nitpicker but the division of voltage is Vref/1023. 0 is a valid value which is 0V, then followed by 1023 more divisions up to Vref. That said, your accuracy may not require you worry too much about it, and division by 1024, or a binary shift-right 10 times, saves code space in a small PIC.
Also, PIC ADC's require low impendance sources, generally not over 2K and much lower is recommended. The higher the impedance the less accuracy and more time is required for acquisition.
mmormota
Feb 08, 2007, 04:21 PM
I hate to be a nitpicker but the division of voltage is Vref/1023. 0 is a valid value which is 0V, then followed by 1023 more divisions up to Vref.
Sorry, false... :D
Consider a 2 bit a/d, 4V reference.
input voltage average voltage a/d result
0...1V 0.5V 0
1...2V 1.5V 1
2...3V 2.5V 2
3...4V 3.5V 3
The best form:
V_in = 4V * (ad_result + 0.5) / 4
xorcise
Feb 08, 2007, 05:13 PM
PIC's are specified to be not more than 1/2LSB error. Your illustration shows average values, which is not how PIC ADC's work. There is a minimum acquisition time to charge the internal cap, based on variables such as impedance and temperature, and then starts the conversion of a fixed value.
The max possible ADC reading is 1023. Dividing Vref by 1024 and then multiplying by 1023 will leave you short of Vref....even with the specified error.
ejaf
Feb 08, 2007, 05:36 PM
I was actually looking at the datasheet for the PIC12F683, in order to understand. Thanks for pointing out that there is no internal reference. Now it's starting to make some sense.
I'll try to track down a datasheet for a PIC that does have internal reference, to see the differences between datasheets.
Thanks all.
Eric
xorcise
Feb 08, 2007, 06:00 PM
If there is no internal reference, use a micropower reference, like this one:
http://rocky.digikey.com/WebLib/Texas%20Instruments/Web%20data/REF2912_20_25_30_33_40.pdf
Measure the fixed 1.25 V of the device using the Vdd as reference.
Considering a 10 bit a/d (typical in smaller PIC's)
1.25V = Vdd * AD_result / 1024
Vdd = 1,25V * 1024 / AD_result
3V should be the minimum reference for the specified accuracy if using a 5V PIC.
Dan Baldwin
Feb 08, 2007, 06:02 PM
You can also use something as simple as a TL431 and a resistor as the external 2.5 volt reference. The only problem is that it takes up an I/O. Can you spare an I/O?
Dan
xorcise
Feb 08, 2007, 06:21 PM
I was actually looking at the datasheet for the PIC12F683, in order to understand. Thanks for pointing out that there is no internal reference. Now it's starting to make some sense.
I'll try to track down a datasheet for a PIC that does have internal reference, to see the differences between datasheets.
GP1/AN1 can be used as Vref for the 12F683. Otherwise, Vdd (usually 5V) is used by the PIC as Vref. ADCON0.VCFG (bit 6 of ADCON0) is for setting your voltage reference source.
Also note that if Vdd is 5V then your minimum user Vref will be 3V, although I use 2.5V without any problems.
mmormota
Feb 08, 2007, 10:53 PM
3V should be the minimum reference for the specified accuracy if using a 5V PIC.
If there is a stabilized 5V Vdd, then external reference voltage is unnecessary.
I considered that the PIC is connected to a Lipo battery. Then 3V is too much because of the dropout, maybe 2,5V, depends on how low dropout circuit can be find.
I still think (and pretty sure) that the correct division factor is 2^n and not 2^n-1. :D
jeffs555
Feb 08, 2007, 11:07 PM
I have to agree with xorcise. I don't use PIC's, but for all the other ADC's I have ever used, it was (2^n)-1.
mmormota
Feb 08, 2007, 11:19 PM
I have to agree with xorcise. I don't use PIC's, but for all the other ADC's I have ever used, it was (2^n)-1.
There are two different things.
1. The highest value you get is 2^n-1, but this is not the point we are arguing.
2. One step represents V_ref/2^n
jeffs555
Feb 08, 2007, 11:36 PM
Reduce your 2-bit example to 1 bit and see how it works out with a 4 volt reference. Is one step equal to 2volts(ie 4V/2^1) or is it equal to 4volts(ie 4V/2^1-1). Again, an ADC could be made the way you suggest, but all that I have used were not.
JimDrew
Feb 08, 2007, 11:37 PM
Also, since you are planning to use the internal ref (Vdd), make sure that you take samples when the voltage does not fluctuate due to improper power supply voltages. For example, if your voltage regulator did not have the proper filitering, it is possible to get a distinctly different A/D conversion value when a LED is ON and when it is OFF. People don't seem to want to filter the input and output of their voltage regulators properly. I have a fixed a lot of designs where the entire project didn't work at all until a few caps were added.
JimDrew
Feb 08, 2007, 11:38 PM
The PICS use 1024 steps for the 10 bit A/D versions and 256 steps for the 8 bit versions.
ejaf
Feb 08, 2007, 11:45 PM
Reading my mind, are we?
Yes, I can probably spare one IO port, to swap it for a vRef. Yes, vDD will be from a Lipo.
Don't have a clue (yet), about the formula you guys are debating...last kind of programming I was doing was RPG and COBOL, now it's all Perl :eek: Hex values, BAL, and Boolean Algebra was a long, long time ago :D . I do remember my teacher for Boolean, though...funny guy who used to work for IBM :eek:
Is there an 8-Pin PIC that supports internal reference? Can't seem to find any in the 12 series. Will digest the OpAmp into GP0 idea, but didn't want to have to add other components onto the PCB, if possible (but if I need the 12F683, then I'll have to, at least I understand that much ;) ).
Wow, you guys are great...thanks again.
E
jeffs555
Feb 09, 2007, 12:14 AM
The PICS use 1024 steps for the 10 bit A/D versions and 256 steps for the 8 bit versions.
You can't read 1024 steps with 10 bits, and you can't read 256 steps with 8 bits. You get 1024 and 256 discrete values, but only 1023 and 255 steps. The only question is whether in the PIC(using an 8 bit ADC), a digital value of 255 represents the reference voltage, or if it represents the reference voltage times 255/256.
PS This app note http://ww1.microchip.com/downloads/en/AppNotes/00546e.pdf
implies that at least for the PIC16C7x, mmormota is right, and a digital value of 255 represents the reference voltage times 255/256. I guess that is what you meant by 256 steps Jim.
ejaf
Feb 09, 2007, 01:43 PM
Just for my understanding...
If I am reading this datasheet right, the PIC12HV615/PIC12F609 will allow me to compare vDD to an internal vREF (at least I think I'm reading section 8.10 correct).
Just would like confirmation of that, before I rack my brains anymore.
Boy, I got a lot of learning to do!
PIC12F609 Datasheet (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2057&ty=&dty=Data+Sheets§ion=Data+Sheets&ssUserText=PIC12HV615)
JimDrew
Feb 09, 2007, 01:50 PM
If you want to use a voltage higher than 5 volts (the maximum most PICs will handle properly), I would suggest a simple resistor divider circuit. If you need incredible resolution, then you are going to need to use an op-amp that is adjusted for the input voltage you expect, either preset or adjustable electronically.
mmormota
Feb 09, 2007, 02:29 PM
Just for my understanding...
If I am reading this datasheet right, the PIC12HV615/PIC12F609 will allow me to compare vDD to an internal vREF (at least I think I'm reading section 8.10 correct).
Just would like confirmation of that, before I rack my brains anymore.
Boy, I got a lot of learning to do!
PIC12F609 Datasheet (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2057&ty=&dty=Data+Sheets§ion=Data+Sheets&ssUserText=PIC12HV615)
If my understanding is correct, this one is tricky. You can't select an internal reference voltage as the reference of the a/d.
But, there are internal reference voltages, and you can select as input and measure them. ;)
Using this feature, you can accurately measure voltages. Select the Vdd as reference, select as input and measure the internal reference first, then select the input you want to measure, then apply correction according the known voltage.
Ie.
you measured the 1.25 V internal voltage as say 153,
then measured the V_in as 317, then
V_in= 1,25V * 317/153
Gary Warner
Feb 09, 2007, 04:59 PM
I understand you want to act on a voltage threshold. The 12F683 has an analog comparator module with programmable internal reference voltage. Seems learning this part of the PIC will serve you better than the AD approach. Read section 9.0
ejaf
Feb 09, 2007, 05:47 PM
I'll read that one next...thanks.
Bruce Abbott
Feb 09, 2007, 11:47 PM
The 12F683 does not have an internal reference. The comparator's 'reference' voltage is just a proportion of Vdd.
If you don't want to waste an I/O pin then you can regulate Vdd and use it as the reference. Either a series or shunt regulator (eg. TL431) would work. The TL431 provides good accuracy at low cost, but needs a volt or two to work with. A good LDO regulator can work down to within 0.1V of the supply.
The math required to determine A/D output can be quite tricky. It might be easier to first create a program that displays the actual digital values for various input voltages, then embed these values into your code (or perhaps write them into the EEPROM?).
ejaf
Feb 10, 2007, 12:10 AM
So it's a proportion of the vDD, based on the Rss and CHOLD in figure 9-4 in the datasheet? Rss would have to be chosen to give me a digital reading which could be then converted to some actual voltage?
I think I'm getting lost...and seeing double right now...better get something to drink.
westfw
Feb 10, 2007, 01:55 AM
If you're trying to monitor your supply voltage, you can also set the A-D to use Vdd as the reference and
connect a real voltage reference to the A-D input pin. This is eqivalent to re-solving the equation for Vdd:
V_input = V_ref * AD_value / 2^n
or V_input = Vdd*AD_value/2^n
becomes: Vdd = V_input*2^n/AD_Value
So if your reference part (AD_input) is 2.5V, and Vdd starts at 5V, you'll read 128.
If you read 200, you know your that Vdd must now be 3.2V (checking, see if
2.5 = 3.2*200/256 Yep!) This saves you a pin...
ejaf
Feb 10, 2007, 09:08 AM
westfw...
So, in that idea, I would still need to set up one of the pins to supply 2.5 V, via an opamp, or some other thing, which supplies vRef that constant current, correct? Therefore it would take up 2 pins, one for Vdd and one for Vref.
How does that save a pin? Unless I'm way off base in understanding this.
That formula you have is exactly the output I want:
- check every x seconds
- if result > 3.3, flash green
- if result between 3.3 and 3.1, flash green and red
- if result less than 3.1, flash red, find a landing spot that you don't care about blowing up ;)
Bear with me, please, I'm quite a newbie at this.
Eric
dleroi
Feb 10, 2007, 09:17 AM
Ok, I know you've answered this somewhere, but I can't find it now. Is the battery you are monitoring the same one that will power the monitor circuit you are building?
ejaf
Feb 10, 2007, 09:43 AM
yup...don't know whether I specifically answered that before, though.
dleroi
Feb 10, 2007, 01:54 PM
I would start with a low drop out regulator, either 3.0 or 2.5 volts, like the TPS7230 or TPS7225, for VDD and use VDD as the reference. Then, I would scale the A/D input down a little with a voltage divider to ensure it's always below VDD.
I suggest you breadboard something simple right now, using whatever you have available (a PIC, LED, variable resistor, and 5V power supply?), then sort this out. Start simple - light the LED. Then, light it based on a high or low on a digital input. Then, based on a voltage level on an A/D input. Going from the simple to the complex will do wonders for your morale and you'll be amazed at how quickly you can erase and re-program the PIC!
ejaf
Feb 10, 2007, 03:35 PM
okey dokey...confidence booster needed right now. If I keep asking all these questions, I'll never get around to practicing.
Just one quick question...will the PIC12F683 eventually do what I want? That way, I can order a bunch, and then won't have to order another to handle the Voltage reference question.
dleroi
Feb 10, 2007, 04:31 PM
Yes.
I was going to suggest a supplier ( www.glitchbuster.com ), that has really reasonable shipping and no minimums, but I just went to his site and found that he's having a going out of business sale. Too, bad. I'm sure there are others, but Newark (www.newark.com) is another that comes to mind that doesn't charge handling on small orders.
You still might want to look at Glitchbuster's other stuff, though.
ejaf
Feb 10, 2007, 06:01 PM
Awesome...I was going to take a bath on shipping from either Microchip directly, or Digikey. Will look into Newark.
Just one more question, before I stop bugging you all. Without an internal voltage reference on the PIC, the only way to do what I want to do is via one pin with Vdd, and one with Vref. Right?
TIA...Eric
dleroi
Feb 10, 2007, 11:27 PM
Without an internal voltage reference on the PIC, the only way to do what I want to do is via one pin with Vdd, and one with Vref. Right?
No. If you use VDD as the reference, it becomes the "internal" reference and the Vref pin can be used for other purposes.
ejaf
Feb 11, 2007, 01:33 PM
So...you can specify Vdd as an internal reference of let's say 3.0 V, and then run the ADC on Vdd and compare the ref value to the value calculated on Vdd.
OK...thanks...
E
dleroi
Feb 11, 2007, 04:16 PM
So...you can specify Vdd as an internal reference of let's say 3.0 V, and then run the ADC on Vdd and compare the ref value to the value calculated on Vdd.
E
Even simpler.
You tell it to use Vdd for Vref and you set up a pin for analog input. Then, you tell it to read that pin into a variable. The result will be a number between 0 and 1023. If you multiply that by the resolution (Vdd/1023), you get the voltage. Alternatively, you can compute what the numbers will be for the voltages you want and just compare the result with your calculations. That would reduce the overhead significantly.
For example, let's say that Vdd is 3V and you're using 2 equal resistors as a voltage divider to cut the input voltage in half. You do the A/D and the result is 682. The battery voltage is (682 x 3/1023 x 2), or 4 volts. Of course, the PIC is seeing only 2 volts because of the voltage divider.
Now, let's say you want to do something when the voltage drops below 3.3 volts. You could do the read, calculate the voltage as we did above, test if result < 3.3, then light an LED if it is.
Or, you could do the read, test if returned value is < 563, then light an LED if it is.
How did I get the 563? It's 3.3 divided by 2 (because of the voltage divider) divided by the resolution of the A/D (3/1023). Or, (3.3/2)/(3/1023) = 562.65
- D
ejaf
Feb 11, 2007, 10:06 PM
Awesome! Thanks for the real world explanation.
E
dleroi
Feb 12, 2007, 12:07 AM
Ejaf,
Here's another good parts place that I couldn't think of before:
http://www.hobbyengineering.com/SectionPC.html
- D
westfw
Feb 12, 2007, 04:12 AM
Therefore it would take up 2 pins, one for Vdd and one for Vref.
How does that save a pin? the Vdd pin is the power pin, which you need anyway,
so it's "free." Or, this scheme uses a known voltage as the A-D input, and an unknown
voltage for the power supply AND internal Vref, for a total of two pins. The other
scheme for reading a varying supply voltage needs the supply pin, an A-D pin connected
to the supply, AND an external reference voltage connected to the external Vref pin, for
a total of THREE pins.
GeorgeP
Feb 12, 2007, 10:22 PM
-D...
Thanks for your "real world" explanation, as ejaf said.
I have been following this thread because I want to program up a 12F675 as a low voltage detector for my Corona battery. I have searched high and low for a example of doing just what you said and I can't find anything. I did print out the 12F675 data sheet but sorry... it's beyond me at least at this point in the game.
Do you or does anyone else have a example of a simple .asm for voltage sampling using the Vdd as ref and the battery input on another pin as you described above? I understand the hardware voltage divider and bypassing caps etc, it's the software end I need to see.
tnx
George
ejaf
Feb 12, 2007, 11:29 PM
George...
That's cheating!!! We both have to go take the "lab" classes first ;)
There's a good example of this in mikroBasic, if that's your style, right on their website. Doesn't actually "compare", but does the ADC conversion. Funny thing is that it lights up LEDs upon the conversion, but what they stand for is anybody's guess (perhaps just a randomizer).
E
GeorgeP
Feb 13, 2007, 07:41 AM
"Cheating"? Well... maybe.
I have programmed in assembly in the past - 6502, 8080, Z80, but that was when most folks were "Beginners" because computers were just starting and everyone was learning. There was always a lot of examples of how the various parts worked and how to intergrate what you needed into the program you were writing. I just recently heard about the PIC's and bought a bunch of 12F675's to play with, but I can't find any step by step examples how to use the AtoD that is written in .asm.
I want to use the 5v BEC output from the ESC as the Vdd supply and then thru a voltage divider to sample the Nimh battery (9.6v) level and feed that to a input pin. Program the 12F675 so when the battery level drops to 8.8v (1.1v/cell) the alarm sounds.
I currently have MPLab and with it's build in simulator and register "Watch" function I would really like to use it for my programming, but I will take a look at the Microbasic as you suggested. tnx
We're Havin Fun.... Right??
dleroi
Feb 13, 2007, 07:57 AM
I'll try to find time in the next few days to build a battery alarm using the 12F675 as I described above, but for a 3s Li-ion pack. I'll share the experience, here.
- D
GeorgeP
Feb 13, 2007, 09:47 AM
-D
3S or 8C, the principals will be the same. Once I see how it's done, I can tailor it for my specific needs. This will be great... tnx
George
ejaf
Feb 13, 2007, 11:40 AM
No fair...I want the code in Basic, not ASM :D
Long time since I took BAL in school, so wanted to do this in Basic.
I do agree, though, that seeing example code to do it usually helps in understanding. In my work life, there's not much coding done that's truly "new", just "reworked".
E
dleroi
Feb 13, 2007, 11:44 AM
No fair...I want the code in Basic, not ASM :D
E
OK, how about both?
Malc C
Feb 13, 2007, 11:56 AM
No fair...I want the code in Basic, not ASM :D
E
Just yahoo'd "picbasic battery monitor" and came up with some links that you might be able to adapt
http://www.picbasic.co.uk/forum/showthread.php?t=541
http://list.picbasic.com/forum/messages/4011/4066.html?1024857059
ejaf
Feb 13, 2007, 01:07 PM
(how about both???)
LOL!!!
(Bowing down and chanting the above).
Also will plow through Malc's links. So far, I was at more of a "design" and "understanding" level, rather than the "dev" stage, but I'll take all of this in...it will sink in eventually, right?
E
dleroi
Feb 13, 2007, 07:52 PM
'Example code for battery monitor
'Uses Vdd as reference and internal oscillator
'Lights one LED when voltage is below 50% of Vdd
'Lights two LEDs when voltage is below 25% of Vdd
'For Proton IDE Lite Basic Compiler
Device = 12F675
' Pin 1: Vdd
' Pin 2: No connection
' Pin 3: No connection
' Pin 4: No connection
' Pin 5: GP2 LED 2
' Pin 6: GP1 LED 1
' Pin 7: AN0 (voltage in)
' Pin 8: Vss
XTAL = 4
' Set data code protection, code protection, brown out detection, watchdog timer, and mclr function OFF;
' power-up timer ON; and oscillator to internal.
Config CPD_OFF, CP_OFF, BODEN_OFF, WDT_OFF, MCLRE_OFF, PWRTE_ON, INTRC_OSC_NOCLKOUT
Dim ADC_Val As ADRESL.Word ' Combine ADRESL and ADRESH registers into a word variable
Dim i As Byte ' For/Next loop counter
Symbol LED1 = GPIO.1 ' Define pin 6 as LED1
Symbol LED2 = GPIO.2 ' Define pin 5 as LED2
DelayMS 500 ' Wait for PIC to settle
' ----- Init the ADC ----------------------------------
INIT_ADC:
TRISIO = %111001 ' Pins 5&6 as outputs, rest as inputs
ANSEL = %00110001
'ANSEL.0 = 1 ' Analog
'ANSel.1 = 0 ' Digital
'ANSel.2 = 0 ' Digital
'ANSel.3 = 0 ' Digital
'Ansel.4 = 1 ' Set ADCS to internal clock
'Ansel.5 = 1 ' "
'Ansel.6 = 0 ' "
'Ansel.7 = 0 ' Unused
ADCON0 = %10000000
' ADCON0.0 = 0 ' ADC off
' ADCON0.1 = 0 ' ADC status (GO/!DONE)
' ADCON0.2 = 0 ' Channel 0 selected
' ADCON0.3 = 0 ' "
' ADCON0.4 = 0 ' Unused
' ADCON0.5 = 0 ' Unused
' ADCON0.6 = 0 ' Set VREF To VDD
' ADCON0.7 = 1 ' Right justify the ADC result
' ----- Main ----------------------------------
For i = 1 To 4 'Flash the LEDs at startup
High LED1
DelayMS 250
Low LED1
High LED2
DelayMS 250
Low LED2
Next i
While 1 = 1 ' Loop forever
GoSub GET_ADC ' Read the ADC pin
If ADC_Val < 256 Then '25% of Vdd
High LED2
Else
Low LED2
EndIf
If ADC_Val < 512 Then '50% of Vdd
High LED1
Else
Low LED1
EndIf
DelayMS 500 ' Wait for .5 second
Wend
' ----- Read the voltage ----------------------------------------
GET_ADC:
ADCON0.0 = 1 ' Enable ADC - bit 0 of ADCON0 register is the enable bit: 1 = enabled, 0 = disabled.
DelayUS 50 ' Wait for capacitors to charge
ADCON0.1 = 1 ' Do conversion - bit 1 of ADCON0 register is status (Go/Done): 1 =Go (start), 0 = Done
While ADCON0.1 = 1 : Wend ' Watch GO/DONE flag 'til conversion is done
ADCON0.0 = 0 ' Disable the ADC
Return
dleroi
Feb 13, 2007, 07:54 PM
Sorry, guys. All my nice formatting got lost when I posted the above code. Here's a better one, hopefully, for studying.
-Don
'Example code for battery monitor
'Uses Vdd as reference and internal oscillator
'Lights one LED when voltage is below 50% of Vdd
'Lights two LEDs when voltage is below 25% of Vdd
'For Proton IDE Lite Basic Compiler
Device = 12F675
' Pin 1: Vdd
' Pin 2: No connection
' Pin 3: No connection
' Pin 4: No connection
' Pin 5: GP2 LED 2
' Pin 6: GP1 LED 1
' Pin 7: AN0 (voltage in)
' Pin 8: Vss
XTAL = 4
' Set data code protection, code protection, brown out detection, watchdog timer, and mclr function OFF;
' power-up timer ON; and oscillator to internal.
Config CPD_OFF, CP_OFF, BODEN_OFF, WDT_OFF, MCLRE_OFF, PWRTE_ON, INTRC_OSC_NOCLKOUT
Dim ADC_Val As ADRESL.Word ' Combine ADRESL and ADRESH registers into a word variable
Dim i As Byte ' For/Next loop counter
Symbol LED1 = GPIO.1 ' Define pin 6 as LED1
Symbol LED2 = GPIO.2 ' Define pin 5 as LED2
DelayMS 500 ' Wait for PIC to settle
' ----- Init the ADC ----------------------------------
INIT_ADC:
TRISIO = %111001 ' Pins 5&6 as outputs, rest as inputs
ANSEL = %00110001
'ANSEL.0 = 1 ' Analog
'ANSel.1 = 0 ' Digital
'ANSel.2 = 0 ' Digital
'ANSel.3 = 0 ' Digital
'Ansel.4 = 1 ' Set ADCS to internal clock
'Ansel.5 = 1 ' "
'Ansel.6 = 0 ' "
'Ansel.7 = 0 ' Unused
ADCON0 = %10000000
' ADCON0.0 = 0 ' ADC off
' ADCON0.1 = 0 ' ADC status (GO/!DONE)
' ADCON0.2 = 0 ' Channel 0 selected
' ADCON0.3 = 0 ' "
' ADCON0.4 = 0 ' Unused
' ADCON0.5 = 0 ' Unused
' ADCON0.6 = 0 ' Set VREF To VDD
' ADCON0.7 = 1 ' Right justify the ADC result
' ----- Main ----------------------------------
For i = 1 To 4 'Flash the LEDs at startup
High LED1
DelayMS 250
Low LED1
High LED2
DelayMS 250
Low LED2
Next i
While 1 = 1 ' Loop forever
GoSub GET_ADC ' Read the ADC pin
If ADC_Val < 256 Then '25% of Vdd
High LED2
Else
Low LED2
EndIf
If ADC_Val < 512 Then '50% of Vdd
High LED1
Else
Low LED1
EndIf
DelayMS 500 ' Wait for .5 second
Wend
' ----- Read the voltage ----------------------------------------
GET_ADC:
ADCON0.0 = 1 ' Enable ADC - bit 0 of ADCON0 register is the enable bit: 1 = enabled, 0 = disabled.
DelayUS 50 ' Wait for capacitors to charge
ADCON0.1 = 1 ' Do conversion - bit 1 of ADCON0 register is status (Go/Done): 1 =Go (start), 0 = Done
While ADCON0.1 = 1 : Wend ' Watch GO/DONE flag 'til conversion is done
ADCON0.0 = 0 ' Disable the ADC
Return
GeorgeP
Feb 13, 2007, 08:50 PM
-Don...
Tnx for the example in Basic. While I was planning in getting back into assembly programming, I do have the Proton IDE Lite Basic Compiler also, so maybe I'll give it a try.
George
dleroi
Feb 13, 2007, 09:06 PM
-Don...
Tnx for the example in Basic. While I was planning in getting back into assembly programming, I do have the Proton IDE Lite Basic Compiler also, so maybe I'll give it a try.
George
George,
I would. It beats the heck out of coding in assembly.
I'm still planning to do the assembly code, but thought I'd do the easier one first. I used to think in assembly back in the day, but that was a long time ago and not PICs. So, I have to bone up on the PIC opcodes.
- Don
GeorgeP
Feb 13, 2007, 10:40 PM
-Don
I have to admit that the Basic code is a lot easier to follow, a lot of the "overhead" is taken care of. I dumped your example into Proton IDE Lite and it compiled fine so I'm going to experiment with it a bit in the next few days and set the assembly code on the back burner for a while.
Do have a question tho... What kicks it out of the "While 1 = 1 ' Loop forever" in line #73?
Really Havin Fun Now!! :-)
tnx
George
ejaf
Feb 13, 2007, 11:31 PM
Yes...one big thanks...Monsieur Le Roi...or should I say, "King of Teachers" (although there are many on this forum).
Saving PDF now...
Edit...
What kicks you out of the loop would be crash, or you powering off.
What I don't get is where do the 50% and 25% figure here...we're using Vdd as Vref, right? So if that's the case, Vdd will be decreasing, as well as Vref, no?
Basically, how do you know that 256 is 50% of Vdd, and 512 is 25%?
When the capicitor is charging, it charges to a set voltage? Confusion in my head about this now...
dleroi
Feb 13, 2007, 11:52 PM
George,
All of the set up takes place first. Once it gets into the loop, it just keeps repeating every 1/2 second until it's turned off. Within the loop, it jumps to the Get_ADC subroutine, which does the read and leaves the result in ADC_VAL. When it returns from Get_ADC, it checks ADC_Val against the values 256 and 512 to see if it should activate either LED. Then it takes a short breather before it returns to the top of the loop to do it over again.
Make sense?
- Don
ejaf
Feb 14, 2007, 12:03 AM
but how do you know to check against the values 256 and 512?
dleroi
Feb 14, 2007, 12:29 AM
What I don't get is where do the 50% and 25% figure here...we're using Vdd as Vref, right? So if that's the case, Vdd will be decreasing, as well as Vref, no?
Basically, how do you know that 256 is 50% of Vdd, and 512 is 25%?
When the capicitor is charging, it charges to a set voltage? Confusion in my head about this now...
Ejaf,
No, Vdd doesn't change and, therefore, Vref doesn't either.
In my case, I will be monitoring a 11.1 volt pack, so I will use a 5 volt regulator to supply Vdd and an appropriate voltage divider to scale the 11.1 down to less than 5 volts for input to the ADC.
In your case, you will use either a 3.0 or 2.5 volt LDO regulator for Vdd and an appropriate voltage divider to scale your battery's voltage down to less than Vdd. So, you will have landed or crashed before Vdd changes.
I used 512 (50% of 1024) and 256 (25% of 1024) in the example because I could do the math in my head.
The capacitor, which is part of the ADC, charges to whatever voltage is on the pin being used for ADC input. Technically, you would calculate the required delay using a formula that takes into account the input resistance from your voltage divider. I threw in 50 uSeconds to cover just about any setup.
- Don
dleroi
Feb 14, 2007, 12:53 AM
but how do you know to check against the values 256 and 512?
I used 512 and 256 only as an example to test the program. I programmed a chip (12F675), hooked up a 10K potentiometer between Vdd and ground and feed the voltage on the wiper to AN0 of the PIC. I hooked a voltmeter to the wiper also. As I adjusted the pot down from 5 volts, the first LED lit at 2.5 and the other one came on at 1.25. That was all I needed to see to feel comfortable posting the code.
Now, let's say you want to do something when the voltage drops below 3.3 volts. You could do the read, calculate the voltage as we did above, test if result < 3.3, then light an LED if it is.
Or, you could do the read, test if returned value is < 563, then light an LED if it is.
How did I get the 563? It's 3.3 divided by 2 (because of the voltage divider) divided by the resolution of the A/D (3/1023). Or, (3.3/2)/(3/1023) = 562.65
- D
You will use something different, based on the quote above, for yours and I will use something different for mine.
Now, you have to do some building, sir!!!
Regards,
Don
Malc C
Feb 14, 2007, 04:35 AM
Sorry, guys. All my nice formatting got lost when I posted the above code.
-Don
Don,
You can use the "[ code ]" and "[ /code ]" commands (without the quote marks and spaces) to list code on most forums.
dleroi
Feb 14, 2007, 07:31 AM
Malc,
I didn't know that. Thanks for the tip!
ejaf
Feb 14, 2007, 08:38 AM
get it now...thanks.
Is there any advantage to setting Vdd to Vref, instead of just pushing constant voltage through AN0 and using that for Vref?
dleroi
Feb 14, 2007, 08:46 AM
get it now...thanks.
Is there any advantage to setting Vdd to Vref, instead of just pushing constant voltage through AN0 and using that for Vref?
Not sure what you mean. You have 2 choices. If you set Vref to Vdd, the PIC grabs Vdd internally. If you set Vref to external, you have to connect your own reference source to pin 6.
Here's a rough schematic of the circuit I'm using:
ejaf
Feb 14, 2007, 02:45 PM
got it...and thanks once again.
Don't think my PIC order's going to get here today, though...major ice storm outside here in the NY area.
E
dleroi
Feb 14, 2007, 02:56 PM
got it...and thanks once again.
Don't think my PIC order's going to get here today, though...major ice storm outside here in the NY area.
E
Ejaf,
I think that once you get started you'll find many more uses for PICs. From whom did you decide to order yours?
I hear you about the weather! We're just across the L.I. Sound in CT.
- Don
ejaf
Feb 14, 2007, 04:33 PM
Actually...Microchip directly...their prices were just a tad lower than Newark's, and I also needed some of these, since I'm building a Lipo charger out of them...
Lipo charger chip (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocName=en027785)
Shipping is only by FedEX second day air, though, cost me 9 bucks, but no one had that charger chip in stock, except them.
E
GeorgeP
Feb 14, 2007, 04:39 PM
- Don
I got it now.... I missed the "Wend" at the end of the loop. When I saw the "While 1 = 1" I was thinking of the DO-LOOP type of command where it would just sit there and loop until a interrupt of some sort would kick it out. When I looked up the "While" command I saw that it loops to the "Wend" statement and sure enough... there you put one. I have 10 of these 12F675's, this is going to be fun. I may have to invest in the full Proton IDE, 50 lines in free Lite version won't go too far.
tnx agn
Hey Ejaf....
I hear there is a market for fresh snow on Ebay... ?? :-)
dleroi
Feb 14, 2007, 05:12 PM
George and Ejaf,
I'm glad you're both pursuing this. It is a lot of fun and these PICs make it easy to accomplish things that used to require a ton of components.
George, if you're in no hurry for the assembly version, I'll take a short break. What part of the world are you in, anyway?
Ejaf, I've been happy ordering from MicroChip in the past. I, too, used one of their Li-ion/Lipo ICs for a battery charger recently. Small world.
Take care.
- Don
GeorgeP
Feb 14, 2007, 06:43 PM
-Don
I'm going to stick with the Basic for now, but I would like to see this in assembly at some time. I did have Proton display the assembly version it, but I quickly got lost, so it's Basic for the foreseeable future on this end.
I'm in Minnesota.... It -never- snows here. In fact, we are having such a great winter that all the snowbirds from Canada are stopping here instead of going to Florida! It got up to 10 degrees above zero today... We're Havin a Heatwave... I went out and washed my truck. :-)
George
dleroi
Feb 18, 2007, 10:33 PM
George and Ejaf,
Here it is in assembly - written and debugged with the MPLAB IDE.
I had trouble getting it to work with 2 triggers until I realized that the comparator had to be disabled. I don't think I disabled it in the BASIC version, so you may want to go back and check that.
The formatting got whacked a little when I copied it here. It isn't too bad, but let me know if you want me to email you a clean copy.
Have fun with it.
- Don
; MPASM code for PIC12F675-based voltage detector.
;
; Requires 12F675.lkr
;
; Uses Vdd as Vref
; Calculates alert levels based on Vref
;
; Uses the leftmost 8 bits from the ADC
; Resolution is roughly (Vdd/1023)*4
;
; Set LowV1 and LowV2 to the desired value in mV plus resolution in mV, i.e. d'3320'
; for 3.3 volt trigger with Vdd of 5 volts.
;
; Set Vref to the Vdd voltage in mV, i.e. d'5000' for 5 volts
;
; Configuration fuses:
; CP disabled
; CPD disabled
; BODEN disabled
; MCLR disabled
; PWRTE enabled
; WDT disabled
; OSC internal RC (no clockout)
;
; Pins:
; AN0 (7)<- Analog Voltage
; GP1 (6)-> Alert 1 (LED1)
; GP2 (5)-> Alert 2 (LED2)
;
;***********************************************
list p=12f675 ; list directive to define processor
#include <p12f675.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
#DEFINE LED1 GPIO,1
#DEFINE LED2 GPIO,2
Delay1 equ 0x20
Delay2 equ 0x21
Temp1 equ 0x28
Count equ 0x36 ;For..Next Index
LowV1 equ d'3520' ;First low voltage point in mV
LowV2 equ d'3320' ;Second low voltage point in mV
Vref equ d'5000' ;Reference voltage in mV
Org 0x000
goto Main
Main
call 0x3FF ;Retrieve factory cal value
bsf STATUS,5 ;RAM BANK 1
movwf OSCCAL ;Update register
bcf STATUS,5 ;RAM BANK 0
; Wait for PIC to stabilise
movlw d'250'
Call DelayMS
; Initialize
bsf STATUS,5 ;RAM BANK 1
movlw b'00101001' ;TRISIO - set pins 7,4, and 2 as inputs; 6,5,3 as outputs
movwf TRISIO
movlw b'00110001' ;ANSEL - set pin 7 to analog; 6,5, and 4 to digital; FRC for clock
movwf ANSEL
movlw b'0000000' ;ADCONO - left justify ADC result, Vref=Vdd, Select ADC channel 0
bcf STATUS,5 ;RAM BANK 0
movwf ADCON0
movlw b'00000111' ;CMCON - disable comparator
movwf CMCON
bcf LED1 ;Off
bcf LED2 ;Off
;Blink the LEDs 4 times on startup
movlw 1
movwf Count ;Initialize Count to 1
Blink
movlw 5 ;Load 'W' with 5
subwf Count,W
btfsc STATUS,0
GoTo Blinked
bsf LED1 ;On
movlw d'250' ;Pause
Call DelayMS
bcf LED1 ;Off
bsf LED2 ;On
movlw d'250'
Call DelayMS
bcf LED2 ;Off
bcf STATUS,5 ;RAM BANK 0
incfsz Count,F
GoTo Blink
Blinked
ADCLoop
Call GET_ADC
Call VoltCheck1
Call VoltCheck2
;Wait for half a second
movlw d'250'
Call DelayMS
movlw d'250'
Call DelayMS
GoTo ADCLoop
;************************************************* ****
GET_ADC
;************************************************* ****
bsf ADCON0,0 ;Enable ADC
movlw d'5' ;Wait 50 uSec
Call DelayuS
bsf ADCON0,1 ;Set ADCON bit 1 (GO/DONE) to start conversion
ADC_Wait
btfsc ADCON0,1 ;Test GO/DONE.
GoTo ADC_Wait ;It isn't done, so loop
GoTo ADC_Done ;It's done, so exit loop
ADC_Done
bcf ADCON0,0 ;Disable ADC
Return
;************************************************* ****
VoltCheck1
;************************************************* ****
;Check ADC against the first limit
movfw ADRESH
sublw (LowV1 * d'255') / Vref
btfss STATUS,C
GoTo VoltCheck1OK
bsf LED1
Return
VoltCheck1OK
bcf LED1
Return
;************************************************* ****
VoltCheck2
;************************************************* ****
;Check ADC against the second limit
movfw ADRESH
sublw (LowV2 * d'255') / Vref
btfss STATUS,C
GoTo VoltCheck2OK
bsf LED2
Return
VoltCheck2OK
bcf LED2
Return
;************************************************* ****
DelayMS ;Delays the number of millisecs in W on entry
;************************************************* ****
movwf Delay2 ; save 'W'
MSloop
movlw d'100'
Call DelayuS
decfsz Delay2, f
goto MSloop
Return
DelayuS ;Delays 10x 'W' microsecs on entry
movwf Delay1 ; save 'W' in a register of our own
uSloop
nop ; each nop is 1 microsec
nop
nop ; each total loop is 10 microseconds
nop
nop
nop
nop
decfsz Delay1, f ; this is 1 microsec if skip not taken
goto uSloop ; this is 2 X 1 microsec
Return
END ;end of program
xorcise
Feb 18, 2007, 11:37 PM
Actually...Microchip directly...their prices were just a tad lower than Newark's, and I also needed some of these, since I'm building a Lipo charger out of them...
We carry a few PIC's including the 12F683 and ship from NYC. I'm sure we can save you some shipping time and shipping costs for some items.
CircuitED (http://circuit-ed.com)
GeorgeP
Feb 19, 2007, 10:18 AM
DON
Thanks for the .asm vesion. I have been playing with your basic version and have realized quickly that the 50 lines of code allowed in Proton Lite gets used up rather fast. I want to add a cell # detect and the ability to switch it for Nimh or A123's levels. I do like the ease of Basic, but not sure I am ready to invest the $295 they want for the full version. I'll take a look at your .asm example tonight.
tnx
George
rmteo
Feb 19, 2007, 12:00 PM
George,
You should really take a look at mikroBasic - a FREE version that is limited to 2,000 hex words, more than you need for now - is available for download here:
http://www.mikroe.com/en/compilers/mikrobasic/pic/download.htm
It sells for $149.99 and if you get one of their development boards, the compiler will cost you just $99. Their EasyPIC4 development system is a full-featured development Board for the Microchip PIC MCU's. There is USB 2.0 on-board programmer and mikro ICD (In-Circuit Debugger) on-board and will handle 8-40pin PICs.
http://www.mikroe.com/en/tools/easypic4/
You can get a fully integrated hardware and software development system for about $250.
xorcise of CircuitED can supply these items (see post #73).
Disclaimer: I am not connected in any way with CircuitED or mikroElectronica except for being a very pleased customer.
ejaf
Feb 19, 2007, 12:31 PM
Thanks for the circuitED link...real PITA from Microchip, since they need a signture when delivering via FedEX. Will look into them next time.
My chips are here, but I'm afraid that if I open them up now, my wife and kids won't see me for several days ;)
Have to fix my printer first...better half gave the go ahead for this.
thanks again all....E
xorcise
Feb 19, 2007, 01:10 PM
I have been playing with your basic version and have realized quickly that the 50 lines of code allowed in Proton Lite gets used up rather fast. I want to add a cell # detect and the ability to switch it for Nimh or A123's levels. I do like the ease of Basic, but not sure I am ready to invest the $295 they want for the full version.
George,
I have rewritten Don's PDS code to mikroBasic. rmteo referred you to the free download. You can program anything for a 12F675 for free since its ROM is only 2K. If you wish to purchase you can purchase in the US at CircuitED (http://circuit-ed.com/). Don's program compiles to only 103 ROM in mB. Try this:
program Batt_Monitor_12F675
'*** Program by dleroi...translated to mikroBASIC by xorcise 2.19.2007 ***'
'*** Device, Oscillator, and Configurations are set up in Project Editor ***'
'Example code for battery monitor
'Uses Vdd as reference and internal oscillator
'Lights one LED when voltage is below 50% of Vdd
'Lights two LEDs when voltage is below 25% of Vdd
'For Proton IDE Lite Basic Compiler
' Device = 12F675
' Pin 1: Vdd
' Pin 2: No connection
' Pin 3: No connection
' Pin 4: No connection
' Pin 5: GP2 LED 2
' Pin 6: GP1 LED 1
' Pin 7: AN0 (voltage in)
' Pin 8: Vss
' XTAL = 4
' Set data code protection, code protection, brown out detection, watchdog timer, and mclr function OFF;
' power-up timer ON; and oscillator to internal.
' Config CPD_OFF, CP_OFF, BODEN_OFF, WDT_OFF, MCLRE_OFF, PWRTE_ON, INTRC_OSC_NOCLKOUT
symbol LED1 = GPIO.1 ' define pin 6 as LED1
symbol LED2 = GPIO.2 ' define pin 5 as LED2
dim i as Byte ' for-next loop counter
sub procedure Delay250
Delay_ms(250)
end sub
sub procedure Delay500
Delay250
Delay250
end sub
sub procedure GET_ADC
ADCON0.0 = 1 ' ADC reading enabled
Delay_us(50) ' wait for capacitor to charge (acquisition)
ADCON0.1 = 1 ' set conversion status bit...starts 10-bit conversion
While ADCON0.1 <> 0 ' wait for conversion to complete
Wend
ADCON0.0 = 0 ' ADC reading disabled
end sub
main:
TRISIO = %00111001 ' pins 5 & 6 as outputs, rest as inputs
ANSEL = %00110001 ' select analog input for AN0, internal RC clock
ADCON0 = %10000000 ' ADC=off, select channel 0, Vref=Vdd, right-justify result
For i = 1 to 4 ' flash the LED's at startup
LED1 = 1
Delay250
LED1 = 0
Delay250
LED2 = 1
Delay250
LED2 = 0
Next i
While 1=1 ' loop forever
GET_ADC ' read the ADC pin
Select Case ADRESH
Case 0 ' <256...25% of Vdd
LED1 = 1
LED2 = 1
Case 1 ' <512...50% of Vdd
LED1 = 1
LED2 = 0
Case Else
GPIO = 0
End Select
Delay500 ' wait for 0.5 seconds
Wend
end.
dleroi
Feb 19, 2007, 01:10 PM
I have to agree that BASIC or C is the way to go, but I do think that an inkling of assembly will make you a better BASIC, C, or whatever, programmer.
rmteo
Feb 19, 2007, 02:00 PM
One of the nice features of mikroBasic is that you can embed assembly code in it. So for critical routines (timing related for example) you can use ASM and Basic for the rest. Allows you to get started quickly and then get into specific details later when required.
xorcise
Feb 19, 2007, 02:10 PM
Added a new feature to Don's program....flashing LED's when the voltage falls below 12.5%. It utilizes the Timer0 interrupt. Still a very small program in mikroBASIC at 159 ROM:
symbol LED1 = GPIO.1 ' define pin 6 as LED1
symbol LED2 = GPIO.2 ' define pin 5 as LED2
dim i as Byte ' for-next loop counter
dim flash as Boolean ' LED blinking flag
sub procedure Delay250
Delay_ms(250)
end sub
sub procedure Delay500
Delay250
Delay250
end sub
sub procedure GET_ADC
ADCON0.0 = 1 ' ADC reading enabled
Delay_us(50) ' wait for capacitor to charge (acquisition)
ADCON0.1 = 1 ' set conversion status bit...starts 10-bit conversion
While ADCON0.1 <> 0 ' wait for conversion to complete
Wend
ADCON0.0 = 0 ' ADC reading disabled
end sub
sub procedure interrupt
If flash = true Then
GPIO = not(GPIO)
End If
INTCON.T0IF = 0 ' reset Timer0 Flag for next interrupt...TMR0 continues running
end sub
sub procedure INIT
TRISIO = %00111001 ' pins 5 & 6 as outputs, rest as inputs
OPTION_REG = %00000111 ' input pullups enabled, Timer0 prescaler = 256
ANSEL = %00110001 ' select analog input for AN0, internal RC clock
ADCON0 = %10000000 ' ADC=off, select channel 0, Vref=Vdd, right-justify result
CMCON = 7 ' disable comparators
INTCON = %11100000 ' Global, Peripheral, T0IE interrupts enabled, T0IF reset
TMR0 = 0 ' start TMR0 for full 256 count...interrupt on overflow
flash = false ' 256 x 256 prescaler = 65536 counts @ 1us each = 65.536ms cycle
end sub
main:
INIT ' initialize important registers subroutine
For i = 1 to 4 ' flash the LED's at startup
LED1 = 1
Delay250
LED1 = 0
Delay250
LED2 = 1
Delay250
LED2 = 0
Next i
While 1=1 ' loop forever
GET_ADC ' read the ADC pin
Select Case ADRESH
Case 0 ' <256...25% of Vdd
If ADRESL.7 = 0 Then ' <128...12.5% of Vdd
flash = true ' enable LED flashing
Else
LED1 = 1
LED2 = 1
flash = false
End If
Case 1 ' <512...50% of Vdd
LED1 = 1
LED2 = 0
flash = false
Case Else ' 512+
GPIO = 0
flash = false
End Select
Delay500 ' wait for 0.5 seconds
Wend
end.
Edit: added CMCON=7 to disable comparators
GeorgeP
Feb 20, 2007, 10:40 PM
Xorcise...
Thanks for your mikroBasic example. I did download and install it tonight, it looks good but I have to ask.... Subroutines BEFORE the main? I have been playing with programming for many many years starting in machine language with my KIM-1, then on to .asm and finally various Basic's in the Commadore PET and 64's, TRS-80's and IBM's via MSBasic and Quick Basic. This is the first time I have seen the subs before the main. Even in machine language I learned to do the init first, main program loop next, then the calls. No big deal, I just have to get used to scrolling down to the end to work on my loop. I did try cutting/pasting your subs after the main but that tilted so after looking at the included examples I realized that must be the way they do it now, it's all what one gets used to. I think I like the more traditional way of Proton, but then I have only had it for less than one day.
tnx agn for posting your example. I'm sure there are many of us out here that want to learn more about these little PIC buggers and learn better from examples than data sheets.
George
xorcise
Feb 20, 2007, 11:14 PM
Sorry...that's the structure of mikroBasic, but easily learned. You can put the subroutines in their own module and simply "Include" the module if you like.
If you are used to Proton then you will surely like Swordfish Basic for PIC18's (which we also sell at CircuitED). The developer of Swordfish was closely associated with the developers of PDS. This is a highly structured Basic language that has many of the same syntax features of Proton. I like Proton but it is not structured and creating large programs becomes a bit of a chore. Give Swordfish a try. They also have a free download of the full IDE of the compiler with some limitations, good documentation, and a support forum.
You can try the mikroBasic forums on the CircuitED site and the mikroElektronika site for numerous code examples.
dleroi
Feb 21, 2007, 12:11 AM
I have been playing with programming for many many years starting in machine language with my KIM-1, then on to .asm and finally various Basic's in the Commadore PET and 64's, TRS-80's and IBM's via MSBasic and Quick Basic.George
Hi George,
Boy, your resume reads just like mine! You left out the Heathkit trainer, though. So, we must be around the same age?
- Don
GeorgeP
Feb 21, 2007, 08:37 AM
Hi George,
Boy, your resume reads just like mine! You left out the Heathkit trainer, though. So, we must be around the same age?
- Don
I'm 56 and have been out of programming for a while now, but these PIC's kinda bring back the old days :rolleyes: and am having fun with the Low Voltage Alarm program. I am also going to use one to control the 5in1 camera on my Corona. Actually, I'm hoping to use only one PIC to do both functions as well as maybe a few others.... We'll see.
Yes, the Heath trainer was a real nice self contained unit with keypad and 7-segment display. I believe they also came out with a keyboard interface for it.
George
vBulletin® Copyright ©2000-2009, Jelsoft Enterprises Ltd.