|
|
View previous topic :: View next topic |
Author |
Message |
Trent
Joined: 13 Apr 2004 Posts: 2 Location: Melbourne, FL
|
Unstable 10bitA/D on 16F819: On 0v it varies up to 0.2v etc |
Posted: Tue Apr 13, 2004 2:10 pm |
|
|
I have a PIC16F819 based project driven by a 8MHz ext osc. I use Interrupts to keep track of two independent RPMs and I use four 10Bit A/Ds. The code below has erratic A/D results that are typically 0.2v from the correct value and jump around in every 10ms packet to the RS232 port.
Example output with a 3volt input and 5v on the ref pin RA3: [readings every 10ms]
3.05
3.12
3.03
3.11
2.87
3.03
etc
Without the interrupt code in place the readings were rock solid on the same platform. I can also revert back to just the A/D code and have it solid.
Here is the code:
==================
Code: | #include <16F819.H>
#use delay(clock=8000000)
#use rs232(baud=57600,xmit=PIN_B3,rcv=PIN_B0)
// Timing Vars //
int16 int8_Timer0_Rolls; // Number of times Timer0 has rolled from 254,255,0,1,2,3
int8 int8_LED_Counter; // For LED "alive" Blinking
int1 int1_Power_Light_Blink; // For LED "alive" Blinking also
int16 int16_counter_rs232; // Packet Counting Var
// ADC Vars //
int16 int32_ADC_A;
int16 int32_ADC_B;
int16 int32_ADC_C;
int16 int32_ADC_D;
int8 int8_IntCounter_RB5; // Interrupt Counter 1
int8 int8_IntCounter_RB7; // Interrupt Counter 2
int1 int1_IntCounterFlag_RB5; // Interrupt Counter 1 Flag
int1 int1_IntCounterFlag_RB7; // Interrupt Counter 2 Flag
#int_RB
// External Interrupt on Interrupt Pin RB4-RB7 //
interrupt1_trigger() {
// Find which pin triggered the interrupt RB4-7 //
if(input(PIN_B5)==1) { // Interrupt because of Pin B5 //
if(int1_IntCounterFlag_RB5==0){
++int8_IntCounter_RB5;
int1_IntCounterFlag_RB5 = 1;
OUTPUT_HIGH(PIN_B6); // Blink Yellow LED
}
}else{
int1_IntCounterFlag_RB5 = 0; // Unlatch Debounce //
}
if(input(PIN_B7)==1) { // Interrupt because of Pin B7 //
if(int1_IntCounterFlag_RB7==0){
++int8_IntCounter_RB7;
int1_IntCounterFlag_RB7 = 1;
OUTPUT_HIGH(PIN_B1); // Blink Green LED
}
}else{
int1_IntCounterFlag_RB7 = 0;
}
}
// Timer Overflow Interrupt //
#int_rtcc // This function is called every time
clock_isr() { // the RTCC (timer0) overflows (255->0).
int8_Timer0_Rolls++;
SET_TIMER0(100); // Timer0 needs to roll every 10ms [Exactly] //
if(int8_LED_Counter++>100) { // Blink LED every Second as "alive" communication //
if(int1_Power_Light_Blink==1) {
OUTPUT_HIGH(PIN_B1); // Green //
int1_Power_Light_Blink=1;
int8_LED_Counter=0;
} else {
int1_Power_Light_Blink=1;
int8_LED_Counter=0;
}
}
}
main() { // Main Settings //
int8_Timer0_Rolls = 0;
// Clear Interrupt Vars //
int8_IntCounter_RB5=0;
int8_IntCounter_RB7=0;
int1_IntCounterFlag_RB5=0;
int1_IntCounterFlag_RB7=0;
int16_counter_rs232=0; // Clear Packet Counter Var
Port_B_Pullups(FALSE); // TRUE Pulls B Ports up to 5v False leave them at 0v.
set_rtcc(0);
setup_timer_0( RTCC_INTERNAL|RTCC_DIV_128);
//setup_timer_0( RTCC_INTERNAL|RTCC_DIV_2); // Old value from 4mhz RC Clock
enable_interrupts(RTCC_ZERO);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
// Setup ADC Ports //
// RA3 is tied to +5v ref voltage //
setup_adc_ports(A_ANALOG_RA3_REF); // RA0 RA1 RA2 RA5 RE0 RE1 RE2 Ref=RA3 RA3=Pin 2 +5V Ref
//setup_adc(ADC_CLOCK_INTERNAL); // Tried this, no help //
setup_adc(ADC_CLOCK_DIV_32);
while(TRUE) {
if(int8_Timer0_Rolls > 0) { // This happens every 10ms //
int8_Timer0_Rolls=0;
// Turn Off LEDs every 10ms //
OUTPUT_LOW(PIN_B6); // LED 2 OFF = Pin B5/A6 //
OUTPUT_LOW(PIN_B1); // LED 1 OFF = Pin B1/B4 // B4 Low + B1 High = Green
// ADC Data Collection //
delay_us(50);
SET_ADC_CHANNEL(0); // RA0 //
delay_us(50);
int32_ADC_A = READ_ADC();
SET_ADC_CHANNEL(1); // RA1 //
delay_us(50);
int32_ADC_B = READ_ADC();
SET_ADC_CHANNEL(2); // RA2 //
delay_us(50);
int32_ADC_C = READ_ADC();
SET_ADC_CHANNEL(4); // RA4 //
delay_us(50);
int32_ADC_D = READ_ADC();
// Send Data Frame every 100ms //
printf("S%4LX%4LX%4LX%4LX%4LX%4LX%4LXL",int8_IntCounter_RB5,int8_IntCounter_RB7,int32_ADC_A,int32_ADC_B,int32_ADC_C,int32_ADC_D,int16_counter_rs232++);
if(int16_counter_rs232>1000) {
int16_counter_rs232=1;
}
} // If Timer0 Rolls //
} // While Loop // |
Any help would be greatly appreciated! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 13, 2004 3:40 pm |
|
|
I notice that your interrupts are turning LEDs on and off.
I wonder what this is doing to the external Vref voltage ?
Is it it drooping momentarily when an LED is turned on ?
You could test this theory by commenting out the lines of
code in your ISR that turn the LEDs on and off.
See if that fixes the problem.
Could the A/D input voltages also be affected by turning
the LEDs on and off ? |
|
|
Trent
Joined: 13 Apr 2004 Posts: 2 Location: Melbourne, FL
|
It was the 8MHz Ext Osc AND the LEDs causing the noise |
Posted: Tue Apr 13, 2004 9:56 pm |
|
|
Thanks PCM Programmer,
Now the LEDs was a simple fix, I just flash them MUCH faster, less power, less noise.
The ext oscillator was chosen because of my critical need for exactly 10ms between packets [RS232 printf’s]. The internal RC [INTRC] is not calibrated very well on some PIC16F819s and thus the timing is off. There seems to be a large variation between actual oscillations at 8MHz, so much so that my RS232 56K has many errors. My solution was to add the Ext Osc. I know I can calibrate the internal osc, but how and in what step would I do that in the manufacturing process?
New Questions:
How do I calibrate the internal RC Osc to 8MHz?
Sample Code?
Thanks again, this was killin me. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|