PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sketch - fehlermeldung "expected initializer before 'switch'"



wendtdir
02.08.2015, 18:56
Hallo,

momentan bin ich am basteln, einer kleinen Temperaturanzeige mit Alarmfunktion. Ich habe eine Schaltung gebaut, die einen Temperatursensor, einen Bewegungssensor, zwei LEDs und einen IR-Empfänger enthält. Wenn ich mein Arduino einschalte, soll mir die Temperatur angezeigt werden. Wenn ich auf meiner IR Fernbedienung eine Taste drücke soll er in den Alarm-Modus wechseln und eine grüne LED als Status leuchten, weiterhin die Temperatur anzeigen, wenn aber eine Bewegung wahrgenommen wird, soll auf meinem Display eine Meldung ausgegeben werden und eine rote LED leuchten. Drücke ich eine andere Taste, soll er in den reinen Temperatur-Modus zurück wechseln. Ich denke, es wäre das richtige Problem für eine Case-Abfrage. Folgenden Code habe ich geschrieben:


#include <LiquidCrystal.h>
#include <IRremote.h>
int receiverpin = 3;
IRrecv irrecv(receiverpin);
decode_results results;

LiquidCrystal lcd(4,5,6,7,8,9);
float sensor = 0;
float celsius = 0;
float voltage = 0;
int bewegung=13;
int bewegungsstatus=0;
int ledg=11;
int ledr=12;

void setup() {

lcd.begin(16,2);
lcd.clear();
pinMode(bewegung, INPUT);
pinMode(ledg, OUTPUT);
pinMode(ledr, OUTPUT);
irrecv.enableIRIn();

}

void translateIR()

switch(results.value)

{
case 16724175:
bewegungsstatus=digitalRead(bewegung);

sensor = analogRead(0);
voltage = (sensor*5000)/1024;
voltage = voltage - 500;
celsius = voltage/10;


if(bewegungsstatus==HIGH)
{
lcd.setCursor(0,0);
lcd.print("Eindringling");
lcd.setCursor(0,1);
lcd.print("Erkannt");
digitalWrite(ledr, HIGH);
digitalWrite(ledg, LOW);
delay(10000);
lcd.clear();


}
else

{
lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);

}

break;

case 16743045:

lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);
break;
}

void loop()
{
translateIR();
irrecv.resume();
}

Beim kompilieren bekomme ich die Fehlermeldung:

Arduino: 1.6.5 (Windows 8.1), Platine: "Arduino Uno"

Build-Optionen wurden verändert, alles wird neu gebaut

Verwende die Bibliothek LiquidCrystal im Ordner: C:\Program Files (x86)\Arduino\libraries\LiquidCrystal

Verwende die Bibliothek IRremote im Ordner: C:\Program Files (x86)\Arduino\libraries\IRremote



C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standa rd -IC:\Program Files (x86)\Arduino\libraries\LiquidCrystal\src -IC:\Program Files (x86)\Arduino\libraries\IRremote C:\Users\Dirk\AppData\Local\Temp\build503432504808 1929215.tmp\Temp-Bewegung-LCD-IR-Fallabfrage.cpp -o C:\Users\Dirk\AppData\Local\Temp\build503432504808 1929215.tmp\Temp-Bewegung-LCD-IR-Fallabfrage.cpp.o

Temp-Bewegung-LCD-IR-Fallabfrage.ino:29:1: error: expected initializer before 'switch'
Multiple libraries were found for "IRremote.h"

Used: C:\Program Files (x86)\Arduino\libraries\IRremote

Not used: C:\Program Files (x86)\Arduino\libraries\RobotIRremote

expected initializer before 'switch'

Was bedeutet das?

cdk
03.08.2015, 00:11
Ich glaube Du hast lediglich die geschweiften Klammern um den Befehlsblock von translateIR vergessen. Die öffnende wird vor switch erwartet, daher die irreführende Fehlermeldung...

wendtdir
03.08.2015, 15:43
Genau. Das hat gefehlt. Danke.

Leider macht der Sketch nicht das, was er machen soll. Wenn ich auf der IR-Fernbedienung Taste 1 (entspricht dem DEC-Wert 16724175) drücke soll die Alarmfunktion aktiviert werden + Tempmesser. Wenn Taste 3 (Wert 16743045) gedrückt wird, soll nur noch die Temp-Messung funktionieren. Habe ich in dem Sketch ein Gedankenfehler?

Valen
03.08.2015, 18:43
Vielleicht wird ein andere IR-Code empfangen. Was soll er damit tun? Oder wird überhaupt etwas empfangen? Die empfangene Code erst zu dein PC senden wurde ich sagen (oder auf das LCD abbilden), damit du das auch mit vernimmst. Jedenfalls beim testen.

- - - Aktualisiert - - -

Und die Gedankenfehler ist nicht erzählen WAS er macht. Statt was er nicht macht.

wendtdir
03.08.2015, 18:45
Hallo Valen,

ich habe den übermittelten Code über den seriellen Monitor ausgegeben. Der ist korrekt. Der Sketch wurde von mir auch jetzt etwas umgebaut:


#include <LiquidCrystal.h>
#include <IRremote.h>
int receiverpin = 3;
IRrecv irrecv(receiverpin);
decode_results results;

LiquidCrystal lcd(4,5,6,7,8,9);
float sensor = 0;
float celsius = 0;
float voltage = 0;
int bewegung=13;
int bewegungsstatus=0;
int ledg=11;
int ledr=12;


void setup() {

lcd.begin(16,2);
lcd.clear();
pinMode(bewegung, INPUT);
pinMode(ledg, OUTPUT);
pinMode(ledr, OUTPUT);
irrecv.enableIRIn();
Serial.begin(9600);

}

void translateIR()
{
switch(results.value)

{
case 16724175:


if(bewegungsstatus==HIGH)
{
lcd.setCursor(0,0);
lcd.print("Eindringling");
lcd.setCursor(0,1);
lcd.print("Erkannt");
digitalWrite(ledr, HIGH);
digitalWrite(ledg, LOW);
delay(10000);
lcd.clear();
Serial.println("1");


}
else

{
lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);
Serial.println("2");

}

break;

case 16743045:

lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);
Serial.println("3");
break;
}
}
void loop()
{
bewegungsstatus=digitalRead(bewegung);
sensor = analogRead(0);
voltage = (sensor*5000)/1024;
voltage = voltage - 500;
celsius = voltage/10;


if (irrecv.decode(&results))
{
translateIR();

{
irrecv.resume();
}
}
}

Wenn ich die "erste taste" drücke, geht Arduino in den ersten case und gibt mir eine "2" aus, drücke ich die andere Taste, gibt er mir eine "3" aus. Somit geht er also in den Switch und auch korrekt.

ABER, er beachtet nicht meine If-Bedingung im ersten Case. Da soll überprüft werden, ob der Bewegungssensor einen Input an Pin 13 liefert, wenn ja dann Alarm. Wenn kein Input erfolgt, soll er in den Else-Teil des ersten Cases gehen.

Sprich, zu 2/3 funktioniert der Sketch, aber warum bearbeitet er nicht die Bedingung?

Valen
04.08.2015, 18:46
...
ABER, er beachtet nicht meine If-Bedingung im ersten Case. Da soll überprüft werden, ob der Bewegungssensor einen Input an Pin 13 liefert, wenn ja dann Alarm. Wenn kein Input erfolgt, soll er in den Else-Teil des ersten Cases gehen.

Sprich, zu 2/3 funktioniert der Sketch, aber warum bearbeitet er nicht die Bedingung?Ich nehme an das an deine Arduino pin 13 auch ein LED angeschlossen ist? Eine weitere LEd von dir, oder die bekannte Blink-led? Oder beide vielleicht? Leuchtet sie? Kann den bewegungssensor diese LED zum leuchten bringen? Welcher sensor ist das? Ist es stark genug so einer last zu treiben?

wendtdir
04.08.2015, 21:12
Es ist ein Bewegungsmelder HC-SR501 (http://www.amazon.co.uk/HC-SR501-Sensor-Module-Pyroelectric-Infrared/dp/B007XQRKD4). In meinem vorherigen Sketch funktionierte dieser ohne Probleme. Da ich bis jetzt das gebaute nicht auseinandergenommen habe, ist es unwahrscheinlich, dass er nun defekt ist.

Das vorherige Programm war quasi die Grundfunktion. Lies die Temperatur aus, zeige sie mir auf dem Display an, wenn Bewegung erkannt, melde es mir auf dem Display statt der Temperatur und schalte die LED auf rot. Das alles lief mit einer normalen If ... Else Anweisung.

Nun wollte ich lediglich den Switch in meinem Sketch einbauen. Da ich um es mal in die Praxis zu bringen, am Tage nur die Temperatur angezeigt haben möchte und Nachts oder wenn ich nicht da bin die Funktion Bewegungssensor einschalten möchte. Es kommt auch noch ein Piezo hinzu, auch dieses hatte ich schon getestet. Von daher ist nur die Frage, was an meinem Sketch ist falsch, dass die If -Anweisung im ersten Case nicht durchlaufen wird, wenn ich den Case aktiviert habe und eine Bewegung vor dem Sensor stattfindet?

Oder ist mein Sketch so korrekt?

wendtdir
05.08.2015, 19:14
Kurzes Update. Ich habe


bewegungsstatus=digitalRead(bewegung);

nun mal auf =1; gesetzt und den Part digitalRead(Bewegung); aus kommentiert und siehe da, die rote LED begann zu leuchten und auf dem Display stand Eindringling erkannt. Das bedeutet für mich, die IF-Bedingung funktioniert, aber warum liest er die Bewegung nicht ein, wenn ich den Code wie oben geschrieben einbaue?

Alle Werte werden in void Loop() bearbeitet, nur dieser Wert, wenn eine Bewegung wahrgenommen wird, wird nicht übertragen?

HeXPloreR
05.08.2015, 20:04
bau doch mal ein "Serial.println(bewegungssatus);" in den Code von vorher dahinter ein und guck was rauskommt. Setze mal " =0" ein und gucke ob der else Zweig jetzt wieder ausgeführt wird.

wendtdir
05.08.2015, 20:40
Ich habe mir den Bewegungsstatus in void Loop() ausgeben lassen, Ergebnis. Die Bewegung wird erkannt, es wird mir eine 1 Ausgegeben. Wenn ich den Bewegungsstatus auf 0 setze, geht er weiterhin in den Else-Zweig. Bedeutet für mich, die Bewegung wird erkannt, aber der Status wird nicht übergeben an die Bedingung in der Funktion. Sie wird quasi "übergangen" und er geht sofort in den Else-Zweig.

Ich habe den Bewegungssensor mittlerweile auch von Pin 13 entfernt und bei Pin 10 angeschlossen um zu vermeiden, dass es evtl. mit der LED an Pin 13 kollidiert. Übrigens, zufälligerweise habe ich gesehen, dass die LED an Pin 13 auf dem Board aufleuchtet, wenn ich die Hand vor den Sensor halte.

Warum also wird der Status nicht an die Funktion bzw. die If-Anweisung in der Funktion übergeben?

HeXPloreR
06.08.2015, 11:54
Versuhe mal ein Volatile vor "int bewegung = 10" // 13.

wendtdir
06.08.2015, 14:12
Nein. Funktioniert auch nicht. Ich habe bei der IF-Anweisung mittlerweile auch mal eine ==1 eingetragen, geht auch nicht. Ich kann es nicht nachvollziehen, alle anderen Daten werden berechnet und ausgegeben. Kann es ein zeitliches Problem sein? Die Verzögerung von 10 Sekunden dürfte nicht stören, denn die betrifft ja nur die Dauer des Blinkens und die Dauer der Anzeige.

- - - Aktualisiert - - -

Ich habe den Fehler gefunden, weiß nur nicht wie ich ihn ausbessern kann. Das Problem, ich drücke die erste Taste, in dem Moment wird die Bedingung des Bewegunsstatus überprüft. Sie wird aber nicht ohne Pause überprüft. Sondern immer nur in dem Moment, wo die Taste 1 gedrückt wird.

Wie kann ich also eine fortlaufende Prüfung einbauen?

cdk
07.08.2015, 00:16
Ich kann Dir da nicht im Detail weiterhelfen, aber das klingt mir doch nach einem typischen Kandidat für Interruptverarbeitung. In dem Moment, wo die erste Tastenbetätigung erfolgt muß diese den Interrupt auslösen und der Rest dann in der Interruptroutine weiterverarbeitet werden...

wendtdir
07.08.2015, 08:44
Okay, mit Interrupts kenne ich mich nicht aus, da ich mich erst langsam an das Thema ran taste. Muss ich jetzt erstmal anlesen.

Danke für die Info.

cdk
07.08.2015, 15:56
Interruptprogrammierung ist quasi die Königsdisziplin. Du solltest erstmal anfangen kleine Brötchen zu backen, d.h. den Status eines simplen Schalters ohne weitere Funktion abfragen. Dazu benötigst Du INT4 (Pin Change Interrupt Request 0) falls der Schalter an Pin D8..D13 hängt. Dieser INT hat hohe Priorität - Du mußt also nicht befürchten daß Dir die Arduino-IDE mit ihren Timern dazwischenfunkt - sehr pflegeleicht!
Wenn das funktioniert baust Du anstelle des Schalters Deine eigentliche Hardware in den Code ein.

Um das Ganze zu verstehen empfehle ich die Website von Nick Gammon (http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123). Ich selbst habe nur ein einziges Arduino-Projekt mit einem einzigen (Timer-)Interrupt realisiert (bin also wirklich nicht DER Programmier-Freak...:)), aber er hat mir immerhin dies ermöglicht - und das recht schnell. Im Speziellen interessant für Dich ist seine Abhandlung über Interrupts (http://www.gammon.com.au/interrupts). Die versucht zwar allgemeingültig zu erklären, aber glücklicherweise ist seine Testplattform der Uno.

Bevor Du anfängst solltest Du erstmal den gesamten Thread durchlesen und *halbwegs* verstehen. Die Abschnitte über Timer kannst Du guten Gewissens auslassen. Das allererste Code-Beispiel ("Example of interrupts") kommt Deiner ersten Aufgabe schon ziemlich nahe.
Dann erst versuchen selbst was zu basteln.

wendtdir
07.08.2015, 21:40
Danke. Ich werde mir das durchlesen.

Irgendwie ist es gerade so, dass ich mein gebautes "Gerät" nämlich gerade nicht auseinander nehmen möchte, bevor es nicht wirklich so funktioniert, wie ich es mir vorstelle :). Dann werde ich es aufzeichnen und erst dann mit den anderen Sachen weitermachen, die ich noch offen habe.

wendtdir
08.08.2015, 22:03
Das mit den Interrupts ist ein echt haariges Thema. Scheint aber die Lösung zu sein. Ich habe einen Interrupt eingebaut und seit dem funktioniert auch die IF Bedingung. Natürlich kommt jetzt wieder ein ABER. Wenn die Unterbrechung durch eine Bewegung verursacht wird, leuchtet meine LED und mein Text wird ausgegeben. Leider wird dann die Routine nicht abgebrochen. Ich denke, es liegt an dem Befehl
if (irrecv.decode(&results)).

Mein Interrupt lässt solange die LED leuchten und den Text erscheinen, bis wieder ein Befehlt über die IR-Schnittstelle gesendet wird, er soll aber automatisch zurückkehren nach z.B. 10 Sekunden und die Temperatur wieder anzeigen. Was auch interessant ist, wenn ich einfach nur den zweiten Case durch Druck auf die zugehörige Taste auslöse, wird mir die Temperatur angezeigt, aber ich kann den ersten Case nicht mehr starten.

So ist momentan mein Code aufgebaut:


#include <LiquidCrystal.h>
#include <IRremote.h>
int receiverpin = 3;
IRrecv irrecv(receiverpin);
decode_results results;

LiquidCrystal lcd(4,5,6,7,8,9);
float sensor = 0;
float celsius = 0;
float voltage = 0;
volatile int bewegungsstatus=0;
volatile int bewegung=2;
int ledg=11;
int ledr=12;
//unsigned long zeit=millis();



void setup() {

lcd.begin(16,2);
lcd.clear();
pinMode(bewegung, INPUT);
pinMode(ledg, OUTPUT);
pinMode(ledr, OUTPUT);
irrecv.enableIRIn();
Serial.begin(9600);
attachInterrupt(0, sehdich,CHANGE);
}

void sehdich()
{

bewegungsstatus=digitalRead(bewegung);
if (bewegungsstatus==HIGH)
{
lcd.setCursor(0,0);
lcd.print("Eindringling");
lcd.setCursor(0,1);
lcd.print("erkannt");
digitalWrite(ledr, HIGH);
digitalWrite(ledg, LOW);
Serial.println("1");
}
}

void translateIR()
{
switch(results.value)

{
case 16724175:

{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);
Serial.println("2");


}

break;

case 16743045:


lcd.clear();
noInterrupts();
lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
digitalWrite(ledr, LOW);
digitalWrite(ledg, HIGH);
Serial.println("3");

break;
}
}

void berechnung()
{
sensor = analogRead(0);
voltage = (sensor*5000)/1024;
voltage = voltage - 500;
celsius = voltage/10;
}

void loop()
{

if (irrecv.decode(&results))
{
irrecv.resume();
berechnung();
translateIR();


}
}


Wäre die Lösung etwas wie eine Art Goto last Case? Das ich in der ISR einen Befehle einbaue wie Goto Sprungmarke Case 16724175?
Warum kann ich, wenn ich den zweiten Case "Temp-Messung Standalone" aufrufe nicht erneute den erweiterten Fall mit Bewegungssensor aufrufen? Void Loop () müsste doch immer wieder durchlaufen werden, somit müsste die Abfrage nach einem IR Code immer erfolgen und die Funktion translateIR ebenfalls immer durchgeführt werden.

HeXPloreR
09.08.2015, 10:25
Hallo,

du könntest den Speicher der Variable results.value auf eine andere neue Variable übergeben, diese im Switch prüfen und nach Prüfung zurücksetzen. Zusätzlich dazu könntest du einen default-Zweig im Switch setzen der anzeigt wenn nichts oder nichts passnedes empfangen wird.

Ob das jetzt unbedingt aber das gennate Problem umschifft kann ich nicht sagen.

Sisor
09.08.2015, 10:34
Hi wendtdir,

ich hatte grade mal wieder Lust auf C++ schreiben. Daher hab ich deinen Code mal umgebaut und ein paar grundlegende Programmierregeln umgesetzt.
Was ich da gemacht habe, und warum? - Das darfst du dir gerne selber erarbeiten;).

#include <LiquidCrystal.h>
#include <IRremote.h>

const byte ANALOG_PIN_TEMP = 0;
const byte PIN_MOVEMENT = 2;
const byte PIN_RECEIVER = 3;
const byte PIN_LED_GREEN = 11;
const byte PIN_LED_RED = 12;
enum {CODE_TASTE1 = 16724175,
CODE_TASTE2 = 16743045};
const int MESSAGE_EINDRINGLING_DURATION = 3000;
LiquidCrystal lcd(4,5,6,7,8,9);
IRrecv irrecv(PIN_RECEIVER);


volatile boolean movementDetected = false;


void setup() {
lcd.begin(16,2);
lcd.clear();
pinMode(PIN_MOVEMENT, INPUT);
pinMode(PIN_LED_GREEN, OUTPUT);
pinMode(PIN_LED_RED, OUTPUT);
digitalWrite(PIN_LED_RED, LOW);
digitalWrite(PIN_LED_GREEN, LOW);
irrecv.enableIRIn();
Serial.begin(9600);
Serial.println("Start");
}

void ISR_OnMovement() {
movementDetected = true;
}

void printEindringling() {
lcd.setCursor(0, 0);
lcd.print("Eindringling");
lcd.setCursor(0, 1);
lcd.print("erkannt");
}

void printTemperatur(float celsius) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperatur:");
lcd.setCursor(0,1);
lcd.print(celsius,0);
lcd.setCursor(3,1);
lcd.print("Grad");
}

float analog2celsius(float analogValue) {
float voltage = analogValue*5000/1023 - 500;
float celsius = voltage / 10;
return celsius;
}

void loop() {
decode_results results;
static unsigned long detectionMoment = -MESSAGE_EINDRINGLING_DURATION-1;

if (movementDetected) {
digitalWrite(PIN_LED_RED, HIGH);
printEindringling();
Serial.println("1");
detectionMoment = millis();
movementDetected = false;
}

if (irrecv.decode(&results)) {
irrecv.resume();
switch(results.value) {
case CODE_TASTE1:
digitalWrite(PIN_LED_GREEN, HIGH);
attachInterrupt(0, ISR_OnMovement, RISING);
Serial.println("2");
break;
case CODE_TASTE2:
digitalWrite(PIN_LED_GREEN, LOW);
detachInterrupt(0);
Serial.println("3");
break;
}
}

boolean messageTimeExpired = millis()-detectionMoment > MESSAGE_EINDRINGLING_DURATION;
if (messageTimeExpired ) {
digitalWrite(PIN_LED_RED, LOW);
float celsius = analog2celsius(analogRead(ANALOG_PIN_TEMP));
printTemperatur(celsius);
detectionMoment = millis()-MESSAGE_EINDRINGLING_DURATION-1; // Meldung nach 49 Tagen vermeiden
}
}

wendtdir
10.08.2015, 16:24
Erstmal ein Danke an alle, für die Hilfe. Ich muss wirklich sagen, dass bei allen Problemen, die ich bis jetzt hatte hier immer geholfen wurde, anders als in anderen Foren.

Zu dem Sketch von Sisor, ich habe halbwegs versucht das nachzuvollziehen, da ich bisher wenig Erfahrung habe mit C und noch weniger mit C++ ist es natürlich für mich nur teilweise möglich, denn ich versuche mich da mit einem Buch ein wenig einzuarbeiten.

Dein Sketch funktioniert ohne Probleme, etwas musste ich je doch verändern, die Temperaturanzeige war nicht zu lesen, da sie im Loop immer wieder schnell hintereinander ausgegeben wurde. Jetzt läuft es so, dass sie angezeigt wird. Danke also nochmals für die Arbeit.

Für mich bleibt jetzt nur noch eins, ich werde meine Schaltung abspeichern zusammen mit dem Code und weiter mit dem Workshop fortfahren.

Gab es nicht mal die Möglichkeit ein Thema als "Erledigt" zu markieren?