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
constintls1pin=1;// Lichtschranke 1 ist auf Pin 1
2
constintls2pin=2;// Lichtschranke 2 ist auf Pin 2
3
4
intcounter=4;// Zählerfunktion
5
intsummer=3;// Summer ist auf Pin 3
6
intLS1;
7
intLS2;
8
9
booleanMerker1=0;// Merker für Lichtschranke 1
10
booleanMerker2=0;// Merker für Lichtschranke 2
11
12
13
voidsetup(){// 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
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.
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...
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?
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
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!
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...
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
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
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".
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.
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.
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 :)
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.
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
constintls1pin=2;// Lichtschranke 1 ist auf Pin 2
2
constintls2pin=3;// Lichtschranke 2 ist auf Pin 3
3
constintsummerPin=4;// Summer ist auf Pin 4
4
5
6
voidsetup(){// 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
intcounter;// Zähler
13
booleanls1state;
14
booleanls2state;
15
unsignedlongdoppelUnterbrechungStart;
16
booleandoppelUnterbrechung;
17
unsignedlongsummerStart;
18
booleansummerAktiv;
19
20
voidloop()
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?
doppelUnterbrechung=false;// Zu kurze Unterbrechung <3000ms, ignorieren
39
}
40
elseif(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
elsecounter++;// 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.
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
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