denkfehler??

hallo zusammen,
ich habe ich ein problem über das ich schon so lange nachdenke, dass ich bestimmt einen denkfehler mache weil ich dafür keine lösung finde...

und zwar habe ich einen motor, der ein objekt (geführt auf einer schiene) bewegt. dieses objekt soll an bestimmten stellen dieser schiene anhalten. das habe ich durch kleine taster gelöst die an der schiene angebracht sind und bei berührung mit dem objekt dieses stoppen. ist das objekt angekommen soll es da zwei kleine befehle ausführen und zum nächsten taster weitefahren...
hört sich einfach an...ist es aber irgendwie für mich nicht...
weil wenn der stopptaster gedrückt ist durch das objekt ist er ja gedrückt...das bedeutet das objekt bleibt da stehen und führt bis zum umkippen diese zwei befehle aus...negiere ich nun diesen taster fährt das objekt dann sofort weiter?
was würde sich am besten eignen? if,case oder for? ich hab ja eigentlich case bevorzugt bin mir nun aber nicht mehr sicher...
hab mich da in meinen überlegungen irgendwie verknotet und sehe nun wahrscheinlich den wald vor lauter bäumen nicht mehr...
grüße
pling

pling:
und zwar habe ich einen motor, der ein objekt (geführt auf einer schiene) bewegt. dieses objekt soll an bestimmten stellen dieser schiene anhalten. das habe ich durch kleine taster gelöst die an der schiene angebracht sind und bei berührung mit dem objekt dieses stoppen.

"Bei Berührung"? Macht man sowas nicht besser und zuverlässiger berührungslos mit Reedkontakt auf der Schiene und einem Magneten am bewegten Objekt?

pling:
ist das objekt angekommen soll es da zwei kleine befehle ausführen und zum nächsten taster weitefahren...
hört sich einfach an...ist es aber irgendwie für mich nicht...
weil wenn der stopptaster gedrückt ist durch das objekt ist er ja gedrückt...das bedeutet das objekt bleibt da stehen und führt bis zum umkippen diese zwei befehle aus...negiere ich nun diesen taster fährt das objekt dann sofort weiter?
was würde sich am besten eignen? if,case oder for? ich hab ja eigentlich case bevorzugt bin mir nun aber nicht mehr sicher...
hab mich da in meinen überlegungen irgendwie verknotet und sehe nun wahrscheinlich den wald vor lauter bäumen nicht mehr...

Im Prinzip hast Du mehrere Teilstrecken und am Ende jeder Teilstrecke sitzt ein Schalter, der etwas auslösen soll.

Dann verfolgst Du einfach mit, auf welcher Teilstrecke Dein Objekt gerade ist und achtest nur auf den Schalter, der als nächstes drankommt. Also einen "fahrStatus" auf den jeweiligen Streckenabschnitt setzen, je nach fahrStatus dann auf den Schalter reagieren, und nach Abarbeitung den fahrStatus auf den nächsten Streckenabschnitt setzen.

Beispielcode:

enum {STRECKE1, STRECKE2, STRECKE3, FAHRTENDE};

#define FAHRSTROM 4
#define FAHREN HIGH
#define ANHALTEN LOW

// Pins für die Stoptaster
enum {STOP1=5, STOP2=6, STOP3=7};

byte fahrStatus=STRECKE1;

void setup() {
  Serial.begin(9600);
  pinMode(FAHRSTROM, OUTPUT);
  digitalWrite(FAHRSTROM, FAHREN);
}


void loop() 
{
  switch (fahrStatus)
  {
    case STRECKE1: if (digitalRead(STOP1)==HIGH)
                   {
                     digitalWrite(FAHRSTROM, ANHALTEN);
                     // Zwei kleine Befehle ausführen
                     fahrStatus=STRECKE2;
                     digitalWrite(FAHRSTROM, FAHREN);
                   }  
                   break;
    case STRECKE2: if (digitalRead(STOP2)==HIGH)
                   {
                     digitalWrite(FAHRSTROM, ANHALTEN);
                     // Zwei kleine Befehle ausführen
                     fahrStatus=STRECKE3;
                     digitalWrite(FAHRSTROM, FAHREN);
                   }  
                   break;
    case STRECKE3: if (digitalRead(STOP3)==HIGH)
                   {
                     digitalWrite(FAHRSTROM, ANHALTEN);
                     // Zwei kleine Befehle ausführen
                     fahrStatus=FAHRTENDE;
                     // Und am Ende gar nicht erst wieder losfahren
                   }  
                   break;
    case FAHRTENDE: ; // was auch immer am Fahrtende passieren soll
    default:       ; // der Fall ist in diesem Sketch nicht vorgesehen
  }
}

Das hängt im allgemeinen natürlich auch davon ab, wie du dein Programm dazu aufgebaut hast.
Du wirst ja den Taster nicht als "mechanische" Unterbrechung der Motorsteuerung nehmen, sondern (fortlaufend oder besser durch einen Interrupt) nur seinen seinen Status kontrollieren.
Eine "if" Abfrage wäre hier schon das richtige, um festzustellen, das der Motor stoppen soll.
Danach lässt dein Programm eben die anderen Arbeiten ausführen und befiehlt "Motor weiter".

Also so etwas in der Art wie:
Motor starten, Status Motor gestartet = wahr
"(Nur) Wenn (Status Motor gestartet) und (Taster geschlossen), dann (Motor stoppen und Status Motor gestartet = falsch

EDITH:
Da war jemand schneller und ausführlicher ... :smiley:

jurs:
"Bei Berührung"? Macht man sowas nicht besser und zuverlässiger berührungslos mit Reedkontakt auf der Schiene und einem Magneten am bewegten Objekt?

Braucht man nicht unbedingt. Wenn das mechanisch richtig gemacht ist geht es auch im Vorbeifahren. Vor allem wenn man langsam fährt. Es gibt z.B. Taster, die eine Art Metal-Fahne haben. Die kann man mit einem Stift/Stab am Objekt betätigen. Oder auch direkt.

Oder wenn ich mit Google-Image suche, haben viele Endschalter eine Rolle:

Wenn man damit von Links drauf fährt wird er ausgelöst und springt wieder zurück wenn das Objekt vorbei ist.

vielen dank für die hilfe...
ich habe mir den sketch angeguckt und genau da hat es bei mir "geklemmt", genialer gedanke mit der streckennummerierung, wäre ich mangels genialität nie drauf gekommen.
ich habe also den teil des sketches übernommen und nur leicht abgeändert:

void loop() 
{
  switch (fahrStatus)
  {
    case STRECKE1: if (digitalRead(TASTER1)==LOW)
                   {
                     digitalWrite(MIN_SIGNAL, ANHALTEN);
                     digitalWrite(HOCH);      
...   }}}

leider erhalte ich da jetzt die fehlermeldung:
In function 'void loop()':
sketch_jun19b:77: error: expected primary-expression before '{' token

find ich ziemlich komisch, weil ich eigentlich nix geändert habe was die klammern betrifft.
kann mir jemand nochmal einen kleinen tipp geben? hab das i-net schon gefragt, aber das konnte mir nicht wirklich weiterhelfen...

pling:
find ich ziemlich komisch, weil ich eigentlich nix geändert habe was die klammern betrifft.

Der Funktionsaufruf digitalWrite(HOCH); ist fehlerhaft (benötigt zwei Parameter).

mmh, das habe ich jetzt behoben, aber leider bleibt die fehlermeldung wie gehabt...

Denke mal man müsste den ganzen Code sehen um den Fehler zu finden.

Sijjim:
Denke mal man müsste den ganzen Code sehen um den Fehler zu finden.

Bin da uneingeschränkt einverstanden. :wink: :wink:
Grüße Uwe

sorry, war lange abgetaucht, aber jetzt kann es wieder losgehen...
also hier der code:

#include <Servo.h>

enum {STRECKE1, STRECKE2, STRECKE3, STRECKE4, STRECKE5,STRECKE6, FAHRTENDE};

#define MAX_SIGNAL 85
#define MIN_SIGNAL 70
#define FAHRENLINKS {transistorl = HIGH, transistorr = LOW}
#define FAHRENRECHTS {transistorl = LOW, transistorr = HIGH}
#define ANHALTEN {transistorl = LOW, transistorr = LOW}
#define HOCH {RELAY = LOW, LED = HIGH}
#define RUNTER {RELAY = HIGH, LED = HIGH}
#define LED 23
#define RELAY 22




Servo servo;


const int transistorl = 24;
const int transistorr = 25;

int SelektButton = 36;

byte fahrStatus=STRECKE1;
byte SelektButtonState=0;


enum {TASTER = 26,// schieber start
TASTER1 = 27,//portionierer 1
TASTER2 = 28,//portionierer 2
TASTER3 = 29,//portionierer 3
TASTER4 = 30,//portionierer 4
TASTER5 = 31,//portionierer 5
TASTER6 = 32,//portionierer 6
TASTER7 = 33,//schieber ende
TASTER8 = 34,//drücker unten
TASTER9 = 35};//drücker oben




void setup(){

  servo.attach(3);
  pinMode(transistorl, OUTPUT);
  pinMode(transistorr, OUTPUT);

  pinMode(TASTER, INPUT);
  pinMode(TASTER1, INPUT);
  pinMode(TASTER2, INPUT);
  pinMode(TASTER3, INPUT);
  pinMode(TASTER4, INPUT);
  pinMode(TASTER5, INPUT);
  pinMode(TASTER6, INPUT);
  pinMode(TASTER7, INPUT);
  pinMode(TASTER8, INPUT);
  pinMode(TASTER9, INPUT);

  pinMode(LED, OUTPUT);               // led steht hier für ein anderes relay
  pinMode(RELAY, OUTPUT);          // 


  servo.write(MIN_SIGNAL);
}
  



  void loop() 
{
  switch (fahrStatus)
  {
    case STRECKE1: if (digitalRead(TASTER1)==LOW)
                   {
                     digitalWrite(MIN_SIGNAL, ANHALTEN);
                     digitalWrite(HOCH, MIN-_SIGNAL);           // turn LED O
                    delay(5000);
                    digitalWrite(RUNTER, MIN_SIGNAL);           // turn LED ON
                     fahrStatus=STRECKE2;
                     digitalWrite(MAX_SIGNAL, FAHRENLINKS);
                   }  
                   break;
    case STRECKE2: if (digitalRead(TASTER2)==LOW)
                   {
                     digitalWrite(MIN_SIGNAL, ANHALTEN);
                     digitalWrite(HOCH, MIN_SIGNAL);           // turn LED O
                    delay(5000);
                    digitalWrite(RUNTER,MIN_SIGNAL);           // turn LED ON
                     fahrStatus=STRECKE3;
                     digitalWrite(MAX_SIGNAL, FAHRENLINKS);
                   }  
                   break;
    case STRECKE3: if (digitalRead(TASTER3)==LOW)
                   {
                     digitalWrite(MIN_SIGNAL, ANHALTEN);
                     digitalWrite(HOCH, MIN_SIGNAL);           // turn LED O
                    delay(5000);
                    digitalWrite(RUNTER, MIN_SIGNAL);           // turn LED ON
                     fahrStatus=FAHRTENDE;
                     // Und am Ende gar nicht erst wieder losfahren
                   }  
                   break;
    case FAHRTENDE: ; // 
    default:       ; // 
  }
}

Du schreibst oben:

#define FAHRENLINKS {transistorl = HIGH, transistorr = LOW}

und unten:

digitalWrite(MAX_SIGNAL, FAHRENLINKS);

Das funktioniert so nicht!

Und da der Compiler überlicherweise den Konstantenname mit dem im #define festgelegten Inhalt ersetzt, hast du dann unten nach der Kompilierung stehen:

digitalWrite(MAX_SIGNAL,  {transistorl = HIGH, transistorr = LOW});

Das geht nicht, logisch!

#defines sind gefährlich! eben weil sie solche Freiheiten erlauben und nichts überprüft wird.
besser ist immer ein const, weil hier die Compiler prüfungen zuschlagen. http://arduino.cc/en/Reference/Const

Ich mache mir bei solchen Aufgaben immer externe funktionen auserhalb der loop.

  1. Macht es das Programm übersichtlicher
  2. Exterene Aktionen sind dadruch ausgelagert und nicht in der eigntlichen Logik.

Hier könnte man ja drei Funktionen schrieben

void FAHRENLINKS(){
digitalWrite(transistorl,HIGH);
digitalWrite(transistorr,LOW);
}

void FAHRENRECHTS(){
digitalWrite(transistorl,LOW);
digitalWrite(transistorr,HIGH);
}

void ANHALTEN(){
digitalWrite(transistorl,LOW);
digitalWirte(transistorr,LOW);
}

 void loop(){
FAHRENRECHTS();  // ruft die Funtion FAHRENRECHTS auf und die Ausgänge werden entspechend       
gesetzt
etc...
}

Das gleiche noch für Hoch und Runter und kannst du die direkt in den Case strukturen aufrufen.

Nur sollte man die Funktionen nicht unbedingt groß schreiben. Klar geht das, aber es entspricht nicht den Konventionen.

Großbuchstaben sind für Konstanten, d.h. enums, const, defines, etc.

danke! ich werde da mal gucken und versuchen das umzusetzen.
könnte noch einen witz über frauen und logik anbringen, aber eigentlich bin da nicht so schlecht drin :smiley:
wird mich also noch einige nächte kosten...wenn euch noch was ein-/auffällt bitte immer raus damit.

hi,

könnte noch einen witz über frauen und logik anbringen, aber eigentlich bin da nicht so schlecht drin

mußt Dir nicht Dein zartes köpfchen zerbrechen, puppili, wir starken männer helfen ja gern.

gruß, stefan

In deinem loop steht im ersten case "MIN-_SIGNAL"
Wohl ein "Bindestrich" rein gerutscht :wink: