Rotor besturing - concept

Plaatsingsdatum: 19-okt-2013 5:46:11

Het doel is een betaalbare oplossing voor een satelliet elevatie rotor.Ik heb al een heel eenvoudige rotor (zo'n een die vroeger voor tv antennes werd gebruikt). En ik wil een sateliet schotel actuator gebruiken om de elevatie de doen. Elk kan ik natuurlijk afzonderlijk bedienen, maar dat maakt het nog al lastig en complex. Ik kwam een arduino projectje tegen waarbij de arduino micro controller de volledige aansturing overneemt. Eerst wou ik dat projectje helemaal nabouwen, maar ik wil eigenlijk nog een aantal stappen verder gaan.

Het probleem vind ik altijd de richting en elevatie hoek bepalen. Er ontstaat zo snel een afwijking. Oplossing voor een paar euro een gyroscoop printje besteld via ebay. Deze komt op de antenne. Via een 5 aderige kabel komende signalen bij de rotor controller. En ik weet precies de richting en de elevatie hoek van de antenne. Even snel een stukje code geschreven (zie hieronder) en een test opstelling bouwen. Zodra de test opstelling klaar is maak ik de volgende blog entry,

/* ---------------------------------------------

Dit is de rotor controller van PE1NNQ

---------------------------------------------

Hardware:

Arduino Mega2560

LCD Keypad shield 1602

4 Channel relay module

HMC5883L 3V-5V Triple Axis Compass Magnetometer Sensor module (http://www.loveelectronics.co.uk/Tutorials/8/hmc5883l-tutorial-and-arduino-library)

---------------------------------------------

Beschrijving

- Init

- Seriele poort initialiseren

- Compas initialiseren

- Compas uitlezen en begin instellen op huidige positie

- Display initialiseren

- Loop

- Uitlezen compass

- Toon compas regel

- Uitlezen toetsen

- Instel modus

- Preset modus

- Toon instelling regel

- Aanpassen richting

- Sturen relais

* Display : 1234567890123456

compas A=xxx E=yy NNW xxx=Richting NNW=Text richting yy=Elevatie

Instel A=xxx E=yy sssss xxx=Richting yy=Elevatie ssss=status relais <Left> <Right> <Up> <Down> <Ok>

Preset P=pppppppp sssss ppppppp = Preset richting <Noord> <Oost> <Zuid> <West> etc.

* Keybaord : Select = Modus / Left Right = richting / Up down = elevatie /

* Invoer via keyboard & potmeter. Instelling wordt ook op scherm getoond.

* 2 assen worden gebruikt. X en Y. Dus ook voor sateliet sturing.

*/

#include <LiquidCrystal.h>

#include <LCDKeypad.h>

LCDKeypad lcd;

#include <Wire.h>

#include <HMC5883L.h>

HMC5883L compass;

// Als debug aan staat wordt via de seriele poort alle debug info verzonden.

#define Debug

// Constants

float declinationAngle = 0.00; // Compas declination angle in Rad.

int Relay_Left = 40; // Output voor Relais kanaal voor linksom draaien.

int Relay_Right = 42; // Output voor Relais kanaal voor rechts draaien.

int Relay_Up = 44; // Output voor Relais kanaal voor omhoog draaien.

int Relay_Down = 46; // Output voor Relais kanaal voor omlaag draaien.

// Globals

int AzimuthD = 0; // Measured compas heading

int ElevationD = 0; // Measured elevation angle

int SetAzimuthD = 0; // Setting compas heading

int SetElevationD = 0; // Setting elevation angle

int error = 0;

char display_string[80] = "";

char * rotor_status_Azimuth = "";

char * rotor_status_Elevation = "";

int RotorStepSize = 5;

void setup()

{

#ifdef Debug

// Initialize the serial port.

Serial.begin(9600);

Serial.println("Starting the I2C interface.");

#endif

// Initialize I2C bus

Wire.begin(); // Start the I2C interface.

// Initialize Compass

#ifdef Debug

Serial.println("Constructing new HMC5883L");

#endif

compass = HMC5883L(); // Construct a new HMC5883 compass.

#ifdef Debug

Serial.println("Setting scale to +/- 1.3 Ga");

#endif

error = compass.SetScale(1.3); // Set the scale of the compass.

#ifdef Debug

if(error != 0) Serial.println(compass.GetErrorText(error)); // If there is an error, print it out.

Serial.println("Setting measurement mode to continous.");

#endif

error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous

#ifdef Debug

if(error != 0) Serial.println(compass.GetErrorText(error)); // If there is an error, print it out.

Serial.println("Read all details from the compas");

#endif

MagnetometerRaw raw = compass.ReadRawAxis(); // Retrive the raw values from the compass (not scaled).

MagnetometerScaled scaled = compass.ReadScaledAxis(); // Retrived the scaled values from the compass (scaled to the configured scale).

// int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis) // Values are accessed like so:

float AzimuthR = atan2(scaled.YAxis, scaled.XAxis) + declinationAngle; // Calculate heading when the magnetometer is level, then correct for signs of axis.

float ElevationR = scaled.YAxis;

#ifdef Debug

Serial.print("Found AzimuthR ");

#endif

if(AzimuthR < 0) AzimuthR += 2*PI; // Correct for when signs are reversed.

if(AzimuthR > 2*PI) AzimuthR -= 2*PI; // Check for wrap due to addition of declination.

#ifdef Debug

Serial.println(AzimuthR);

Serial.print("Found ElevationR ");

#endif

if(ElevationR < 0) ElevationR += 2*PI; // Correct for when signs are reversed.

if(ElevationR > 2*PI) ElevationR -= 2*PI; // Check for wrap due to addition of declination.

#ifdef Debug

Serial.println(ElevationR);

#endif

AzimuthD = (int)(AzimuthR * 180/M_PI) % 360; // Convert radians to degrees for readability.

ElevationD = (int)(ElevationR * 180/M_PI) %90; // Convert radians to degrees for readability.

SetAzimuthD = AzimuthD; // Set Initial Azimuth setting

#ifdef Debug

Serial.print("Found AzimuthD ");

Serial.println(AzimuthD);

#endif

SetElevationD = ElevationD; // Set Initial Elevation setting

#ifdef Debug

Serial.print("Found ElevationD ");

Serial.println(ElevationD);

// Initialize LCD

Serial.println("Initialize display");

#endif

lcd.begin(16, 2);

lcd.clear();

lcd.print("PE1NNQ v1.0");

lcd.setCursor(0,1);

lcd.print("Rotor Controller");

delay(1000);

lcd.clear();

// Initialize Relay board

pinMode(Relay_Left, OUTPUT);

pinMode(Relay_Right, OUTPUT);

pinMode(Relay_Up, OUTPUT);

pinMode(Relay_Down, OUTPUT);

}

void loop()

{

// - Uitlezen compass

MagnetometerScaled scaled = compass.ReadScaledAxis(); // Retrived the scaled values from the compass (scaled to the configured scale).

float AzimuthR = atan2(scaled.YAxis, scaled.XAxis) + declinationAngle; // Calculate heading when the magnetometer is level, then correct for signs of axis.

float ElevationR = scaled.YAxis;

if(AzimuthR < 0) AzimuthR += 2*PI; // Correct for when signs are reversed.

if(AzimuthR > 2*PI) AzimuthR -= 2*PI; // Check for wrap due to addition of declination.

if(ElevationR < 0) ElevationR += 2*PI; // Correct for when signs are reversed.

if(ElevationR > 2*PI) ElevationR -= 2*PI; // Check for wrap due to addition of declination.

AzimuthD = (int)(AzimuthR * 180/M_PI) % 360; // Convert radians to degrees for readability.

ElevationD = (int)(ElevationR * 180/M_PI) %90; // Convert radians to degrees for readability.

#ifdef Debug

sprintf(display_string,"Gemeten A=%3d E=%2d, Ingesteld A=%3d E=%2d",AzimuthD,ElevationD,SetAzimuthD,SetElevationD);

Serial.println( display_string );

#endif

// - Toon compas regel

lcd.setCursor(0,0);

#ifdef Debug

sprintf(display_string,"A=%3d E=%2d %s",(int)AzimuthD,(int)ElevationD,GetDirection(AzimuthD));

lcd.print( display_string );

#endif

// - Uitlezen toetsen

int key_status = lcd.button();

if(key_status > -1)

{

#ifdef Debug

Serial.println( key_status );

#endif

delay(200);

if (key_status == KEYPAD_RIGHT)

{

if (SetAzimuthD < 359) SetAzimuthD = (SetAzimuthD + RotorStepSize) % 360;

else SetAzimuthD = 360;

}

else if (key_status == KEYPAD_UP)

{

if (SetElevationD < 90) SetElevationD += RotorStepSize;

else SetElevationD = 90;

}

else if (key_status == KEYPAD_DOWN)

{

if (SetElevationD > 0) SetElevationD -= RotorStepSize;

else SetElevationD = 0;

}

else if (key_status == KEYPAD_LEFT)

{

if (SetAzimuthD > 0) SetAzimuthD = (SetAzimuthD - RotorStepSize) % 360;

else SetAzimuthD = 0;

}

else if (key_status == KEYPAD_SELECT)

{

// Hiermoet nog wat voor bedacht worden.

;

}

}

// Aanpassen horizontale richting

if ((AzimuthD - SetAzimuthD) < (-1*RotorStepSize))

{

#ifdef Debug

// Draai naar Rechts

sprintf(display_string,"Draai naar Rechts, %d, %d, %d", AzimuthD, SetAzimuthD, (AzimuthD-SetAzimuthD));

Serial.println( display_string );

#endif

rotor_status_Azimuth = "R";

digitalWrite( Relay_Left, LOW );

digitalWrite( Relay_Right, HIGH );

}

else if ((AzimuthD - SetAzimuthD) > RotorStepSize )

{

#ifdef Debug

// Draai naar Links

sprintf(display_string,"Draai naar Links, %d, %d, %d", AzimuthD, SetAzimuthD, (AzimuthD-SetAzimuthD));

Serial.println( display_string );

#endif

rotor_status_Azimuth = "L";

digitalWrite( Relay_Right, LOW );

digitalWrite( Relay_Left, HIGH );

}

else

{

// Alles stil zetten.

rotor_status_Azimuth = "-";

digitalWrite( Relay_Right, LOW );

digitalWrite( Relay_Left, LOW );

}

// Aanpassen vertikale stand

if ((ElevationD - SetElevationD) > RotorStepSize)

{

#ifdef Debug

// Draai omhoog

Serial.println( "Draai naar Omhoog" );

#endif

rotor_status_Elevation = "U";

digitalWrite( Relay_Down, LOW );

digitalWrite( Relay_Up, HIGH );

}

else if ((ElevationD - SetElevationD) > RotorStepSize)

{

#ifdef Debug

// Draai omhoog

Serial.println( "Draai naar Beneden" );

#endif

rotor_status_Elevation = "D";

digitalWrite( Relay_Up, LOW );

digitalWrite( Relay_Down, HIGH );

}

else

{

rotor_status_Elevation = "-";

digitalWrite( Relay_Down, LOW );

digitalWrite( Relay_Up, LOW );

}

// - Toon instelling regel

lcd.setCursor(0,1);

sprintf(display_string,"A=%3d E=%2d %s%s ",SetAzimuthD,SetElevationD,rotor_status_Azimuth,rotor_status_Elevation);

lcd.print( display_string );

// Serial.println( display_string );

}

char * GetDirection(float Heading)

{

if (Heading < 11.25) return "N";

else if (Heading < 33.75) return "NNE";

else if (Heading < 56.25) return "NE";

else if (Heading < 78.75) return "ENE";

else if (Heading < 101.25) return "E";

else if (Heading < 123.75) return "ESE";

else if (Heading < 146.25) return "SE";

else if (Heading < 168.75) return "SSE";

else if (Heading < 191.25) return "S";

else if (Heading < 213.75) return "SSW";

else if (Heading < 236.25) return "SW";

else if (Heading < 258.75) return "WSW";

else if (Heading < 281.25) return "W";

else if (Heading < 303.75) return "WNW";

else if (Heading < 326.25) return "NW";

else if (Heading < 348.75) return "NNW";

else return "N";

}

int waitButton()

{

int buttonPressed;

waitReleaseButton;

lcd.blink();

while((buttonPressed=lcd.button())==KEYPAD_NONE)

{

}

delay(50);

lcd.noBlink();

return buttonPressed;

}

void waitReleaseButton()

{

delay(50);

while(lcd.button()!=KEYPAD_NONE)

{

}

delay(50);

}