Programm läuft nur mit seriellem Port

Hallo zusammen,

ich habe eine Garagenampel gebaut, die mit einem HC-Sr04 Ultraschallsensor die Entfernung zum Auto misst und eine Ampel(LED-Strips, WS2812) ansteuert.

Das ganze funktioniert sehr gut, wenn das Notebook am seriellen Port angeschlossen ist und einige Werte mitloggt. Betreibe ich das gleiche Programm ohne seriellen Port, springt die Statemachine ständig zwischen "CAR_COMING_YELLOW" und "CAR_COMING_RED" hin und her.

Hat jemand eine Idee woran das liegen könnte?

Distanzsensor_state_machine.ino (5.23 KB)

Hier nochmal direkt der Code:

#include "FastLED.h"


#include <stdio.h>





//LED-Strip


#define LED_PIN     2                // Digitaloutputpin für LED-Strip


#define NUM_LEDS    60               // Anzahl der LEDs


#define BRIGHTNESS  180              // Helligkeit der LEDs


#define LED_TYPE    WS2812


#define COLOR_ORDER GRB


CRGB leds[NUM_LEDS];





//Temperature sensor (LM35)


const int TEMPERATURE_ANALOG_IN = A7;





//Ultraschallpins


#define US_TRIGGER 5


#define US_ECHO 6 





//Statemachine


#define CAR_THERE 1


#define CAR_AWAY 2


#define CAR_COMING_GREEN 3


#define CAR_COMING_YELLOW 4


#define CAR_COMING_RED 5


#define HUMAN 6


#define FEHLER 7    //undefined state





//Distances


#define L0 2000      //Distance floor


#define L1_min 1300  //Distance "green"(with hysteresis)


#define L1_max 1900


#define L2_min  760  //Distance "yellow"(with hysteresis)


#define L2_max 1100


#define L3  510       //Distance "red"


#define LH_MAX  150  //Distance human





//Timeout in ms


#define T_OUT 8000





float temp = 20;  //temperature


unsigned int s = 0; //Distance to object


float c = 335;    //propagation velocity





unsigned short state = 7; //Statemachine


unsigned short state_old = 7;


unsigned long t_old = 0;  //Variable to save system time








void setup() {


  delay(3000);                    // power-up safety delay


  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); //LED-Strips


  FastLED.setBrightness(  BRIGHTNESS );


  


  ledtest();


  black();


  


  // Portinit ultrasonic sensor


  pinMode(US_ECHO,INPUT);                // Echo- Eingang


  pinMode(US_TRIGGER,OUTPUT);               // Trigger- Ausgang


  


  s = valueEditing(true);





  //set current state


  if(s<L3) {


    state = CAR_THERE;


  }


  else if(s>L0) {


    state = CAR_AWAY;


  }


  else {


    state = FEHLER;


  }


  


  Serial.begin(9600); 


  delay(20);


}





void loop() {


 


  s = getDistance();


  


  Serial.print("Entfernung: ");


  Serial.println(s);


  Serial.print("State: ");


  Serial.println(state);


  


  state_old = state;





  if(state_old != state) {


    led_setting();    //set LEDs


    t_old = millis(); //reset timeout


  }


}





void statemachine() {


    switch(state) {


    case CAR_THERE:


      if(s>L0) {


        state = CAR_AWAY;


      }


      else delay(5000);


      break;


    case CAR_AWAY:


      if(s<L1_max) {


        state = CAR_COMING_GREEN;


      }


      if(s<LH_MAX) {


        state = HUMAN;


      }


      break;


    case CAR_COMING_GREEN:


      if(s<L2_max) {


        state = CAR_COMING_YELLOW;


      }


      else if (timeout()) {


        state = FEHLER;


      }


      break;


    case CAR_COMING_YELLOW:


      if(s<L3) {


        state = CAR_COMING_RED;


      }


      else if(s>L1_min) {


        state = CAR_COMING_GREEN;


      } 


      else if (timeout()) {


        state = FEHLER;


      }


      break;


    case CAR_COMING_RED:


      if(timeout()) {


        state = CAR_THERE;


      }


      else if(s>L2_min) {


        state = CAR_COMING_YELLOW;


      }


      break ;  


     case HUMAN:


      if(s>L0) {


        state = CAR_AWAY;


      }


      break;


     case FEHLER:


      if(s<L3) {


        state = CAR_THERE;


      }


      else if(s>L0) {


        state = CAR_AWAY;


      }


      break;


  }


}





//Measure several times and return average


unsigned int getDistance() {


  int sSum=0;


  int distance = 0;


  for(int i=0;i<7;i++) {


    do {


        if(state == CAR_COMING_GREEN || state == CAR_COMING_YELLOW) {


          delay(30);


        }


        else {


          delay(80);


        }


        distance = valueEditing(state==CAR_THERE);


    }while(distance>2400);


    sSum +=distance;


  } 


   return sSum/7;


}





//mesure temperature and return distance of object in mm


int valueEditing(boolean temperature) {


  if(temperature) {


    temp = analogRead(TEMPERATURE_ANALOG_IN);


    temp = (temp*500.0)/1024.0;    


    c = 331.5+(0.6*temp);


  }


  digitalWrite(US_TRIGGER,LOW);            // Trigger ultrasonic sensor


  delayMicroseconds(3);


  digitalWrite(US_TRIGGER,HIGH);


  delayMicroseconds(10);


  digitalWrite(US_TRIGGER,LOW);


  long t = pulseIn(US_ECHO,HIGH);       // Read echo of ultrasonic sensor


  delay(5);


  return (t*c)/2000.0;                // calculate and return distance in mm


}





//Turn off all LEDs


void black() {


  int e = 30;


  for(int i = 29; i > -1; i--) {


    leds[i] = CRGB::Black;


    leds[e] = CRGB::Black;


    FastLED.show();


    e++;


    delay(15);


  }


}





//Set LEDs depending on statemachine


void led_setting() {


 switch(state) {


    case CAR_COMING_GREEN:


    {


     int e = 59;


     for(int i = 0; i < 30; i++) {


       leds[i] = CRGB::Green;


       leds[e] = CRGB::Green;


       FastLED.show();


       e--;


       delay (10);


     }


     break;


    }


   case CAR_COMING_YELLOW:


     for(int i = 0; i < 60; i++) leds[i] = CRGB::Yellow;


     FastLED.show();


     break;


   case CAR_COMING_RED: 


    for(int i = 0; i < 60; i++) leds[i] = CRGB::Red;


    FastLED.show(); 


    break;


   case HUMAN:


    black();


    break;


   default:


    black();


    break;


  }


}





//LED-test on system start


void ledtest() {


   for(int i = 0; i < 60; i++) leds[i] = CRGB::Green;


   FastLED.show();


   delay(1000);


   for(int i = 0; i < 60; i++) leds[i] = CRGB::Blue;


   FastLED.show();


   delay(1000);


   for(int i = 0; i < 60; i++) leds[i] = CRGB::Red;


   FastLED.show();


   delay(1000);


}





//Check whether there is a timeout


boolean timeout() {


    if((millis()-t_old)>T_OUT) return true;


    else return false;


}

Bei aller Liebe, aber hier gehst du zu weit:

state_old = state;
Dafür habe ich ja noch Verständnis!
Da sehe ich ja noch ein, dass das irgendwann mal gemacht werden muss.

Aber das unmittelbar darauffolgende:

if(state_old != state)
Kann niemals wahr werden.
Der ganze if Block ist ohne jede Funktion.

Das ganze funktioniert sehr gut,

Dass sich überhaupt ein Statuswechsel einstellt, halte ich für sehr unwahrscheinlich, da der Automat nichts tut. Nichts tun kann. Da er nie aufgerufen wird.

//---
Das sind jetzt nur die beiden Tretminen, welche mir sofort ins Auge gesprungen sind...

Moin,

sorry, ich hab die Statemachine gerade vor dem hochladen noch ausgelagert und vergessen aufzurufen, so ist das natürlich unsinnig da hast du Recht :wink:

die gehört da noch zwischen, habe ich jetzt eingefügt.

Hier nochmal direkt der Code:

#include "FastLED.h"
#include <stdio.h>

//LED-Strip
#define LED_PIN     2                // Digitaloutputpin für LED-Strip
#define NUM_LEDS    60               // Anzahl der LEDs
#define BRIGHTNESS  180              // Helligkeit der LEDs
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

//Temperature sensor (LM35)
const int TEMPERATURE_ANALOG_IN = A7;

//Ultraschallpins
#define US_TRIGGER 5
#define US_ECHO 6 

//Statemachine
#define CAR_THERE 1
#define CAR_AWAY 2
#define CAR_COMING_GREEN 3
#define CAR_COMING_YELLOW 4
#define CAR_COMING_RED 5
#define HUMAN 6
#define FEHLER 7    //undefined state

//Distances
#define L0 2000      //Distance floor
#define L1_min 1300  //Distance "green"(with hysteresis)
#define L1_max 1900
#define L2_min  760  //Distance "yellow"(with hysteresis)
#define L2_max 1100
#define L3  510       //Distance "red"
#define LH_MAX  150  //Distance human

//Timeout in ms
#define T_OUT 8000

float temp = 20;  //temperature
unsigned int s = 0; //Distance to object
float c = 335;    //propagation velocity

unsigned short state = 7; //Statemachine
unsigned short state_old = 7;
unsigned long t_old = 0;  //Variable to save system time


void setup() {
  delay(3000);                    // power-up safety delay
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); //LED-Strips
  FastLED.setBrightness(  BRIGHTNESS );
  
  ledtest();
  black();
  
  // Portinit ultrasonic sensor
  pinMode(US_ECHO,INPUT);                // Echo- Eingang
  pinMode(US_TRIGGER,OUTPUT);               // Trigger- Ausgang
  
  s = valueEditing(true);

  //set current state
  if(s<L3) {
    state = CAR_THERE;
  }
  else if(s>L0) {
    state = CAR_AWAY;
  }
  else {
    state = FEHLER;
  }
  
  Serial.begin(9600); 
  delay(20);
}

void loop() {
 
  s = getDistance();
  
  Serial.print("Entfernung: ");
  Serial.println(s);
  Serial.print("State: ");
  Serial.println(state);
  
  state_old = state;
  statemachine();
  if(state_old != state) {
    led_setting();    //set LEDs
    t_old = millis(); //reset timeout
  }
}

void statemachine() {
    switch(state) {
    case CAR_THERE:
      if(s>L0) {
        state = CAR_AWAY;
      }
      else delay(5000);
      break;
    case CAR_AWAY:
      if(s<L1_max) {
        state = CAR_COMING_GREEN;
      }
      if(s<LH_MAX) {
        state = HUMAN;
      }
      break;
    case CAR_COMING_GREEN:
      if(s<L2_max) {
        state = CAR_COMING_YELLOW;
      }
      else if (timeout()) {
        state = FEHLER;
      }
      break;
    case CAR_COMING_YELLOW:
      if(s<L3) {
        state = CAR_COMING_RED;
      }
      else if(s>L1_min) {
        state = CAR_COMING_GREEN;
      } 
      else if (timeout()) {
        state = FEHLER;
      }
      break;
    case CAR_COMING_RED:
      if(timeout()) {
        state = CAR_THERE;
      }
      else if(s>L2_min) {
        state = CAR_COMING_YELLOW;
      }
      break ;  
     case HUMAN:
      if(s>L0) {
        state = CAR_AWAY;
      }
      break;
     case FEHLER:
      if(s<L3) {
        state = CAR_THERE;
      }
      else if(s>L0) {
        state = CAR_AWAY;
      }
      break;
  }
}

//Measure several times and return average
unsigned int getDistance() {
  int sSum=0;
  int distance = 0;
  for(int i=0;i<7;i++) {
    do {
        if(state == CAR_COMING_GREEN || state == CAR_COMING_YELLOW) {
          delay(30);
        }
        else {
          delay(80);
        }
        distance = valueEditing(state==CAR_THERE);
    }while(distance>2400);
    sSum +=distance;
  } 
   return sSum/7;
}

//mesure temperature and return distance of object in mm
int valueEditing(boolean temperature) {
  if(temperature) {
    temp = analogRead(TEMPERATURE_ANALOG_IN);
    temp = (temp*500.0)/1024.0;    
    c = 331.5+(0.6*temp);
  }
  digitalWrite(US_TRIGGER,LOW);            // Trigger ultrasonic sensor
  delayMicroseconds(3);
  digitalWrite(US_TRIGGER,HIGH);
  delayMicroseconds(10);
  digitalWrite(US_TRIGGER,LOW);
  long t = pulseIn(US_ECHO,HIGH);       // Read echo of ultrasonic sensor
  delay(5);
  return (t*c)/2000.0;                // calculate and return distance in mm
}

//Turn off all LEDs
void black() {
  int e = 30;
  for(int i = 29; i > -1; i--) {
    leds[i] = CRGB::Black;
    leds[e] = CRGB::Black;
    FastLED.show();
    e++;
    delay(15);
  }
}

//Set LEDs depending on statemachine
void led_setting() {
 switch(state) {
    case CAR_COMING_GREEN:
    {
     int e = 59;
     for(int i = 0; i < 30; i++) {
       leds[i] = CRGB::Green;
       leds[e] = CRGB::Green;
       FastLED.show();
       e--;
       delay (10);
     }
     break;
    }
   case CAR_COMING_YELLOW:
     for(int i = 0; i < 60; i++) leds[i] = CRGB::Yellow;
     FastLED.show();
     break;
   case CAR_COMING_RED: 
    for(int i = 0; i < 60; i++) leds[i] = CRGB::Red;
    FastLED.show(); 
    break;
   case HUMAN:
    black();
    break;
   default:
    black();
    break;
  }
}

//LED-test on system start
void ledtest() {
   for(int i = 0; i < 60; i++) leds[i] = CRGB::Green;
   FastLED.show();
   delay(1000);
   for(int i = 0; i < 60; i++) leds[i] = CRGB::Blue;
   FastLED.show();
   delay(1000);
   for(int i = 0; i < 60; i++) leds[i] = CRGB::Red;
   FastLED.show();
   delay(1000);
}

//Check whether there is a timeout
boolean timeout() {
    if((millis()-t_old)>T_OUT) return true;
    else return false;
}

Andi10:
Moin,

sorry, ich hab die Statemachine ausgelagert und vergessen aufzurufen, so ist das natürlich unsinnig da hast du Recht :wink:

die gehört da noch zwischen, habe ich jetzt eingefügt.

Nur mal so am Rande.
Warum hast du denn die überflüssigen Leerzeilen in deinem Sketch ?
Die machen den Sketch total unlesbar.

HotSystems:
Nur mal so am Rande.
Warum hast du denn die überflüssigen Leerzeilen in deinem Sketch ?
Die machen den Sketch total unlesbar.

Ich weiß auch nicht wie das passiert ist, irgendwie beim einfügen... Jetzt sollte es passen :wink:

Andi10:
Ich weiß auch nicht wie das passiert ist, irgendwie beim einfügen... Jetzt sollte es passen :wink:

Ja, prima.....danke.

Andi10:
Das ganze funktioniert sehr gut, wenn das Notebook am seriellen Port angeschlossen ist und einige Werte mitloggt. Betreibe ich das gleiche Programm ohne seriellen Port, springt die Statemachine ständig zwischen "CAR_COMING_YELLOW" und "CAR_COMING_RED" hin und her.

Hat jemand eine Idee woran das liegen könnte?

Wie versorgst du die Schaltung mit Strom, vor allem, wenn kein Laptop angeschlossen ist?
Ich hatte in der Vergangenheit manchmal Probleme mit "unsauberer" Stromversorgung.
Schaltnetzteile produzieren mitunter ziemlich viele Störungen. Wenn du mit Ultraschall-Sensoren arbeitest könnte das zum Problem werden.
Ich würde versuchen den Fehler einzugrenzen:

  • Probiere es mit anderen Netzteilen
  • Probiere es mit Batterie (nur zum Testen für kurze Zeit)
  • ...

Als ersten Test würde ich es mit dem Notebook versuchen, mal eingeschaltet und mal ausgeschaltet. Wenn beides funktioniert, aber nicht wenn das Notebook ausgestöpselt wird, dann ist irgendwas mit der Masse faul.

Debuggen ohne PC ist natürlich schwierig. Du könntest z.B. eine LED Leiste (Bargraph) anschließen, und darauf den gemessenen Pegel anzeigen. Wenn die Werte so zappeln, daß sich das nicht erkennen läßt, kann ein Piezo verwendet werden, um Änderungen an einem Pin wiederzugeben. Oder die Werte auf ein LCD Display ausgeben, statt auf Serial.

Hängt denn das Funktionieren davon ab ob der Stecker im Notebook steckt, oder davon ob die Serielle Ausgabe auskommentiert ist?

Vieln Dank für die schnellen Antworten! Ich habe das Netzteil getauscht und tatsächlich funktioniert es jetzt :slight_smile:
Die Fehler sind immer bei gelben Licht aufgetreten, bei dem die LEDs am meisten Strom benötigen und somit auch das Netzteil am meisten belasten. Es ist also plausibel, dass dort mehr Störungen waren. Ich werde aber zur Sicherheit noch ein paar Kondensatoren am US-Modul und am Arduino spendieren. Wenn mir noch etwas auffällt melde ich mich nochmal.

gsezz:
Hängt denn das Funktionieren davon ab ob der Stecker im Notebook steckt, oder davon ob die Serielle Ausgabe auskommentiert ist?

Wenn der Stecker gesteckt ist funktioniert es. Ob die serielle Ausgabe auskommentiert ist oder nicht spielt keine Rolle.

Super, dass es jetzt funktioniert!