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);
}