Andi10
February 27, 2018, 10:48am
1
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)
Andi10
February 27, 2018, 10:58am
2
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;
}
combie
February 27, 2018, 11:04am
3
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...
Andi10
February 27, 2018, 12:09pm
4
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
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
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.
Andi10
February 27, 2018, 12:18pm
6
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
uxomm
February 27, 2018, 12:51pm
8
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.
gsezz
February 28, 2018, 7:41am
10
Hängt denn das Funktionieren davon ab ob der Stecker im Notebook steckt, oder davon ob die Serielle Ausgabe auskommentiert ist?
Andi10
February 28, 2018, 6:02pm
11
Vieln Dank für die schnellen Antworten! Ich habe das Netzteil getauscht und tatsächlich funktioniert es jetzt
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.
Andi10
February 28, 2018, 6:09pm
12
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.
uxomm
February 28, 2018, 9:39pm
13
Super, dass es jetzt funktioniert!