- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Arduino automatische Abschaltzeit

  1. #1

    Arduino automatische Abschaltzeit

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo,

    mein Projekt beinhaltet zur Zeit 2 Arduinos. Einen Sender und einem Empfänger mit Hilfe der RF24 Libary. Der Sender sendet an den Empfänger die Nummer des zu schaltenden Kanals/Pins. Der Empfänger soll dann diesen Kanal/Pin anschalten und nach z.B. 200ms diesen Kanal auch wieder ausschalten. Das hört sich jetzt erstmal nicht so schwer an, aber wenn der Sender jetzt 2 Kanäle im Abstand von 100ms sendet werden die Ersten jetzt denke ich wissen das es nicht einfach mit

    Code:
    digitalWrite(kanal, HIGH);
    delay(200);
    digitalWrite(kanal, LOW);
    getan ist. Denn hier werden nicht die 100ms Abstand eingehalten sondern erst wenn die 200ms, die der Kanal halten soll abgelaufen um sind, wird der nächste Kanal geschalten.

    Ich habe schonmal was mit
    Code:
    millis();
    versucht aber bin leider nicht wirklich weiter gekommen.


    Mein Versuch

    Code:
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <Conceptinetics.h>
    
    DMX_Master        dmx_master ( 24 , 2 ); //DMX
    
    RF24 radio(7, 8); // CNS, CE
    const byte address[6] = "00001";
    long buttonState;
    int State = LOW;
    int Anzahl[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; //Kanäle die geschalten werden dürfen
    int Anzahl2 = 0;
    long OnTime = 200;
    unsigned long preMills = 0;
    
    void setup() {
      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      dmx_master.enable ();
      radio.begin();
      radio.openReadingPipe(0, address);
      radio.setPALevel(RF24_PA_MIN);
      radio.startListening();
    }
    
    void loop() {
      while (!radio.available());
      radio.read(&buttonState, sizeof(buttonState)); //Hier enthalten der Kanal
      Anzahl2 = buttonState - 1;
      if(buttonState == Anzahl[Anzahl2]) { //Wenn geschalten werden darf
          schuss(buttonState); 
      }
    }
    
    void schuss(int kanal) { //Mein versuch mit millis();
    unsigned long currentMills = millis();
    if(State == LOW){
    digitalWrite(kanal, HIGH);
    dmx_master.setChannelValue (kanal , 255);
    State = HIGH;
    preMills = currentMills; 
    }
    if((State == HIGH) && (currentMills - preMills >= OnTime)){
    digitalWrite(kanal, LOW);
    dmx_master.setChannelValue (kanal , 0);
    State = LOW;
    }
    }

    Vielen Dank

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Hallo,

    ähnliche Frage, grade 2 Tage her.
    Ich nehme grade mal mein Beispiel von da:

    Code:
    unsigned long prev1micros = 0;
    const long toggleinterval = 1000; // nach wieviel Millisekunden soll ein Zustandswechsel erfolgen
    int togglestate = LOW;
    
    void setup() {
    }
    
    void loop() {
    <<<<< hier passiert was das nichts mit der Zeit zu tun hat
      unsigned long cur1micros = millis();
      if (cur1micros - prev1micros >= toggleinterval) { //alle 10ms umschalten
        prev1micros = cur1micros;
        if (togglestate == LOW){
          togglestate = HIGH;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }else{
          togglestate = LOW;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }
      }
    <<<<< hier passiert was das nichts mit der Zeit zu tun hat
    }
    den Code hatte ich für einen Arduino Nano geschrieben.

    Deine Ausgangslage ist halt anders.
    Also immer wenn der Befehl zum setzen des Pins kommt, setzt man 'prev1micros = cur1micros' (oder 'prev1micros = millis()') schaltet den Pin und setzt 'togglestate = HIGH'.
    Wenn 'togglestate == HIGH' ist und 'cur1micros - prev1micros >= toggleinterval' ist, löscht man den Pin wieder und setzt 'togglestate = LOW'.

    Soll nach dem ersten Empfangs des Befehls ein zweiter Befehl ignoriert werden, solange der Pin gesetzt ist, muß man das auch noch verriegeln.

    Ich hoffe das hilft als Denkanstoß.
    Geändert von i_make_it (29.06.2017 um 11:02 Uhr)

  3. #3
    Zitat Zitat von i_make_it Beitrag anzeigen
    Hallo,

    ähnliche Frage, grade 2 Tage her.
    Ich nehme grade mal mein Beispiel von da:

    Code:
    unsigned long prev1micros = 0;
    const long toggleinterval = 1000; // nach wieviel Millisekunden soll ein Zustandswechsel erfolgen
    int togglestate = LOW;
    
    void setup() {
    }
    
    void loop() {
    <<<<< hier passiert was das nichts mit der Zeit zu tun hat
      unsigned long cur1micros = millis();
      if (cur1micros - prev1micros >= toggleinterval) { //alle 10ms umschalten
        prev1micros = cur1micros;
        if (togglestate == LOW){
          togglestate = HIGH;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }else{
          togglestate = LOW;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }
      }
    <<<<< hier passiert was das nichts mit der Zeit zu tun hat
    }
    den Code hatte ich für einen Arduino Nano geschrieben.

    Deine Ausgangslage ist halt anders.
    Also immer wenn der Befehl zum setzen des Pins kommt, setzt man 'prev1micros = cur1micros' (oder 'prev1micros = millis()') schaltet den Pin und setzt 'togglestate = HIGH'.
    Wenn 'togglestate == HIGH' ist und 'cur1micros - prev1micros >= toggleinterval' ist, löscht man den Pin wieder und setzt 'togglestate = LOW'.

    Soll nach dem ersten Empfangs des Befehls ein zweiter Befehl ignoriert werden, solange der Pin gesetzt ist, muß man das auch noch verriegeln.

    Ich hoffe das hilft als Denkanstoß.

    Hallo,
    Ja vielen Dank schonmal.
    Aber das wäre ja dann im Prinzip das gleiche was ich schon unten stehen habe, nur das dass von dir direkt in der void loop ausgeführt wird. In wie fern macht das ein Problem das in eine Funktion umzulagern?

    Gruß

    - - - Aktualisiert - - -

    Code:
    unsigned long prev1micros = 0;
    const long toggleinterval = 1000; // nach wieviel Millisekunden soll ein Zustandswechsel erfolgen
    int togglestate = LOW;
    
    void setup() {
    }
    
    void loop() {
    <<<<< hier passiert was das nichts mit der Zeit zu tun hat
      unsigned long cur1micros = millis();
      if (cur1micros - prev1micros >= toggleinterval) { //alle 10ms umschalten
        prev1micros = cur1micros;
        if (togglestate == LOW){
          togglestate = HIGH;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }else{
          togglestate = LOW;
    <<<<< hier passiert was das Abhängig von der Zeit ist
        }
      }
    Zudem das Problem was ich hier sehe ist, das wenn ein Kanal geschalten ist die Variable togglestate auf HIGH gesetzt wird. Sendet der Sender also nach 100ms, wo der 1. Kanal noch am Halten ist (200ms), wird der gesendete Kanal auch erst nach Ablauf der 200ms geschalten, da togglestate noch auf HIGH ist und der Kanal erst geschaltet werden kann, wenn togglestate wieder gleich LOW ist.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Wer sagt dir denn, das es nicht möglich ist:

    curmil1
    prevmil1
    toggel1

    curmil2
    prevmil2
    toggel2

    etc. zu nutzen.

    Die Frage ist, wie willst Du es schreiben um es in Funktionen (Methoden) auszulagern? das ist einfach eine Frage des Programmdesigns.
    Aber wenn Du bei dem Beispiel noch nicht darauf schließen konntes, das Du das auch mit mehreren Variabeln machen kannst, würde ich Dir für den Moment von Methoden abraten.

    Denn wenn Du die selbe Methode aufrufst um damit die Zeiten von z.B. 10 Pins zu verwalten, mußst Du ja auch die 10 Zustände und 10 Zeiten sauber getrennt speichern können.
    Das setzt vorraus, das Du mindestns erkennen kannst, das toggelstate und prevmicros auch mit einem Zähler als x verschiedene Variablen vorkommen kann oder das man ein Toggelstate Array und ein prevmicros array erstellt und da dann immer nur das jeweils passende Feld setzt, auswertet, löscht.
    Mein Beispiel ist halt erst mal ein Hinweis in die Richtung "Freilaufender Zähler mit millis()".
    Wie umfangreich Du das programmieren willst hängt ja von Dir ab.

    Du kannst es auch ganz elegant machen und mit Timerinterrupts arbeiten, dann hast Du für jeden IRQ eine ISR, was ja dann auch aus der Loop ausgelagerte Funktionen sind.
    Die sind dann sogar ganz präzise. die Varinte mit milis() stellt ja nur Sicher, das mindestens die Zeit und maximal die Zeit plus einmal der komplette Programmdurchlauf vergehen.
    Geändert von i_make_it (29.06.2017 um 12:02 Uhr)

  5. #5
    Zitat Zitat von i_make_it Beitrag anzeigen
    Wer sagt dir denn, das es nicht möglich ist:

    curmil1
    prevmil1
    toggel1

    curmil2
    prevmil2
    toggel2

    etc. zu nutzen.

    Die Frage ist, wie willst Du es schreiben um es in Funktionen (Methoden) auszulagern? das ist einfach eine Frage des Programmdesigns.
    Aber wenn Du bei dem Beispiel noch nicht darauf schließen konntes, das Du das auch mit mehreren Variabeln machen kannst, würde ich Dir für den Moment von Methoden abraten.

    Denn wenn Du die selbe Methode aufrufst um damit die Zeiten von z.B. 10 Pins zu verwalten, mußst Du ja auch die 10 Zustände und 10 Zeiten sauber getrennt speichern können.
    Das setzt vorraus, das Du mindestns erkennen kannst, das toggelstate und prevmicros auch mit einem Zähler als x verschiedene Variablen vorkommen kann oder das man ein Toggelstate Array und ein prevmicros array erstellt und da dann immer nur das jeweils passende Feld setzt, auswertet, löscht.
    Mein Beispiel ist halt erst mal ein Hinweis in die Richtung "Freilaufender Zähler mit millis()".
    Wie umfangreich Du das programmieren willst hängt ja von Dir ab.

    Du kannst es auch ganz elegant machen und mit Timerinterrupts arbeiten, dann hast Du für jeden IRQ eine ISR, was ja dann auch aus der Loop ausgelagerte Funktionen sind.
    Die sind dann sogar ganz präzise. die Varinte mit milis() stellt ja nur Sicher, das mindestens die Zeit und maximal die Zeit plus einmal der komplette Programmdurchlauf vergehen.
    Leider ist es so das noch nicht mal die erste Variante zu 100% funktioniert. Der Kanal wird zwar angeschalten aber Nicht wieder aus.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Bei deinem Code defienierst Du ein Array mit 24 Werten, aber ohne dem Array mitzugeben das auch 24 Speicherplätze haben soll.
    Ist unschöner Code. Wurde das nicht beim Compilieren angemeckert?
    wenn du also 24 verschiedene Kanäle hast, warum hast Du dann nur einmal State und auch nur einmal preMills ?
    Wann enthält State den Status von welchem der 24 Kanäle und wann enthällt preMills die Startzeit von welchem Kanal?

    Anzahl2 ist ja der Index mit dem du alles was in
    if(buttonState == Anzahl[Anzahl2])
    drin ist zu 24 verschiedenen Programmteilen machst.
    nur kannst Du mit State nicht 24 Verscheidene Zustände gleichzeitig speichern State[Anzahl2] könnte das.
    Genau das Selbe bei preMills: --> preMills[Anzahl2].

    Gehe Deinen Code erst mal durch und führe ihn auf Papier aus. Schreib Dir dazu immer auf welche Variable welchen Wert hat.
    Dann fallen Dir solche Sachen sofort auf. denn die eine Variabel wird halt ständig neu befüllt und liefert dann für index 1 den Wert zurück der ihr vorher bei index 24 eingeschrieben wurde und schon lange nicht mehr den Wert der beim letzten Durchlauf von Index1 geschrieben wurde.

  7. #7
    HaWe
    Gast
    Zitat Zitat von i_make_it Beitrag anzeigen
    Bei deinem Code defienierst Du ein Array mit 24 Werten, aber ohne dem Array mitzugeben das auch 24 Speicherplätze haben soll.
    Ist unschöner Code. Wurde das nicht beim Compilieren angemeckert?
    "unschöner Code"?
    auf was beziehst du dich?
    auf dies hier:
    int Anzahl[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; //Kanäle die geschalten werden dürfen



    falls ja: dieser Teil ist völlig korrekt, super schön, entspricht vollständig den C++(04/11) und C99 specs und da hat der Compiler absolut überhaupt nichts dran rumzumeckern

    OT, ps, allerdings: "geschaltet werden dürfen, nicht: geschalten...

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Ich habe auch geschrieben unschön nicht falsch.

    Unschön deshalb, weil man mit 'int Anzahl[24] = {...' sofort die Größe des Array sieht auch wenn da mal andere Werte stehen als eine monoton steigende, ununterbrochene Folge aus natürlichen Zahlen.
    Wird hilfreich wenn man mal nach 2-3 Jahren seinen eigenen Code versucht zu verstehen oder was verändern will.
    Da ich schon seit über 3 Jahrzehnten programmier, bin ich über so Schwächen selbst schon oft genug gestolpert.
    Irgendwann kommt der Punkt wo man seinem jüngeren ich dankbar ist für jeden schnell zu verstehenden Code den man hinterlassen hat.

    Da auch kein Hinweis vorhanden ist das es sich um ein dynamisches Array handelt, kann man das halt für die Lesbarkeit machen.
    Geändert von i_make_it (29.06.2017 um 17:51 Uhr)

  9. #9
    HaWe
    Gast
    Zitat Zitat von i_make_it Beitrag anzeigen
    Ich habe auch geschrieben unschön nicht falsch.

    Unschön deshalb, weil man mit 'int c = {...' sofort die Größe des Array sieht auch wenn da mal andere Werte stehen als eine monoton steigende, ununterbrochene Folge aus natürlichen Zahlen.
    Wird hilfreich wenn man mal nach 2-3 Jahren seinen eigenen Code versucht zu verstehen oder was verändern will.
    Da ich schon seit über 3 Jahrzehnten programmier, bin ich über so Schwächen selbst schon oft genug gestolpert.
    Irgendwann kommt der Punkt wo man seinem jüngeren ich dankbar ist für jeden schnell zu verstehenden Code den man hinterlassen hat.

    Da auch kein Hinweis vorhanden ist das es sich um ein dynamisches Array handelt, kann man das halt für die Lesbarkeit machen.
    nein, sorry, der Code ist weder unschön, noch hat der Compiler Grund zu meckern:

    Es ist per
    int Anzahl[] = // ...
    der einzige (!) mögliche (!) Weg, diesen 24er array direkt bei der Definition zu initialisieren.
    Definiert man ihn per
    int Anzahl[24] //...
    kann man ihn anschließend nicht mehr per
    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
    initialisieren.
    In diesem Falle legt C also eindeutig die einzig mögliche und richtige Syntax fest, die Frage nach schön oder nicht stellt sich also gar nicht.
    Und ob der Code Enkel-sicher ist, ist sowieso hier nicht wichtig - er muss zunächst einmal überhaupt nur einfach mal funktionieren....

  10. #10
    Zitat Zitat von i_make_it Beitrag anzeigen
    Bei deinem Code defienierst Du ein Array mit 24 Werten, aber ohne dem Array mitzugeben das auch 24 Speicherplätze haben soll.
    Ist unschöner Code. Wurde das nicht beim Compilieren angemeckert?
    wenn du also 24 verschiedene Kanäle hast, warum hast Du dann nur einmal State und auch nur einmal preMills ?
    Wann enthält State den Status von welchem der 24 Kanäle und wann enthällt preMills die Startzeit von welchem Kanal?

    Anzahl2 ist ja der Index mit dem du alles was in
    if(buttonState == Anzahl[Anzahl2])
    drin ist zu 24 verschiedenen Programmteilen machst.
    nur kannst Du mit State nicht 24 Verscheidene Zustände gleichzeitig speichern State[Anzahl2] könnte das.
    Genau das Selbe bei preMills: --> preMills[Anzahl2].

    Gehe Deinen Code erst mal durch und führe ihn auf Papier aus. Schreib Dir dazu immer auf welche Variable welchen Wert hat.
    Dann fallen Dir solche Sachen sofort auf. denn die eine Variabel wird halt ständig neu befüllt und liefert dann für index 1 den Wert zurück der ihr vorher bei index 24 eingeschrieben wurde und schon lange nicht mehr den Wert der beim letzten Durchlauf von Index1 geschrieben wurde.
    Also mir war es erstmal wichtig das es funktioniert! Schönmachen kann man es danach immer noch... Habe es jetzt komplett fertig aber anders gelöst. Falls es dich interessiert:
    Code:
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <Conceptinetics.h>
    
    DMX_Master        dmx_master ( 24 , 2 );
    
    RF24 radio(7, 8); // CNS, CE
    const byte address[6] = "00001";
    long kanal;
    #define ANZAHL_KANAL 24
    uint32_t anschaltzeit[ANZAHL_KANAL];
    int Anzahl[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
    const uint32_t OnTime = 300;
    
    
    void setup() {
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      dmx_master.enable ();
      radio.begin();
      radio.openReadingPipe(0, address);
      radio.setPALevel(RF24_PA_MAX);
      radio.startListening();
    }
    
    void loop() {
      checkKanal();  
      if (radio.available()){
        radio.read(&kanal, sizeof(kanal));
          if(kanal == Anzahl[kanal-1]) {   
            kanalEinschalten(kanal);
          }
      }
    }
    
    void kanalEinschalten(byte nummer) { // 1 bis 24
       anschaltzeit[nummer-1] = millis();
       digitalWrite(nummer,HIGH);
       dmx_master.setChannelValue (nummer , 255);
    }
    void kanalAusschalten(byte nummer) { // 1 bis 24
       anschaltzeit[nummer-1] = 0;
       digitalWrite(nummer,LOW);
       dmx_master.setChannelValue (nummer , 0);
    }
    void checkKanal() {
      uint32_t aktMillis = millis();
      for(byte i=0; i<ANZAHL_KANAL; i++) {
        if (anschaltzeit[i] != 0 && aktMillis - anschaltzeit[i] >= OnTime) kanalAusschalten(i+1); 
      }
    }
    Ist zwar noch nicht ganz schön aber macht was es soll.

    Trotzdem nochmal vielen dank!

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Automatische Stromversorgung
    Von AndreasMüler im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 4
    Letzter Beitrag: 14.08.2010, 13:36
  2. automatische Heizungsreglung
    Von daniel.weber im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 3
    Letzter Beitrag: 27.03.2008, 06:56
  3. automatische Toröffnung?
    Von spec im Forum Elektronik
    Antworten: 4
    Letzter Beitrag: 16.12.2007, 08:44
  4. automatische Singalamplitudenanpassung
    Von hacker im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 23.08.2006, 14:37
  5. Automatische Sensorerkennung
    Von Tomili im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 07.04.2006, 21:26

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests