View previous topic :: View next topic |
Author |
Message |
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
12f1572 ADC problem |
Posted: Mon Jun 26, 2017 7:48 am |
|
|
Hi guys.
I've spent a lot of time with experiments on how to make ADC work on 12f1572.
i cant debug so i go blind using some leds etc.
I try to use Analog channel 3 (porta.4) to read a voltage. Then i light a led if its above 25% (50 out of 255). However it acts like digital.
Led goes off when i go below 2Volts and then it never goes on even if give 4Volts.
Any help appreciated. It must be on configuration....
Code: | #include <12F1572.h>
#device ADC=8
//#FUSES WDT //Watch Dog Timer
#FUSES PUT //Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES PROTECT //Code protected from reads
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES NOWRT //Program memory not write protected
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES LPBOR //Low-Power Brownout reset is enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=4000000,restart_wdt)
//#use FIXED_IO( A_outputs=PIN_A2,PIN_A0,PIN_A1,pin_a5)
//setup_comparator(nc);
#define Status PIN_A0
#define deb2 PIN_A1
#define Relay PIN_A2
#define deb PIN_A3
#define sensor PIN_A4
#define voltage PIN_A5
unsigned int8 counter1=0;
int8 temperature,previous=0,a=0;
#INT_TIMER1
void TIMER1_isr(void)
{
restart_wdt();
counter1++;
if (counter1>=15){
output_toggle(status);
counter1=0;
}
}
void main()
{
set_tris_a(0b00011010);
port_A_pullups(0x00);
delay_ms(400);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //65,5 ms overflow
setup_adc(adc_clock_div_8);
setup_adc_ports(sAN3, VSS_VDD);
set_adc_channel( 3 );
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
//setup_wdt(WDT_ON);
//setup_wdt(8); //~2,3 s reset
while(true)
{
output_high(voltage);
delay_ms(10);
temperature=read_adc();
delay_ms(10);
for(a=0;a==temperature;a++){ // for debugging purposes. it doesnt work
output_toggle(deb2);
delay_ms(1);
}
if ((temperature>=50)) {
output_high(relay);
previous=1;
}
else if (temperature<=50) {
output_low(relay);
previous=0;
}
delay_ms(100);
restart_wdt();
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 26, 2017 8:19 am |
|
|
First, your watchdog is enabled, and enabled for the minimum time of 1mSec. It'll be continuously resetting the chip....
To disable the watchdog, you have to specify NOWDT. The watchdog defaults to 'on'. The restart_wdt call in delays is once every major loop of the delay. Your one in the timer is every time the interrupt is called. Neither is often enough for a watchdog set this fast....
In your code you have setup_wdt functions handled incorrectly. The syntax to setup the watchdog timer for a 2 second reset is:
setup_wdt(WDT_ON | WDT_2S);
Then:
for(a=0;a==temperature;a++)
Now, a is set to 0. Is this ever going to be equal to 'temperature'?. Only if the ADC actually returns 0. So 'of course' this code will rarely if at all get executed...
You then have the line to turn off the comparator (needed), up as a configuration line with the fuses and clock settings. It isn't. It's a line of code.
Obvious comments then apply, about if you do have a trap diode on the relay coil, and a current limiting resistor on the LED?. |
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
|
Posted: Mon Jun 26, 2017 8:37 am |
|
|
Hi. Yes circuit is ok. I think it's not wdt problem. I partially disable it, probably in wrong manner after some tests. How can I disable the comparator? Is the line with nc that I have commented out? I'm on the way right now. I will check your suggestions later more careful. Thank you. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 26, 2017 8:50 am |
|
|
It is the watchdog. I tested before posting, and it is watchdog resetting.
You cannot 'partially disable' it. It is on or off. Where you have remmed out the line to enable it in the fuses, does not work, since the fuse defaults to 'on'.
The syntax for lines is in the header file for the chip.
setup_comparator(NC_NC);
Are you _sure_ you have the relay properly trapped. 90% of the posters here do not, or lack basic smoothing by the chip. |
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
|
Posted: Mon Jun 26, 2017 10:09 am |
|
|
i must be in the 10% !. I use diode for relay, external zener to most pins and tenths of capacitors!
setup_comparator(NC_NC); is not working, i placed this
#define NC_NC
i also placed nowdt fuse, but its still the same. Led goes off but it doesnt turn on. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 26, 2017 12:35 pm |
|
|
What compiler version do you have?.
The comparator setup, is correct on the current compilers. |
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
|
Posted: Mon Jun 26, 2017 1:59 pm |
|
|
5.046.
Could it be something else;still acting the same
i used
setup_comparator(NC_NC); in main but it
This is header file (sorry about before, i had place it before main)
Code: | // Constants used in setup_comparator() are:
//
#define NC_NC 0x37
// Constants used in setup_comparator() are:
#define CP1_A1_A0 0x8000
#define CP1_A4_A0 0x8001
#define CP1_FVR_A0 0x8006
#define CP1_VSS_A0 0x8007
#define CP1_A1_DAC 0x8010
#define CP1_A4_DAC 0x8011
#define CP1_FVR_DAC 0x8016
#define CP1_VSS_DAC 0x8017
#define CP1_A1_FVR 0x8020
#define CP1_A4_FVR 0x8021
#define CP1_FVR_FVR 0x8026
#define CP1_VSS_FVR 0x8027
#define CP1_A1_VSS 0x8030
#define CP1_A4_VSS 0x8031
#define CP1_FVR_VSS 0x8036
#define CP1_VSS_VSS 0x8037
//Optionally OR with any of the following
#define CP1_INT_L2H 0x0080
#define CP1_INT_H2L 0x0040
#define CP1_OUT_ON_A2 0x2000
#define CP1_INVERT 0x1000
#define CP1_FAST 0x0400
#define CP1_HYST 0x0200
#define CP1_SYNC 0x0100
#bit C1OUT = getenv("SFR_CM1CON0").6 |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 26, 2017 2:20 pm |
|
|
Simplify, and prove your hardware is working:
Code: |
#include <12F1572.h>
#device ADC=8
#use delay(internal=4000000)
//do this before the fuses - ensures it does not override the NOCLKOUT
#FUSES NOWDT //Start without the watchdog
#FUSES PUT //Power Up Timer
#FUSES NOMCLR //Master Clear pin disabled
#FUSES NOPROTECT //Always develop with protection off
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES NOWRT //Program memory not write protected
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#define Relay PIN_A2
void main(void)
{
port_A_pullups(0x0xFF);
setup_comparator(NC_NC);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_adc(aADC_CLOCK_DIV_8);
setup_adc_ports(sAN3, VSS_VDD);
set_adc_channel( 3 );
while(TRUE)
{
output_high(RELAY);
delay_ms(2000);
output_low(RELAY);
delay_ms(2000);
}
}
|
Just turns the relay on for 2 seconds and off for 2 seconds. Does it work?. |
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
|
Posted: Mon Jun 26, 2017 2:26 pm |
|
|
yeap
It works |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Jun 26, 2017 2:33 pm |
|
|
So, using this as the start add one thing. Read the ADC and do the tests (your tests are slightly flawed. Think about the logic{
Code: |
temperature=read_adc();
if ((temperature>=50))
{
output_high(relay);
previous=1;
}
else //you only get here if the signal is <50. Pointless to test for <= here
{
output_low(relay);
previous=0;
}
|
Generally make your variables local, unless they _must_ be global.
Does this then work.
This is the basics of debugging. Take the problem _one step at a time_. |
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
|
Posted: Mon Jun 26, 2017 2:35 pm |
|
|
Thank you Ttelmah.
I will check it again step by step. |
|
|
|