Forum: Mikrocontroller und Digitale Elektronik Arduino Programm funktioniert nicht


von Bethge (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen zusammen,

Ich habe ein Problem mein Arduino Uno zu Programmieren,
hab mir alles was ich weiß selbst beigebracht und komme jetzt nicht mehr 
weiter.
Mein Projekt besteht darin, dass ich 2 Lichtschranken an das Board 
angeschlossen habe, durch die ein Zählvorgang gesteuert werden soll, 
welcher bei dem maximalen Zählwert einen summer schalten soll.
Dazu sollen noch Verzögerungen eine mögliche Manipulation des Zählers 
einschränken.
Das Programm was im Anhang ist habe ich selbst geschrieben aber es 
funktioniert nicht.
Habe die Lichtschranken über Optokoppler an dem board 
angeschlossen(diese laufen über externe 24V Spannungsversorgung) und 
habe erstmal provisorisch für den Summer eine LED angeschlossen.
Meine große Frage ist nun eigentlich ob ich in dem Programm einen 
Denkfehler habe, den ich als "Leihe" nicht erkenne, ob ich komplett 
falsche funktionen benutze oder das Programm so wie ich es geschrieben 
habe überhaupt nicht funktioniert?
Ich hoffe auf baldige Antwort und bedanke mich schonmal im Vorraus,
Mfg Bethge

P.S.: Da ich befürchte das mein Anhang das falsche Format hat schreib 
ich das Programm hier nochmal hin:
1
const int ls1pin = 1; // Lichtschranke 1 ist auf Pin 1
2
const int ls2pin = 2; // Lichtschranke 2 ist auf Pin 2
3
4
int counter = 4; // Zählerfunktion
5
int summer = 3; // Summer ist auf Pin 3
6
int LS1;
7
int LS2;
8
9
boolean Merker1 = 0; // Merker für Lichtschranke 1
10
boolean Merker2 = 0; // Merker für Lichtschranke 2
11
12
13
void setup(){ // Setzt Ein- und Ausgänge, unveränderlich
14
  pinMode(ls1pin, INPUT); // Lichrschranke 1 ist ein Eingang
15
  pinMode(ls2pin, INPUT); // Lichtschranke 2 ist ein Eingang
16
  pinMode(summer, OUTPUT); // Summer ist ein Ausgang
17
}
18
void loop()
19
20
{
21
22
  for (counter=0; counter<10;) // Setzbedingung Counter
23
{
24
  
25
   LS1 = digitalRead(ls1pin); // Signalerfassung Lichtschranke 1
26
  LS2 = digitalRead(ls2pin); // Signalerfassung Lichtschranke 2 
27
  if (LS1 && LS2 == LOW); // lichtschranken sind beide Unterbrochen
28
  {
29
    Merker1 = 1;
30
    Merker2 = 1;
31
    
32
      delay(3000); // 3 sek verzögerung 
33
}
34
35
  if (LS1 && LS2 == HIGH); //Lichtschranken sind nicht mehr unterbrochen, counter zählt +1
36
{
37
    Merker1 = 0;
38
    Merker2 = 0;
39
    counter++;
40
}
41
42
if (LS1 && LS2 == LOW); // Wenn die Lichtschranken 10 sekunden unterbrochen sind, zählt counter +1
43
{
44
  Merker1 = 1;
45
  Merker2 = 1;
46
  delay(10000);
47
  counter++;
48
}
49
  
50
     if  (counter = 10);
51
{
52
 
53
  summer = 1;
54
  delay(2500);
55
  summer = 0;
56
  counter= 0;
57
  
58
}
59
}
60
}

von Georg G. (df2au)


Lesenswert?

Bethge schrieb:
> if (LS1 && LS2 == LOW);

nur ein Beispiel:
- Bindungsregeln beachten, == ist stärker als &&. Der Ausdruck macht 
nicht das, was du willst.
- das ; am Ende (kommt bei dir häufiger vor) bewirkt, dass der Compiler 
den Ausdruck komplett weg optimiert. Er ist nämlich wirkungslos ("wenn 
xx wahr ist, mach nichts"). Du solltest dir angewöhnen, nach if() 
immer eine { zu setzen.

Bitte korrigieren und dann neu versuchen.

von Kaj (Gast)


Lesenswert?

Bethge schrieb:
> if (LS1 && LS2 == HIGH);
Der Ausdruck ist falsch und bewirkt nicht was du willst.

Bethge schrieb:
> if (LS1 && LS2 == HIGH);
> if (LS1 && LS2 == LOW)
> if  (counter = 10);

Keine Semikola nach einem if... wo habt ihr den Mist her? Buecher 
lesen ist wohl zu uncool... besonders wenn es sich um ein C-Buch 
handelt...

von Bethge (Gast)


Lesenswert?

Hab mir von meinem chef jetzt ein Arduino starter kit bestellen lassen, 
da ist endlich mal ein Buch auf deutsch dabei.

Die Semikola sind weg, aber es scheint ja die funktion schon falsch zu 
sein.
Ich weiß aber nicht wie bzw. welche Befehle ich benutzen muss, damit ich 
die Signale die ich von den Lichtschranken erhalte zum Zählen verwende?

von Leuchtmensch (Gast)


Lesenswert?

if (LS1 == HIGH && LS2 == HIGH) {

}

von Marcus W. (marcusaw)


Lesenswert?

Bethge schrieb:
> void loop()
> {
>   for (counter=0; counter<10;) // Setzbedingung Counter
>   {
> ...

Da fehlt die Inkrementierung - Konnte das so kompiliert werden?

Normalerweise braucht "for" auch eine "Schrittweite", also
1
for (int i = 0; i < 255; i++)
2
{
3
  // do something 
4
}

oder in deinem Fall
1
for (counter=0; counter<10; counter++) // Setzbedingung Counter
2
{
3
  // do something
4
}

von Jürgen S. (jurs)


Lesenswert?

Bethge schrieb:
> Das Programm was im Anhang ist habe ich selbst geschrieben aber es
> funktioniert nicht.

Logisch. Kann ja auch gar nicht funktionieren.

> Meine große Frage ist nun eigentlich ob ich in dem Programm einen
> Denkfehler habe, den ich als "Leihe" nicht erkenne, ob ich komplett
> falsche funktionen benutze oder das Programm so wie ich es geschrieben
> habe überhaupt nicht funktioniert?

Ja, ja und ja.

Für irgendwelche "zählenden Lichtschranken" kannst Du die Funktion 
"delay" (Blockierung des Programms für eine angegebene Dauer) komplett 
vergessen, sobald mehr als eine einzige Lichtschranke in der 
Zähl-/Programmlogik zu berücksichtigen ist. Die Funktion "delay" darf in 
Deinem Programm nicht vorkommen, sonst wird es kaum so funktionieren, 
wie Du es möchtest.

Die beabsichtigte Zähllogik habe ich auch nicht ganz verstanden:
1. Wenn beide Lichtschranken unterbrochen sind, counter++
2. Wenn beide Lichtschranken nicht unterbrochen sind, counter++
3. Wenn counter==10, dann counter=0

Ach ja, C-Programmierung, Du brauchst dringend wenigstens ein paar 
Anfängerkenntnisse:

Mit "if (counter = 10)" setzt Du counter auf 10, weil das 
Gleichzeitszeichen für die Zuweisung eines Wertes steht. Wenn Du an der 
Stelle einen vergleich machen möchtest, müßte das doppelte 
Gleichheitszeichen für Vergleich stehen "if (counter == 10)"

Deine anderen if-Abfragen machen auch fast alle etwas anderes als Du im 
Kommentar daneben schreibst.

Deine for-Schleifen laufen auch sicher nicht so wie beabsichtigt.

Und die Programmlogik müßte wie bereits oben geschrieben grundsätzlich 
anders sein als mit "delay". Vielleicht schreibst Du nochmal leicht 
verständlich die gewünschte Lichtschranken-/Counter-Logik in Worten auf, 
wie es laufen soll, dann kann ich Dir ggf. weitere Hinweise geben, wie 
es machbar wäre.

Und ansonsten: Lerne die Basics der Programmierung!

von Marcus W. (marcusaw)


Lesenswert?

Außerdem setzt du den Counter auf counter  = 4 im Setup, nur um in dann 
als erstes im loop mit for(counter = 0;... wieder auf 0 zu setzen.

Bei if (counter = 10) kommt immer 1 oder true raus, weil du mit dem 
einzelnen = nicht vergleichst, sondern eine Zuweisung vornimmst.

Ich würde dir raten, nochmal bei den Basics der Programmierung 
anzufangen: Was ist eine Variable, wie funktioniert eine Schleife, wie 
funktioniert eine Verzweigung etc...

von Paul B. (paul_baumann)


Lesenswert?

Wenn Du Dir das Leben leichter machen willst, dann nimm statt dieses
Arduino-C-Gelumpes lieber Bascom. In der aktuellen Version ist es
möglich, den Arduino direkt aus der Bascom-Oberfläche heraus zu 
"brennen".
Wenn im Quelltext ein syntaktischer Fehler gemacht wird, dann wird der
auch erkannt und nicht wie hier -irgendwelcher Blödsinn erzeugt.

MfG Paul

von Bethge (Gast)


Lesenswert?

Jürgen S. schrieb:

> Und die Programmlogik müßte wie bereits oben geschrieben grundsätzlich
> anders sein als mit "delay". Vielleicht schreibst Du nochmal leicht
> verständlich die gewünschte Lichtschranken-/Counter-Logik in Worten auf,
> wie es laufen soll, dann kann ich Dir ggf. weitere Hinweise geben, wie
> es machbar wäre.

Auf einem Förderband fahren Kisten durch die Lichtschranken, die 
Lichtschranken sind direkt nebeneinander angebracht.
Verlässt eine kiste die Lichtschranken soll +1 gezählt werden.
Nach spätestens jeder 10. kiste soll der summer einen Ton abgeben.
Dazu kommen dann noch die Einschränkungen, das die Lichtschranken 3 
Sekunden unterbrochen sein müssen um +1 zu zählen.
Und wenn zum Beispiel 2 Kisten direkt hintereinander durch die 
Lichtschranken fahren(Diese also keine Unterbrechung haben) soll +2 
gezählt werden.

Dieses Programm hab ich Funktionsfähig auf der Siemens Logo! 
programmiert und soll es nun auf einen Microcontroller übertragen und 
meine Meister können mir nicht helfen, da sie keine ahnung davon haben 
... ich scheinbar ja auch nicht :D

von Frank (Gast)


Lesenswert?

Pin 0 und 1 würde ich nicht verwenden, die sind nämlich gleichzeitig RX 
und TX.

Dann mal 'was ganz Allgemeines für komplexere Programme: Man entwickelt 
nach der Methode "bottom up", was soviel heisst wie "von Unten nach 
Oben".

In deinem Falle würde ich z.B. erstmal eine Funktion schreiben, die 
einfach nur die Lichtschranken abfragt. Als Parameter z.B. eine Null 
oder 1 für die Nummer der Lichtschranke und als Rückgabewert eben der 
Zustand als 0 oder 1.

Das kann man nämlich einzeln testen und sich die Ergebnisse z.B. per USB 
(serial Monitor) oder über ebenfalls angeschlossene Status-LEDs 
(ebenfalls schön ordentlich in eine Funktion verpackt!) zurückgeben 
lassen.

Ist das erledigt, kann man quasi die nächste Schicht angehen, z.B. eine 
Funktion, die zyklisch oder per Interrupt die Lichtschranken abfragt und 
aufgrund der zeitlichen Verschiebung die Richtung feststellt.

Auch hier lassen sich die Ergebnisse zunächst per Ausgabe testen. Ist 
das erledigt, kommt der Zähler dran .. usw.

Vielen Neulingen fehlt vollkommen ein Plan, komplexere Dinge in einzeln 
überschaubare, extrem simple Teilprobleme zu zerlegen und sie verheddern 
sich total ...

Ein so entstandener Code mag sicher nicht super-optimal sein, aber er 
ist nachvollziehbar. Fehler sind leicht einzugrenzen und du guckst auch 
in vier Monaten nicht wie das berühmte "Schwein ins Uhrwerk".

von Jürgen S. (jurs)


Lesenswert?

Bethge schrieb:
> Dazu kommen dann noch die Einschränkungen, das die Lichtschranken 3
> Sekunden unterbrochen sein müssen um +1 zu zählen.

Kein Problem. Dazu kann man sich etwas einfallen lassen.

> Und wenn zum Beispiel 2 Kisten direkt hintereinander durch die
> Lichtschranken fahren(Diese also keine Unterbrechung haben) soll +2
> gezählt werden.

Dazu brauche ich mehr Input: Woran genau soll es denn festgemacht 
werden, dass +2 gezählt wird?

Meinste Du mit "keine Unterbrechung haben", dass es zwischen zwei Kisten 
passieren kann, dass nicht beide Lichtschranken gleichzeitig freigegeben 
werden, sondern nur eine der beiden Lichtschranken, bevor die nächste 
Kiste diese wieder unterbricht?

Oder sollen die beiden Kisten so dicht "auf knirsch" 
hintereinanderkommen, dass keine der beiden Lichtschranken unterbrochen 
wird und es stattdessen an der Durchlaufzeit (>6 Sekunden?) festgemacht 
werden soll, dass eine Doppelzählung stattfinden soll? Der Punkt ist mir 
unklar.

von Mark B. (markbrandis)


Lesenswert?

Bethge schrieb:
> Dieses Programm hab ich Funktionsfähig auf der Siemens Logo!
> programmiert und soll es nun auf einen Microcontroller übertragen und
> meine Meister können mir nicht helfen, da sie keine ahnung davon haben
> ... ich scheinbar ja auch nicht :D

Wenn Du in C programmieren willst, musst Du eben C lernen. Da führt dann 
kein Weg dran vorbei.

Eventuell muss es aber auch nicht C sein - es gibt auch andere 
Programmiersprachen.

von Bethge (Gast)


Lesenswert?

Jürgen S. schrieb:

> Dazu brauche ich mehr Input: Woran genau soll es denn festgemacht
> werden, dass +2 gezählt wird?
>
>
Falls 2 Kisten "direkt" hintereinander laufen und die Lichtschranken 
unterbrochen sind soll anhand der Zeit +2 gezählt werden, wie du in 
deiner 2. Möglichkeit beschreibst.

Frank schrieb:
> Pin 0 und 1 würde ich nicht verwenden, die sind nämlich
> gleichzeitig RX
> und TX.
>
> Dann mal 'was ganz Allgemeines für komplexere Programme: Man entwickelt
> nach der Methode "bottom up", was soviel heisst wie "von Unten nach
> Oben".

Ok Danke schonmal für diesen Tipp, dann werde ich mal versuchen das 
programm so zu erarbeiten :)

von Karl H. (kbuchegg)


Lesenswert?

Bethge schrieb:
> Jürgen S. schrieb:
>
>> Dazu brauche ich mehr Input: Woran genau soll es denn festgemacht
>> werden, dass +2 gezählt wird?
>>
>>
> Falls 2 Kisten "direkt" hintereinander laufen und die Lichtschranken
> unterbrochen sind soll anhand der Zeit +2 gezählt werden,


was ist wenn 5 Kisten direkt hintereinander laufen?

Ist es wirklich so, dass die Lichtschranke auch nicht gaaaanz kurz 
wieder durchschaltet, wenn 2 Kisten hintereinander laufen. Gerade auf 
einem Förderband hat man doch meistens zumindest ein paar 
Zehntelmillimeter "Luft" zwischen dem Fördergut. Luft genug, so dass 
eine Lichtschranke ganz kurz mal wieder durchschaltet um dann von der 
nächsten Kiste unterbrochen zu werden.

von Jürgen S. (jurs)


Lesenswert?

Bethge schrieb:
> Falls 2 Kisten "direkt" hintereinander laufen und die Lichtschranken
> unterbrochen sind soll anhand der Zeit +2 gezählt werden, wie du in
> deiner 2. Möglichkeit beschreibst.

Was für ein Pfusch!

Wenn also das Förderband bei einer Kiste stoppt, während beide 
Lichtschranken unterbrochen sind, und nach drei Minuten läuft das Band 
wieder los, werden dann gleich zwei Kisten gezählt?

Und eine dritte Kiste "auf Knirsch" hintereinander kann nicht kommen?

Anyway. Was man als Programmlogik beschreiben kann, kann man auch 
programmieren.

Codevorschlag (mit Doppelzählung ab 6s Unterbrechung beider 
Lichtschranken und Einfachzählung zwischen 3s und 6s Unterbrechung):
1
const int ls1pin = 2; // Lichtschranke 1 ist auf Pin 2
2
const int ls2pin = 3; // Lichtschranke 2 ist auf Pin 3
3
const int summerPin = 4; // Summer ist auf Pin 4
4
5
6
void setup(){ // Setzt Ein- und Ausgänge, unveränderlich
7
  pinMode(ls1pin, INPUT); // Lichrschranke 1 ist ein Eingang
8
  pinMode(ls2pin, INPUT); // Lichtschranke 2 ist ein Eingang
9
  pinMode(summerPin, OUTPUT); // Summer ist ein Ausgang
10
}
11
12
int counter; // Zähler
13
boolean ls1state;
14
boolean ls2state;
15
unsigned long doppelUnterbrechungStart;
16
boolean doppelUnterbrechung;
17
unsigned long summerStart;
18
boolean summerAktiv;
19
20
void loop()
21
{
22
  // Status der beiden Lichtschranken auslesen
23
  ls1state=digitalRead(ls1pin);
24
  ls2state=digitalRead(ls2pin);
25
  
26
  // liegt eine doppelte Unterbrechung vor, aber der Status "doppelUnterbrechung" ist noch nicht gesetzt?
27
  if (ls1state==LOW && ls2state==LOW && doppelUnterbrechung==false)
28
  {
29
    doppelUnterbrechung=true;           // Status doppelUnterbrechung setzen
30
    doppelUnterbrechungStart=millis();  // Zeitpunkt merken
31
  }
32
  
33
  // falls Doppelunterbrechung vorliegt prüfen, ob eine Lichtschranke vor 3 Sekunden wieder öffnet
34
  if (doppelUnterbrechung)
35
  {
36
    if ((ls1state==HIGH || ls2state==HIGH) && millis()-doppelUnterbrechungStart<3000)
37
    {
38
      doppelUnterbrechung=false; // Zu kurze Unterbrechung <3000ms, ignorieren
39
    } 
40
    else if (ls1state==HIGH || ls2state==HIGH) // eine der Lichtschranken wieder frei nach >=3000ms
41
    {
42
      doppelUnterbrechung=false;
43
      if (millis()-doppelUnterbrechungStart>6000) counter=counter+2; // lange Unterbrechung, 2 Kisten zählen
44
      else counter++; // eine Kiste zählen
45
    }
46
  }
47
  if (counter>=10) // Zählerstand hat 10 erreicht?
48
  {
49
    counter=0; // Zähler zurücksetzen
50
    summerAktiv=true; // Summer auf aktiv setzen
51
    summerStart=millis(); // Zeit merken
52
  }
53
  if (summerAktiv && millis()-summerStart>=2500) // ist der Summer schon 2500ms an?
54
  {
55
    summerAktiv=false;
56
  }
57
  digitalWrite(summerPin, summerAktiv); // Logischen Status des Summers auf dem Summerpin ausgeben
58
}

Code ungetestet, nur hingeschrieben.
Debuggen müßtest Du selbst, bei Fragen zum Code einfach nachfragen.

Die beiden Pins 0 und 1 solltest Du, wie hier im Thread bereits von 
jemand anderem erwähnt, an Arduino-Boards für "Serial" freilassen und 
nicht für allgemeines I/O verwenden, daher verwende ich im Beispielcode 
Pinnummern ab 2 aufwärts.

Im Zweifelsfalls kannst Du "Serial" dann auch während der 
Programmentwicklung zur Ausgabe von Debug-Meldungen auf Serial verwenden 
und Dir im seriellen Monitor anzeigen lassen.

von Bethge (Gast)


Lesenswert?

Also rein Theoretisch werden nie 2 kisten so nah hintereinander laufen. 
Allerdings muss ich in diesem fall davon ausgehen. Da die Anlage mit der 
Logo schon lief und ich festgestellt habe das 2 kisten so eng 
hintereinander laufen können, muss ich das ausschließen können.

Mehr als 2 kisten passen nicht hintereinander auf das Förderband :D

von ich (Gast)


Lesenswert?

Hi,
und von wen oder was wird das Förderband befüllt. (Wäre ich da wäre jede 
auf knirsch angesetzt, nur um die Steuerung zu ärgern,vll würde ich auch 
mal schieben dass ich 2 Kisten in 3 Sekunden Durchkriege, entweder was 
ausdenken dass das verhindert oder eine Einweisung geben.)
MfG
ich

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.