el código está dividio en varios files.
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include <Wire.h>
#include <ArduinoBLE.h>
#include "Constans.h"
#include "VariablesGlobals.h"
// Per sensor BWT901, via bluetooth
BLEDevice sensorAngles;
BLECharacteristic caracSensor;
// Display oled
Adafruit_SSD1306 oled(ANCHO,ALTO,&Wire,OLED_RESET);
void Inicialitzar();
void DisplayInicial();
void DisplayMissatge();
void GeneraPuntetsEnMissatge(bool Reiniciar=false);
void CapceleraAngles();
void MostrarAngles(char _Tipus, int _AngAct, int _AngDest);
void Format3(int _Valor, char _cAux[]);
void DisplayOffsets();
void AssignaOffsets();
void LlegirDesti();
void TrevallaMissatge(char _Dades[], uint8_t _NumChars);
void CalculaSentits();
bool InitzialitzarConexioSensor();
void ObtenirAngles();
int AjustarAngle(int _AngleBrut);
void IniciaConexionsSerie();
void AssignaMotors();
void DesactivaMotorST(stMotor _Motor);
void ActuaMotorST(stMotor &_Motor, eSentit _Sentit, int _Velocitat);
void setup() {
Wire.begin();
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENB, OUTPUT);
estatActual = Inici;
}
void loop() {
switch (estatActual){
case Inici:
Inicialitzar();
IniciaConexionsSerie();
estatSeguent = IniciConexioSensor;
break;
case IniciConexioSensor:
if(InitzialitzarConexioSensor()) estatSeguent=LLegirAngles;
else estatSeguent = IniciConexioSensor;
break;
case LLegirAngles:
ObtenirAngles();
break;
case CompararAngles:
CalculaSentits();
break;
case MoureMotors:
ActuaMotorST(MotorElevacio,SentitElevacio,VelRapida);
ActuaMotorST(MotorAzimut,SentitAzimut,VelLenta);
estatSeguent = LLegirAngles;
break;
default:
Serial.println("==== ERROR: estat no definit. ====");
}
estatActual = estatSeguent;
BLE.poll();
}
void IniciaConexionsSerie(){
u_long millisAnt;
Serial.begin(9600);
millisAnt=millis();
while (!Serial && (millis() <( millisAnt + SEGONS_ESPERA_CONEXIO_SERIE_DEBUG*1000))){
strcpy(gTitol,"USB CONS.");
strcpy(gDetall,"Inician ");
GeneraPuntetsEnMissatge();
DisplayMissatge();
delay(500);
}
if(!Serial){
strcpy(gTitol,"USB CONS.");
strcpy(gDetall,"=== NO CONECTAT === ");
DisplayMissatge();
delay(2000);
} else gConectatUsbConsola = true;
Serial1.begin(9600);
millisAnt=millis();
while (!Serial1 && (millis() < (millisAnt + SEGONS_ESPERA_CONEXIO_SERIE_SATPC*1000))){
strcpy(gTitol,"USB SATPC");
strcpy(gDetall,"Inician ");
GeneraPuntetsEnMissatge();
DisplayMissatge();
delay(200);
}
if(!Serial1){
strcpy(gTitol,"USB SATPC");
strcpy(gDetall,"=== NO CONECTAT === ");
DisplayMissatge();
delay(2000);
} else {
gConectatUsbSatPC = true;
strcpy(gTitol,"USB SATPC");
strcpy(gDetall," CONECTAT ");
DisplayMissatge();
delay(2000);
}
}
void Inicialitzar(){
AssignaMotors();
DisplayInicial();
// Per seguretat, sortides motors.
DesactivaMotorST(MotorElevacio);
DesactivaMotorST(MotorAzimut);
delay(10000);
gCapceleraAnglesYaActivada=false;
}
void CalculaSentits(){
// per probes, cada x cridades enviem resultats a pantalla.
static int vegadaActual = NUM_VEGADES_ENVIAR;
static unsigned long milIni;
AngleX_Actual = AngXLlegit;
AngleZ_Actual = AngZLlegit;
// En cada loop verifiquem si ens ha arrivat alguna nova dada de destinacció
LlegirDesti();
AngleX_Desti = AjustarAngle(AngleX_Desti);
AngleZ_Desti = AjustarAngle(AngleZ_Desti);
MostrarAngles('A', AngleZ_Actual, AngleZ_Desti);
MostrarAngles('E', AngleX_Actual, AngleX_Desti);
if(gConectatUsbConsola){
if(vegadaActual>=NUM_VEGADES_ENVIAR){
Serial.print("Temps per ");Serial.print(vegadaActual);Serial.print(" : "); Serial.print(millis()-milIni);
Serial.print(" Ang Z Actual: "); Serial.print(AngleZ_Actual);
Serial.print(" AngZ Destí: "); Serial.print(AngleZ_Desti);
Serial.print(" AngX Actual: "); Serial.print(AngleX_Actual);
Serial.print(" AngX Destí: "); Serial.println(AngleX_Desti);
vegadaActual = 0;
milIni = millis();
}
vegadaActual++;
}
/* El nou estat podra ser:
.-Llegir angles.
.-Moure motors. Aquest será assignat si un cuansevols del angles ho requereix.
El process de moure motors activará el que necessiti per cada motor,
en funció del sentit calculat aqui.
.-al mneys per proves, el igual ho fem amb un marge de MARGE_COMPARACIO_ANGLES º.
ULL: si destí es entre 0 i MARGE, al comprobar respecte a 359 no es considera
assolit. No crec que sigui problema, pero....
*/
// ELEVACIO. Angle X
if (abs(AngleX_Actual - AngleX_Desti) < MARGE_COMPARACIO_ANGLES){ // (Angle_Actual==Angle_Desti){
DesactivaMotorST(MotorElevacio);
SentitElevacio = Parat;
} else if(AngleX_Actual>90 && AngleX_Actual < (ANGLE_DE_TALL_X )){
SentitElevacio= SentitEnrere;
} else if (AngleX_Actual<=360 && AngleX_Actual >(ANGLE_DE_TALL_X )){
SentitElevacio= SentitEndevant;
} else if (AngleX_Actual<=90 && AngleX_Actual >= 0){
if (AngleX_Desti>AngleX_Actual) {
SentitElevacio= SentitEndevant;
} else if (AngleX_Desti<AngleX_Actual) {
SentitElevacio = SentitEnrere;
} else {
SentitElevacio = Parat; //no es donará el cas, pero...
}
} else {
SentitElevacio = Parat; //no es donará el cas, pero...
}
// Per Azimut, angle Z
if (abs(AngleZ_Actual - AngleZ_Desti) < MARGE_COMPARACIO_ANGLES){
DesactivaMotorST(MotorAzimut);
SentitAzimut = Parat;
} else{
if (AngleZ_Desti<=ANGLE_DE_TALL_Z){
if (AngleZ_Actual>ANGLE_DE_TALL_Z){
SentitAzimut= SentitEndevant;
} else {
if (AngleZ_Desti>AngleZ_Actual) {
SentitAzimut = SentitEndevant;
} else {
SentitAzimut = SentitEnrere;
}
}
} else { //desti >AngleDeTallZ
if (AngleZ_Actual<ANGLE_DE_TALL_Z){
SentitAzimut = SentitEnrere;
} else {
if (AngleZ_Desti>AngleZ_Actual){
SentitAzimut = SentitEndevant;
} else {
SentitAzimut = SentitEnrere;
}
}
}
}
// Només si els dos motors estan en lloc ( i per tant el seu sentit es Parat), el estat seguent global será
// llegir angles. Després de moure motors ja es fa la llegir angles.
if(SentitElevacio==Parat&&SentitAzimut==Parat) estatSeguent = LLegirAngles;
else estatSeguent = MoureMotors;
}
#include "SatPc.h"
#include "DisplayOled.h"
#include "Angles.h"
#include "Motors.h"
Constantes:
const char VERSIO[] ="3.02";
// Per temps conexions serie
const uint8_t SEGONS_ESPERA_CONEXIO_SERIE_DEBUG = 10;
const uint8_t SEGONS_ESPERA_CONEXIO_SERIE_SATPC = 15;
// Per Display oled
const uint8_t ANCHO = 128;
const uint8_t ALTO = 64;
const uint8_t OLED_RESET = 4;
// Per sensor
const uint8_t NUM_MOSTRES = 3;
const uint8_t NUM_LECTURA_PER_ASSIGNA_OFFSET = 4;
const ulong MILLIS_PROVAN_CONEXIO = 1000;
// Pins conexió driver motor angle X-Elevacio
const int IN1 = 4; // Endevant
const int IN2 = 5; // Enrere
const int ENA = 6; // Enable
// Pins conexió driver motor angle Z-Azimut
const int IN3 = 7; // Endevent
const int IN4 = 8; // Enrere
const int ENB = 9; // Enable
// Valors per velocitat Lenta i Rapida
const int VelRapida = 255;
const int VelLenta = 125;
const int SEGONS_MAXIM_ACTIVACIO_MOTORS_SEGUIT = 5;
const int SEGONS_ESPERA_ENTRE_ACTIVACIO_MOTOR = 2;
// Per calculs sentit
const int MARGE_COMPARACIO_ANGLES = 5;
const int NUM_VEGADES_ENVIAR = 10;
const int ANGLE_DE_TALL_X = 180;
const int ANGLE_DE_TALL_Z = 180;
Variales globales
// Per Missatges. En lloc de passar per parametre, definim global. ho sento...
char gTitol[10]="blanc";
char gDetall[36]="blanc";
bool gCapceleraAnglesYaActivada =false;
// Indicadors si hi ha conexió per usb de consola i per usb del SatPC
bool gConectatUsbConsola = false;
bool gConectatUsbSatPC = false;
// ANGLES---
int AngXLlegit, AngYLlegit, AngZLlegit;
int AngleX_Actual;
int AngleX_Desti;
int AngleZ_Actual;
int AngleZ_Desti;
int OffsetX=0;
int OffsetZ=0;
// Indicador de offset assignats. Per seguretat ho farem a la NUM_LECTURA_PER_ASSIGNA_OFFSET.
uint8_t offsetsAssignats = 0;
// ENUMS----
// Sentit de gir del motor
enum eSentit {SentitEndevant=0,SentitEnrere=1,Parat=3};
eSentit SentitElevacio, SentitAzimut;
// ================== Maquina estats.
enum eEstats {Inici, IniciConexioSensor, LLegirAngles, CompararAngles, MoureMotors};
eEstats estatActual, estatSeguent, estatUltim;
// prova a fer servir estructures.
struct stMotor{
char Codi;
int8_t PinEndevant;
int8_t PinEnrera;
int8_t PinEnable;
char Nom[9];
eSentit UltimSentit;
ulong MilisActivacioUltimSentit;
byte EnEspera;
ulong MilisIniciEspera;
};
stMotor MotorAzimut, MotorElevacio;
Angulos:
void ObtenirAngles(){
int16_t iX, iY, iZ;
int16_t iangle[3][NUM_MOSTRES];
if (!sensorAngles.localName().startsWith("HC")){
// per seguretat, si no hi ha conexio, desactivem motors
DesactivaMotorST(MotorElevacio);
DesactivaMotorST(MotorAzimut);
strcpy(gTitol,"SENSOR");
strcpy(gDetall,"Desconectat ");
DisplayMissatge();
GeneraPuntetsEnMissatge(true);
gCapceleraAnglesYaActivada=false;
delay(3000);
estatSeguent = IniciConexioSensor;
return;
}
for(uint8_t mAct=0;mAct<NUM_MOSTRES;mAct++){
uint8_t valors[64];
bool bTrobat = false;
// possem un timer per verure si no hi ha conexio. No esperarem més de 1 segon.
unsigned long inici = millis();
while(!bTrobat ){
// a lo bestiaaaa. Per el hipotetic cas de que estigués en marxa mes de no se quantes horas (crec dies), verifico millis no reiniciat.
if((millis() - inici > MILLIS_PROVAN_CONEXIO ) || millis() < inici ){
if(gConectatUsbConsola) Serial.print("Desconectem per timeout");
BLE.disconnect();
DesactivaMotorST(MotorElevacio);
DesactivaMotorST(MotorAzimut);
estatSeguent = IniciConexioSensor;
return;
}
if (caracSensor.valueUpdated()){
caracSensor.readValue(valors,20);
for (int pos = 0;pos <10;pos++){
if(valors[pos]==0x55&&valors[pos+1]==0x53){
iangle[0][mAct] = (short(valors [pos+3]<<8| valors [pos+2]))*180/32768;
iangle[1][mAct] = (short(valors [pos+5]<<8| valors [pos+4]))*180/32768;
iangle[2][mAct] = (short(valors [pos+7]<<8| valors [pos+6]))*180/32768;
bTrobat= true;
}
}
}
}
}
// tenim NUM_MOSTRES mostres.Calculemn la mitja i asignem a globals
iX=0; for( int i=0;i<NUM_MOSTRES;i++) iX+=iangle[0][i];
AngXLlegit = int(iX / NUM_MOSTRES);
iY=0; for( int i=0;i<NUM_MOSTRES;i++) iY+=iangle[1][i];
AngYLlegit = int(iY / NUM_MOSTRES);
iZ=0; for( int i=0;i<NUM_MOSTRES;i++) iZ+=iangle[2][i];
AngZLlegit = int(iZ / NUM_MOSTRES);
// Ajustar angle Z.
AngZLlegit=-AngZLlegit;
if(AngZLlegit<0) AngZLlegit+=360;
// Ajustar angle X;
if(AngXLlegit<0) AngXLlegit+=360;
AngXLlegit += OffsetX;
AngZLlegit += OffsetZ;
estatSeguent=CompararAngles;
// A les proves no estaba funcionan i diria que no es necessari..
/*
if(offsetsAssignats<=NUM_LECTURA_PER_ASSIGNA_OFFSET)
AssignaOffsets(); // internament assigna només en la segona lectura.
else
estatSeguent = CompararAngles;
*/
// hem acabat.
}
// ======================= SENSOR =====================
bool InitzialitzarConexioSensor(){
bool _bRet = false;
gCapceleraAnglesYaActivada=false;
strcpy(gTitol,"SENSOR");
strcpy(gDetall,"Inician Bluetooh");
GeneraPuntetsEnMissatge();
DisplayMissatge();
// initialize the Bluetooth® Low Energy hardware
if (!BLE.begin()) {
if(gConectatUsbConsola) Serial.println("starting Bluetooth® Low Energy module failed!");
return _bRet;
}
if(gConectatUsbConsola) Serial.println("Bluetooth® Low Energy Central inicializat.");
BLE.scan();
delay(250);
sensorAngles = BLE.available();
while (sensorAngles){
if(sensorAngles.localName().startsWith("HC-06")){
break;
}
sensorAngles = BLE.available();
}
/*
BLE.scanForAddress("00:0c:bf:07:69:17");
delay(100);
sensorAngles = BLE.available();
*/
if(!sensorAngles){
if(gConectatUsbConsola) Serial.println("No trobat el sensor en sensorAngles.");
return _bRet;
}
if(gConectatUsbConsola) Serial.print("Nom Device: ");
if(gConectatUsbConsola) Serial.println(sensorAngles.localName());
delay(250);
BLE.stopScan();
if (sensorAngles.connect()) {
if(gConectatUsbConsola) Serial.println("Connected");
} else {
if(gConectatUsbConsola) Serial.println("Failed to connect!");
return _bRet;
}
if(sensorAngles.discoverAttributes()) {
if(gConectatUsbConsola) Serial.println("Attributes discovered");
} else {
if(gConectatUsbConsola) Serial.println("Attribute discovery failed!");
sensorAngles.disconnect();
return _bRet;
}
BLEService servei = sensorAngles.service("49535343-fe7d-4ae5-8fa9-9fafd205e455");
if(!servei){
if(gConectatUsbConsola) Serial.println("servei no trobat");
return _bRet;
}
caracSensor = sensorAngles.characteristic("49535343-1e4d-4bd9-ba61-23c647249616");
if(!caracSensor){
if(gConectatUsbConsola) Serial.print("caracteristica no trobada");
sensorAngles.disconnect();
return _bRet;
}
caracSensor.subscribe();
strcpy(gDetall,"Conectat ");
DisplayMissatge();
return true;
}
void AssignaOffsets(){
// Asumim que el primer cop que es activat el processador (alimentació o reset)
// l'antena está a 0º azimut i 0º elevació.
offsetsAssignats++;
if(offsetsAssignats>NUM_LECTURA_PER_ASSIGNA_OFFSET) return;
if(offsetsAssignats==NUM_LECTURA_PER_ASSIGNA_OFFSET){
OffsetX = -AngXLlegit;
OffsetZ = -AngZLlegit;
DisplayOffsets();
gCapceleraAnglesYaActivada=false;
}
}
int AjustarAngle(int _AngleBrut){
// Ajustem angles a 0-359.
while (_AngleBrut < 0) _AngleBrut += 360;
if(_AngleBrut>=360) _AngleBrut %= 360;
return _AngleBrut;
}
Motores
void AssignaMotors(){
MotorAzimut.Codi='Z';
strcpy(MotorAzimut.Nom,"Azimut");
MotorAzimut.PinEnable=ENB;
MotorAzimut.PinEndevant=IN3;
MotorAzimut.PinEnrera=IN4;
MotorAzimut.UltimSentit=Parat;
MotorAzimut.MilisActivacioUltimSentit=0;
MotorAzimut.EnEspera=false;
MotorAzimut.MilisIniciEspera=0;
MotorElevacio.Codi = 'E';
strcpy(MotorElevacio.Nom,"Elevacio");
MotorElevacio.PinEnable=ENA;
MotorElevacio.PinEndevant=IN1;
MotorElevacio.PinEnrera=IN2;
MotorElevacio.UltimSentit=Parat;
MotorElevacio.MilisActivacioUltimSentit=0;
MotorElevacio.EnEspera=false;
MotorElevacio.MilisIniciEspera=0;
}
void DesactivaMotorST(stMotor _Motor){
// Serial.print("DesactivaMotor------");
digitalWrite(_Motor.PinEndevant,LOW);
digitalWrite(_Motor.PinEnrera,LOW);
analogWrite(_Motor.PinEnable,LOW);
_Motor.UltimSentit=Parat;
}
void ActuaMotorST(stMotor &_Motor, eSentit _Sentit, int _Velocitat){
if(_Motor.EnEspera){
if(millis() - _Motor.MilisIniciEspera > SEGONS_ESPERA_ENTRE_ACTIVACIO_MOTOR*1000ul){
_Motor.EnEspera= false;
_Motor.MilisIniciEspera=0;
_Motor.MilisActivacioUltimSentit = millis();
} else {
_Motor.UltimSentit=_Sentit;
return; // a esperar...
//=============
}
}
// prova a optimitzar. Si el nou sentit es el que ja te actiu el motor,
// no fem res.
if(_Motor.UltimSentit==_Sentit){
if( (_Motor.UltimSentit != Parat) && ((millis() - _Motor.MilisActivacioUltimSentit)
> SEGONS_MAXIM_ACTIVACIO_MOTORS_SEGUIT*1000ul)){
_Motor.EnEspera=true;
_Motor.MilisIniciEspera=millis();
DesactivaMotorST(_Motor);
return;
//==============
}
} else {
_Motor.MilisActivacioUltimSentit = millis();
}
switch (_Sentit) {
case SentitEndevant:
digitalWrite(_Motor.PinEndevant, HIGH);
digitalWrite(_Motor.PinEnrera, LOW);
analogWrite(_Motor.PinEnable, _Velocitat);
break;
case SentitEnrere:
digitalWrite(_Motor.PinEndevant, LOW);
digitalWrite(_Motor.PinEnrera, HIGH);
analogWrite(_Motor.PinEnable, _Velocitat);
break;
default:
// incluim tambe el sentit Parat.
analogWrite(_Motor.PinEnable, LOW);
digitalWrite(_Motor.PinEndevant, LOW);
digitalWrite(_Motor.PinEnrera, LOW);
}
_Motor.UltimSentit=_Sentit;
}
SatPc
void LlegirDesti(){
static char DadesValides[10];
static uint8_t NumCharsTractar=-1;
char CharLlegit;
if(!gConectatUsbSatPC){ //Si no está conectat, podem treballar igual per proves.
AngleZ_Desti=0;
AngleX_Desti=0;
return;
//=============
}
if(!Serial1.available()) return;
//==================
/*
A veure: Estem reben continuament el C2. Fa molta nosa. Em de fer un tractamente de Missatge per elimarho.
De moment, ho deixem. Funciona prou be.
*/
while (Serial1.available()){
CharLlegit=Serial1.read();
if(CharLlegit=='C' || CharLlegit=='W'){ // Si es inici de Missatge.
NumCharsTractar=0;
DadesValides[NumCharsTractar] = CharLlegit;
NumCharsTractar++;
continue;
}
if(CharLlegit=='\n' || ((DadesValides[0]=='W')&&NumCharsTractar>=8)) { //Final Missatge
TrevallaMissatge(DadesValides, NumCharsTractar);
NumCharsTractar=-1;
continue;
}
if(NumCharsTractar==-1) continue; // Quansevol altre caracter, si estem al mitg de Missatge l'afegim; si no, es perd.
DadesValides[NumCharsTractar] = CharLlegit;
NumCharsTractar++;
}
}
void TrevallaMissatge(char _Dades[], uint8_t _NumChars){
// Missatge que enviará el Sat32: “Waaa eee” a on “aaa” l'angle desviació azimut i “eee” l'angle d'elevació target.
char caux[]= "000";
switch (_Dades[0]) {
case 'W':
for (int8_t i=0;i<=3;i++) caux[i]=_Dades[i+1];
AngleZ_Desti = atoi(caux);
for (int8_t i=0;i<=3;i++) caux[i]=_Dades[i+5];
AngleX_Desti = atoi(caux);
break;
default:
// res
break;
}
}
DisplayOled
void DisplayInicial(){
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setCursor(0,0);
oled.setTextSize(2);
oled.print("--INICI--");
oled.setCursor(0, 30);
oled.print("V: "); oled.print(VERSIO);
oled.display();
}
void CapceleraAngles(){
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setCursor(0,0);
oled.setTextSize(2);
oled.print("T Act Dest");
}
void MostrarAngles(char _Tipus, int _AngAct, int _AngDest){
int _linea;
char cAux[]="000";
// oled.clearDisplay();
if(!gCapceleraAnglesYaActivada){
CapceleraAngles();
gCapceleraAnglesYaActivada=true;
}
oled.setTextColor(WHITE,BLACK);
if(_Tipus=='A') _linea = 21; else _linea = 41;
oled.setCursor(0,_linea);
oled.print(_Tipus);
oled.setCursor(30,_linea);
Format3(_AngAct,cAux);
oled.print(cAux);
eSentit _sentit;
if(_Tipus=='A') _sentit = SentitAzimut; else _sentit = SentitElevacio;
oled.setCursor(65, _linea);
switch (_sentit){
case SentitEndevant:
oled.print('>');
break;
case SentitEnrere:
oled.print('<');
break;
default:
oled.print('=');
}
oled.setCursor(80, _linea);
Format3(_AngDest,cAux);
oled.print(cAux);
oled.display();
}
void Format3(int _Valor, char _cAux[]){
int ind = 0;
char buff[]="000";
char buffFin[]=" 0";
if(_Valor!=0){
itoa(_Valor,buff,10);
while(pow(10,ind) <= _Valor) ind++;
for (int i = 0; i< 3; i++){
if(3-i >ind) buffFin[i]=' '; else buffFin[i]=buff[i -(3-ind)];
}
}
memmove(_cAux,&buffFin,3);
}
void DisplayMissatge(){
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setCursor(0,0);
oled.setTextSize(2);
oled.print(gTitol);
oled.setCursor(0,22);
oled.setTextSize(1);
char caux[18]=" ";
//memmove(msg, &msg[1], displayWidth - 1);
memmove(caux,&gDetall,18);
oled.print(caux);
//caux[0]=' ';
//memset(hyphen, '-', sizeof(hyphen));
memset(caux,' ',18);
memmove(caux,&gDetall[18],18);
oled.setCursor(0,42);
oled.print(caux);
oled.display();
}
void GeneraPuntetsEnMissatge(bool _Reiniciar){
static byte index=0;
if(_Reiniciar){
index=0;
return;
}
if(index>=17){
index=0;
strcpy(&gDetall[18]," ");
}
strcpy(&gDetall[18 + index],".");
index++;
}
void DisplayOffsets(){
strcpy(gTitol," OFFSETS ");
strcpy(gDetall,"Elev. Azim. ");
Format3(OffsetX,&gDetall[6]);
Format3(OffsetZ,&gDetall[24]);
DisplayMissatge();
delay(3000);
}