0,0 → 1,227 |
#include <avr/boot.h> |
|
#include <avr/io.h> |
#include <avr/interrupt.h> |
|
#include "main.h" |
#include "timer0.h" |
#include "uart0.h" |
#include "uart1.h" |
#include "fat16.h" |
#include "led.h" |
#include "menu.h" |
#include "printf_P.h" |
#include "analog.h" |
#include "gps.h" |
#include "button.h" |
#include "logging.h" |
#include "settings.h" |
|
#define FOLLOWME_INTERVAL 1000 // 1 second update |
#define CELLUNDERVOLTAGE 32 // lowest allowed voltage/cell; 32 = 3.2V |
|
#ifdef USE_FOLLOWME |
int16_t UBat = 120; |
int16_t Zellenzahl = 0; |
int16_t PowerOn = 0; |
int16_t i = 0; |
int16_t delay = 0; |
#endif |
|
uint16_t Error = 0; |
SysState_t SysState = STATE_UNDEFINED; |
|
int main (void) |
{ |
static uint16_t FollowMe_Timer = 0; |
|
// disable interrupts global |
cli(); |
|
// disable watchdog |
MCUSR &=~(1<<WDRF); |
WDTCSR |= (1<<WDCE)|(1<<WDE); |
WDTCSR = 0; |
|
// initalize modules |
LED_Init(); |
LEDRED_ON; |
TIMER0_Init(); |
USART0_Init(); |
UBX_Init(); |
USART1_Init(); |
ADC_Init(); |
Button_Init(); |
// enable interrupts global |
sei(); |
|
LEDRED_OFF; |
LEDGRN_ON; |
|
// try to initialize the FAT 16 filesystem on the SD-Card |
Fat16_Init(); |
|
// initialize the settings |
Settings_Init(); |
// initialize logging (needs settings) |
Logging_Init(); |
|
#ifdef USE_SDLOGGER |
printf("\r\n\r\nHW: SD-Logger"); |
#endif |
#ifdef USE_FOLLOWME |
printf("\r\n\r\nHW: Follow-Me"); |
#endif |
printf("\r\nFollow Me\n\rSoftware:V%d.%d%c ",VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + 'a'); |
printf("\r\n------------------------------"); |
printf("\r\n"); |
|
|
//BeepTime = 2000; |
|
LCD_Clear(); |
|
FollowMe_Timer = SetDelay(FOLLOWME_INTERVAL); |
|
while (1) |
{ |
// get gps data to update the follow me position |
GPS_Update(); |
|
// update logging |
Logging_Update(); |
|
// check for button action and change state resectively |
if(GetButton()) |
{ |
BeepTime = 200; |
|
switch(SysState) |
{ |
case STATE_IDLE: |
if(!Error) SysState = STATE_SEND_FOLLOWME; // activate followme only of no error has occured |
break; |
|
case STATE_SEND_FOLLOWME: |
SysState = STATE_IDLE; |
break; |
|
default: |
SysState = STATE_IDLE; |
break; |
} |
|
} |
|
// state machine |
switch(SysState) |
{ |
case STATE_SEND_FOLLOWME: |
if(CheckDelay(FollowMe_Timer)) // time for next message? |
{ |
if(FollowMe.Position.Status == NEWDATA) // if new |
{ // update remaining data |
FollowMe_Timer = SetDelay(FOLLOWME_INTERVAL); // reset timer |
FollowMe.Heading = -1; // invalid heading |
FollowMe.ToleranceRadius = 1; // 1 meter |
FollowMe.HoldTime = 60; // go home after 60s without any update |
FollowMe.Event_Flag = 0; // no event |
FollowMe.reserve[0] = 0; // reserve |
FollowMe.reserve[1] = 0; // reserve |
FollowMe.reserve[2] = 0; // reserve |
FollowMe.reserve[3] = 0; // reserve |
Request_SendFollowMe = 1; // triggers serial tranmission |
|
} |
else // now new position avalable (maybe bad gps signal condition) |
{ |
FollowMe_Timer = SetDelay(FOLLOWME_INTERVAL/4); // reset timer on higer frequency |
} |
LEDGRN_TOGGLE; // indication of active follow me |
} |
break; |
|
case STATE_IDLE: |
// do nothing |
LEDGRN_ON; |
break; |
|
default: |
// triger to idle state |
SysState = STATE_IDLE; |
break; |
|
} |
|
|
// restart ADConversion if ready |
if(ADReady) |
{ |
DebugOut.Analog[0] = Adc0; |
DebugOut.Analog[1] = Adc1; |
DebugOut.Analog[2] = Adc2; |
DebugOut.Analog[3] = Adc3; |
DebugOut.Analog[4] = Adc4; |
DebugOut.Analog[5] = Adc5; |
DebugOut.Analog[6] = Adc6; |
DebugOut.Analog[7] = Adc7; |
|
#ifdef USE_FOLLOWME |
// AVcc = 5V --> 5V = 1024 counts |
// the voltage at the voltage divider reference point is 0.8V less that the UBat |
// because of the silicon diode inbetween. |
// voltage divider R2=10K, R3=3K9 |
// UAdc4 = R3/(R3+R2)*UBat= 3.9/(3.9+10)*UBat = UBat/3.564 |
UBat = (3 * UBat + (64 * Adc4) / 368) / 4; |
DebugOut.Analog[8] = UBat; |
|
// check for zellenzahl |
if(PowerOn < 100) |
{ |
if(UBat<=84) Zellenzahl = 2; |
else Zellenzahl = 3; |
PowerOn++; |
} |
DebugOut.Analog[16] = Zellenzahl; |
DebugOut.Analog[17] = PowerOn; |
|
//show recognised Zellenzahl to user |
if(i < Zellenzahl && PowerOn >= 100 && BeepTime == 0 && delay > 1000) |
{ |
BeepTime = 100; |
i++; |
delay = 0; |
} |
if(delay < 1500) delay++; |
|
// monitor battery undervoltage [...||(UBat<74) as temporary workaround to protect 2s lipo packs] |
if(((UBat < Zellenzahl * CELLUNDERVOLTAGE)||(UBat < 74)) && (PowerOn >= 100)) |
{ // sound for low battery |
BeepModulation = 0x0300; |
if(!BeepTime) |
{ |
//BeepTime = 6000; // 0.6 seconds |
} |
Error |= ERROR_LOW_BAT; |
} |
else |
{ |
Error &= ~ERROR_LOW_BAT; |
} |
#endif |
ADReady = 0; |
ADC_Enable(); // restart ad conversion sequence |
} |
|
// serial communication |
USART0_ProcessRxData(); |
USART0_TransmitTxData(); |
|
// indicate error, blinking code tbd. |
if(Error) LEDRED_ON; |
else LEDRED_OFF; |
|
} |
return (1); |
} |
|