Go Down

Topic: [Projekt] INTERVAL (Read 7129 times) previous topic - next topic

agmue

#15
Jul 21, 2016, 06:54 pm Last Edit: Jul 21, 2016, 06:58 pm by agmue
Ist es dir recht, wenn ich das bei den Beispielen mit aufnehme?
Ich bewerbe mich mit dieser vereinfachten Variante:
Code: [Select]
#include <INTERVAL.h>

unsigned long dauer;
const byte LED = 13;

void setup()
{
  pinMode(LED, OUTPUT);
}

void loop()
{
  INTERVAL(dauer)
  {
    dauer = random(500) % 43 * 5;
    digitalWrite(LED, !digitalRead(LED));
  }
}


Ich schließe mich dem Lob der anderen gerne an :)
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

ElEspanol

auch die einfache Variante ist genehm.

Vielleicht solltest du in die Beispiele noch das mit aufnehmen, wo man unterschiedliche Hell-/Dunkelfasen hat. Das bereitet Anfängern auch gerne Probleme, wenn die von delay auf nicht blockierend umsteigen

agmue

auch die einfache Variante ist genehm.
Freut mich :)
Vielleicht solltest du in die Beispiele noch das mit aufnehmen, wo man unterschiedliche Hell-/Dunkelfasen hat. Das bereitet Anfängern auch gerne Probleme, wenn die von delay auf nicht blockierend umsteigen
Meinst Du sowas:
Code: [Select]
#include <INTERVAL.h>

const byte LED = 8;
const unsigned long dauer[] = {200, 50, 50, 50};
const byte anzahlDauer = sizeof(dauer) / sizeof(dauer[0]);
byte index;

void setup()
{
  pinMode(LED, OUTPUT);
}

void loop()
{
  INTERVAL(dauer[index])
  {
    digitalWrite(LED, !digitalRead(LED));
    index = ++index % anzahlDauer;
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

michael_x

Es ist übrigens nicht erforderlich, die Intervall-Dauer mit einem unsigned long Datentyp zu versehen.

Wenn man nicht eigentlich ein Beispiel für den % Operator machen will, flackert auch

Code: [Select]
#include <INTERVAL.h>

const byte LED = 13;

void setup() {  pinMode(LED, OUTPUT); }

byte dauer;
void loop() {
  INTERVAL(dauer)  {
     dauer = random(200);
     digitalWrite(LED, !digitalRead(LED));
  }
}

ElEspanol

Meinst Du sowas:
Code: [Select]
#include <INTERVAL.h>

const byte LED = 8;
const unsigned long dauer[] = {200, 50, 50, 50};
const byte anzahlDauer = sizeof(dauer) / sizeof(dauer[0]);
byte index;

void setup()
{
  pinMode(LED, OUTPUT);
}

void loop()
{
  INTERVAL(dauer[index])
  {
    digitalWrite(LED, !digitalRead(LED));
    index = ++index % anzahlDauer;
  }
}

das ist schon fast zuviel des guten und von Anfängern nicht gleich nachzuvollziehen.

einfach mit
Code: [Select]
if(dauer==200) dauer=1000 else dauer=200;
das es jeder gleich blickt

volvodani

Ich mag das Dingen und es kommt jetzt in meine Programme rein da ich viel mit "blink" merken arbeite,


 
Code: [Select]
if (goodidea==true && usable==true){
Karma++;
}

 Gruß
DerDani
"Komm wir essen Opa!" - Satzzeichen retten Leben!

Doc_Arduino

#21
Jul 25, 2016, 06:28 pm Last Edit: Jul 25, 2016, 06:29 pm by Doc_Arduino

Code: [Select]
if (goodidea==true && usable==true){
Karma++;
}

 
dafür drück ich den Button   :)


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

ElEspanol

#22
Jul 25, 2016, 11:13 pm Last Edit: Jul 25, 2016, 11:41 pm by ElEspanol
Ich hätte da noch einen Verbesserungsvorschlag:

Es wird ja der Code erstmalig nach Verstreichen der Periodendauer ausgeführt.

Bei langen Perioden, z.B. loggen, wäre es aber günstig, vor allem beim testen, dass der Code sofort ausgeführt wird und dann erst die Wartezeit kommt.

Damit könnte man auch hervorragend Alarmmeldungen händeln.
Code: [Select]
if(alarm) INTERVAL(300000UL,1){sendsms();}
würde dann im Alarmfall eine SMS senden und alle 5 Minuten wieder, bis alarm 0 wird

Evtl. durch einen optionalen 2. Parameter wie im Beispiel?

Was haltet ihr davon?

Jede Wette, dann kannst du dich vor Karma nicht mehr retten ;)

ElEspanol

#23
Jul 26, 2016, 12:21 pm Last Edit: Jul 26, 2016, 12:21 pm by ElEspanol
Nachtrag:
Der (aus kompatibilitätsgründen optionale) 2. Parameter könnte die Verzögerung bis zur ERSTmaligen Ausführung sein, also z.B.
Code: [Select]
INTERVAL(3600000UL,30000UL)
{
datenloggen();
}
30 Sekunden nach Systemstart werden die Daten erstmalig geloggt, dann alle Stunde

combie

#24
Jul 26, 2016, 12:25 pm Last Edit: Jul 26, 2016, 12:27 pm by combie
Quote
Bei langen Perioden, z.B. loggen, wäre es aber günstig, vor allem beim testen, dass der Code sofort ausgeführt wird und dann erst die Wartezeit kommt.
Wenn sichs nur ums Debuggen dreht, kann man den Zusatzcode auch mit #ifdef DEBUG aktivieren.
Schöner wird der Code dadurch dann leider nicht......

Code: [Select]

unsigned long dauer = 0;
void setup() {  pinMode(LED, OUTPUT); }


void loop() {
  INTERVAL(dauer)  {
     dauer =500;
     digitalWrite(LED, !digitalRead(LED));
  }
}

Quote
Evtl. durch einen optionalen 2. Parameter wie im Beispiel?
Hmmm....

Gegenvorschlag:
Dann eher ein 2tes Macro, fast identisch zu INTERVAL(), welches nur eine zusätzliche statische "firstRun" Variable mitführt/verwaltet.


Edit:
Quote
Nachtrag:
Der (aus kompatibilitätsgründen optionale) 2. Parameter könnte die Verzögerung bis zur ERSTmaligen Ausführung sein, also z.B.
Machbar!?!?
"firstRun" ins Macro einführen.

Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

combie

@ElEspanol

Die "neue" INTERVAL.H

Code: [Select]

#ifndef __INTERVAL__h__
#define __INTERVAL__h__

#include <Arduino.h>

extern bool DoINTERVAL; // Merker für das Interval Macro

// Start of Interval Macro
#define INTERVAL(interval)                     \
{                                              \
  static unsigned long lastHit = 0;            \
  DoINTERVAL = millis() - lastHit >= interval; \
  if(DoINTERVAL) lastHit = millis();           \
}                                              \
if(DoINTERVAL)
// End of Interval Macro



// Start of Interval Macro
#define INTERVAL_FIRST(interval,firstInterval)                     \
{                                              \
  static unsigned long lastHit = 0;            \
  static bool firstRun = true;                 \
  DoINTERVAL = millis() - lastHit >= (firstRun?firstInterval:interval); \
  firstRun = false;                            \
  if(DoINTERVAL) lastHit = millis();           \
}                                              \
if(DoINTERVAL)
// End of Interval Macro


#endif





Aufruf, dann z.B. so: (in Beispiel IntervalTest.ino)
Code: [Select]

void loop()
{
  // alter Kram
  // ...............

  // neu
   INTERVAL_FIRST(1000UL,0UL)
   {
     //Tu was alle 1000ms
     Serial.println(millis());
   }
}



....
Naja....
Gehen tuts schon....
Aber schöner oder schneller ist es nicht geworden....

Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

ElEspanol

Schöner muss es ja nicht werden, aber damit erschlägst du viele Probleme, von denen viele gar nicht wissen, dass sie sie haben.

Werds später Zuhause gleich mal testen.

combie

#27
Jul 26, 2016, 02:31 pm Last Edit: Jul 26, 2016, 03:09 pm by combie
Ich kann dir noch eine Variante bieten!
Du sprachest ja von "optionalen Parametern".

Optionale Parameter in Macros sind ein Fluch, eine Qual.
Und für mich eigentlich außerhalb des erwünschten.

Aber da machbar, hier mal eine Vorführung:

Die "schlimme" INTERVAL.h
Code: [Select]

#ifndef __INTERVAL__h__
#define __INTERVAL__h__

#include <Arduino.h>

extern bool DoINTERVAL; // Merker für das Interval Macro


// Start of Interval Macro

#define INTERVAL_1(interval)                   \
{                                              \
  static unsigned long lastHit = 0;            \
  DoINTERVAL = millis() - lastHit >= interval; \
  if(DoINTERVAL) lastHit = millis();           \
}                                              \
if(DoINTERVAL)
// End of Interval Macro


// Start of Interval Macro
#define INTERVAL_2(interval,firstInterval)     \
{                                              \
  static unsigned long lastHit = 0;            \
  static bool firstRun = true;                 \
  DoINTERVAL = millis() - lastHit >= (firstRun?firstInterval:interval); \
  if(DoINTERVAL)                   \
  {                                \
     lastHit = millis();           \
     firstRun = false;             \
  }                                \
}                                  \
if(DoINTERVAL)
// End of Interval Macro

#define INTERVAL_X(x,A,B,INNER_INTERVAL, ...)  INNER_INTERVAL

#define INTERVAL(...)    INTERVAL_X(,##__VA_ARGS__,\
                         INTERVAL_2(__VA_ARGS__),\
                         INTERVAL_1(__VA_ARGS__),\
                         INTERVAL_0(__VA_ARGS__)\
                                         )


#endif



Damit sind dann auch solche Dinge möglich:
Code: [Select]

void loop()
{
   INTERVAL(1000UL,0UL)// starte sofort
   {
     //Tu was alle 1000ms
     Serial.println(millis());
   }
   
   INTERVAL(1000UL,4000UL) // starte erst nach 4 Sekunden
   {
     //Tu was alle 1000ms
     Serial.println(millis());
   }


   INTERVAL(333UL)
   {
     //Tu was alle 333ms
     Serial.println(333UL);
   }
}

Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

ElEspanol

#28
Jul 26, 2016, 04:46 pm Last Edit: Jul 26, 2016, 04:49 pm by ElEspanol
Die "schlimme" INTERVAL.h scheint wirklich das gewünschte zu machen. Somit ist Schluss mit negativen previous-Werten, damit die Funktion direkt am Anfang ausgeführt wird.

Ich blick bei der Macro-Geschichte noch gar nicht durch. Deswegen Hut ab!

Karma++

P.S.: Für was sind die anderen Argumente?
#define INTERVAL_X(x,A,B,INNER_INTERVAL, ...)  INNER_INTERVAL


combie

#29
Jul 26, 2016, 05:30 pm Last Edit: Jul 26, 2016, 05:32 pm by combie
P.S.: Für was sind die anderen Argumente?
#define INTERVAL_X(x,A,B,INNER_INTERVAL, ...)  INNER_INTERVAL
Ich sach ja, gruselig....
Die anderen Parameter sind willkürlich benannt.

Im Grunde ist INTERVAL_X ein Dispatcher von einem "Variadic macro" zu Macros mit fester Parameter Liste.

Quote
Ich blick bei der Macro-Geschichte noch gar nicht durch.
Ich auch noch nicht....
Fundiertes Halbwissen, ja, aber viel mehr auch nicht.

Und wie du selber merkst, hier ist mit dem schlimmen INTERVAL Gedöns, die Grenze des "offensichtlichen Verhaltens" überschritten.
Auch verhalten sich, an der Stelle, die verschiedensten Compiler unterschiedlich.
Höllen tun sich auf.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Go Up