Kommunikation zwischen Arduino und Flugcontroller

OP #7512755
Lesenswert?
• ▲
▼

Ich versuche gerade, Daten vom Arduino Uno über den Pixhawk an QGroundcontrol zu senden. An Bord meines Flugzeugs habe ich zwei NTC-Sensoren und einen RPM-Sensor, um Temperatur und Geschwindigkeit (rpm) zu messen. Ich denke, Mavlink ist der richtige Weg, um die Daten vom Arduino zu meinem Pixhawk und dann zu QGroundcontrol zu senden, oder was denkt ihr?

Dies ist mein Arduino-Code:

1
#include <Thermistor.h>
2
#include <NTC_Thermistor.h>
3
// wiring: https://funduino.de/nr-54-ntc-temperatursensor
4
const int Sensor_Pin1 = A0;
5
const int Sensor_Pin2 = A1;
6
const int signalPin = 2;
7

8
#define Referenzwiderstand   10000 // 
9
#define Nominalwiderstand     10000 // 
10
#define Nominaltemperatur    25 // 
11
#define BWert                3950 // 
12

13
Thermistor* thermistor1;
14
Thermistor* thermistor2;
15

16
volatile unsigned long startMicros = 0;
17
volatile bool firstEdgeDetected = false;
18

19
void setup() {
20
  Serial.begin(9600);
21
  
22
  pinMode(signalPin, INPUT);
23
  attachInterrupt(digitalPinToInterrupt(signalPin), handleInterrupt, RISING);
24
  
25
  thermistor1 = new NTC_Thermistor(Sensor_Pin1, Referenzwiderstand, Nominalwiderstand, Nominaltemperatur, BWert);
26
  thermistor2 = new NTC_Thermistor(Sensor_Pin2, Referenzwiderstand, Nominalwiderstand, Nominaltemperatur, BWert);
27
}
28

29
void loop() {
30
  double celsius1 = 0;
31
  double celsius2 = 0;
32

33
  for (int i = 0; i <= 999; i++) {
34
    celsius1 += thermistor1->readCelsius();
35
    celsius2 += thermistor2->readCelsius();
36
  }
37

38
  celsius1 /= 1000;
39
  celsius2 /= 1000;
40

41
  Serial.print("Temperatur1: ");
42
  Serial.print(celsius1);
43
  Serial.print(" °C");
44
  Serial.print(" Temperatur2: ");
45
  Serial.print(celsius2);
46
  Serial.println(" °C");
47

48
  delay(100);
49
}
50

51
void handleInterrupt() {
52
  if (!firstEdgeDetected) {
53
    startMicros = micros();
54
    firstEdgeDetected = true;
55
  } else {
56
    unsigned long endMicros = micros();
57
    firstEdgeDetected = false;
58
    
59
    unsigned long timeBetweenEdges = endMicros - startMicros;
60
    float frequency = 1000000.0 / timeBetweenEdges;
61
    Serial.print("Frequenz: ");
62
    Serial.print(frequency);
63
    Serial.println(" Hz");
64
  }
65
}
#7512763
Lesenswert?
• ▲
▼

Das "Serial.print" im "handleInterrupt" ist sehr ungünstig. Berechne da lieber nur deine "frequency", und mach die Ausgabe mit zu den anderen Ausgaben in der loop().

Dann könnte man noch in die Details gehen, z.B. startMicros und firstEdgeDetected müssen nicht volatile sein, könnten stattdessen "static" in's handleInterrupt.

Und du könntest, wie bei den Temperaturen auch, für die Frequenz einen durchschnitt über die letzten X Takte bilden.

Moderator (Firma: Titel) Persönliche Seite #7512828
Lesenswert?
• ▲
▼

Εrnst B. schrieb:

Das "Serial.print" im "handleInterrupt" ist sehr ungünstig.

Weil erstens die Echtzeit kaputt gemacht wird und zudem die SIO-Übertragung aus der Mainloop durch den Interrupt unterbrochen werden kann.

Berechne da lieber nur deine "frequency"

Schon die Float-Berechnung dürfte den sehr ins Stolpern bringen. Ich würde also nur die Differenz der beiden Zeitstempel wegspeichern und den Rest in der Mainloop berechnen.

In der Mainloop ist zudem noch ein Fehler, der sich delay(100) nennt. Aber dazu kommen wir später, wenn irgendwas zusätzlich "nebenher" gemacht werden muss.

#7512956
Lesenswert?
• ▲
▼

Εrnst B. schrieb:

Berechne da lieber nur deine "frequency", und mach die Ausgabe mit zu den anderen Ausgaben in der loop().

Die Auswertung der Messdaten hat in der ISR nichts zu suchen. Da frequency sowieso nur für die Ausgabe benötigt wird, kann die genau dort unmittelbar vor der Ausgabe erfolgen. Da du immer nur den Abstand zweier aufeinander folgender Pulse auswertet, kann es dir passieren, dass der Wert für die Drehzahl deutlich instabil ist - hängt davon ab, in welchem Drehzahlbereich du dich bewegst. Stabiler wird der Wert, wenn du die Zeit für mehrere Umdrehungen auswertet. Häufiger, als du die Daten ablesen kannst, brauchst du sowieso keinen neuen Wert zu messen/übertragen.

Moderator (Firma: Titel) Persönliche Seite #7513187
Lesenswert?
• ▲
▼

Thomas E. schrieb:

mir ging es zunächst ein mal darum den Code zum laufen zu bringen

Das sollte man sich dann im Zuge der Weiterentwicklung aber auch im Kopf behalten. Und rechtzeitig vom urschleimigen "Ablaufprogrammieren" (= das, was weiter oben steht, wird zuerst ausgeführt) ins Programmieren mit Zustandsautomaten (= Programmteile werden abhängig von Systemzuständen ausgeführt) übergehen.

Beim zweiten Programmierstil ist kein delay() nötig (weil Zeiten über einen Zeitstempel verwaltet werden) und Funktionen können deshalb an jeder Stelle der Mainloop zum Programmablauf hinzugefügt werden. Die Mainloop (und alle ihre Unterprogramme) wird jedes Mal ohne jegliches Warten möglichst schnell durchlaufen. Im Idealfall einige tausend Mal pro Sekunde.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.