Subversion Repositories MK3Mag

Compare Revisions

Regard whitespace Rev 18 → Rev 19

/branches/MK3Mag V0.14 Code Redesign Killagreg/main.c
54,68 → 54,75
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <avr/interrupt.h>
#include <math.h>
#include <stdlib.h>
 
signed int OffsetN, OffsetR, OffsetZ;
 
signed int RawMagnet1a,RawMagnet1b; // raw AD-Data
signed int RawMagnet2a,RawMagnet2b;
signed int RawMagnet3a,RawMagnet3b;
signed int Xmin = 0, Xmax = 0; Ymin = 0, Ymax = 0; Zmin = 0, Zmax = 0;
signed int UncalMagnetN,UncalMagnetR,UncalMagnetZ; // Messwert-Delta ohne Offset- und Verstärker korrektur
signed int MagnetN,MagnetR,MagnetZ;
unsigned int PwmHeading = 0;
unsigned int PC_Connected = 0;
unsigned int Heading;
#include "main.h"
#include "timer0.h"
#include "twislave.h"
#include "led.h"
#include "analog.h"
#include "uart.h"
 
uint16_t eeXmin EEMEM = 0;
uint16_t eeXmax EEMEM = 0;
uint16_t eeYmin EEMEM = 0;
uint16_t eeYmax EEMEM = 0;
uint16_t eeZmin EEMEM = 0;
uint16_t eeZmax EEMEM = 0;
 
int16_t RawMagnet1a, RawMagnet1b; // raw AD-Data
int16_t RawMagnet2a, RawMagnet2b;
int16_t RawMagnet3a, RawMagnet3b;
 
//############################################################################
//
void Wait(unsigned char dauer)
//############################################################################
typedef struct
{
dauer = (unsigned char)TCNT0 + dauer;
while((TCNT0 - dauer) & 0x80);
}
int16_t Range;
int16_t Offset;
} Scaling_t;
 
typedef struct
{
Scaling_t X;
Scaling_t Y;
Scaling_t Z;
} Calibration_t;
 
Calibration_t eeCalibration EEMEM; // calibration data in EEProm
Calibration_t Calibration; // calibration data in RAM
 
 
int16_t UncalMagnetX, UncalMagnetY, UncalMagnetZ; // sensor signal difference without Scaling
int16_t MagnetX, MagnetY, MagnetZ; // rescaled magnetic field readings
 
uint8_t PC_Connected = 0;
 
int16_t Heading;
 
 
void CalcFields(void)
{
UncalMagnetN = (1 * UncalMagnetN + (RawMagnet1a - RawMagnet1b)) / 2;
UncalMagnetR = (1 * UncalMagnetR + (RawMagnet3a - RawMagnet3b)) / 2;
UncalMagnetX = (1 * UncalMagnetX + (RawMagnet1a - RawMagnet1b)) / 2;
UncalMagnetY = (1 * UncalMagnetY + (RawMagnet3a - RawMagnet3b)) / 2;
UncalMagnetZ = (1 * UncalMagnetZ + (RawMagnet2a - RawMagnet2b)) / 2;
 
OffsetN = (Xmin + Xmax) / 2;
OffsetR = (Ymin + Ymax) / 2;
OffsetZ = (Zmin + Zmax) / 2;
 
MagnetN = (1024L * (long)(UncalMagnetN - OffsetN)) / (Xmax - Xmin);
MagnetR = (1024L * (long)(UncalMagnetR - OffsetR)) / (Ymax - Ymin);
MagnetZ = (1024L * (long)(UncalMagnetZ - OffsetZ)) / (Zmax - Zmin);
MagnetX = (1024L * (int32_t)(UncalMagnetX - Calibration.X.Offset)) / (Calibration.X.Range);
MagnetY = (1024L * (int32_t)(UncalMagnetY - Calibration.Y.Offset)) / (Calibration.Y.Range);
MagnetZ = (1024L * (int32_t)(UncalMagnetZ - Calibration.Z.Offset)) / (Calibration.Z.Range);
}
 
void CalcHeading(void)
{
double nick_rad, roll_rad, Hx, Hy, Cx, Cy, Cz;
int heading;
int16_t heading = -1;
nick_rad = ((double)ExternData.Winkel[0]) * M_PI / (double)(1800);
roll_rad = ((double)ExternData.Winkel[1]) * M_PI / (double)(1800);
// calculate nick and roll angle i rad
nick_rad = ((double)ExternData.Attitude[NICK]) * M_PI / (double)(1800);
roll_rad = ((double)ExternData.Attitude[ROLL]) * M_PI / (double)(1800);
 
Cx = MagnetN;
Cy = MagnetR;
Cx = MagnetX;
Cy = MagnetY;
Cz = MagnetZ;
 
if(ExternData.Orientation == 1)
{
Cx = MagnetR;
Cy = -MagnetN;
Cx = MagnetX;
Cy = -MagnetY;
Cz = MagnetZ;
}
 
134,21 → 141,30
else if(Hx > 0 && Hy > 0) heading = 360 - (atan(Hy / Hx) * 180.0) / M_PI;
 
if(abs(heading) < 361) Heading = heading;
PwmHeading = Heading + 10;
 
}
 
 
void Calibrate(void)
{
unsigned char cal;
uint8_t cal;
static int16_t Xmin = 0, Xmax = 0, Ymin = 0, Ymax = 0, Zmin = 0, Zmax = 0;
 
// check both sources of communication for calibration request
if(I2C_WriteCal.CalByte) cal = I2C_WriteCal.CalByte;
else cal = ExternData.CalState;
 
// calibration state machine
switch(cal)
{
case 0:
LED_ON;
case 0: // no calibration
LED_GRN_ON;
break;
case 1:
 
case 1: // 1st step of calibration
// initialize ranges
// used to change the orientation of the MK3MAG in the horizontal plane
LED_GRN_OFF;
Xmin = 10000;
Xmax = -10000;
Ymin = 10000;
155,37 → 171,48
Ymax = -10000;
Zmin = 10000;
Zmax = -10000;
LED_OFF;
break;
case 2:
LED_ON; // find Min and Max of the X- and Y-Sensors
if(UncalMagnetN < Xmin) Xmin = UncalMagnetN;
if(UncalMagnetN > Xmax) Xmax = UncalMagnetN;
if(UncalMagnetR < Ymin) Ymin = UncalMagnetR;
if(UncalMagnetR > Ymax) Ymax = UncalMagnetR;
 
case 2: // 2nd step of calibration
// find Min and Max of the X- and Y-Sensors during rotation in the horizontal plane
LED_GRN_ON;
if(UncalMagnetX < Xmin) Xmin = UncalMagnetX;
if(UncalMagnetX > Xmax) Xmax = UncalMagnetX;
if(UncalMagnetY < Ymin) Ymin = UncalMagnetY;
if(UncalMagnetY > Ymax) Ymax = UncalMagnetY;
break;
case 3:
LED_OFF;
 
case 3: // 3rd step of calibration
// used to change the orietation of the MK3MAG vertical to the horizontal plane
LED_GRN_OFF;
break;
 
case 4:
LED_ON; // find Min and Max of the Z-Sensor
// find Min and Max of the Z-Sensor
LED_GRN_ON;
if(UncalMagnetZ < Zmin) Zmin = UncalMagnetZ;
if(UncalMagnetZ > Zmax) Zmax = UncalMagnetZ;
break;
 
case 5:
LED_OFF; // Save values
if((Xmax - Xmin) > 150 && (Ymax - Ymin) > 150 && (Zmax - Zmin) > 150)
LED_GRN_OFF; // Save values
Calibration.X.Range = Xmax - Xmin;
Calibration.X.Offset = (Xmin + Xmax) / 2;
Calibration.Y.Range = Ymax - Ymin;
Calibration.Y.Offset = (Ymin + Ymax) / 2;
Calibration.Z.Range = Zmax - Zmin;
Calibration.Z.Offset = (Zmin + Zmax) / 2;
if((Calibration.X.Range > 150) && (Calibration.Y.Range > 150) && (Calibration.Z.Range > 150))
{
eeprom_write_word(&eeXmin, Xmin);
eeprom_write_word(&eeXmax, Xmax);
eeprom_write_word(&eeYmin, Ymin);
eeprom_write_word(&eeYmax, Ymax);
eeprom_write_word(&eeZmin, Zmin);
eeprom_write_word(&eeZmax, Zmax);
eeprom_write_block(&Calibration, &eeCalibration, sizeof(Calibration_t));
Delay_ms(2000);
}
LED_ON;
LED_GRN_ON;
break;
 
default:
LED_GRN_ON;
break;
}
}
 
192,95 → 219,81
 
void SetDebugValues(void)
{
DebugOut.Analog[0] = MagnetN;
DebugOut.Analog[1] = MagnetR;
DebugOut.Analog[0] = MagnetX;
DebugOut.Analog[1] = MagnetY;
DebugOut.Analog[2] = MagnetZ;
DebugOut.Analog[3] = UncalMagnetN;
DebugOut.Analog[4] = UncalMagnetR;
DebugOut.Analog[3] = UncalMagnetX;
DebugOut.Analog[4] = UncalMagnetY;
DebugOut.Analog[5] = UncalMagnetZ;
DebugOut.Analog[6] = ExternData.Winkel[0];
DebugOut.Analog[7] = ExternData.Winkel[1];
DebugOut.Analog[8] = Xmin;
DebugOut.Analog[9] = Xmax;
DebugOut.Analog[10] = Ymin;
DebugOut.Analog[11] = Ymax;
DebugOut.Analog[12] = Zmin;
DebugOut.Analog[13] = Zmax;
DebugOut.Analog[6] = ExternData.Attitude[NICK];
DebugOut.Analog[7] = ExternData.Attitude[ROLL];
DebugOut.Analog[8] = Calibration.X.Offset;
DebugOut.Analog[9] = Calibration.X.Range;
DebugOut.Analog[10] = Calibration.Y.Offset;
DebugOut.Analog[11] = Calibration.Y.Range;
DebugOut.Analog[12] = Calibration.Z.Offset;
DebugOut.Analog[13] = Calibration.Z.Range;
DebugOut.Analog[14] = ExternData.CalState;
DebugOut.Analog[15] = Heading;
DebugOut.Analog[16] = ExternData.UserParameter[0];
DebugOut.Analog[17] = ExternData.UserParameter[1];
DebugOut.Analog[16] = ExternData.UserParam[0];
DebugOut.Analog[17] = ExternData.UserParam[1];
}
 
 
//############################################################################
//Hauptprogramm
int main (void)
//############################################################################
{
DDRC = 0x08;
PORTC = 0x08;
DDRD = 0xf4;
PORTD = 0xA0;
DDRB = 0x04;
PORTB = 0x35;
Led_Init();
LED_GRN_ON;
TIMER0_Init();
USART0_Init();
ADC_Init();
I2C_Init();
LED_ON;
sei(); //Globale Interrupts Einschalten
UART_Init();
Timer0_Init();
ADC_Init();
InitIC2_Slave();
sei();//Globale Interrupts Einschalten
Debug_Timer = SetDelay(100); // Sendeintervall
Xmin = eeprom_read_word(&eeXmin);
Xmax = eeprom_read_word(&eeXmax);
Ymin = eeprom_read_word(&eeYmin);
Ymax = eeprom_read_word(&eeYmax);
Zmin = eeprom_read_word(&eeZmin);
Zmax = eeprom_read_word(&eeZmax);
// read calibration info from eeprom
eeprom_read_block(&Calibration, &eeCalibration, sizeof(Calibration_t));
 
VersionInfo.Hauptversion = VERSION_HAUPTVERSION;
VersionInfo.Nebenversion = VERSION_NEBENVERSION;
VersionInfo.PCKompatibel = 7;
ExternData.Orientation = 0;
ExternData.CalState = 0;
I2C_WriteCal.CalByte = 0;
// main loop
while (1)
{
FLIP_LOW;
Delay_ms(2);
RawMagnet1a = MessAD(0);
RawMagnet2a = -MessAD(1);
RawMagnet3a = MessAD(7);
RawMagnet1a = ADC_GetValue(ADC0);
RawMagnet2a = -ADC_GetValue(ADC1);
RawMagnet3a = ADC_GetValue(ADC7);
Delay_ms(1);
 
FLIP_HIGH;
Delay_ms(2);
RawMagnet1b = MessAD(0);
RawMagnet2b = -MessAD(1);
RawMagnet3b = MessAD(7);
RawMagnet1b = ADC_GetValue(ADC0);
RawMagnet2b = -ADC_GetValue(ADC1);
RawMagnet3b = ADC_GetValue(ADC7);
Delay_ms(1);
 
CalcFields();
 
if(ExternData.CalState || I2C_WriteCal.CalByte) Calibrate();
else CalcHeading();
BearbeiteRxDaten();
 
// check data from USART
USART0_ProcessRxData();
 
if(PC_Connected)
{
DDRD |= 0x02; // TXD-Portpin
UCR |= (1 << TXEN);
DatenUebertragung();
USART0_EnableTXD();
USART0_TransmitTxData();
PC_Connected--;
}
else
{
UCR &= ~(1 << TXEN);
DDRD &= ~0x02; // TXD-Portpin
USART0_DisableTXD();
}
} // while(1)
}