Anfänger braucht Hilfe bei einem Schulprojekt (Steuerung für einen Heißluftballo

Moin moin,

wie Ihr der Überschrift entnehmen könnt brauche ich etwas. Ich möcchte mit meiner Projektgruppe einen Höhenautopiloten für einen Heißluftballon konzepieren.
Das ganze soll nur in der Theorie erarbeitet werden, aber es wäre natürlich schön eine theoretisch funktionale Programmierung dafür zu haben.

Nun bin ich schon vertraut mit elektrischen Schaltungen und SPS-Programmierung, aber ich verzweifle an C.

Ich möchte das Programm in mehreren Schritten programmieren und zuerst einmal soll die Möglichkeit gegeben sein, das Arduino in einen Stanby zu schalten und dann eine Sollhöhe einzustellen, dabei geht eine Standby-Lampe an und über zwei Knöpfe kann die Sollhöhe in 10er-Schritten von 500m verändert werden.

Wird der Standby ausgeschaltet, soll die Regelung anfangen zu arbeiten und jederzeit mit dem Standby unterbrochen werden, aber soweit bin ich noch garnicht.

Mein aktuelles Problem ist, das man nur am Anfang der Standby wählen kann und das Programm sich danach nicht wiederholt, also eine Änderung des Standby-Knopfes sich nicht auf die LED auswirkt.

Vielen Dank für Eure Hilfe im Vorraus!

Hier der Code:

#include <Wire.h>
#include <Adafruit_MPL3115A2.h>
Adafruit_MPL3115A2 baro = Adafruit_MPL3115A2();

  //Konstante Variablen:
  const int stbyLED = 13;     //Standby-Indikator
  const int incPin = 12;      //Taster zum erhöhen des Sollwerts
  const int decPin = 11;      //Taster zum verringern des Sollwerts
  const int stbyPin = 10;     //Standby Schalter
  const int ventilPin = 9;    //Transistor, der das Magnetventil steuert
  
  // Variable die sich ändern:
  short sollHoehe = 500;      //Sollhöhe
  int stbyState;              //Zustand des Standbies
  int dec;                    //Zustand des Increase-Tasters
  int inc;                    //Zustand des Decrease-Tasters
  
  
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(incPin, INPUT);
  pinMode(decPin, INPUT);
  pinMode(stbyPin, INPUT);
  pinMode(ventilPin, OUTPUT);
  pinMode(stbyLED, OUTPUT);

}

/// -------------------------------------------------------------
///                 Hauptprogramm (Endlosschleife)
/// -------------------------------------------------------------
void loop() {
   // put your main code here, to run repeatedly:
   
//---------Ist-Höhe feststellen:--------
  int aktuelleHoehe = (int)baro.getAltitude();    //Ist-Höhe vom Barometer abfragen
  
//---------Ist-Höhe anzeigen:--------
  Serial.print("IST= "); Serial.print(aktuelleHoehe); Serial.println("m");
//---------Soll-Höhe anzeigen:--------
  Serial.print("SOLL= "); Serial.print(sollHoehe); Serial.println("m");
  
//---------STBY Abfrage:--------
   //Stand-By LED(STBYSTATE) (EIN= STBY aktiv; AUS= STBY inaktiv) AutopilotSystem ist erst aktiv wenn stbyState=LOW ist
  int stbyPinState = digitalRead(stbyPin);
  if (stbyPinState == HIGH) {
      stbyState = LOW;
      digitalWrite(stbyLED, LOW);
      
    }
  else{
      stbyState = HIGH;
      digitalWrite(stbyLED, HIGH);
    }
}
//---------ENDE--------


/// -------------------------------------------------------------
///                 Unterprogramm Höheneingabe
/// -------------------------------------------------------------  
//STBY muss aktiv sein

  void hoeheneingabe() {
     //Soll-Hoehe eingeben:
 
  int inc = digitalRead(incPin);
  while (inc == HIGH && stbyState == HIGH) sollHoehe + 10;
    
  int dec = digitalRead(decPin);
  while (dec == HIGH && stbyState == HIGH) sollHoehe - 10;
    
}
//---------ENDE--------

Bitte setze Deinen Sketch in Codetags (oben links </> im Foreneditor oder [code] davor und [/code] dahinter - ohne die *).
Das kannst Du auch noch nachträglich durch Editieren tun. Bitte mach das, der Sketch ist besser zu lesen, besonders auf mobilen Geräten.

Gruß Tommy

Die LED müsste gemäss deinem Code eigentlich auf stbyPin reagieren. Was hast du hardwaremässig an diesem Pin angeschlossen?

Gruss
René

Ich vermisse in Deinem Code die Entprellung der Schalter, und eine Verzögerung beim Einstellen der Höhe (siehe StateChangeDetection).

Du rufst das Unterprogramm hoeheneingabe() nirgends auf.

Gruß Tommy

Servus nochmal,

die Entprellung bastel ich noch mit ein, aber wofür genau brauche ich die StateChangeDetection? Wenn ich das richtig verstanden habe, ist die ja da um eine Flankenerkennung umzusetzen. Inwiefern ist das für diesen Fall von Vorteil?

Richtig das Unterprogramm wird noch garnicht aufgerufen, das soll auch erstmal Nebensache sein.
Ehrlich gesagt verstehe ich auch noch nicht wo der Vorteil von dem Unterprogrammen ist. Wie gesagt kenne ich normalerweise FUP, GRAPH7 etc. deswegen ist für eine gewisse Umstellung und auch Umdenken.
Ich habe gedacht, dass das Hauptprogramm dauernd läuft und nur im Bedarfsfall die Unterprogrammer ausgeführt werden, ist das so richtig?

Da ich gerade auf Entsendung bin habe ich nur das Arduino und ein wenig Draht, des Schalter ist also ein Stück Draht das ich mit 5V oder Masse kurzschließe.

Und es funktioniert nicht so wirklich. Nur nach einem Rest kann man den Status der LED ändern indem man Pin10 auf GND oder 5V legt.

Eine Frage noch: Wenn if- oder while-Bedingungen nicht erfüllt werden, bleibt das Arduino an dieser Bedingungen hängen bis sie erfüllt wird oder Schaut sie sich alle Bedingungen an und arbeitet die ab die gerade erfüllt werden?

Vielen Dank

Deine bisherigen Programmiererfahrungen stehen Dir leider im Wege. Die Schleife loop wird, Interrupts unberücksichtigt gelassen, von Anfang bis Ende sequenziell abgearbeitet, dann kommt etwas Hintergrundzauber, dann geht es mit loop weiter. Jede Funktion mußt Du mindestens einmal aufrufen, damit sie was tun kann.

Funktionen sind nicht zwingend notwendig, sondern diesen, sehr vereinfacht ausgedrückt, der Übersichtlichkeit durch Gliederung. Sie machen weder Compiler noch µC sondern hoffentlich den Typen vor der IDE glücklich :slight_smile:

Auf einem Arduino gibt es keine Apps, keine Threads und kein Betriebssystem, da muß alles in einen einzigen Sketch reingepackt werden.

StateChangeDetection hilft z.B. dabei, daß beim Drücken einer Taste ein Zähler nicht sofort zum Überlaufen kommt, sondern nur bei jedem neuen Tastendruck um z.B. 10 erhöht wird.

Ok,

danke für die Rückmeldungen, die helfen mir auf jeden Fall weiter!

Ich habe die letzten Tage noch ein wenig rumgebastelt und wollte Euch nun nochmal das Ergebnis zeigen.

Nochmal zu Erklärung des Programms:

Ein NC namens STBY(Der Name ist vielleicht irreführend…) Schaltet die Modi der Stuerung. Im Stanby leuchtet eine Lampe und mann kann eine Sollhöhe in 10er-Schritten eingeben.

Gleichzeitig, unabhängig von der Schalterstellung wird die aktuelle Höhe gemessen und zu Anzeige gebracht und nach jeder Sekunde überprüft ob der Ballon steigt oder sinkt.

Schließt man den Schalter wird der Standby “beendet” und das Programm schaltet nun einen Transistor, der 12V für ein Ventil zur Verfügung stellt.
Dieses Unterprogramm darf nur alle 7 Sekunde geöffnet werden um der Trägheit des Ballons entgegenzuwirken und nicht zu oft zu heizen.

Schlussendlich wird ein weiteres Unterprogramm aktiv sobald das Steuerunterprogramm ein HIGH ausgibt. In diesem Programm wird der transistor aktiviert und nach 2,5 sekunden wieder geschlossen.

Ich bitte Euch mir noch Denkfehler etc. aufzuzeigen, da das hier wie gesagt meine ersten Programmiererfahrungen wiederspiegelt.

Viele Dank :wink:

/*
   Autor F. Wiechers
   Steuerung für einen Höhenautopiloten
   Komponenten:
   1x MPL3115A2
   2x Taster (NO)
   1x Schalter (NC)
   1x Transistor zum anteuern des Magnetventils
*/

#include <Wire.h>
#include <Adafruit_MPL3115A2.h>
#include <Bounce2.h>
#define LED_PIN 13
Adafruit_MPL3115A2 baro = Adafruit_MPL3115A2();

//Konstante Variablen:
const int stbyLED = 13;       //Standby-Indikator
const int stbyPin = 10;       //Standby Schalter
const int valvePin = 9;       //Transistor, der das Magnetventil steuert
#define incPin 12             //Taster zum erhöhen des Sollwerts
#define decPin 11             //Taster zum verringern des Sollwerts
const long interval = 8000;   //Intervall nach dem der Autopilot wieder zünden kann (milliseconds)
const long intervalHoehe = 1000;  //Intervall für die Abfrage der Vergleichshöhe
const long intervalValve = 2500;  //Intervall für das Schließen des Ventils

//Variable die sich ändern:
short sollHoehe = 500;        //Sollhöhe
short aktuelleHoehe = 500;
int differenzHoehe = 1;
int stbyState;                //Zustand des Standbies
int dec;                      //Zustand des Increase-Tasters
int inc;                      //Zustand des Decrease-Tasters
int valveState;                //Zustand des Transistors
unsigned long previousMillis = 0;
unsigned long previousMillisHoehe = 0;
unsigned long previousMillisValve = 0;
unsigned long currentMillis = millis();

//Debounce
Bounce debounceInc = Bounce();
Bounce debounceDec = Bounce();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(incPin, INPUT);
  pinMode(decPin, INPUT);
  pinMode(stbyPin, INPUT);
  pinMode(valvePin, OUTPUT);
  pinMode(stbyLED, OUTPUT);
  debounceInc.attach(incPin);
  debounceInc.interval(30);   //Debounceintervall in ms
  debounceDec.attach(decPin);
  debounceDec.interval(30);   //Debounceintervall in ms
}

/// -------------------------------------------------------------
///                 Hauptprogramm (Endlosschleife)
/// -------------------------------------------------------------
void loop() {
  // put your main code here, to run repeatedly:

  //---------Bounce Instanzen aktualisieren:--------
  debounceInc.update();
  debounceDec.update();


  //---------Ist-Höhe anzeigen:--------
  Serial.print("IST= "); Serial.print(aktuelleHoehe); Serial.println("m");
  //---------Soll-Höhe anzeigen:--------
  Serial.print("SOLL= "); Serial.print(sollHoehe); Serial.println("m");

  //---------STBY Abfrage:--------
  //Stand-By LED(STBYSTATE) (EIN= STBY aktiv; AUS= STBY inaktiv) AutopilotSystem ist erst aktiv wenn stbyState=LOW ist
  int stbyPinState = digitalRead(stbyPin);
  if (stbyPinState == HIGH) {
    stbyState = LOW;
    digitalWrite(stbyLED, LOW);
    hoeheneingabe();
  }
  else {
    stbyState = HIGH;
    digitalWrite(stbyLED, HIGH);
    steuerung();
  }
  hoehe();
  valve();
  delay(1);
}
//---------ENDE--------


/// -------------------------------------------------------------
///                 Unterprogramm Höheneingabe
/// -------------------------------------------------------------
//STBY muss aktiv sein

void hoeheneingabe() {
  //Soll-Hoehe eingeben:

  int inc = debounceInc.read();
  if (inc == HIGH && stbyState == HIGH) sollHoehe + 10;

  int dec = debounceDec.read();
  if (dec == HIGH && stbyState == HIGH) sollHoehe - 10;

  delay(1);
}
//---------ENDE--------


/// -------------------------------------------------------------
///                 Unterprogramm Steuerung
/// -------------------------------------------------------------
//STBY muss inaktiv sein
/*Liegt die Ist-Höhe unter der Soll-Höhe
  und bewegt sich der Ballon nicht auffährts wird der valveState auf HIGH gesetzt.
  Das Unterprogramm kann nur alle 7 sek aufgerufen werden.
  ValveState wird noch 2,5 sek wieder auf LOW gesetzt*/

void steuerung() {
  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;
    if (sollHoehe << aktuelleHoehe && differenzHoehe <= 0) {
      valveState = HIGH;
    }

  }
  delay(1);
}
//---------ENDE--------


/// -------------------------------------------------------------
///                 Unterprogramm Höhendifferenz festellen
/// -------------------------------------------------------------
// Höhen messen und eine einfache Steig-/Sinkrate feststellen

void hoehe() {

  short aktuelleHoehe = (short)baro.getAltitude();            //Ist-Höhe vom Barometer abfragen

  if (currentMillis - previousMillisHoehe >= intervalHoehe) {

    previousMillisHoehe = currentMillis;
    int vergleichshoehe = (int)baro.getAltitude();            //Vergleichsöhe vom Barometer abfragen
    int differenzHoehe = vergleichshoehe - aktuelleHoehe;     //Differenz ausrechnen (<0 gesunken; >0 gestiegen)
  }
  delay(1);
}
//---------ENDE--------


/// -------------------------------------------------------------
///                 Unterprogramm Ventil steuern
/// -------------------------------------------------------------
// Ist ValveState auf HIGH wird der Transistor für 2,5 Sekunden angestuert

void valve() {

  if (valveState == HIGH) {

    previousMillisValve = currentMillis;
    digitalWrite(valvePin, HIGH);
    if (currentMillis - previousMillisValve >= intervalValve) {
      digitalWrite(valvePin, LOW);
      valveState = LOW;
    }

  }

}

Sehr ordentlich dokumentiert :slight_smile:

Allerdings solltest Du noch etwas an Deiner Terminologie feilen. Unter “Ein NC namens STBY” kann sich niemand was vorstellen, ich rate mal, daß das ein Schalter sein soll.

Auch die Zustandsvariablen, die nur HIGH oder LOW sein können, sollten “bool” sein, nicht int, und wenn Du dann noch true und false für die Zustände nimmst, oder ON und OFF statt HIGH und LOW, wird das Programm für Außenstehende viel besser verständlich. Wer weiß schon, ob ein Eingang oder Ausgang oder LED bei Dir active high oder low ist?

In hoeheneingabe() kannst Du einmal prüfen, ob STBY aktiv ist, und falls nicht gleich wieder zurückspringen.

    if (sollHoehe << aktuelleHoehe && differenzHoehe <= 0) {
      valveState = HIGH;

Das << ist hier sicher falsch. Auch weiß niemand, ob das Ventil hier geöffnet oder geschlossen werden soll, da fehlt ein entsprechender Kommentar. Hier wäre ON oder OFF verständlicher. Du kannst auch eigenen Namen vergeben, wie AUF und ZU.

Die restlichen Fehler werden Dir vermutlich noch auffallen, wenn Du die Zeitsteuerung eingebaut hast und das Programm life testen kannst.