Go Down

Topic: Nach Zustandswechsel nur 1 mal senden (Read 1 time) previous topic - next topic

Marc2012

Hallo Leute,
Ich hab eine Frage zum Programmablauf...


Ich habe einen LDR am Analogeingang des Arduino Uno.
Dann noch 3 Leds am Digitalport 3,4,5.

Je nach Lichtstärke werden die Leds geschaltet.
Das heist : Led dunkel  port 3
                Led mittel  port 4
                Led hell port 5

Mit case 0, case 1, case 2, werden jeweils die leds dementsprechend geschaltet.
Ich habe aber noch zusätzlich die rc switch libarie für funksteckdosen mit im programm.
Soll bedeuten wenn die "led dunkel" eingeschaltet wird hab ich danach die Anweisung im Programm für die funksteckdose  dass diese eingeschaltet werden soll.
Das ganze funktioniert auch mit den leds und der funksteckdose einwandfrei!

Mein eigentliches Problem ist das der 433 mhz sender dauerhaft sendet solang das programm die dunkelkeit erkennt ich wollte gern das es jedoch nur nach Änderung der helligkeit 1 mal kurz sendet und die leds umschalter und nicht dauerhaft im loop sendet.

Wie mach ich das am einfachsten?
Gruß Marc


pylon

Quote
Wie mach ich das am einfachsten?


Poste Deinen Code, dann können wir Dir vielleicht helfen. Ohne Code wird das wohl nichts werden.

Legriano

Also ohne programm code ist das natürlich schwer zu beurteilen aber versuchs mal mit einer while schleife die du nur einmal durchlaufen lässt.

Marc2012

Vielen Dank,
ok hier der code (bin Anfänger  :)  )

Code: [Select]

// Lichterkennung (Helligkeit) je nach Helligkeit werden 3 Ausgänge geschaltet und über die serielle Schnittstelle ausgegeben.
// + Schalten der Funksteckdosen bei Helligkeitsänderung.



const int sensorMin =200;     
const int sensorMax = 800;   
#define Leddark 5             // Led dunkel
#define Ledmedium 4          // Led mittel
#define Ledbright 3         // Led hell

// Sender ist am Arduino Pin #10 angeschlossen 


#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();



void setup() {
 
  Serial.begin(9600); 
  pinMode(Leddark, OUTPUT);
  pinMode(Ledmedium, OUTPUT);
  pinMode(Ledbright, OUTPUT);
  mySwitch.enableTransmit(10);
}

void loop() {
 
  int sensorReading = analogRead(A0);    // Sensor am analog port 0 lesen
 
 
  int range = map(sensorReading, sensorMin, sensorMax, 0, 3); // Umwandeln in 4 Bereiche

  switch (range) {                              // Bereich erkennen
     
  case 0:                                   // es ist dunkel
 
    Serial.println("Es ist dunkel!");
    mySwitch.switchOn("11001", 2);
    digitalWrite(Leddark, HIGH);
    digitalWrite(Ledmedium, LOW);
    digitalWrite(Ledbright, LOW);
    delay(60000);
    break;
   
   
  case 1:           
                                             // zwischenwert ohne Angabe
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledmedium, LOW);
    digitalWrite(Ledbright, LOW);
    break;
   
  case 2:                                   // es ist mittel
    Serial.println("Es ist mittel!");
    mySwitch.switchOff("11001", 2);
    digitalWrite(Ledmedium, HIGH);
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledbright, LOW);
    delay(60000);
    break;
   
   
  case 3:                                   // es ist hell
   
    Serial.println("Es ist hell!");
    mySwitch.switchOff("11001", 2);
    digitalWrite(Ledbright, HIGH);
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledmedium, LOW);
    delay(60000);
    break;
   


 
  }

     }
     















Marc2012

Hab noch was vergessen!

Die Pausen bei den case Anweisungen ( delay (60000) ) hab ich jetzt nur als "Notlösung" genommen dann sendet das 433mHz Modul wenigstens nur einmal alle 60 Sekunden aber normal sollten da so ca 5-10 Sekunden stehen.

Ich wollte ja nur das es bei einem Wechsel 1 mal sendet.

Also von hell auf dunkel (switch on -> für die Funksteckdosen).
Vom Wechsel von dunkel auf hell ( switch off -> für die Funksteckdosen).

Und die Led s sollten jeweils dauerhaft den jeweiligen helligkeitszustand anzeigen.

Danke euch ;)




circuit99

Schau einfach mit einer If-Abfrage ob sich dein zustand geändert hat wenn ja gehst du in dein case wenn nicht machst du nix

Code: [Select]

// Lichterkennung (Helligkeit) je nach Helligkeit werden 3 Ausgänge geschaltet und über die serielle Schnittstelle ausgegeben.
// + Schalten der Funksteckdosen bei Helligkeitsänderung.



const int sensorMin =200;     
const int sensorMax = 800;   
int old_range;
#define Leddark 5             // Led dunkel
#define Ledmedium 4          // Led mittel
#define Ledbright 3         // Led hell

// Sender ist am Arduino Pin #10 angeschlossen 


#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();



void setup() {
 
  Serial.begin(9600); 
  pinMode(Leddark, OUTPUT);
  pinMode(Ledmedium, OUTPUT);
  pinMode(Ledbright, OUTPUT);
  mySwitch.enableTransmit(10);
}

void loop() {
 
  int sensorReading = analogRead(A0);    // Sensor am analog port 0 lesen
 
 
  int range = map(sensorReading, sensorMin, sensorMax, 0, 3); // Umwandeln in 4 Bereiche

  if old_range != range {
  old_range = range;
  switch (range) {                              // Bereich erkennen
     
  case 0:                                   // es ist dunkel
 
    Serial.println("Es ist dunkel!");
    mySwitch.switchOn("11001", 2);
    digitalWrite(Leddark, HIGH);
    digitalWrite(Ledmedium, LOW);
    digitalWrite(Ledbright, LOW);
    delay(60000);
    break;
   
   
  case 1:           
                                             // zwischenwert ohne Angabe
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledmedium, LOW);
    digitalWrite(Ledbright, LOW);
    break;
   
  case 2:                                   // es ist mittel
    Serial.println("Es ist mittel!");
    mySwitch.switchOff("11001", 2);
    digitalWrite(Ledmedium, HIGH);
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledbright, LOW);
    delay(60000);
    break;
   
   
  case 3:                                   // es ist hell
   
    Serial.println("Es ist hell!");
    mySwitch.switchOff("11001", 2);
    digitalWrite(Ledbright, HIGH);
    digitalWrite(Leddark, LOW);
    digitalWrite(Ledmedium, LOW);
    delay(60000);
    break;
   


 
     }
   }
  }
     

Marc2012

Wenn ich den Sketch von "circuit99" Kompilieren will kommt immer eine Fehlermeldung:

In function 'void loop()':
error: expected `(' before 'old_range'
error: expected `}' at end of input



Da ich noch Anfänger bin und einige Zusammenhänge nicht verstehe weis ich leider nicht was das Problem ist!?

Ps. Gibt es eine Seite oder ein Tutorial indem die einzelne Befehle genau Beschrieben sind?
Nur als Bsp. :

Jetzt in meinem Fall wurde mir von euch ja die Änderung mit if vorgeschlagen :


if old_range != range {         // was bedeutet das Ausrufezeichen vor dem =  ?
  old_range = range;            // muss ich das "range" durch irgendetwas ersetzen? oder is das schon die fertige Funktion?
  switch (range) {     

Sorry für die vielen Fragen
Ich habe schon einiges durch testen und die Google Suche herausgefunden aber manche Sachen versteht man wohl erst besser
wenn man es erklärt bekommt.

Gruß Marc

Marc2012

Hab die Fehlermeldungen doch selbst beseitigen können....


if (old_range != range) {
  old_range = range;
  switch (range) {


So geht's zu kompilieren, allerdings macht das Programm das selbe wie mein Code es sendet alle 60 sek das Signal für den 433mHz Sender ...

??

circuit99

Prinzipiell sollte das Programm nur die Switchanweisung ausführen, wenn sich range geändert hat. Lass dir mal vor dem if mit serial.println(range) und serial.println(old_range) die Werte ausgeben. Ich vermute das sich der Wert ständig ändert und des halb laufend das Signal gesendet wird. Oder des stimmt etwas mit den geschweiften klammern nicht. Die Switchanweisung muss im if-Block stehen, nicht danach.

Die 60 Sekunden kommen natürlich von dem delay, das habe ich nicht geändert.

Marc2012

Ja genau die Helligkeit ändert sich dauerhaft um einen kleinen Bereich.

Gibt es keine Funktion die etwas nur einmal ausführen lässt?

Ich hab jetzt mal was anderes Versucht:

Code: [Select]
#define Leddark 5             // Led dunkel
#define Ledmedium 4          // Led mittel
#define Ledbright 3         // Led hell





int ldr = 0;             //analog pin LDR
int ldr_value = 0;       

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

void setup()
{
  Serial.begin(9600); 
  mySwitch.enableTransmit(10);
  pinMode(Leddark, OUTPUT);
  pinMode(Ledmedium, OUTPUT);
  pinMode(Ledbright, OUTPUT);
}

void loop()
{
  ldr_value = analogRead(ldr) ;       
  if (ldr_value > 600) digitalWrite(Leddark, LOW), mySwitch.switchOn("11001", 2);

 
  if (ldr_value <500) digitalWrite(Leddark, HIGH), mySwitch.switchOff("11001", 2);

 
}




Leider auch hier das doofe dauer senden ;(


circuit99

Was heißt bei dir einmal senden? du willst ja sicher jeden Tag an und ausschalten

Dein Ansatz war schon richtig. Du musst anstatt der map-Funktion deine Switchcase-Variable mit if-Anweisungen festlegen. Ich weiß jetzt nicht, was für werte dein Sensor liefert aber du kannst es z.b. so machen:


if (ldr_value < 200) range =0;  //dunkel
if (ldr_value > 400 && ldr_value < 600) range =1;  //mittel
if (ldr_value > 800) range = 2; // hell

if (old_range != range) {
  old_range = range;
  switch (range) {
    case 0:
    case 1:
    case 2:
    }
}

Damit sollte es eigentlich funktionieren. Mit einer Mittelwertbildung von ldr_value kannst du die Funktion nochmals stabilisieren. Das Prinzip ist hier unter dem Stichwort Glätten (Smoothing) erklärt.

http://creativecoding.uni-bayreuth.de/tools/arduino/arduino-patterns/

Wenn das noch nicht geht musst du mit mills() arbeiten und zeitdifferenzen festlegen, in denen geschaltet werden darf.

volvodani

Es gibt noch eine Art der Glättung in dem der neuer gelesene Wert nur einen kleinen Einfluss auf den gelesenen Wert hat.

Nur so geschiebener Code
Code: [Select]


Wertaktuell=analogRead(A0);   // Aktuellwert Einlesen
X=Wertneu*10;                    // Neuerwert nur 10% Einfluss auf den alten
Y=Wertalt*90;                     // Wert aus dem Vorherigien Zyklus auf 90%
Wertneu=X+Y/100;                      // Beide Werte addieren und Neuen Wert Bilden
Wertalt=Wertneu;                 // Für den nächsten Zyklus ist der neue (aktueller gesmoother Wert)


Mit den Faktoren 0.1 (neuer) und 0.9 (alter Wert) kannst du den Einfluss des gelesenen Wertes ändern.  X,Y,Wertneu müssen vom typ long sein.
So verbringt man keine Zeit in einer for Schleife.
So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

Marc2012

Super ;)

Vielen Dank!

Es geht jetzt einwandfrei :)

Gruß Marc

Go Up