Code Appendix 2 – Embedded Probe Software
peripherals.h
#ifndef PERIPHERALS_H
#define PERIPHERALS_H
//#define SCALE 308L
#define Vref 3.3// Reference voltage
#define LOWBATT
5.95 // Min voltage of battery
#define HIGHBATT 7.60 // Max voltage of battery
#define CHARGEBATT 7.15
// Min voltage to charge battery
#define SOLAR_RATIO 4.0303
#define BATTERY_RATIO 2.4242
#define DELAY (long unsigned int) 219726
// ~4 hours (0.065536 seconds per unit)
volatile double battVoltage;
volatile double srcVoltage;
void msDelay(unsigned int ms);
void initButtons(unsigned int mask);
unsigned int getButton(unsigned int mask);
void initBargraph(void);
void setBargraph(unsigned int display);
void initADC(unsigned int initChannel);
double getADC(unsigned int channel);
void _10usDelay(unsigned char _10us);
int checkCharge();
int checkShutdown();
#endif
peripherals.c
// peripherals.c
#include "peripherals.h"
#include <htc.h>
#include <pic16f684.h>
#include <pic.h>
void _10usDelay(unsigned char _10us)
{
const long loops = 1; // 1 cycles @ 4MHz for 10 us
long total_loops = loops*_10us;
long k = 0;
while(k<total_loops)
{
k++;
}
}
void msDelay(unsigned int ms)
{
const long loops = 50; // 50 cycles @ 4MHz for 1 ms
long total_loops = loops*ms;
long k = 0;
while(k<total_loops)
{
k++;
}
}
void initADC(unsigned int initChannel)
{
ADCON0 = 0xC0;
// right justified, Vref, turn off
initChannel &= 0x7; // make sure only 3 bits are used
ADCON0 |= (initChannel << 2); // add channel into config
ADCON1 = 0b00000001;
// Sample at Fosc/8
ADON = 1;
// turn on ADC
}
double getADC(unsigned int channel)
{
double adc_result = 0;
ADRESL = 0;
ADRESH = 0;
initADC(channel);
_10usDelay(2);
// initial and reset variables
// enable ADC
// wait 20us
GODONE = 1;
while(GODONE == 1)
;
ADIF = 0;
adc_result = ADRESL;
adc_result += (ADRESH << 8);
adc_result *= (Vref/0x3FF);
// wait for conversion to finish...
// reset interrupt
// get lower 8 bits
// add on higher 2 bits
// calculate ADC ratio
if(channel == 0x03)
// Battery
adc_result *= BATTERY_RATIO;
if(channel == 0x04)
// Solar
adc_result *= SOLAR_RATIO;
ADON = 0;
// multiply by voltage divider
// multiply by voltage divider
// turn off ADC
return adc_result;
}
int checkCharge()
{
int charge = 0;
if(srcVoltage > battVoltage)
// check if the source can charge the battery
{
if(RC4 == 1)
// Charging already started
charge = (battVoltage < HIGHBATT);
// Reached final charge when false
else
charge = (battVoltage < CHARGEBATT); // Check if battery should start charging
}
return charge;
}
int checkShutdown()
{
int shutdown = 0;
if(battVoltage < LOWBATT)
shutdown = 0;
else
shutdown = 1;
return shutdown;
}
battery.c
// Thomas Meismer & Matt Barranyk
// Battery below low threshold
// Shut off power to ext devices
// battery.c
#include <htc.h>
#include <pic16f684.h>
#include <pic.h>
#include "peripherals.h"
volatile unsigned int time0;
volatile unsigned int time1;
volatile long unsigned int time2;
__CONFIG (INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT & UNPROTECT & BORDIS & IESODIS & FCMDIS);
int main(void)
{
/*#########################################################################
________________________________Pin Layout_________________________________
Pin
I/O
Function
1
2
3
4
5
6
7
8
9
10
11
12
Vdd
RA5
RA4 (AN3)
RA3
RC5
RC4
RC3
RC2
RC1
RC0 (AN4)
RA2
Vref (RA1)
power : main power (battery input)
input : xBee done xmitting
input : Battery voltage ADC input
*unused
output : Debug (TMR0 interupt signal)
output : Charge signal (enable/disable charge)
output : Wakeup signal for xBee module
output : Battery voltage shutdown
*unused
input : Charging source ADC input
input : Manual wakeup (external wakeup button)
power : Reference voltage (RA0) {3.3V from reference diode}
13
RA0
*unused
14
Vss
power : Ground
___________________________________________________________________________
#########################################################################*/
TRISA = 0b110111;
TRISC = 0b000001;
ANSEL = 0b00011000;
// Sets RA0, RA1, RA2, RA4 and RA5 as inputs
// Sets RC0 as input and rest as outputs
// Sets AN3 and AN4 as analog (RA4, RC0)
ADIF = 0;
ADIE = 1;
// Turn off IF for ADC
// Enable interrupts for ADC
OPTION = 0b11000111; // Timer 0 options, post scale 1:256
T0IF = 0;
// Turn off IF for Timer 0
T0IE = 1;
// Enable interrupts for Timer 0
TMR1ON = 0;
// Turn off timer 1
T1CON = 0b00110000; // Timer 1 set up for 1:8 prescale and int clock
TMR1H = 0;
// Clear TMR1
TMR1L = 0;
TMR1IF = 0;
TMR1IE = 1;
// Turn off IF for Timer 1
// Enable interrupts for Timer 1
PR2 = 0xFF;
// Period for Timer2 set to 256
T2CON = 0b01111010; // Timer 2 set for 1:16 pre & post scale
TMR2 = 0;
// Clear Timer 2
TMR2ON = 1;
// Turn on Timer 2
TMR2IF = 0;
TMR2IE = 1;
// Turn off IF for Timer 2
// Enable interrupts for Timer 2
INTF = 0;
INTE = 1;
// Clear the RA2 interrupt flag
// Enable RA2 external change interrupt
PEIE = 1;
GIE = 1;
// uC peripheral and global interrupts enabled
time0 = 0;
time1 = 0;
time2 = 0;
RC4 = 1;
RC2 = 0;
RC3 = 1;
// initialize values
// Disable charge
// Disable output
// Initalize sleep mode
while(1)
{
// ..wait
if(RC3 == 0)
// Wakeup pin enabled...
{
if(TMR1ON == 0)
TMR1ON = 1;
// Turns on the xmit timeout counter
if(RA5 == 1)
// if xBee is done xmitting
{
msDelay(1000); // wait 1 second to restore xBee ready pin
RC3 = 1;
// Turn on xBee wakeup pin (puts to sleep)
TMR1ON = 0;
// Turn off timeout counter
}
}
}
}
// ISR's
void interrupt isr(void)
{
if (T0IF == 1) // Timer0 interrupt
{
T0IF = 0;
// Reset IF
srcVoltage = 0;
battVoltage = 0;
// initialize values
battVoltage = getADC(0x03);
srcVoltage = getADC(0x04);
RC4 = checkCharge();
RC2 = checkShutdown();
if(time0 == 0)
{
RC5 = 1;
time0 = 1;
}
else
{
RC5 = 0;
time0 = 0;
}
// get ADC reading on channel 3
// get ADC reading on channel 4
// Checks if battery needs charged
// Checks battery status
// For debug interrupt cycles
}
if (TMR2IF == 1) // Timer2 interrupt
{
TMR2IF = 0;
time2++;
if(time2 > DELAY)
{
time2 = 0;
// Reset timer interupt
// Adds longer delay
// Reset time2 to recount
if(RC2 == 1)
RC3 = 0;
else
RC3 = 1;
// Checks if battery is safe to use
// Turn off xBee wakeup pin (wakes from sleep)
// Battery is under voltage
}
}
if (TMR1IF == 1) // Timer1 interrupt
{
TMR1IF = 0;
time1++;
if(time1 == 200)
{
TMR1ON = 0;
RC3 = 1;
time1 = 0;
}
}
// Reset interrupt
// Turn off timer
// Turn on xBee wakeup pin (puts to sleep)
if (INTF == 1)
// Pin change interrupt
{
INTF = 0;
// Clear RA2 interrupt flag
if(RC2 == 1)
// Checks if battery is safe to use
RC3 = 0;
// Turn off xBee wakeup pin (wakes from sleep)
else
RC3 = 1;
// Battery is under voltage
}
}
© Copyright 2026 Paperzz