Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
mechatronik:sose24:radioantenne_ausrichten [2024/08/01 17:56] Jonny5 [ESP32:] |
mechatronik:sose24:radioantenne_ausrichten [2024/08/04 13:05] (aktuell) Jonny5 [Durchlauf:] |
||
---|---|---|---|
Zeile 28: | Zeile 28: | ||
===== Code: ===== | ===== Code: ===== | ||
+ | <code> | ||
+ | // Libraries | ||
+ | #include <SoftwareSerial.h> | ||
+ | #include <Servo.h> | ||
+ | #include <Stepper.h> | ||
+ | |||
+ | // Pins | ||
+ | const byte rxPin = 2; | ||
+ | const byte servoPin = 3; | ||
+ | const byte stepperStepPin = 5; | ||
+ | const byte stepperDirPin = 6; | ||
+ | |||
+ | const byte ledRSSIPin = 8; | ||
+ | const byte ledRSSI2Pin = 9; | ||
+ | const byte ledRSSI3Pin = 10; | ||
+ | |||
+ | const byte buttonScanPin = 4; | ||
+ | |||
+ | //config | ||
+ | SoftwareSerial SerialESP(rxPin, -1); | ||
+ | |||
+ | Servo servoX; | ||
+ | Stepper stepperZ(800, stepperStepPin, stepperDirPin); | ||
+ | |||
+ | //Servo | ||
+ | int currentPositionX = 90; | ||
+ | int bestPositionX = 90; | ||
+ | float bestSignalX = 1000; | ||
+ | |||
+ | //Stepper | ||
+ | int currentPositionZ = 0; | ||
+ | int bestPositionZ = 9; | ||
+ | float bestSignalZ = 1000; | ||
+ | |||
+ | //RSSI-Reading | ||
+ | int rssi = 0; | ||
+ | const int numReadings = 5; | ||
+ | int rssiArray[numReadings]; | ||
+ | int readIndex = 0; | ||
+ | int readCount = 0; | ||
+ | |||
+ | //Steuerbedingungen | ||
+ | bool scanningCompleteZ = false; | ||
+ | bool scanningCompleteX = false; | ||
+ | bool scanEnabled = false; | ||
+ | bool scanButtonPressed = false; | ||
+ | |||
+ | //Entprellen | ||
+ | unsigned long lastButtonPressTime = 0; | ||
+ | const int debounceDelay = 50; | ||
+ | |||
+ | //Serieller Befehl | ||
+ | String command = ""; | ||
+ | |||
+ | void setup() { | ||
+ | //pins | ||
+ | pinMode(rxPin, INPUT); | ||
+ | pinMode(servoPin, OUTPUT); | ||
+ | pinMode(ledRSSIPin, OUTPUT); | ||
+ | pinMode(ledRSSI2Pin, OUTPUT); | ||
+ | pinMode(ledRSSI3Pin, OUTPUT); | ||
+ | pinMode(buttonScanPin, INPUT_PULLUP); | ||
+ | //Serielle Verbindungen | ||
+ | Serial.begin(9600); | ||
+ | SerialESP.begin(9600); | ||
+ | //Servo Setup | ||
+ | servoX.attach(servoPin); | ||
+ | servoX.write(90); | ||
+ | //Stepper Setup | ||
+ | stepperZ.setSpeed(100); // | ||
+ | //Initialisieren des Read Arrays | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | rssiArray[i] = 0; | ||
+ | } | ||
+ | //Wartezeit und Bereitschaft | ||
+ | delay(500); | ||
+ | Serial.println(); | ||
+ | Serial.println("Hello There!"); | ||
+ | delay(500); | ||
+ | Serial.println(F("E.R.O.S. ready")); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Lesen des Seriellen Befehls | ||
+ | if (Serial.available() > 0) { | ||
+ | command = Serial.readStringUntil('\n'); | ||
+ | command.trim(); | ||
+ | } | ||
+ | //Starten des Scans durch Button oder Befehl | ||
+ | if ((digitalRead(buttonScanPin) == LOW && !scanButtonPressed && millis() - lastButtonPressTime > debounceDelay) || (command.equalsIgnoreCase("scan"))) { | ||
+ | //Entprellen und einmaliges Drücken | ||
+ | lastButtonPressTime = millis(); | ||
+ | scanButtonPressed = true; | ||
+ | |||
+ | Serial.println(F("starting SCAN")); | ||
+ | //Stepper zurück auf 0 (falls bereits gescant) | ||
+ | stepperZ.step(-currentPositionZ); // | ||
+ | currentPositionZ = 0; | ||
+ | bestPositionZ = 0; | ||
+ | //Servo zurück auf 90 (falls bereits gescant) | ||
+ | currentPositionX = 90; | ||
+ | bestPositionX = 90; | ||
+ | servoX.write(90); | ||
+ | delay(500); //Wartezeit während sich der Servo bewegt (nach jedem servo.write) | ||
+ | //Aktivieren der Bedingung fürs Scannen und Zurücksetzen der Ergebnisse | ||
+ | scanEnabled = true; | ||
+ | scanningCompleteX = false; | ||
+ | scanningCompleteZ = false; | ||
+ | bestSignalX = 1000; | ||
+ | bestSignalZ = 1000; | ||
+ | //Rücksetzen und Initialisieren der Readings | ||
+ | readIndex = 0; | ||
+ | readCount = 0; | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | rssiArray[i] = 0; | ||
+ | } | ||
+ | //Ausgeben der ersten (Start) Position | ||
+ | Serial.print(F("Z: ")); | ||
+ | Serial.print(currentPositionZ); | ||
+ | Serial.print(F(" | X: ")); | ||
+ | Serial.println(currentPositionX); | ||
+ | //Leerung des Seriellen Befehls | ||
+ | command = ""; | ||
+ | } else if (digitalRead(buttonScanPin) == HIGH) { | ||
+ | //Reset des Buttons, sobald nicht mehr gedrückt (gegen Gedrückthalten) | ||
+ | scanButtonPressed = false; | ||
+ | } | ||
+ | |||
+ | //Scan Programm (wird durch das obere aktiviert, nur wenn Signal vorhanden) | ||
+ | if (scanEnabled && !scanningCompleteX && rssi != 0) { | ||
+ | //Empfang des Signals durch ESP jede Sekunde als Trigger | ||
+ | if (SerialESP.available() > 0) { | ||
+ | //Einlesen des Signals | ||
+ | String rssiRX = SerialESP.readStringUntil('\n'); | ||
+ | rssi = rssiRX.toInt(); | ||
+ | Serial.print(F("RSSI: -")); | ||
+ | Serial.println(rssi); | ||
+ | |||
+ | rssiArray[readIndex] = rssi; | ||
+ | readIndex = (readIndex + 1) % numReadings; | ||
+ | if (readCount < numReadings) { | ||
+ | readCount++; | ||
+ | } | ||
+ | //Auswertung wenn 5 Signale empfangen wurden | ||
+ | if (readCount == numReadings) { | ||
+ | int sum = 0; | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | sum += rssiArray[i]; | ||
+ | } | ||
+ | //Durchschnitt aus den Signalen | ||
+ | float average = (float)sum / numReadings; | ||
+ | |||
+ | Serial.print(F("⌀ RSSI: -")); | ||
+ | Serial.println(average); | ||
+ | Serial.println(); | ||
+ | //nur während Stepper Drehung | ||
+ | if (!scanningCompleteZ) { | ||
+ | if (average < bestSignalZ) { | ||
+ | //Speichern des besten Signals und der entsprechenden Stepper Position | ||
+ | bestSignalZ = average; | ||
+ | bestPositionZ = currentPositionZ; | ||
+ | } | ||
+ | //Einstellen der nächsten Stepper Position | ||
+ | currentPositionZ += 100; | ||
+ | } | ||
+ | //nur während Servo Drehung | ||
+ | if (scanningCompleteZ) { | ||
+ | if (average < bestSignalX) { | ||
+ | //Speichern des besten Signals und der entsprechenden Servo Position | ||
+ | bestSignalX = average; | ||
+ | bestPositionX = currentPositionX; | ||
+ | } | ||
+ | //Einstellen der nächsten Servo Position | ||
+ | currentPositionX += 15; | ||
+ | } | ||
+ | //Prüfung ob Stepper einmal durch ist | ||
+ | if (currentPositionZ > 700 && !scanningCompleteZ) { | ||
+ | //Übermitteln der besten gemessenen Stepper Position | ||
+ | Serial.print(F("best Z: ")); | ||
+ | Serial.print(bestPositionZ); | ||
+ | Serial.print(F(" | best ⌀ RSSI: -")); | ||
+ | Serial.println(bestSignalZ); | ||
+ | //Anfahren und Einstellen der besten Stepper Position | ||
+ | stepperZ.step(-(700-bestPositionZ)); // | ||
+ | currentPositionZ = bestPositionZ; | ||
+ | //Reset der Readings | ||
+ | readIndex = 0; | ||
+ | readCount = 0; | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | rssiArray[i] = 0; | ||
+ | } | ||
+ | //Servo auf Startposition für Servo Drehung | ||
+ | currentPositionX = 45; | ||
+ | servoX.write(45); | ||
+ | delay(500); | ||
+ | //Bedingungen, dass der Stepper fertig ist | ||
+ | scanningCompleteZ = true; | ||
+ | //Prüfung ob Stepper noch nicht fertig ist | ||
+ | } else if (!scanningCompleteZ){ | ||
+ | //Anfahren der nächsten Stepper Position | ||
+ | stepperZ.step(100); | ||
+ | //Reset der Readings | ||
+ | readIndex = 0; | ||
+ | readCount = 0; | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | rssiArray[i] = 0; | ||
+ | } | ||
+ | //Übermitteln der Position | ||
+ | Serial.print(F("Z: ")); | ||
+ | Serial.print(currentPositionZ); | ||
+ | Serial.print(F(" | X: ")); | ||
+ | Serial.println(currentPositionX); | ||
+ | } | ||
+ | //Prüfung ob Servo fertig ist | ||
+ | if (currentPositionX > 135) { | ||
+ | //Bedingungen, dass der Scan nicht weiterläuft | ||
+ | scanningCompleteX = true; | ||
+ | scanEnabled = false; | ||
+ | //Übermitteln der besten Positionen | ||
+ | Serial.println(F("SCAN completed:")); | ||
+ | Serial.print(F("best Z: ")); | ||
+ | Serial.print(bestPositionZ); | ||
+ | Serial.print(F(" | best X: ")); | ||
+ | Serial.print(bestPositionX); | ||
+ | Serial.print(F(" | best ⌀ RSSI: -")); | ||
+ | Serial.println(bestSignalX); | ||
+ | //Einstellen und Anfahren der besten Servo Position | ||
+ | currentPositionX = bestPositionX; | ||
+ | servoX.write(bestPositionX); | ||
+ | delay(500); | ||
+ | //Prüfung ob Servo noch nicht fertig ist | ||
+ | } else if (scanningCompleteZ) { | ||
+ | //Anfahren der nächsten Servo Position | ||
+ | servoX.write(currentPositionX); | ||
+ | delay(500); | ||
+ | //Reset der Readings | ||
+ | readIndex = 0; | ||
+ | readCount = 0; | ||
+ | for (int i = 0; i < numReadings; i++) { | ||
+ | rssiArray[i] = 0; | ||
+ | } | ||
+ | //Übermitteln der Position | ||
+ | Serial.print(F("Z: ")); | ||
+ | Serial.print(currentPositionZ); | ||
+ | Serial.print(F(" | X: ")); | ||
+ | Serial.println(currentPositionX); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } else { | ||
+ | //Aktualisierung des Signals während Scan nicht läuft für LEDs | ||
+ | if (SerialESP.available() > 0) { | ||
+ | String rssiRX = SerialESP.readStringUntil('\n'); | ||
+ | rssi = rssiRX.toInt(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </code> | ||
===== 3D-Druck: ===== | ===== 3D-Druck: ===== | ||
Ein weiterführendes Ziel des Projektes war es, eine Yagi-Antenne selbst zu bauen und diese mit Hilfe von zwei Motoren zu bewegen. | Ein weiterführendes Ziel des Projektes war es, eine Yagi-Antenne selbst zu bauen und diese mit Hilfe von zwei Motoren zu bewegen. | ||
Zeile 39: | Zeile 298: | ||
Bild 3: Servo-Motor in Halterung auf Schrittmotor und Halterung für den Boom der Antenne | Bild 3: Servo-Motor in Halterung auf Schrittmotor und Halterung für den Boom der Antenne | ||
+ | |||
+ | ===== Durchlauf: ===== | ||
+ | |||
+ | {{:mechatronik:sose24:antirector_durchlauf.mp4|}} \\ | ||
+ | Bitte ignoriert die LEDs und Taster auf dem Breadboard. Das Video zeigt eine Vorversion, in welcher noch Statusanzeige und Knöpfe für bestimmte Befehle integriert waren. Erst nach der Aufnahme haben wir die Schaltung reduziert. Das Prinzip bleibt aber dasselbe. | ||
+ | |||
===== Fazit: ===== | ===== Fazit: ===== | ||
Dass Antirector ein cooles System mit Realitätsnutzen ist, sehen wir nach wie vor so. (Beispiel: [[https://www.youtube.com/watch?v=udqbDNeuZ58 |Starlink]]). Die Zusammensetzung unserer Gruppe war relativ gut, da wir für jeden Teilbereich des Systems jemanden hatten, der/die sich gerne damit beschäftigte und somit kein Bereich unterbesetzt blieb. \\ In seiner jetzigen Form stellt Antirector eine absolute Basis dar, die noch um einiges erweitert werden müsste. Natürlich war es nicht der Plan unserer Gruppe, ein marktreifes Produkt auf die Beine zu stellen. Nichtsdestotrotz besteht bei den Themen Zeitmanagement und Kommunikation für das nächste Projekt noch Luft nach oben. Es wäre sinnvoll gewesen, sich zuallererst ausführlich damit auseinanderzusetzen, welche genauen Anforderungen man an das fertige System stellt. Auf diese Art und Weise ließen sich Aufgabenpakete mit Deadlines leichter erstellen.\\ Von dieser kleinen Kritik abgesehen, hat es uns dennoch Spaß gemacht, an diesem Projekt zu arbeiten und einige Ideen in die Tat umzusetzen. | Dass Antirector ein cooles System mit Realitätsnutzen ist, sehen wir nach wie vor so. (Beispiel: [[https://www.youtube.com/watch?v=udqbDNeuZ58 |Starlink]]). Die Zusammensetzung unserer Gruppe war relativ gut, da wir für jeden Teilbereich des Systems jemanden hatten, der/die sich gerne damit beschäftigte und somit kein Bereich unterbesetzt blieb. \\ In seiner jetzigen Form stellt Antirector eine absolute Basis dar, die noch um einiges erweitert werden müsste. Natürlich war es nicht der Plan unserer Gruppe, ein marktreifes Produkt auf die Beine zu stellen. Nichtsdestotrotz besteht bei den Themen Zeitmanagement und Kommunikation für das nächste Projekt noch Luft nach oben. Es wäre sinnvoll gewesen, sich zuallererst ausführlich damit auseinanderzusetzen, welche genauen Anforderungen man an das fertige System stellt. Auf diese Art und Weise ließen sich Aufgabenpakete mit Deadlines leichter erstellen.\\ Von dieser kleinen Kritik abgesehen, hat es uns dennoch Spaß gemacht, an diesem Projekt zu arbeiten und einige Ideen in die Tat umzusetzen. | ||
+ | |||
+ | |||
**Quellen:**\\ | **Quellen:**\\ |