I'm having an odd issue with my PIC18F14K50 chip and have basically ignoring for a while. I'm to a point in my project where I can't ignore it anymore and my best (admittedly feeble) troubleshooting skills have not revealed the cause.
I have a small bit of code (displayed below) that initializes the USART and the ADC, and then goes into the main loop. The main loop simply samples the ADC a number of times, finds the maximum value over that period, performs some calculations on the max number and then uses printf to dump the results to the USART. Rinse, Repeat.
The input to the is a current transformer fed through a full wave rectifier and gain=1 peak detector circuit. The voltage input is roughly proportional to the current passing through the transformer coil. I've spent quite a bit of time making sure that it is correct and I've double and triple checked it with my scope and dummy loads and it's showing the proper voltage levels (max 1V @ ~16.5A).
Here's my issue:
When I power on the PIC, it runs through the main loop a few times and then hangs. Reset it and it runs a few more times and then quits. Reset it again and it runs through the main loop once and dies. The number of times through the loop is inconsistent, but the hangs are almost certain. A couple times I've been able to run it for hours without issue. To troubleshoot, I installed the blinking LED, thinking it could be the USART that is simply not giving me output. Well, no. When the PIC hangs, so does the LED. This leads me to think that it could be an ADC issue (with my code), but at this point I'm not terribly sure.
I thought it might be high voltage spikes, or analog noise that could be confusing the ADC, so I've checked the output voltages and I don't see anything like that. I thought it might be something wrong with my MCLR reset pin. Nope. Different ADC channel. No go. To try to make the problem go away, I've moved off my (self made) development board onto a very bare bones breadboard setup and I still get the issue. Cry.
Here's to hoping one of you guys has seen this behavior before and can explain to me the error of my ways. Here's the full code:
I have a small bit of code (displayed below) that initializes the USART and the ADC, and then goes into the main loop. The main loop simply samples the ADC a number of times, finds the maximum value over that period, performs some calculations on the max number and then uses printf to dump the results to the USART. Rinse, Repeat.
The input to the is a current transformer fed through a full wave rectifier and gain=1 peak detector circuit. The voltage input is roughly proportional to the current passing through the transformer coil. I've spent quite a bit of time making sure that it is correct and I've double and triple checked it with my scope and dummy loads and it's showing the proper voltage levels (max 1V @ ~16.5A).
Here's my issue:
When I power on the PIC, it runs through the main loop a few times and then hangs. Reset it and it runs a few more times and then quits. Reset it again and it runs through the main loop once and dies. The number of times through the loop is inconsistent, but the hangs are almost certain. A couple times I've been able to run it for hours without issue. To troubleshoot, I installed the blinking LED, thinking it could be the USART that is simply not giving me output. Well, no. When the PIC hangs, so does the LED. This leads me to think that it could be an ADC issue (with my code), but at this point I'm not terribly sure.
I thought it might be high voltage spikes, or analog noise that could be confusing the ADC, so I've checked the output voltages and I don't see anything like that. I thought it might be something wrong with my MCLR reset pin. Nope. Different ADC channel. No go. To try to make the problem go away, I've moved off my (self made) development board onto a very bare bones breadboard setup and I still get the issue. Cry.
Here's to hoping one of you guys has seen this behavior before and can explain to me the error of my ways. Here's the full code:
#include <p18cxxx.h>
#include <usart.h>
#include <delays.h>
#include <stdlib.h>
#include <stdio.h>
#include <GenericTypeDefs.h>
/*
** PIC18LF14K50 Configuration Bit:
**
** FOSC = IRC - Internal RC Oscillator
** CPUDIV = NOCLKDIV - No CPU System Clock divide
** PLLEN = OFF - PLL is under software control
** FCMEN = OFF - Fail-Safe Clock Monitor disabled
** BOREN = OFF - Brown-out Reset disabled in hardware and software
** WDTEN = OFF - WDT is controlled by SWDTEN bit of the WDTCON register
** MCLRE = ON - MCLR pin enabled, RE3 input pin disabled
** LVP = OFF - Single-Supply ICSP disabled
*/
#pragma config FOSC = IRC, CPUDIV = NOCLKDIV, PLLEN = OFF
#pragma config FCMEN = OFF, BOREN = OFF
#pragma config WDTEN = OFF, MCLRE = ON, LVP = OFF
void delay_ms (unsigned int ms) // approximate
{
do {
Delay1KTCYx(4);
} while(ms--);
}
void delay_us (unsigned int us) {
do {
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
} while (us--);
}
void printfloat(float x) {
unsigned long v1 = 0;
unsigned long v2 = 0;
v1 = (long)((float)x);
v2 = (long)((float)x * 1000) - (v1 * 1000);
printf((rom far char*)"%li.%03li",v1,v2);
}
void main(void)
{
UINT16 result = 0;
UINT16 c = 0;
UINT16 i = 0;
float volts = 0;
float voltsrms = 0;
float v = 0.001;
UINT16 max = 0;
float a = 0.0141; // Irms = 0.098, I = 0.0141
float amps = 0;
float ampsrms = 0;
// Select 16MHz Clock
OSCCONbits.IRCF2=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF0=1;
// Initialize ports
TRISA &= ~(0x20); // Set RA5 port to output
LATA |= 0x20; // Init RA5 port to high (LED off)
// configure USART
OpenUSART( USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH,
25 );
// ADC Initialization
// Using AN7 which is RC3 and is pin7 on the dip version of the pic18F14K50
ANSEL = 0x00; // enable digital input buffer
ANSELH = 0x00; // enable digital input buffer
ANSELbits.ANS7=1; // disable digital input buffer on AN3 only
TRISC = 0x00;
TRISCbits.TRISC3=1; // set port direction to input, disable output driver
ADCON0bits.CHS3=0; // ADC port channel 7 (AN7)
ADCON0bits.CHS2=1;
ADCON0bits.CHS1=1;
ADCON0bits.CHS0=1;
ADCON0bits.ADON=1; // Enable ADC
REFCON0bits.FVR1EN=1; // Enable Fixed Voltage Reference
REFCON0bits.FVR1S1=0; // Select voltage 01=1v, 10=2v, 11=4v
REFCON0bits.FVR1S0=1;
ADCON1=0x00;
ADCON1bits.PVCFG1=1; // Use Internal Fixed Voltage Reference for Positive Reference
ADCON1bits.PVCFG0=0;
ADCON1bits.NVCFG1=0; // Use Vss for Negative Reference
ADCON1bits.NVCFG0=0;
ADCON2bits.ADFM=1; // Right justify result = 1; Left justify result = 0;
ADCON2bits.ACQT2=1; // 20 TAD
ADCON2bits.ACQT1=1;
ADCON2bits.ACQT0=1;
ADCON2bits.ADCS2=0; // Select Fosc/64
ADCON2bits.ADCS1=1;
ADCON2bits.ADCS0=1;
while(1)
{
result = 0;
max = 0;
volts = 0.0;
c++;
for (i = 0; i < 200; i++) {
delay_us(500);
ADCON0bits.GO=1;
while (ADCON0bits.GO); // Wait conversion done
result = ADRESH;
result = (result << 8);
result += ADRESL;
if (result > max) max = result;
}
volts = max * (float)v;
voltsrms = volts * 0.7;
amps = max * (float)a;
ampsrms = amps * 0.7;
printf((rom far char*)"%d (%d): V: ",c, max);
printfloat(volts);
printf((rom far char*)", I: ");
printfloat(amps);
printf((rom far char*)", Vrms: ");
printfloat(voltsrms);
printf((rom far char*)", Irms: ");
printfloat(ampsrms);
printf((rom far char*)"\r\n");
//LATA ^= 0x20;
}
}
Last edited: