Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
Copyright 2008, by Michael Walter
All functions written by Michael Walter are free software and can be redistributed and/or modified under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.
Please note: The software is based on the framework provided by H. Buss and I. Busker in their Mikrokopter projekt. All functions that
are not written by Michael Walter are under the license by H. Buss and I. Busker (license_buss.txt) published by www.mikrokopter.de
unless it is stated otherwise.
*/
#include "main.h"
#include "kafi.h"
#include "mymath.h"
#include <math.h>
int GPSTracking
= 0;
int targetPosValid
= 0;
int homePosValid
= 0;
uint8_t gpsState
;
gpsInfo_t actualPos
; // measured position (last gps record)
gpsInfo_t targetPos
; // measured position (last gps record)
gpsInfo_t homePos
; // measured position (last gps record)
NAV_STATUS_t navStatus
;
NAV_POSLLH_t navPosLlh
;
NAV_POSUTM_t navPosUtm
;
NAV_VELNED_t navVelNed
;
signed int GPS_Nick
= 0;
signed int GPS_Roll
= 0;
long distanceNS
= 0;
long distanceEW
= 0;
long velocityNS
= 0;
long velocityEW
= 0;
unsigned long maxDistance
= 0;
int roll_gain
= 0;
int nick_gain
= 0;
int nick_gain_p
= 0;
int nick_gain_d
= 0;
int roll_gain_p
= 0;
int roll_gain_d
= 0;
int Override
= 0;
int TargetGier
= 0;
extern int sollGier
;
char *ubxP
, *ubxEp
, *ubxSp
; // pointers to packet currently transfered
uint8_t CK_A
, CK_B
; // UBX checksum bytes
uint8_t ignorePacket
; // true when previous packet was not processed
unsigned short msgLen
;
uint8_t msgID
;
void GPSscanData
(void);
void GPSupdate
(void);
/* ****************************************************************************
Functionname: GPSupdate */ /*!
Description:
@return void
@pre -
@post -
@author Michael Walter
**************************************************************************** */
void GPSupdate
(void)
{
float SIN_H
, COS_H
;
long max_p
= 0;
long max_d
= 0;
if (abs(PPM_in
[EE_Parameter.
Kanalbelegung[K_ROLL
]])> 15 ||
abs(PPM_in
[EE_Parameter.
Kanalbelegung[K_GIER
]])> 10 ||
abs(PPM_in
[EE_Parameter.
Kanalbelegung[K_NICK
]])> 15)
{
Override
= 1;
}
else
{
Override
= 0;
}
/* Set Home Position */
if ((actualPos.
state > 2) &&
(homePosValid
== 0))
{
/* Save Current Position */
homePos.
north = actualPos.
north;
homePos.
east = actualPos.
east;
homePos.
altitude = actualPos.
altitude ;
homePosValid
= 1;
}
/* Set Target Position */
if ((actualPos.
state > 2) &&
(PPM_in
[EE_Parameter.
Kanalbelegung[K_POTI3
]] < -100))
{
/* Save Current Position */
targetPos.
north = actualPos.
north;
targetPos.
east = actualPos.
east;
targetPos.
altitude = actualPos.
altitude ;
targetPosValid
= 1;
if(BeepMuster
== 0xffff)
{
beeptime
= 5000;
BeepMuster
= 0x0100;
}
}
if ((GPSTracking
== 1) &&
(PPM_in
[EE_Parameter.
Kanalbelegung[K_POTI3
]] < 100))
{
GPSTracking
= 0;
beeptime
= 5000;
BeepMuster
= 0x0080;
}
/* The System is in Tracking State*/
if ((GPSTracking
== 0) &&
(targetPosValid
== 1) &&
(PPM_in
[EE_Parameter.
Kanalbelegung[K_POTI3
]] > 100) &&
(actualPos.
state > 2))
{
GPSTracking
= 1;
beeptime
= 5000;
BeepMuster
= 0x0c00;
}
max_p
= (MAX
(0, (PPM_in
[EE_Parameter.
Kanalbelegung[K_POTI1
]] + 170)) / 20);
max_d
= (MAX
(0, (PPM_in
[EE_Parameter.
Kanalbelegung[K_POTI2
]] + 170)) / 40);
#if 0
DebugOut.
Analog[11] = max_p
;
DebugOut.
Analog[12] = max_d
;
#endif
static int GPSTrackingCycles
= 0;
long maxGainPos
= 140;
long maxGainVel
= 140;
/* Slowly ramp up gain */
if (GPSTrackingCycles
< 1000)
{
GPSTrackingCycles
++;
}
maxGainPos
= (maxGainPos
* GPSTrackingCycles
) / 1000;
maxGainVel
= (maxGainVel
* GPSTrackingCycles
) / 1000;
if (actualPos.
state > 2 )
{
distanceNS
= actualPos.
north - targetPos.
north; // in 0.1m
distanceEW
= actualPos.
east - targetPos.
east; // in 0.1m
velocityNS
= actualPos.
velNorth; // in 0.1m/s
velocityEW
= actualPos.
velEast; // in 0.1m/s
maxDistance
= sqrt(distanceNS
* distanceNS
+ distanceEW
* distanceEW
);
// Limit GPS_Nick to 25
nick_gain_p
= (long) MAX
(-maxGainPos
, MIN
(maxGainPos
, ((distanceNS
* max_p
)/50))); //m
nick_gain_d
= (long) MAX
(-maxGainVel
, MIN
(maxGainVel
, ((actualPos.
velNorth * max_d
)/50))); //m/s
roll_gain_p
= (long) MAX
(-maxGainPos
, MIN
(maxGainPos
, ((distanceEW
* max_p
)/50))); //m
roll_gain_d
= (long) MAX
(-maxGainVel
, MIN
(maxGainVel
, ((actualPos.
velEast * max_d
)/50))); //m/s
TargetGier
= c_atan2
(-distanceEW
/ 8, -distanceNS
/ 8) * 10;
}
if ((GPSTracking
== 1) &&
(actualPos.
state > 2) &&
(Override
== 0))
{
/* Calculate Distance to Target */
SIN_H
= (float) sin(status.
Psi);
COS_H
=(float) cos(status.
Psi);
/* PD-Regler */
nick_gain
= nick_gain_p
+ nick_gain_d
;
roll_gain
= -(roll_gain_p
+ roll_gain_d
);
GPS_Nick
= (int) (COS_H
* (float) nick_gain
- SIN_H
* (float) roll_gain
);
GPS_Roll
= (int) (SIN_H
* (float) nick_gain
+ COS_H
* (float) roll_gain
);
GPS_Nick
= MAX
(-maxGainPos
, MIN
(maxGainPos
, GPS_Nick
));
GPS_Roll
= MAX
(-maxGainPos
, MIN
(maxGainPos
, GPS_Roll
));
/* Turn the mikrokopter slowly towards the target position */
{
int OffsetGier
;
if (maxDistance
/ 10 > 2)
{
OffsetGier
= 2;
}
else
{
OffsetGier
= 0;
}
if (TargetGier
< 0)
{
TargetGier
+= 3600;
}
if (TargetGier
> sollGier
)
{
if (TargetGier
- sollGier
< 1800)
{
sollGier
+= OffsetGier
;
}
else
{
sollGier
-= OffsetGier
;
}
}
else
{
if (sollGier
- TargetGier
< 1800)
{
sollGier
-= OffsetGier
;
}
else
{
sollGier
+= OffsetGier
;
}
}
}
#if 0
/* Go round in a square */
if (maxDistance
/ 10 < 10)
{
static int iState
= 0;
switch (iState
)
{
case 0:
targetPos.
north += 400;
targetPos.
east += 0;
GPSTrackingCycles
= 0;
iState
++;
break;
case 1:
targetPos.
north += 0;
targetPos.
east += 400;
GPSTrackingCycles
= 0;
iState
++;
break;
case 2:
targetPos.
north -= 400;
targetPos.
east += 0;
GPSTrackingCycles
= 0;
iState
++;
break;
case 3:
targetPos.
north += 0;
targetPos.
east -= 400;
GPSTrackingCycles
= 0;
iState
=0;
break;
default:
iState
=0;
break;
}
beeptime
= 5000;
BeepMuster
= 0x0c00;
}
#endif
}
else
{
GPS_Nick
= 0;
GPS_Roll
= 0;
GPSTrackingCycles
= 0;
}
}
/* ****************************************************************************
Functionname: InitGPS */ /*!
Description:
@return void
@pre -
@post -
@author
**************************************************************************** */
void InitGPS
(void)
{
// USART1 Control and Status Register A, B, C and baud rate register
uint8_t sreg
= SREG
;
//uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART1_BAUD) - 1);
// disable all interrupts before reconfiguration
cli
();
// disable RX-Interrupt
UCSR1B
&= ~
(1 << RXCIE1
);
// disable TX-Interrupt
UCSR1B
&= ~
(1 << TXCIE1
);
// disable DRE-Interrupt
UCSR1B
&= ~
(1 << UDRIE1
);
// set direction of RXD1 and TXD1 pins
// set RXD1 (PD2) as an input pin
PORTD
|= (1 << PORTD2
);
DDRD
&= ~
(1 << DDD2
);
// set TXD1 (PD3) as an output pin
PORTD
|= (1 << PORTD3
);
DDRD
|= (1 << DDD3
);
// USART0 Baud Rate Register
// set clock divider
UBRR1H
= 0;
UBRR1L
= BAUDRATE
;
// enable double speed operation
//UCSR1A |= (1 << U2X1);
UCSR1A
= _B0
(U2X1
);
// enable receiver and transmitter
UCSR1B
= (1 << TXEN1
) | (1 << RXEN1
);
// set asynchronous mode
UCSR1C
&= ~
(1 << UMSEL11
);
UCSR1C
&= ~
(1 << UMSEL10
);
// no parity
UCSR1C
&= ~
(1 << UPM11
);
UCSR1C
&= ~
(1 << UPM10
);
// 1 stop bit
UCSR1C
&= ~
(1 << USBS1
);
// 8-bit
UCSR1B
&= ~
(1 << UCSZ12
);
UCSR1C
|= (1 << UCSZ11
);
UCSR1C
|= (1 << UCSZ10
);
// flush receive buffer explicit
while ( UCSR1A
& (1<<RXC1
) ) UDR1
;
// enable interrupts at the end
// enable RX-Interrupt
UCSR1B
|= (1 << RXCIE1
);
// enable TX-Interrupt
UCSR1B
|= (1 << TXCIE1
);
// enable DRE interrupt
//UCSR1B |= (1 << UDRIE1);
// restore global interrupt flags
SREG
= sreg
;
gpsState
= GPS_EMPTY
;
}
/* ****************************************************************************
Functionname: InitGPS */ /*!
Description: Copy GPS paket data to actualPos
@return void
@pre -
@post -
@author
**************************************************************************** */
void GPSscanData
(void)
{
if (navStatus.
packetStatus == 1) // valid packet
{
actualPos.
state = navStatus.
GPSfix;
if ((actualPos.
state > 1) && (GPSTracking
== 0))
{
GRN_FLASH
;
}
navStatus.
packetStatus = 0;
}
if (navPosUtm.
packetStatus == 1) // valid packet
{
actualPos.
north = navPosUtm.
NORTH/10L;
actualPos.
east = navPosUtm.
EAST/10L;
actualPos.
altitude = navPosUtm.
ALT/100;
actualPos.
ITOW = navPosUtm.
ITOW;
navPosUtm.
packetStatus = 0;
}
/*
if (navPosLlh.packetStatus == 1)
{
actualPos.longi = navPosLlh.LON;
actualPos.lati = navPosLlh.LAT;
actualPos.height = navPosLlh.HEIGHT;
navPosLlh.packetStatus = 0;
}
*/
if (navVelNed.
packetStatus == 1)
{
actualPos.
velNorth = navVelNed.
VEL_N;
actualPos.
velEast = navVelNed.
VEL_E;
actualPos.
velDown = navVelNed.
VEL_D;
actualPos.
groundSpeed = navVelNed.
GSpeed;
navVelNed.
packetStatus = 0;
}
}
/* ****************************************************************************
Functionname: SIGNAL */ /*!
Description:
@return void
@pre -
@post -
@author
**************************************************************************** */
SIGNAL
(SIG_USART1_RECV
)
{
uint8_t c
;
uint8_t re
;
re
= (UCSR1A
& (_B1
(FE1
) | _B1
(DOR1
))); // any error occured ?
c
= UDR1
;
if (re
== 0)
{
switch (gpsState
)
{
case GPS_EMPTY
:
if (c
== SYNC_CHAR1
)
{
gpsState
= GPS_SYNC1
;
}
break;
case GPS_SYNC1
:
if (c
== SYNC_CHAR2
)
{
gpsState
= GPS_SYNC2
;
}
else if (c
!= SYNC_CHAR1
)
{
gpsState
= GPS_EMPTY
;
}
break;
case GPS_SYNC2
:
if (c
== CLASS_NAV
)
{
gpsState
= GPS_CLASS
;
}
else
{
gpsState
= GPS_EMPTY
;
}
break;
case GPS_CLASS
: // msg ID seen: init packed receive
msgID
= c
;
CK_A
= CLASS_NAV
+ c
;
CK_B
= CLASS_NAV
+ CK_A
;
gpsState
= GPS_LEN1
;
switch (msgID
)
{
case MSGID_STATUS
:
ubxP
= (char*)&navStatus
;
ubxEp
= (char*)(&navStatus
+ sizeof(NAV_STATUS_t
));
ubxSp
= (char*)&navStatus.
packetStatus;
ignorePacket
= navStatus.
packetStatus;
break;
/*
case MSGID_POSLLH:
ubxP = (char*)&navPosLlh;
ubxEp = (char*)(&navPosLlh + sizeof(NAV_POSLLH_t));
ubxSp = (char*)&navPosLlh.packetStatus;
ignorePacket = navPosLlh.packetStatus;
break;
*/
case MSGID_POSUTM
:
ubxP
= (char*)&navPosUtm
;
ubxEp
= (char*)(&navPosUtm
+ sizeof(NAV_POSUTM_t
));
ubxSp
= (char*)&navPosUtm.
packetStatus;
ignorePacket
= navPosUtm.
packetStatus;
break;
case MSGID_VELNED
:
ubxP
= (char*)&navVelNed
;
ubxEp
= (char*)(&navVelNed
+ sizeof(NAV_VELNED_t
));
ubxSp
= (char*)&navVelNed.
packetStatus;
ignorePacket
= navVelNed.
packetStatus;
break;
default:
ignorePacket
= 1;
ubxSp
= (char*)0;
}
break;
case GPS_LEN1
: // first len byte
msgLen
= c
;
CK_A
+= c
;
CK_B
+= CK_A
;
gpsState
= GPS_LEN2
;
break;
case GPS_LEN2
: // second len byte
msgLen
= msgLen
+ (c
* 256);
CK_A
+= c
;
CK_B
+= CK_A
;
gpsState
= GPS_FILLING
; // next data will be stored in packet struct
break;
case GPS_FILLING
:
CK_A
+= c
;
CK_B
+= CK_A
;
if ( !ignorePacket
&& ubxP
< ubxEp
)
{
*ubxP
++ = c
;
}
if (--msgLen
== 0)
{
gpsState
= GPS_CKA
;
}
break;
case GPS_CKA
:
if (c
== CK_A
)
{
gpsState
= GPS_CKB
;
}
else
{
gpsState
= GPS_EMPTY
;
}
break;
case GPS_CKB
:
if (c
== CK_B
&& ubxSp
) // No error -> packet received successfully
{
*ubxSp
= 1; // set packetStatus in struct
GPSscanData
();
}
gpsState
= GPS_EMPTY
; // ready for next packet
break;
default:
gpsState
= GPS_EMPTY
; // ready for next packet
}
}
else // discard any data if error occured
{
gpsState
= GPS_EMPTY
;
}
}