Hallo,
ich habe einen simplen Münzprüfer gebaut welcher nach Münzeinwurf und
betätigen eines Tasters die darunterliegende Steckdose für 3 Stunden mit
Strom versorgt. Bei Einwurf einer Münze welche über eine Rampe mit
Öffnungen rollt wird wenn sie die mechanische Prüfung besteht und nicht
durch die Öffnungen fällt ein Taster (Pin0) betätigt. Anschliesend soll
einer der 16 Taster (Pin1-16) für die jeweilige Schuko gedrückt werden,
dadurch wird der jeweilige Ausgang( Pin 18-33) für eine einstellbare
Zeit auf High geschaltet.
Soweit die Theorie. Das ganze funktioniert mit zwei IOs auch ganz
normal. leider mit 16 nicht mehr und ich schau schon seit 2 Stunden
darauf und find den Fehler nicht...
kann von euch bitte mal einer darüberschauen und mir meinen Fehler
sagen?
Die Hardware ist ein Arduino Mega2560
Ich bedanke mich schon mal herzlich.
hier der Code:
houwdy schrieb:> Interessanterweise macht er gar nichts mehr mit drei oder mehr> Eingängen, die Pegel sind definiert mit pullups.
Seltsam !!
Pullups Hardwaremäßig ?
Wie groß ?
Hallo,
sorry ich hab mich gestern glaub ich etwas undeutlich ausgedrückt.
Das lag warscheinlich an der späten Stunde.
Hier nocheinmal die Aufgabenstellung:
Wir bewirtschafen eine Schutzhütte und dort ist der Strom recht rar da
er nur von einer Photovoltaikanlage zur Verfügung. Um dies kontrollieren
zu können ( da einige Herrschaften von Fön bis Tauchsieder alles
mitttragen und uns damit die Hütte finster machen) und auch die
Betriebskosten zu senken kann man bei uns neben der Küchentüre mit einem
Euro für 3h Strom kaufen. Diese Schukos sind auf 0,5A mittels
elektronischer Sicherung abgesichert. Wir hatten bis jetzt 6 Schukos,
allerdings ist der Bedarf gestiegen und somit habe ich das ganze auf 15
erweitert. Meine erste Version baute ich in der HTL und sie arbeitet mit
einem PIC. nun bin ich auf Arduino umgestiegen.
Die Handhabung durch den Kunden läuft wiefolgt:
Euro einwerfen,
Taste über Steckdose drücken,
dann ist für 3h an der jeweiligen Schuko Energie verfügbar.
Vom Code hab ich schon jetzt viel von euch gelernt.
bei uns hies es immer es ist ein Nogo bei der Initialisierung Schleifen
zu
verwenden. Super wenn er das kann.
Das ganze funktioniert intressanterweise mit zwei Ein und Ausgängen ganz
normal, so ich 3 nehme macht der Arduino gar nichts mehr.
ich mach noch schnell ein Foto von dem Vorgänger damit ihr euch da etwas
vorstllen könnt.
Danke Marian
Wie ist die Hardware denn ausgeführt/verschaltet?
Werden die LEDs über einen Treiber versorgt? Ich habe die Daten nicht im
Kopf, aber ich kann mir vorstellen, 16 gleichzeitig leuchtende LEDs sind
schon ziemlich viel Strom für den kleinen Arduino.
Zumn Code habe ich noch einen Vorschlag. Derzeit ist die Stromausgabe
nicht verriegelt. Ich kann also mehrfach hintereinander die gleiche
Steckdose "kaufen".
Für mich wäre es ziemlich ärgerlich, wenn ich mich vertippe, also eine
bereits eingeschaltete Steckdose auswähle, und dadurch meinen Euro
verschenke.
Davor solltest du mit der Programmierung vorgehen, heutzutage gibt es
genug Idioten, für die das bereits aus, um zum Vandalen zu werden...
int timeVal = 50; // gibt mir die Zeit an die der Ausgang gesetzt werden
soll
1
if(coinState==LOW){
2
Coin=1;// Wenn eine Münze eingeworfen wird wird Coin zu 1
3
4
if(digitalRead(buttonPin01)==LOW&&Coin==1){// wenn Coin 1 und der Schalter der jeweiligen schuko gedrückt wird wird in Button Val die Zeitkonstante geschrieben und coin auf 0 gesetzt
5
buttonVal01=timeVal;
6
Coin=0;
7
}
8
9
//solange Buttonval größer 0 ist wird die Steckdose eingeschaltet
10
//das habe ich so realisiert damit jeder der 16 Outputs seine "eigene Zeit" //hat
11
//und immer die ganze schleife durchlaufen wird ohne das der controller in //einer hängen bleibt. buttonval-- wollte der Compiler komischerweise nicht.
12
13
if(buttonVal01<<0){
14
digitalWrite(ledPin1,HIGH);
15
buttonVal01=buttonVal01-1;
16
}
17
18
//hat die ButtonVal variable dann 0 erreicht wird der Output wider auf 0 gesetzt.
19
if(buttonVal01==0){
20
digitalWrite(ledPin1,LOW);
21
}
22
delay(100);// definiert einen Durchlauf auf ~100ms
Die Outputs gehen natürlich via Optokoppler auf eine Relaiskarte.
Ich habe jetzt keine Lust mich durch den Code zu wühlen.
Ich sitze jetzt vor meinem Mega und habe das Programm aus dem
Eröffnungpost drauf.
Was muss ich jetzt wo anschließen um es mal zu testen.
an IO 0 kommt ein Taster für die Münzerkennung der kurz betätigt wird
an Io 1-16 die Tster für die Schukofreigabe.
an IO 18-33 die LED bzw Relais
Wenn du das ganze mit 3 Tastern und 3 Leds mit IO 1, 2,3 und IO 18, 19
20 probierst und du kommentierst den Code von
else if (digitalRead(buttonPin03) == LOW&& Coin ==1) {
buttonVal03 = timeVal;
Coin =0;
}
bis
else if (digitalRead(buttonPin16) == LOW&& Coin ==1) {
buttonVal03 = timeVal;
Coin =0;
}
aus funktioniert das ganze einwandfrei io 0 betätigen, anschliesend io1
oder/ und io2 und die Leds leuchten für die Zeit.
so wie du
else if (digitalRead(buttonPin03) == LOW&& Coin ==1) {
buttonVal03 = timeVal;
Coin =0;
}
dazu nimmst geht gar nichts mehr??
Danke schonmal
Marian :)
Dussel schrieb:> Was soll> if (buttonVal01 <<0 ) {> bringen?Einer schrieb:> Das << sollte von der Logik wohl eher ein > sein.Kaj schrieb:> Den fehler vom TO 'if (buttonValxx << 0)' hab ich jetzt einfach mal> uebernommen. keine Ahnung was er da machen moechte.Dussel schrieb:> Es ist ja schön, dass du so viel schreibst, aber die Frage bleibt, was> du mit> if (buttonVal[i] << 0) {> bewirken willst.Marian G. schrieb:> //solange Buttonval größer 0 ist wird die Steckdose eingeschaltet> //das habe ich so realisiert damit jeder der 16 Outputs seine "eigene> Zeit" //hat> //und immer die ganze schleife durchlaufen wird ohne das der controller> in //einer hängen bleibt. buttonval-- wollte der Compiler komischerweise> nicht.>> if (buttonVal01 <<0 ) {> digitalWrite(ledPin1, HIGH);> buttonVal01=buttonVal01-1;> }
Ehm, ich will dir nicht zu nahe treten Marian, aber bist du Resistent
gegen konkrete Verbesserungsvorschläge bei offensichtlichen Fehlern?
Kennst du den Unterschied zwischen
1
buttonVal01<<0
und
1
buttonVal01<0
Das eine ist eine Schiebeoperation, und das andere ein Vergleich!
1
if(buttonVal01<<0){
2
//
3
}
4
5
=>Entspricht
6
if((buttonVal01<<0)!=0){
7
//
8
}
Konkret schiebst du die Variable buttonVal01 also um 0 Bit nach links
und prüfst anschliessend ob diese grösser als 0 ist.
Wenn du auf 0 oder grösser 0 prüfen möchtest, dann mach doch das so wie
99.99% alle anderen:
1
if(buttonVal01!=0){
2
}
3
if(buttonVal01>0){
4
}
Das kann man wenigstens lesen und versteht es auf anhieb.
Noch was. Du setzt deine Coin Variable nur in der Schlaufe zurück. Ist
das so gewollt? Sollte das nicht etwa so sein?
1
if(coinState==LOW){
2
Coin=1;
3
}
4
else{
5
Coin=0;
6
}
Versuch doch mit diesem Code mit 1, 2, oder 3 "akzeptieren" Kanälen zu
Arbeiten (for-Schlaufen limitieren). In der Simulation oder beim
Debuggen Schritt für Schritt. Dann siehste ja sofort, wo etwas wann
nicht so soll wie gedacht.
Prüfe mal mit dem seriellen Monitor, ob die einzelnen Taster überhaupt
erkannt werden.
Ich habe "Coin" auf Pin 17 geklemmt, sonst ist die serielle
Schnittstelle nicht nutzbar.
Taste 13 wird so immer erkannt werden, da der interne Pullup für die
serienmäßige LED zu schwach ist, also nicht wundern, oder Pin 13 direkt
auf 5V legen.
Patrick B. schrieb:> Ehm, ich will dir nicht zu nahe treten Marian, aber bist du Resistent> gegen konkrete Verbesserungsvorschläge bei offensichtlichen Fehlern?> Kennst du den Unterschied zwischenbuttonVal01 << 0> undbuttonVal01 < 0>> Das eine ist eine Schiebeoperation, und das andere ein Vergleich!
und genau das war der Fehler!
Es tut mir leid aber das war ein Blackout im Sinne " ich seh den Wald
vor lauter Bäumen nicht mehr"
Ich hab Dussels Statement durch meinen Tunnelblick nicht kapiert.
Klar kanns mit Bitshiftoperatoren nicht gehn.
Danke jedenfalls für eure Hilfe! ich hab jetz den Ungleichoperator (!=)
verwendet und jetzt funktioniert es.
Im Moment läuft das ganze noch mit 3 Kanälen am Steckbrettchen aber ich
denke ich werde es heute Abend auf die Hardware spielen und wenn der
Code dort funktioniert poste ich denselben nochmal der Vollständigkeit
halber.
Tausend Dank euch allen erstmal.
Marian
Ich habe deinen ersten Code verwendet. Interne PullUp aktiviert.
Funktioniert mit 4 Tasten.
Die Pin 0 und 1 werden für den Upload benötigt und sollten nicht
verwendet werden.
Marian G. schrieb:>> Das eine ist eine Schiebeoperation, und das andere ein Vergleich!>> und genau das war der Fehler!
Was aber in deinem Fall durch Zufall nicht schlimm ist. Die if-Bedingung
trifft zu, solange das Ergebnis ungleich null ist. Die Bitschieberei um
null Stellen verändert da nichts.
Wie gesagt, bei mir funktioniert auch deine Codevariante.
StromTuner
Marian G. schrieb:> Im Moment läuft das ganze noch mit 3 Kanälen am Steckbrettchen
...lief es doch vorher auch schon...
>leider mit 16 nicht mehr und ich schau schon seit 2 Stunden>darauf und find den Fehler nicht...
Ob Du nun Bishiftleft zero machst und auf ungleich null testest, oder
sorum. Ist zwar mit "<<" völlig am Ziel vorbei, sollte an der
Fehlerbeschreibung nichts ändern, die am Anfang angegeben hast. Es
funktioniert ja (hier eher zufällig)
Bin ich ja gespannt!
Kaj schrieb:> Ich hab mal den Code aufgeraeumt.
Hier bieten sich Schleifen geradezu an.
Nicht nur der Code wird nen ordentlichen Zacken kürzer und damit
leserlicher.
Auch sinkt die Fehlerwarscheinlichkeit drastisch. Man muß ja nur einen
Schleifendurchgang prüfen und nicht 16 Copy&Paste Stellen.
Ich nehme Schleifen schon ab 2 weitgehend identischen Codeteilen.
Copy&Paste Code vermeide ich, wenn es nur irgend geht.
Lothar M. schrieb:> Ich habe einen Fehler im Programm gefunden:>> delay(100);> Denn in der Hauptschleife aktiv Rechenzeit zu vergeuden ist mit> Sicherheit ein Fehler.
In dem Fall nicht, das Programm ist einfach laienhaft geschrieben.
Das Delay wird im Endeffekt mit int timeVal multipliziert und ergibt
somit die Zeit, die der Output high ist.
An den TO:
Wenn du statt
>>if (digitalRead(buttonPin01) == LOW&& Coin ==1) {>> buttonVal01 = timeVal;>> Coin =0;>>}
das hier
>>if (digitalRead(buttonPin01) == LOW&& Coin ==1) {>> buttonVal01 = buttonVal01 + timeVal;>> Coin =0;>>}
schreibst, kannst du die Zeit verlängern, in der die Steckdose an ist,
wenn eine neue Münze eingeworfen wurde. ;)
Ob das mit dem Fehler zusammenhängt kann ich nicht beurteilen, aber
mache dir am besten nochmal Gedanken über entprellung und
schaltgeschwindigkeit bei den Tastern aber v.a. bei der Münzerkennung.
Wenn ich das richtig sehe kann eine schnell vorbeirollende münze während
dem delay unerkannt bleiben, wenn man das delay verkürzt eine münze
aufgrund von Prellung aber mehrfach registriert werden (ok das ignoriert
der Code bisher, aber vielleicht mal später)
Marian G. schrieb:> ich hab jetz den Ungleichoperator (!=)> verwendet und jetzt funktioniert es.
Ja, aber ist das auch das was du willst?
Willst du testen ob es groesser 0 ist (nur positiver Wertebereich, ohne
die 0), oder willst du testen ob es ungleich 0 ist (negativer und
positiver Wertebereich, ohne die 0)
Martin K. schrieb:> Was genau meinst Du? Ich habe ja den Test vorhin direkt mit der Hardware> gemacht.
Auf dem Arduino Mega ist ein Impedanzwandler (OP?) verbaut, um genau das
von dir genannte Problem zu unterbinden.
Pin13 kann also problemlos mit INPUT_PULLUP verwendet werden.
Warum dein Mega das nicht hat, kann ich dir nicht sagen.
Hi
Martin K. schrieb:> Vermutlich, weil es ein Klon ist.
Hat bei Dolly aber anders ausgesehen ... äh nein, eigentlich genau
gleich :)
Was Du meinst: Ein günstiger Nachbau, landläufig aber auch gerne, da
gebe ich Dir Recht, Klon genannt, wenn's auch nicht wirklich trifft.
Davon ab - laufen jetzt alle 16 Taster/Steckdosen?
Zum Probieren muß man ja nicht jedes Mal 2 Stunden warten - eine Zahl im
Programm geändert und die Zeit wird auf der Basis 10 Sekunden
verwurschtelt.
MfG
Lothar M. schrieb:> Nur mal kurz in die Runde gefragt, was ist denn daran so schwer zu> verstehen:Antwort schreiben> Wichtige Regeln - erst lesen, dann posten!>> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang>> Ich habe einen Fehler im Programm gefunden:>> delay(100);> Denn in der Hauptschleife aktiv Rechenzeit zu vergeuden ist mit> Sicherheit ein Fehler.
Zum Ersten: dafür entschuldige ich mich und gelobe fürs nächste mal
Besserung.
Wie würdest du das delay 100 umgehen in diesem Fall?
Peter schrieb:> Oh man wie kann man so beratungsresistent sein und den auf einem> Silbertablett serviereten super zusammen gefasten Code nicht zu nehmen.
Ich hab den Code ja genommen, auserdem hab ich mir recht viele Gedanken
gemacht wie ich das hier gesehene beim nächsten Projekt anwenden kann,
worauf bezieht sich dann meine Beratungsresistenz? Würde ich so
programmieren wie ich Wig schweisse dann müsste ich nicht nachfragen.
Patrick J. schrieb:> Davon ab - laufen jetzt alle 16 Taster/Steckdosen?> Zum Probieren muß man ja nicht jedes Mal 2 Stunden warten - eine Zahl im> Programm geändert und die Zeit wird auf der Basis 10 Sekunden> verwurschtelt.>> MfG
10 laufen :) die anderen 6 kommen morgen nach der Arbeit drann :) dann
teile ich euch das Ergebnis mit.
Mfg Marian
Woran lag es "denn dann denn" nun, das erst nur zwei Ausgänge
funktionierten und nun alles ok ist?
Doch sicher nicht an der (<<0) ...
Kann das mal jemand zusammenfassen?
StromTuner
Axel R. schrieb:> Kann das mal jemand zusammenfassen?
Ich versuchs mal...
Aus einer unsäglichen, fehlerträchtigen, Codewurst, ist ein
übersichtliches Konstrukt mit Schleifen und Arrays geworden.
Arduino F. schrieb:> Axel R. schrieb:>> Kann das mal jemand zusammenfassen?>> Ich versuchs mal...>> Aus einer unsäglichen, fehlerträchtigen, Codewurst, ist ein> übersichtliches Konstrukt mit Schleifen und Arrays geworden.
Ich tippe eher auf Hardwareprobleme. Die "Codewurst" funktioniert ja auf
meinem Mega.
Das die Wurst nur aus Zufall funktioniert, will ich nicht abstreiten.
Hier der funktionierende Code. ich poste ihn im Beitrag da es ja nur ein
par Zeilen sind. Ich hoffe das ist in Ordnung.
Danke noch einmal für eure Hilfe. Ich glaube der ist jetzt um einiges
schöner als der Erste.
Patrick J. schrieb:> Wenn Du die Klammern mit etwas mehr Sinn setzt, ergeben Diese direkt die> zusammenhängenden Blöcke:>
1
.....
2
>for(uint8_ti=0;i<16;i++){
3
>pinMode(ledPins[i],OUTPUT);
4
>pinMode(buttonPins[i],INPUT_PULLUP);
5
>-->}
6
>
> Alles auf gleicher Ebene ist gleich weit eingerückt, finde ich einfacher> und besser lesbar.
besser lesbar?
halte ich für diskutierbar, ich finde Öffnungsklammern irgendwo hinten
schlecht lesbar
1
.....
2
voidloop()
3
{if((digitalRead(coinPin))==LOW)
4
{Coin=1;
5
for(uint8_ti=0;i<16;i++)
6
{if((digitalRead(buttonPins[i])==LOW)&&(Coin==1))
7
{buttonVal[i]=timeVal;
8
Coin=0;
9
break;
10
}
11
}
12
}
13
14
for(uint8_ti=0;i<16;i++)
15
{if(buttonVal[i]!=0)
16
{digitalWrite(ledPins[i],LOW);
17
buttonVal[i]-=1;
18
}
19
if(buttonVal[i]==0)
20
digitalWrite(ledPins[i],HIGH);
21
}
22
delay(10);
23
}
das halte ich für lesbarer, Einzeiler brauchen selten Klammern
ist vielleicht nur meine Meinung, aber ich sehe wo Blöcke anfangen und
wo enden