|
||||
|
Schaltbild Autopilotmaxsimplex
//Autopilot Maxsimplex // Mit Ruderlagepotentiometer // Mit Aktivierung der Rudermaschine // Mit Aktivierung der Kupplung // Mit Sollkursfeststellung nach dem Reset. // Kompass ohne Tiltkompensation angelehnt an eine Formel aus // https://circuitdigest.com/microcontroller-projects/digital-compass- with-arduino-and-hmc5883l-magnetometer // mit beruhigten Werten //**************** Funktioniert! ***************************** #include<Wire.h> // Library für den I2C-Bus int ruderlagepin = A7; // Ruderlagepotentiometer ist mit AnIn 7 verbunden int ruderlage = 0; // Aktuelle Ruderlage Wertebereich: 10-1000 (erreicht nicht den Anschlag) int ruderlageMitte = 500;// Noch zu ermittelnder Wert für Ruder mittschiffs int anschlaglinks = 1000;// Noch zu ermittelnder Wert für den Anschlag Links int anschlagrechts = 10;// Noch zu ermittelnder Wert für den Anschlag Rechts const int MAG=0x1E; // I2C Adresse des Magnetometers 7bit Adresse const int MPU=0x68; // I2C address of the MPU-6050 float Sollkurs = 0; //Sollkurs ist eine Float-Zahl (mit 2 Nachkommastellen) float Kurs = 0; // Kurs ist eine Float-Zahl (mit 2 Nachkommastellen) int iSollkurs = 0; //Zählvariable zur Beruhigung des Sollkurs. int Kursdifferenz; //Differenz zwischen Soll-Kurs und Ist-Kurs ist eine INT-Zahl int16_t ax = 0; // Beschleunigung Querachse (Pitch) int16_t ay = 0; // Beschleunigung Längsachse (Roll) int16_t az = 0; // Beschleunigung Hochachse (Yaw) int16_t mx = 0; // Magnetvektor Längsachse int16_t my = 0; // Magnetvektor Querachse int16_t mz = 0; // Magnetvektor Hochachse int16_t tmp = 0; // Temperatur aus dem MPU int16_t gx = 0; // Drehbeschleunigung Längsachse int16_t gy = 0; // Drehbeschleunigung Querachse int16_t gz = 0; // Drehbeschleunigung Hochachse int16_t arraymx[11]; // Array zum Speichern von 10 Magnetrohwerten x für Glättung int16_t arraymy[11]; // Array zum Speichern von 10 Magnetrohwerten y für Glättung int16_t arraymz[11]; // Array zum Speichern von 10 Magnetrohwerten z für Glättung int iM = 0; // Zählervariable für Magnetwert //*********************************************************************** //Die Eingänge IN1 und IN2 des BTN7971 liegen an DO5 bzw DO10 int ENkupplung = 7; // ENable ist mit DO 7 verbunden int IN1kupplung = 5; // IN1 ist mit DO 5 verbunden int IN2kupplung = 10; // IN2 ist mit DO 10 verbunden int CTkupplung = A6; // Strommessung ist mit AnIn 6 verbunden int Kpwm = 0; // Anfangswert für das PWM-Signal, 0-255 int i = 10; // Variable für Increment int d = 10; // Variable für Delay //********************************************************************* //Die Eingänge IN1 und IN2 des BTN7971 liegen an DO3 bzw DO6 int ENmotor = 8; // ENable für den Motor ist mit DO 8 verbunden int IN1motor = 6; // IN1 für den Motor ist mit DO 6 verbunden int IN2motor = 3; // IN2 für den Motor ist mit DO 3 verbunden int CTmotor = A3; // Strommessung für den Motor ist mit AnIn 3 verbunden int Mstrom = 0; // Ergebnis der Motorstrommessung int Mpwm = 0; // Anfangswert für das Motor-PWM-Signal, 0-255 //********************************************************************* void vorwaerts() //Rudermaschine dreht vorwärts { digitalWrite(ENmotor,HIGH); // für echten Betrieb auf HIGH setzen digitalWrite(IN1motor,LOW); analogWrite(IN2motor,Mpwm); Mstrom = analogRead(A3);// read the input on analog pin 3: Serial.print("Vor"); ">} //******************************************************************** void rueckwaerts() //Rudermaschine dreht rückwärts { digitalWrite(ENmotor,HIGH); // für echten Betrieb auf HIGH setzen digitalWrite(IN2motor,LOW); analogWrite(IN1motor,Mpwm); Mstrom = analogRead(A3);// read the input on analog pin 3: Serial.print("Rück"); } //********************************************************************* void berechneMpwm() // Berechnen des erforderlichen Motordrehmoments { Mpwm = abs (Kursdifferenz) * 10; if (Mpwm > 255) //Verhinderung von sinnlosen Werten über 255 { Mpwm = 255; } } //********************************************************************* void KupplungEin() // Kupplung in Eingriff bringen (Nur im Setup zu aktivieren) { digitalWrite(ENkupplung,HIGH); digitalWrite(IN1kupplung,LOW); analogWrite(IN2kupplung,255); //Voller PWM-Wert ">} //********************************************************************** void read_mag() // Subroutine zum Lesen der Magnetvektoren (nach erfolgter Initialisierung) { Wire.beginTransmission(MAG); Wire.write(byte(0x03)); Wire.endTransmission(); Wire.requestFrom(MAG,6); if(Wire.available()<=6) { mx=Wire.read()<<8; mx|=Wire.read(); mz=Wire.read()<<8; mz|=Wire.read(); my=Wire.read()<<8; my|=Wire.read(); } } //************************************************************************************** c">void glaetteMagnetrohwert() { // 1.) Array beschreiben arraymx[iM] = mx; //Array entsprechend iM mit Magnetwert x beschreiben arraymy[iM] = my; //Array entsprechend iM mit Magnetwert y beschreiben arraymz[iM] = mz; //Array entsprechend iM mit Magnetwert z beschreiben iM=iM+1; // Zeiger für den nächsten Durchlauf inkrementieren if (iM>10) { iM=0; // Array voll, Zeiger zurücksetzen } //2.) Array lesen mx=(arraymx[0]+arraymx[1]+arraymx[2]+arraymx[3]+arraymx[4]+arraymx[5]+ arraymx[6]+arraymx[7]+arraymx[8]+arraymx[9]+arraymx[10])/10; //Durchschnitt aus 10 Werten my=(arraymy[0]+arraymy[1]+arraymy[2]+arraymy[3]+arraymy[4]+arraymy[5] +arraymy[6]+arraymy[7]+arraymy[8]+arraymy[9]+arraymy[9])/10; //Durchschnitt aus 10 Werten mz=(arraymz[0]+arraymz[1]+arraymz[2]+arraymz[3]+arraymz[4]+arraymz[5] +arraymz[6]+arraymz[7]+arraymz[8]+arraymz[9]+arraymz[9])/10; //Durchschnitt aus 10 Werten //Nach dieser Routine sind die Kompassrohwerte mx, my, mz beruhigt } //*************************************************************************************** void berechneKurs() { Kurs = atan2(my, mx)/0.0174532925; if(Kurs < 0) Kurs+=360; Kurs = 360-Kurs; } //*********************************************************************** void berechneKursdifferenz() { Kursdifferenz = Kurs - Sollkurs; if (Kursdifferenz< -180){Kursdifferenz = Kursdifferenz + 360;} if (Kursdifferenz> 180){Kursdifferenz = Kursdifferenz - 360;} } //*********************************************************************** void leseruderlage()// Ruderlage lesen und auf Anschlag testen { ruderlage = analogRead(ruderlagepin); ="#5e6d03">if (ruderlage >1000){digitalWrite(ENmotor,LOW);}// Motor aus if (ruderlage <10){digitalWrite(ENmotor,LOW);}// Motor aus } //************************************************************************ void setup() { Wire.begin(); Wire.beginTransmission(MPU); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); Wire.begin(); //Kompass Wire.beginTransmission(MAG); // Modus continous Wire.write(byte(0x02)); //Sendung für X MSB register Magnetometer Wire.write(byte(0x00)); Wire.endTransmission(); // Ende der Sendung Serial.begin(9600); // Serial Monitor initialisieren for (iSollkurs=0; iSollkurs<11; iSollkurs ++ ) //Zählschleife zum Lesen des Sollkurses (10*) { read_mag(); glaetteMagnetrohwert(); berechneKurs(); Sollkurs = Kurs; //Der im Setup festgestellte Kurs ist der Sollkurs. ="#000000">} KupplungEin(); // Kupplung in Eingriff bringen } void loop() { Wire.beginTransmission(MPU); Wire.write(0x3B); //Accel_XOUT-H Wire.endTransmission(false); Wire.requestFrom(MPU,14,true); // requests 6 Register (H+L pro Vektor) ax=Wire.read()<<8|Wire.read(); //0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) ay=Wire.read()<<8|Wire.read(); //0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) az=Wire.read()<<8|Wire.read(); //0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) gx=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) gy=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) gz=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) read_mag(); glaetteMagnetrohwert(); ="#000000">berechneKurs(); berechneKursdifferenz(); berechneMpwm(); if (Kursdifferenz < 0)//Entscheidung ob Rudermaschine vorwärts oder rückwärts { vorwaerts(); //Rudermaschine dreht vorwärts } else { rueckwaerts(); //Rudermaschine dreht rückwärts } Serial.print(" Kurs "); Serial.print(Kurs); Serial.print(" Sollkurs "); Serial.print(Sollkurs); Serial.print(" Kursdiff. "); Serial.print(Kursdifferenz); Serial.print(" Mpwm "); Serial.print(Mpwm); Serial.print(" Ruderlage "); Serial.println(ruderlage); //delay (10); } Sowohl die Schaltung als auch das Programm haben vorläufigen Charakter und sind nicht fehlerfrei. Man kann daher nicht erwarten,
daß ein 1:1 Nachbau sofort ohne Nacharbeit funktioniert! haltung weitgehend abgeschlossen ist, kann beim Programm eine fast unendliche Menge an Verbesserungen und Erweiterungen vorgenommen werden.
Angedacht ist, statt dem einfachen Proportionalregler einen selbstlernenden PID-Regler zu programmieren, der seine Parameter selbstständig anpaßt,
und damit Ruderbewegungen und Strom spart. Hierfür kann der Sensor auch Drehbeschleunigungen messen, die bisher gar nicht ausgewertet werden.
Schaltbild Autopilotmaxsimplex mit SHB43A |
|||
© |