Rev 434 | Rev 691 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#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();
// try to initialize the FAT 16 filesystem on the SD-Card
Fat16_Init();
// initialize the settings
Settings_Init();
// initialize logging (needs settings)
Logging_Init();
LEDRED_OFF;
LEDGRN_ON;
#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
DebugOut.Analog[9] = SysState;
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);
}