Thanks Tabsoft for that info & trying to help. I will go over all that until it becomes clear, I refuse to give up!
Thanks again,
Rob
Thanks Tabsoft for that info & trying to help. I will go over all that until it becomes clear, I refuse to give up!
Thanks again,
Rob
Okay I think I have made sense of this now- correct me if I'm wrong.
So if I wanted to set the comparator up with say an internal reference & output (cm<2:0> = 011), I would set the cmcon0 register as CMCON0 = %00000011 ?
Now to the VRR -
I think Im right in saying that the comparator uses the main VDD+ pin on the chip to compare the internal reference to? What I dont understand is this -
IF VRR=1 and VR3 ... VR0 = 1111 (15) with a VDD of 5V the Vref will be (15/24)*5 = 3,125V
^^ Where are they getting that 15 from? Also where do you get the 24 from?
IF VRR=0 and VR3 ... VR0 = 1111 (15) with a VDD of 5V the Vref will be 5/4+(15/32)*5 = 3,593V
^^ Also why has the 24 changed to a 32 just from vrr=1 changing to a 0?
One last question, Am I right in thinking that you have to use the CIN- pin on the chip to provide the voltage to check? Cant you use a comparator on any pin of the chip (apart from gp3, vdd & vss).
Thanks again,
Rob
Update: Ive looked in the data sheet & found out the reason for dividing by either 24 or 32, if your working out low range then : 24, high range : 32. Thats another thing understood.
So the last thing I am struggling to understand now is, how do you get the number from th bits?
VR<3:0> = 1111 (15). < How on earth do you get 15 from just bits 1111?
This is the only thing that I'm struggling to understand now.
Thanks,
Rob
Last edited by robbo78; - 24th January 2015 at 10:06.
the low range internal vref gives you 15 steps of 0.208 volt steps starting at 0v
the high range internal vref gives you 15 steps of 0.156 volt steps starting at 1.25v
if you don't need the cout as an actual physical output CM<2:0> = 110 is a better choice
and lets you chose pin 6 or 7 as your input (select with cmcon0.3 "CIS")
why waste pins on a 8 pin chip
0000=0
0001=1
0010=2
0011=3
...................etc etc
its called binary
Last edited by richard; - 24th January 2015 at 10:16. Reason: binary
Edit: just re-read your post. I need to be able to read a pin & output on it at the same time (obviously with pauses, so do I need to use comparator with output?
Hi Richard, I just came back here from doing a bit of googleing. It took me about 2 mins to figure out that its just binary, maybe if I had paid more attention in Maths I would know this!
I now understand the voltage steps as well, everything is coming together now, its actually quite simple once understood.
I still need to know if you can use a comparator with internal reference on any pin or does it have to be the CIN- pin?
Cheers,
Rob
Last edited by robbo78; - 24th January 2015 at 10:24.
input to comparator is [ cin+ pin 7] or [cin- pin 6] with CM<2:0> = 110 its your choiceif you don't need the cout as an actual physical output CM<2:0> = 110 is a better choice
and lets you chose pin 6 or 7 as your input (select with cmcon0.3 "CIS")
there are other modes but in all cases cin is only on pins 6,7
if you need or can use the comparator output use CM<2:0> = 101
it still lets you chose pin 6 or 7 as your input (select with cmcon0.3 "CIS")
Okay Richard thanks for your help.
So lets say I wanted an LED to be OFF if the voltage on cin+ is below 1.1v, & LED to be ON if the voltage is higher than 1.1v. Would I use this -
VR3 ... VR0 = 1000 (8) with a VDD of 3.3V the Vref will be (8/24) x 3.3 = 1.1V
I hope this is right lol
there is not enough info to answer
what comparator mode ?
what cis setting
is vrr set
what cinv seting
how is led connected ?
Last edited by richard; - 24th January 2015 at 11:42. Reason: spell
Richard, I'm specifically talking about just the VRR nothing else. I just want to know if I've got the workings out right. If you need the whole code to tell me if that part is right or not then I can do that no problem.
that is correct it will set the reference to 1.1 for a vdd of 3.3v
Thats greatthanks for the help, now I can have a go at the code.
Okay I have had a go & failedWhat am I doing wrong?
Code:'PIC12f683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %00001000 'voltage reference TRISIO = %00000010 'pin 6 input POTEN VAR CMCON0.1 'pot pin 6 LED VAR GPIO.2 'led pin 5 PAUSE 20 main: IF CMCON0.1 = 1 THEN HIGH LED ELSE LOW LED ENDIF GOTO main
Rob,
Glad to see your working through the design and issues.
You are very close.
Here are a couple of things you need to correct.
1. VRCON: Look at the register description in "Register 8-3" on page 53 of the datasheet.
In your program you are setting VRCON like this: VRCON = %00001000 'voltage reference
There are more bits in the register that you need to take into account.
A. You have bit7=0 which does this "0 = CVREF circuit powered down, no IDD drain and CVREF = VSS". This turns OFF the internal reference voltage.
You need to change this to "1", 1 = CVREF circuit powered on, to turn on the internal reference voltage circuit.
B. You have bit5 = 0 which does this "VRR: CVREF Range Selection bit 0=High Range"
This changes your CVref equation and result to this: "VRR = 0, CVREF = (VDD/4) + (VR3:VR0 X VDD/32)", which when you plug in your values you get this
for your reference voltage. (3.3/4) + (8/32) = (0.825) + (0.25) = 1.075 Vdc. Now this may be what you were actually trying to do, if so then your are good.
2. In your main loop you are attempting to test the output of the Comparator like this: "IF CMCON0.1 = 1 THEN"...
Look at the CMCON0 register description in "Register 8-1" on page 47 of the datasheet and compare that with the "CMCON0.1 = 1" above.
You are testing bit1 of the CMCON0 register, that is what the ".1" does. xxxx.1 says I want to look at bit1 of xxxx.
Is this the bit you need to check for the Comparator Output? If you're not sure have a look at "FIGURE 8-3" on page 49 and look at the figure for the
CM Mode you are using "100". That diagram indicates what the Comparator Output is by name.
Check and correct this.
3. Lastly, and somewhat obscure in the DS, you need to determine how you want the Comparator to test and output.
As I understand you want to check the input pin voltage against your "1.075 Vdc" reference you are setting up internally and have the following outcomes:
If the input is "Lower than 1.075 Vdc" you want the LED to be OFF and you want the LED to be "ON when the input is Higher than 1.075 Vdc".
To get these results you need to take a look at a couple of items in the datasheet.
A. Look at CMCON0, "Register 8-1" on page 47, and review the information for bit6 and bit4.
Also look at "TABLE 8-1" on page 48.
Between these two, you should be able to piece together how you need to configure the operation to get your desired "Output" of the Comparator.
You are getting close, hopefully these additional points will get you further on your way.
Regards,
Regards,
TABSoft
Hi Tabsoft, thanks a lot for your help I appreciate it. I will go back through everything you have stated & set it up right this time. I did think there were other bits to change but didnt want to mess as I didnt know what I was doing, but ai should now with your info.
Thanks again, I will let you know how it goes.
Rob
Rob,
One correction in my earlier post.
The CVref calculation for High Range is CVREF = (VDD/4) + (VR3:VR0 X VDD/32).
Using your input values of VDD=3.3 and VR3:VR0=8, the calculation will come out like this.
(3.3/4) + (8 x (3.3/32) = (0.825) + (8 x 0.103125) = (0.825) + (0.825) = 1.65 Vdc
If you use Low Range then here is the info:
CVREF = (VR3:VR0/24) x VDD = (8/24) x 3.3 = 0.333 x 3.3 = 1.1 Vdc
Regards,
Regards,
TABSoft
Hi Tabsoft,
Right I have changed the bits in the VRCON to the right stuff, so I think that is right now. I did change bits in the CMCON0 but none of it seemed to make a difference, so I have put it back to how it was. I'm thinking either I'm testing the wrong bit still or my actual hardware setup is wrong.
Maybe you can point something out?
BTW I am using the low rangeAlso this is correct - As I understand you want to check the input pin voltage against your "1.1" reference you are setting up internally and have the following outcomes: If the input is "Lower than 1.075 Vdc" you want the LED to be OFF and you want the LED to be "ON when the input is Higher than 1.075 Vdc".
Code -
Thanks again,Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %10101000 'voltage reference TRISIO = %00000010 'pin 6 input POT1 VAR CMCON0.2 'pot pin 6 LED VAR GPIO.2 'led pin 5 PAUSE 20 main: IF POT1 = 1 THEN HIGH LED ELSE LOW LED ENDIF GOTO main
Rob
Last edited by robbo78; - 25th January 2015 at 11:59.
Rob,
Yes you're not testing the correct bit for the actual output of the Comparator..
Look at my post again where I listed the things you need to correct. Look at item 2.
I point you to where you can find the answer of which bit in which register to test.
I also point you to where you can determine what the output of the comparator will be for different configurations and physical connections.
Have a read of this info again, I'm sure you'll get it.
Regards![]()
Regards,
TABSoft
Hi Tabsoft, okay had another read at first it was just going over my head. Am I right in saying I need to read bit 6 of CMCON0? So CMCON0.6?
Thanks,
Rob
Exactly!
CMCON0 Register:
bit 6 COUT: Comparator Output bit.
This is the logic bit output of the Comparator.
CM: Comparator Mode = 100
With this setup the comparator is comparing VIN- (CIN-/GP1) to VIN+ (which is not an external pin but it is "From CVREF Module", internal voltage reference)
So you need to look at the description of COUT in the CMCON0 register listed below AND you need to look at Table 8-1 in the DS.
This will help you work out what value CMCON0.6 will be based upon a given input on GP1.
Take note that CINV is a configuration bit within the CMCON0 register that determines the logic polarity of COUT.
COUT: Possible values
When CINV = 0:
1 = VIN+ > VIN-
0 = VIN+ < VIN
When CINV = 1:
1 = VIN+ < VIN-
0 = VIN+ > VIN
Regards,
TABSoft
Brilliant! Thanks for the info again your the best! I should be able to get this working how I want it to now, then & only then will I move onto interupt with it.
Thanks again,
Rob
Hi Tabsoft, I got the comparator working perfectlyso I decided to move onto adding an interrupt, which believe it or not hasn't worked. Here is the code I have fully written, maybe you can help where I have gone wrong?
Thanks,
Rob
You will probably have a laugh at this, as its probably completely wrong lol
Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG PAUSE 20 'wait for hardware to settle DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %10101000 'voltage reference TRISIO = %00000010 'pin 6 input ON INTERRUPT GOTO SLSELECT 'interrupt handler is slselect INTCON = %11001000 'enable GIE and GPIE; clear GPIF IOC = %00000010 ' enable IOC1 (GPIO.1 Interrupt on change) PIE1 = %00001000 'enable comparator interrupt POT1 VAR CMCON0.6 'read potentiometer LED VAR GPIO.2 'led pin 5 ENABLE main: HIGH LED 'light led GOTO main 'repeat DISABLE 'disable interrupts in handler SLSELECT: IF POT1 = 1 THEN 'if <1.1v sleep NAP 1 ELSE ENDIF INTCON = %10001000 'enable GIE and GPIE; clear GPIF PIR1 = %00000000 'reset CMIF RESUME 'where left off ENABLE 'enable interrupts
Glad to hear if Rob.
You did not say what is happening only that it is not working.
I took a look at your code and several things jump out at me.
1. You are jumping into the deep end of the pool with testing "nap"
If would take a smaller step first. Set a flag in the ISR and resume. Then in the main act on the flag you set in the ISR.
This way you can see the effects of the ISR logic.
2. You have IOC.1 enabled, which is GP1, which you are using for the comparator. You need to comment out IOC.1.
3. You are not testing for which Interrupt is firing inside of your ISR. It is almost always a good practice to determine what interrupt caused the jump to the ISR.
4. At the end of your ISR you are not setting the INTCON register they way you think. I believe you have a typo in the value you are assigning to it.
I changed your code to the following which shows the changes.
See if this gets you along further.Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG PAUSE 20 'wait for hardware to settle DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %10101000 'voltage reference TRISIO = %00000010 'pin 6 input ON INTERRUPT GOTO SLSELECT 'interrupt handler is slselect INTCON = %11001000 'enable GIE and GPIE; clear GPIF 'IOC = %00000010 ' enable IOC1 (GPIO.1 Interrupt on change) PIE1 = %00001000 'enable comparator interrupt POT1 VAR CMCON0.6 'read potentiometer LED VAR GPIO.2 'led pin 5 bitTest var bit 'Debug test bit. Set/Clear in ISR and Check in maiin bitTest = 0 ENABLE main: 'HIGH LED 'light led LED = bitTest GOTO main 'repeat DISABLE 'disable interrupts in handler SLSELECT: 'IF POT1 = 1 THEN 'if <1.1v sleep 'NAP 1 'ELSE 'ENDIF if PIR1.3 = 1 then 'Comparator Interrupt fired (must be cleared before resume) bitTest = POT1 endif 'INTCON = %10001000 'enable GIE and GPIE; clear GPIF INTCON =%11001000 PIR1 = %00000000 'reset CMIF RESUME 'where left off ENABLE 'enable interrupts
Regards,
TABSoft
Hi Tabsoft, okay thanks for all that. I will go back to flagging. I think I was
Getting a bit ahead of myself lol.
Let you know how it goes![]()
Hi, okay I've been playing about with comparator interrupt now & think I have got the hang of it using flags. The code below is something little I came up with![]()
Now I think I would like to implement the nap command now, or do you think I should learn something else before jumping to the nap command?
Thanks again,
Rob
Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG PAUSE 50 'wait for hardware to settle DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %10101000 'voltage reference TRISIO = %00000010 'pin 6 input ON INTERRUPT GOTO int1 'interrupt handler is int1 INTCON = %11001000 'enable GIE and GPIE; clear GPIF PIE1 = %00001000 'enable comparator interrupt POT1 VAR CMCON0.6 'read potentiometer LED VAR GPIO.2 'led pin 5 loop1 var word 'loop1 counter bitTest var bit 'Debug test bit. Set/Clear in ISR and Check in main bitTest = 0 Loop1 = 0 ENABLE main: IF bittest = 1 THEN GOTO FLASH ENDIF LOW LED GOTO main ENABLE FLASH: do for loop1 = 1 to 1000 HIGH LED PAUSE 1 NEXT LOOP1 for loop1 = 1 to 1000 LOW LED PAUSE 1 NEXT LOOP1 IF bittest = 0 THEN GOTO main ENDIF LOOP DISABLE 'disable interrupts in handler int1: if PIR1.3 = 1 then 'Comparator Interrupt fired (must be cleared before resume) BITtest = pot1 ENDIF INTCON =%11001000 PIR1 = %00000000 'reset CMIF RESUME 'where left off ENABLE 'enable interrupts
Rob,
Looks like you got it working.
One little thing though.
The Pause command is based upon the "DEFINE OSC" value to calculate the pause interval correctly.
It is a good practice to have your "DEFINE OSC" statement up top in the source code before you use any time sensitive commands such as "Pause x".
The way you have your program setup the following occurs, which I presume you have seen in practice on your physical system.
The LED on GP2(pin5) will stay LOW (OFF) while the voltage input on GP1(pin6) is above your reference voltage.
The LED GP2(pin5) will blink in 1sec intervals while the voltage input on GP1(pin6) is below your reference voltage.
This works fine on my simulator.
Good job!
It looks like you're ready for a "nap" now.![]()
Regards,
TABSoft
Hi Tabsoft, thanks for comfirmingalso thanks again for all your help, I wouldnt have got to this point if it wasnt for you. I havent got a simulator so I just test straight on the BB.
I will drop the pause below the osc value, thanks for that tip![]()
Do I implement the nap command in the same way as flashing an LED? So if bittest = 1 : nap 1, if bittest = 0 : goto main? Something like that ?
Thanks again,
Rob
Rob,
Why don't you check this out.
Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000010 'pin 6 analog CMCON0 = %00000100 'comparator mode VRCON = %10101000 'voltage reference TRISIO = %00000010 'pin 6 input PAUSE 50 'wait for hardware to settle ON INTERRUPT GOTO int1 'interrupt handler is int1 INTCON = %11001000 'enable GIE and GPIE; clear GPIF PIE1 = %00001000 'enable comparator interrupt POT1 VAR CMCON0.6 'read potentiometer LED VAR GPIO.2 'led pin 5 loop1 var word 'loop1 counter bitTest var bit 'Debug test bit. Set/Clear in ISR and Check in main high LED 'Start with LED ON pause 500 'Pause .5 secs so you can see the LED turn on bitTest = POT1 'Take initial reading of input voltage state Loop1 = 0 ENABLE main: IF bitTest = 1 THEN 'input voltage is < reference voltage low LED nap 1 else 'bitTest = 0 - input voltage is > reference voltage GOTO FLASH ENDIF GOTO main ENABLE FLASH: do for loop1 = 1 to 1000 HIGH LED PAUSE 1 NEXT LOOP1 for loop1 = 1 to 1000 LOW LED PAUSE 1 NEXT LOOP1 IF bitTest = 1 THEN GOTO main ENDIF LOOP DISABLE 'disable interrupts in handler int1: if PIR1.3 = 1 then 'Comparator Interrupt fired (must be cleared before resume) bitTest = pot1 ENDIF INTCON =%11001000 PIR1 = %00000000 'reset CMIF RESUME 'where left off ENABLE 'enable interrupts
Regards,
TABSoft
Like Tabsoft wrote, you generally want your DEFINEs at the top of the program but it's for readabillity. In reallity it makes no difference because they are not runtime commands.I will drop the pause below the osc value, thanks for that tip
Another little noteWhat's the purpose of setting the LED high inside the loop?Code:for loop1 = 1 to 1000 HIGH LED PAUSE 1 NEXT LOOP1
There's nothing inherently wrong in doing it but it does take (a little) bit of time.
Also, now that you're starting to get the hang of it you might want to consider ditching the HIGH/LOW commands and simply set the pin directly, LED=1, LED=0. For this to work you need to clear the corresponding TRIS-bit first (TRISO.2 = 0 ' Set GPIO.2 to output). Doing it this way executes faster and consumes less codespace since it doesn't waste resources clearing the TRIS bit each and every time (which is what HIGH/LOW does for you).
Again, you're not doing anything "wrong" - it all works fine, I'm just pointing out a couple of things you could improve and take with you to the next project.
/Henrik.
Thanks guys, I will have a play![]()
Rob
Hi guys, okay I've been having a mess today & I am quite happy with myself. I managed to use the comparator successfully, now I have added a button into the routine.
It is all doing what I want it to but I am having this big issue with de-bouncinghow do I sort this out, what is the best way? Do I need to read the button in a different way?
Here is the code -
Code:'PIC 12F683 #CONFIG __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF #ENDCONFIG DEFINE OSC 4 '4mhz ocsillator ANSEL = %00000001 'pin 7 analog CMCON0 = %00011110 'comparator mode VRCON = %10100000 'voltage reference TRISIO = %00101111 'pin 2,4,5,6,7 input PAUSE 50 'wait for hardware to settle ON INTERRUPT GOTO int1 'interrupt handler is int1 INTCON = %11001000 'enable GIE and GPIE; clear GPIF PIE1 = %00001000 'enable comparator interrupt IOC = %00001000 'pin 3 ioc RTPOT VAR CMCON0.6 'right trigger pot RTBITTEST var bit 'trigger debug test bit. Set/Clear in ISR and Check in main BUT VAR GPIO.3 'tactile button BUTBITTEST VAR BIT 'button test bit RTBITTEST = RTPOT 'initial reading BUTBITTEST = 0 'read 0 to start ENABLE main: IF RTBITTEST = 1 THEN GOTO RAPID ENDIF IF RTBITTEST = 0 THEN GOTO SLEEPY ENDIF GOTO main ENABLE RAPID: LOW GPIO.0 PAUSE 70 TRISIO.0 = 1 PAUSE 70 IF RTBITTEST = 0 THEN GOTO SLEEPY ENDIF IF BUTBITTEST = 1 THEN GOTO FLASH ENDIF GOTO RAPID ENABLE SLEEPY: HIGH GPIO.5 PAUSE 1000 TRISIO.5 = 1 PAUSE 1000 IF RTBITTEST = 1 THEN GOTO main ENDIF GOTO SLEEPY ENABLE FLASH: HIGH GPIO.5 PAUSE 300 TRISIO.5 = 1 PAUSE 300 IF BUTBITTEST = 1 THEN GOTO RAPID ENDIF GOTO FLASH DISABLE 'disable interrupts in handler int1: if PIR1.3 = 1 then 'Comparator Interrupt fired (must be cleared before resume) RTBITTEST = RTPOT ENDIF IF IOC.3 = 1 THEN BUTBITTEST = BUT ENDIF INTCON =%11001000 PIR1 = %00000000 'reset CMIF IOC = %00000000 'reset IOC.3 RESUME 'resume to where left off ENABLE 'enable interrupts
Last edited by robbo78; - 31st January 2015 at 18:41.
Rob,
You really don't state what the problem is, only that you see a problem.
A quick scan of the code leads to too many questions for me.
What are you trying to accomplish in the different subroutines Rapid, Sleepy and Flash?
You seem to be using two GPIO pins, one for Rapid (GPIO.0) and another (GPIO.5) for Sleepy and Flash.
Another question is why in each of the subroutines are you setting the GPIO high, pausing and then configuring the same GPIO as an input?
Without more info, it is futile to offer an opinion.
Regards,
TABSoft
Bookmarks