Arduino Sensorablesung unterbrechen

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
mc-gl
Junior Member
**

Beiträge: 16
Registriert seit: Dec 2016
Bewertung: 0
#1
14.12.2016, 01:06

Hallo zusammen

Ich habe ein kleines Problemchen, vieleicht könnt ihr mir helfen.

Ich steuere mittels eines Raspi meinen arduino nano, der jenach Komando etwas anderes machen soll.

nun zum Problem:
Einer der Befehle ist eine Funktion zu starten welche laufend sensor werte ausliest und sendet. Dies habe ich über eine whileschleife gelöst. Jedoch soll, beim senden des nächsten Komandos, die while schleife abgebrochen werden u der nächste zutreffende Befehl ausgeführt werden.

habt ihr eine Idee wie das gehe könnte?
zum Empfangen nutze ich übrigens serialEvent(). Die while scheint das Event jedoch nicht zu interessieren.

Vielen Dank schon Mal im Voraus.

Gruss GL
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 735
Registriert seit: Apr 2014
Bewertung: 5
#2
14.12.2016, 13:14

Hallo mc-gl,

das klingt interessant!
Mal sehen, ob ich das richtig verstanden haben: Dein Raspi hat die Kontrolle über den Nano. Du schickst Befehle an den Nano, der diese in einer Dauerschleife empfängt. Eine der Befehle ist "Lese Sensorwerte aus". Der Nano verzweigt daraufhin in eine While-Schleife, die Sensorwerte ausließt.

Aber nun steckt der Nano in einer Endlosschleife fest und nimmt keine Befehle vom Raspi mehr an. --> Sackgasse.

Habe ich das so richtig dargestellt?

Wenn ja, dann würde ich vorschlagen, die Vorgehensweise ein wenig abzuwandeln und vielleicht einen Interrupt zu nutzen. Allerdings wäre es hilfreich, wenn Du berichten würdest, wie Raspi und Nano miteinander verbunden sind. Über die serielle Schnittstelle?

Und könntest Du Dein Programm, welches auf dem Nano läuft mal posten? Keine Angst! Niemand wird hier Deinen Programmierstil kritisieren, es fällt halt wesentlich leichter, Tipps zu geben, wenn man die Ausgangslage kennt.

Gruß
Uni
-----

Klopapier beidseitig verwenden und der Erfolg liegt auf der Hand!
Zitieren
mc-gl
Junior Member
**

Beiträge: 16
Registriert seit: Dec 2016
Bewertung: 0
#3
14.12.2016, 21:25

Hi Uni

Muss sagen bin gerade überascht. Normalerweise wird man ja in einem Forum nicht so freundlich beraten. Da fühlt man sich direkt wohl Smile


Du hast es richtig verstanden Smile Ich dachte allerdings serialEvent ist ein interupt?
Der nano hängt am USB. Wie kann ich denn jetzt den Interupt über usb auslösen?

hier mein Code:

Code:
#include <SPI.h>
#include <MFRC522.h>

//Variablen Laserschranke
const float ref = 3.3;  // Referenzspannung
const int sen = 0; // sensor an analogpin 0
static boolean newcmd;

int out = 5; // LED an pin 13 (Zeigt an ob Lichtschranke betätigt ist)

//Variablen Zähler
int TorR =0;

//Variablen Commando
const String myID = "Red :";

//Variablen Tagleser
MFRC522 mfrc522(10, 9);


//_______________________________________________________________________________________
void setup()
{
    Serial.begin(9600);
    pinMode(out, OUTPUT); // LED als outpup
    SPI.begin();
    mfrc522.PCD_Init();
    pinMode(6, OUTPUT);
    newcmd =false;
}


//________________________________________________________________________________________
void loop(){
  

}


void serialEvent(){
  newcmd=true;
    // ======= Kommando auslesen
   while(Serial.available() > 0){        // So lange etwas empfangen wird, durchlaufe die Schleife.
    int val = Serial.read();
      switch (val) {
        case 'B':
          ReadTag();            
          break;

        case 'P':
          play();
          break;
      }
    }
  
  
  }

void play(){
  newcmd = false;
  while (!newcmd){
    Serial.println("playing");
    digitalWrite(out,HIGH);
    int var = analogRead(sen);  // Wert vom Sensor einlesen
    float v = (var / 1023.0) * ref;  //Berechnen
    Serial.println(v);
    if (v> 3.0) {
      digitalWrite(out,LOW);
      TorR ++;
      digitalWrite(out,HIGH);
      Serial.print(myID);
      Serial.print("Tor ;;");
      Serial.println(TorR);
    }
  }
  
}



void ReadTag(){
   boolean readC = false;
       MFRC522::MIFARE_Key key;
            while(!readC){
              //---------- leerer Durchgang
              if ( mfrc522.PICC_IsNewCardPresent()){
                if (  mfrc522.PICC_ReadCardSerial()){  
                  for (byte i = 0; i < mfrc522.uid.size; i++) {                  
                  }
                      
                }
              }
                //---------- richtiger Durchgang
                    
                if ( mfrc522.PICC_IsNewCardPresent()){                
                   if (  mfrc522.PICC_ReadCardSerial()){  
                      
                    //Buzzer
                    tone(6, 800);
                    delay(250);
                    noTone(6);
                    Serial.print(myID);
                    Serial.print("Tag ;;");
                    for (byte i = 0; i < mfrc522.uid.size; i++) {                  
                      Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
                      Serial.print(mfrc522.uid.uidByte[i], HEX);
                    }
                    Serial.print('\n');
                    delay(250);
                    tone(6, 1000);
                    delay(250);
                    noTone(6);
                    readC = true;        
                  }
                  //if ( ! mfrc522.PICC_ReadCardSerial()) {
                  //return;
                }                          
          }  
  }
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 735
Registriert seit: Apr 2014
Bewertung: 5
#4
15.12.2016, 12:15

Hi mc-gl,

ja ja... die unfreundliche Art in anderen Foren kenne ich selbst nur allzu gut. Sehr schade, wenn sich die Mitglieder dort für etwas Besseres halten. Die haben auch mal klein angefangen und haben vermutlich diesselben Fragen gehabt, wie wir auch.

Hier im Forum wollen wir einen anderen Umgang pflegen und lediglich mit Spaß und Erfolg unser Hobby bestreiten :-)

So, aber jetzt zu Deinem Anliegen.

Auf den ersten Blick sieht der Code gut aus. Du reagierst im serialEvent-Interrupt auf die serielle Schnittstelle. Du prüfst, was angekommen ist und reagierst darauf. Und am Ende wird serialEvent wieder verlassen (sobald der Puffer leer ist, also keine Zeichen mehr empfangen werden).

Was mir auffällt, ist dass die Variable "val" vom Typ Int ist. Du fragst aber dann ab, ob val == 'B' oder val == 'P' ist. Ich würde meinen, dass val deshalb vom Typ Char oder String sein muss.

Tja, und wie wird der Interrupt ausgelöst? Eigentlich ja durch Aktivitäten auf der seriellen Schnittstelle. Also entweder kommt nix beim Nano an, oder es kommt etwas an, und der Nano hängt sich dann auf.

Hast Du mal versucht, ob Du eine LED an- bzw. ausschalten kannst, wenn Du etwas über die serielle Schnittstelle eingibst. Also in Deiner serialEvent-Routine einen Pin togglen.

Gruß
Uni
-----

Klopapier beidseitig verwenden und der Erfolg liegt auf der Hand!
Zitieren
mc-gl
Junior Member
**

Beiträge: 16
Registriert seit: Dec 2016
Bewertung: 0
#5
15.12.2016, 13:51

Hallo Uni

Vielen Dank Uni, für deine geschätzten Inputs Smile

Das mit dem Umgang finde ich super.Smile bin ich dafür! Smile

Ja das mit der val passt mir auch nicht so ganz. Das Problem dahinter ist aber, dass das Serial.read() nur Zahlen und keine Buchstaben liefert. Die Abfrage ist somit eigentlich so erklärt.
"Ist der gelesene Wert gleich gross wie der Wert von einem grossen B?"
Oder hast du da eine besser Lösung? Habe mir die Finger bereits wund gesucht, um dies Reads als String zu erhalten. die Lösungen haben bei mir aber entweder nicht funktioniert, oder nicht gefallen. daher war ich froh, dass diese Variante funktioniert und hab mir gedacht "Don't touch a running system!"

Ich habe irgendwo noch gelesen dass serialEvent() kein richtige Interrupt ist. Stimmt das? gibt es denn eine andere Lösung?
Ob es ankommt weiss ich nicht genau. Müsste aber zwar, da die vorherigen Kommandos ja auch bearbeitet werden, da sonst gar nichts passieren würde (mache es übrigens noch über die Konsole, da ich auf der raspi Seite das Script auf dieser Grundlage erst aufbaue).
Ich stelle einfach fest dass die Consolenausgabe nicht stoppt. Die Werte der Tore werden weiter gesendet. und der RFIDleser reagiert nicht trotz des Befehls einen Tag zu lesen.
Könnte es heute Abend einmal mit der LED ausprobieren, verspreche mir aber nicht allzu viel davon.

Gibt es eine andere Methode den Interrupt über die USB Schnittstelle auszulösen? habe bisher nur Lösungen gesehen welche auf einen Pin reagieren. Ausser ich würde den Pi zusätzlich noch über die GPIO's mit einem Pin verbinden, welche dem Arduino sagt: "Achtung es kommt ein Befehl" der Arduino resetet und den Befehl auslöst. Gefällt mir allerdings auch nicht.

Oder Gibt es eine andere Möglichkeit die Werte des Sensor aus zu lesen?

Ohhhh da kommt mir während dem schreiben eine Idee:
Ich könnte die Werte immer im loop auslesen und einfach über eine Variable welche durch das Kommando auf true oder false gesetzt wird ermitteln ob die Daten gesendet werden sollen oder nicht. Was meinst du?

Gruss GL
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 735
Registriert seit: Apr 2014
Bewertung: 5
#6
15.12.2016, 14:17

Hi,

wenn Du nichts anderes machst, als die Werte auszulesen und dann eine Aktion auszulesen, dann benötigst Du tatsächlich keinen Interrupt.
serialEvent ist tatrsächlich kein echter Interrupt. Keine Ahnung, wie die das in Arduino-C gelöst haben. Es gibt zwar ein paar AtMega's, die einen solchen Interruptvektor haben, jedoch der Atmega328 nach meinem Wissen nicht (Der Atmega162 hat sowas z.B.).

So, mal überlegen...

Wenn Du in Loop(){ } einfach die serielle Schnittstelle abfragst (mit Serial.Available() ), dann könntest Du dort in der Dauerschleife Dinge tun. Also eigentlich musst Du nur Deine Abfrage aus serialEvent in loop verlagern. Das könnte klappen. loop läuft ja sowieso endlos.

Gruß
Uni
-----

Klopapier beidseitig verwenden und der Erfolg liegt auf der Hand!
Zitieren
mc-gl
Junior Member
**

Beiträge: 16
Registriert seit: Dec 2016
Bewertung: 0
#7
16.12.2016, 00:22

Hi Uni

Es hat geklappt. Tatsächlich war es so, dass serialEvent() während die While am laufen war funktionsloswar. Somit konnte kein neues Komando empfangen werden. Ich habe es nun so gelöst, dass eine Variable bei Komando umgeschaltet wird, und die If abfrage im Loop besteht. Solange die Variable True ist wird die Lichschranke durch Loop ausgelesen. wechsel serialEvent die Variable wieder auf false, überspringt loop das auslesen.

Siehe Code

Code:
#include <SPI.h>
#include <MFRC522.h>

//Variablen Laserschranke
const float ref = 5;  // Referenzspannung
const int sen = 0; // sensor an analogpin 0
static boolean showTor;

int out = 5; // LED an pin 13 (Zeigt an ob Lichtscharanke betätigt ist)
//Variablen Zähler
int TorR =0;
int TorB=0;

//Variablen Commando
char c_inChar;   // Jedes empfangene Zeichen kommt kurzzeitig in diese Variable.
String s_input;  // In diesem String speichern wir dann unseren kompletten Text.
const String myID = "Red :";
//Variablen Tagleser
MFRC522 mfrc522(10, 9);


//_______________________________________________________________________________________
void setup()
{
    Serial.begin(9600);
    pinMode(out, OUTPUT); // LED als outpup
    SPI.begin();
    mfrc522.PCD_Init();
    pinMode(6, OUTPUT);
    showTor=false;
}


//________________________________________________________________________________________
void loop(){
  if(showTor){
    play();
  }
}


//________________________________________________________________________________________
void serialEvent(){
   //  ======= Kommando auslesen
   while(Serial.available() > 0){
    int val = Serial.read();
      switch (val) {
        case 'B':
          showTor=false;
          ReadTag();            
          break;

        case 'P':
          TorR =0;
          showTor=true;
          break;
      }
    }
  }



//________________________________________________________________________________________
void play(){
  digitalWrite(out,HIGH);
  int var = analogRead(sen);  // Wert vom Sensor einlesen
  float v = (var / 1023.0) * ref;  //Berechnen
  if (v< 1.0) {
    digitalWrite(out,LOW);
    TorR ++;
    delay(1000);
    digitalWrite(out,HIGH);
    Serial.print(myID);
    Serial.print("Tor ;;");
    Serial.println(TorR);
    
  }  
}



//________________________________________________________________________________________
void ReadTag(){
   boolean readC = false;
       MFRC522::MIFARE_Key key;
            while(!readC){
              
              //---------- leerer Durchgang
              if ( mfrc522.PICC_IsNewCardPresent()){
                if (  mfrc522.PICC_ReadCardSerial()){  
                  for (byte i = 0; i < mfrc522.uid.size; i++) {                  
                  }
                      
                }
              }
              
                //---------- richtiger Durchgang  
                if ( mfrc522.PICC_IsNewCardPresent()){                
                   if (  mfrc522.PICC_ReadCardSerial()){  
                      
                    //Buzzer
                    tone(6, 800);
                    delay(250);
                    noTone(6);
                    Serial.print(myID);
                    Serial.print("Tag ;;");
                    for (byte i = 0; i < mfrc522.uid.size; i++) {                  
                      Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
                      Serial.print(mfrc522.uid.uidByte[i], HEX);
                    }
                    Serial.print('\n');
                    delay(250);
                    tone(6, 1000);
                    delay(250);
                    noTone(6);
                    readC = true;        
                  }
                }                          
          }  
  }


Vielen Dank Smile

Gruss GL
Zitieren


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste