Hallo zusammen,
ich bin gerade dabei drei Signale mit einem Arduino Mega 2560
auszuwerten. (Ein-Aus, PWM, Analog)
Das Arduino Board erkennt weder high, noch low Signale. Entweder muss
ich im Programm etwas falsch gemacht haben, oder das neue Board ist
platt.
Das Auslesen und Anzeigen des Analogsignals funktioniert allerdings ohne
Probleme.
Hier mal der Anfang vom Code:
high =pulseIn(M_HS,HIGH,1000000); // Measuring high
38
low = pulseIn(M_HS,LOW,1000000); // Measuring low
39
40
if(OK_HS == 1) // Einlesen Status Pin OK_HS
41
{
42
lcd.clear();
43
lcd.setCursor(0,0);
44
lcd.print("STATUS:");
45
lcd.setCursor(0,1);
46
lcd.print("NO FAULT-OKAY");
47
delay(1000);
48
}
49
else
50
{
51
lcd.clear();
52
lcd.setCursor(0,0);
53
lcd.print("STATUS:");
54
lcd.setCursor(0,1);
55
lcd.print("IMD ERROR");
56
delay(1000);
57
}
Egal, was ich mache (z.B. if(OK_HS == 1) ändern zu: if(OK_HS == 0) ) ,
er geht immer in die else "Option".
Findet Ihr einen Fehler im Code?
Besten Dank,
Marco
Edit:
Ich habe von den Eingängen des Arduino Boards zu der Arduino Masse ein
Oszilloskop angeschlossen. Alle Werte sind gut. 4,96V am OK_HS und ein
PWM Signal mit gleicher Spannung an M_HS.
Fang doch erstmal einfach an z.B. Taster Einlesen und LED blinken
lassen. Das hat noch keinem geschadet und danach weist du auch wie man
mit dem Arduino einen Pin einliest.
Furchtbarer Code.
> freq = 1/period;
Ich denke nicht, dass da irgendwas sinnvolles rauskommt. period ist ein
long, damit kann diese Division nur 0 oder 1 ergeben. Hauptsächlich aber
0.
Und selbst wenn da das Problem korrigierst, kann da nur ein Wert
zwischen 0 und 1 rauskommen. Daher ist sowas
> if(freq >= 9 && freq <= 11)
völlig sinnfrei
Lass dir halt mal die Werte die du errechnest ausgeben, ehe du sie
weiter benutzt!
> Habt ihr vielleicht noch nen Tipp, was ich bei der PulseIn> Funktion falsch gemacht habe?
Ich kann dir sagen was du generell falsch machst:
Du schreibst viel zu viel Code in einem Rutsch, in der irrigen Annahme,
dass du es auf Anhieb hinkriegst. Das 'Wichtigste' in deinem Code
scheint zu sein, dass beide Zeilen des LCD immer gut gefüllt sind.
Funktion ist egal - die Haupzsache etwas steht auf dem LCD. Es sind zwar
die Dinge, die zum momentanen Zeitpunkt noch keinen interessieren (weil
du noch in der Entwicklungsphase bist und erst mal die Grundfunktion
sicherstellen musst), aber das stört dich nicht weiter. Dabei könnte man
das LCD so schön benutzen, damit einem das Programm gemessene bzw.
errechnete Werte ausgibt, damit man auch mal die Zahlen sieht, die dann
letzten Endes als die Basis deiner Ausgaben benutzt werden.
Und: du überlegst dir nicht, wie und wo du sinnvoll im Prinzip immer
gleiche Codeteile in Funktionen auslagern kannst, so dass dein Hauptcode
kürzer wird, damit du den Überblick behalten kannst.
Karl Heinz Buchegger schrieb:>> freq = 1/period;>> Ich denke nicht, dass da irgendwas sinnvolles rauskommt. period ist ein> long, damit kann diese Division nur 0 oder 1 ergeben. Hauptsächlich aber> 0.
Bzw. jetzt sehe ich es erst. Das zieht sich ja noch weiter vor.
period = (high+low)/1000000;
freq = 1/period;
period ist praktisch ständig 0.
> Habt ihr vielleicht noch nen Tipp, was ich ... falsch gemacht habe?
Du hast den Anfängerfehler Nummero Uno gemacht:
Du denkst du könntest das alles auch einfach so im vorübergehen
irgendwie lernen und hast daher darauf verzichtet, dir mal in einem
Einsteigerbuch die Grundlagen deiner Programmiersprache zu lernen. Ganz
konkret das überaus wichtige Kapitel über Datentypen und wie sie in
arithmetischen Ausdrücken sich auswirken.
Du unterschätzt die Komplexität die sich hinter dem Vorgang "Ein
Programm schreiben" verbirgt aber ganz massiv. Ein paar Beispiele sich
durchzulesen, reicht eben nicht um Programmieren zu lernen.
Hallo Karl Heinz,
vielen Dank für deine Nachrichten.
Es ist zwar ein privates Projekt, aber da ich keine Zeit hatte und
Arduino nicht programmieren kann, hatte ich das Programmieren an einen
Freelancer von Elance.com abgegeben.
Naja, nun bin ich schlauer und mache das nächstes Mal wohl besser
selber.
Dann werde ich mal anfangen, mich in das Thema einzulesen.
Würdest du den Code komplett neu machen oder versuchen zu flicken?
Beste Grüße,
Marco
M. N. schrieb:> Dann werde ich mal anfangen, mich in das Thema einzulesen.> Würdest du den Code komplett neu machen oder versuchen zu flicken?
Gibt es da noch mehr Code?
Das bisherige ist ja nicht so schwer zu flicken.
period, freq und duty_cycle müssen zumindest float sein.
1
floatperiod;
2
floatfreq;
3
floatduty_cycle;
Hier muss eine Gleitkommadivision hin
1
period=(high+low)/1000000.0;
und für die den Code unsäglich in die Länge ziehenden Ausgaben von
konstanten Texten in die 2 Zeilen würde ich mir gleich mal eine Funktion
schreiben
1
voidlcdUpdate(constchar*text1,constchar*text2)
2
{
3
lcd.clear();
4
lcd.setCursor(0,0);
5
lcd.print(text1);
6
lcd.setCursor(0,1);
7
lcd.print(text2);
8
}
was den ganzen restlichen Code gleich mal verkürzt. Zb
1
if(OK_HS_state)// Checking the status pin, OK_HS
2
lcdUpdate("STATUS:","NO FAULT-OKAY");
3
else
4
lcdUpdate("STATUS:","IMD ERROR");
5
6
delay(1000);
7
}
anstelle von
1
if(OK_HS_state==1)// Checking the status pin, OK_HS
2
{
3
lcd.clear();
4
lcd.setCursor(0,0);
5
lcd.print("STATUS:");
6
lcd.setCursor(0,1);
7
lcd.print("NO FAULT-OKAY");
8
delay(1000);
9
}
10
else
11
{
12
lcd.clear();
13
lcd.setCursor(0,0);
14
lcd.print("STATUS:");
15
lcd.setCursor(0,1);
16
lcd.print("IMD ERROR");
17
delay(1000);
18
}
und beim restlichen Code sind ähnliche Einsparungen in der Länge (und
damit Gewinn an Überschaubarkeit) zu erzielen, indem man sich ein paar
angepasste Ausgaberoutinen schreibt, die zb die Kombination aus Label +
Wert + Einheit in einer Funktion zusammenfasst.
und das ist schon ganz was anderes, als der genau gleiche Code im
Original, der sich anstatt über 17 Zeilen über ganze 2 Seiten hinzieht.
Jetzt sieht man auch, dass da mit den Grenzabfragen was nicht so ganz
stimmen kann. Welche Ausgabe soll denn gemacht werden, wenn der
duty_cycle sich zu 4.5 errechnet hat? Wird das dann einfach ignoriert
oder was? D.h. Hier ist noch gar nicht fertig programmiert worden.
Zumindest sollte ein offensichtlich unsinniger Wert angezeigt werden,
damit wenigstens überhaupt etwas angezeigt wird (und der Benutzer eine
Rückmeldung hat) und nicht wie im Original einfach nichts.
Und PS: alleine die delay da drinnen zeigen schon, dass der ganze
Programm- bzw. Anzeigen-Aufbau nicht stimmt.
> aber da ich keine Zeit hatte und Arduino nicht programmieren kann
Das hat auch weniger mit Arduino zu tun als damit, ob man generell
programmieren kann. Denn die Sachen um die es jetzt geht, die sind in
allen Programmiersprachen mehr oder weniger gleich (sofern es Datentypen
in der Sprache gibt).
> Naja, nun bin ich schlauer und mache das nächstes Mal> wohl besser selber.>> Dann werde ich mal anfangen, mich in das Thema einzulesen.
Bei allem Respekt.
Aber bist du sicher, dass du es dadurch nicht noch schlimmer machst?
> hatte ich das Programmieren an einen Freelancer von Elance.com abgegeben.
Ich hoffe du hast ihm für dieses Machwerk nicht zu viel bezahlt.
Wenn mir jemand bei einem Bewerbungsgespräch so etwas als Beispiel
vorlegt, für etwas das er schon gemacht hat, dann würde ich ihn nicht
nehmen.
Karl Heinz Buchegger schrieb:>> hatte ich das Programmieren an einen Freelancer von Elance.com abgegeben.>> Ich hoffe du hast ihm für dieses Machwerk nicht zu viel bezahlt.> Wenn mir jemand bei einem Bewerbungsgespräch so etwas als Beispiel> vorlegt, für etwas das er schon gemacht hat, dann würde ich ihn nicht> nehmen.
So wie es aussieht scheinbar definitiv zuviel.
M. N. schrieb:> Karl Heinz Buchegger schrieb:>>> hatte ich das Programmieren an einen Freelancer von Elance.com abgegeben.>>>> Ich hoffe du hast ihm für dieses Machwerk nicht zu viel bezahlt.>> Wenn mir jemand bei einem Bewerbungsgespräch so etwas als Beispiel>> vorlegt, für etwas das er schon gemacht hat, dann würde ich ihn nicht>> nehmen.>> So wie es aussieht scheinbar definitiv zuviel.
Es heißt zwar immer "Unter Blinden ist auch der Einäugige ein König"
aber das Gebotene ist mir auch für einen Einäugigen zu wenig, als dass
ich ihn als Führer engagieren würde. :-)
void lcdUpdate( const char* label, long value, const char* unit )
155
{
156
lcd.clear();
157
lcd.setCursor(0,0);
158
lcd.print( label );
159
lcd.setCursor(0,1);
160
lcd.print( value, DEC );
161
lcd.setCursor(8,1);
162
lcd.print( unit );
163
}
Wie kann ich den Code hier so posten, wie du es tust? Das ist wirklich
super übersichtlich. Besser als im Arduino Editor.
Nochmal Danke für deine Mühe;)
M. N. schrieb:> Wie kann ich den Code hier so posten, wie du es tust? Das ist wirklich> super übersichtlich.
Guck mal in den oberen Teil des Textfensters. Das steht etwas von
"Formatierung".
Für Arduino dürfte "[ c ]" und "[ /c ]" ohne Leerzeichen gelten.
STK500-Besitzer schrieb:> M. N. schrieb:>> Wie kann ich den Code hier so posten, wie du es tust? Das ist wirklich>> super übersichtlich.>> Guck mal in den oberen Teil des Textfensters. Das steht etwas von> "Formatierung".> Für Arduino dürfte "[ c ]" und "[ /c ]" ohne Leerzeichen gelten.
Danke:)
Habe versehentlich den falschen Code hochgeladen, daher kann ich es
direkt mal ausprobieren.
if(duty_cycle>4.98&&duty_cycle<10.02)// FOR 5-10% duty cycle PWM
7
lcdUpdate("Isolation","OK");
8
delay(1000);
9
10
elseif(duty_cycle>89.89&&duty_cycle<95.02)// FOR 90-95% duty cycle PWM
11
lcdUpdate("Isolation","Fehlerhaft");
12
delay(1000);
13
14
}
Du hast Glück, dass es sich nur um die Delays handelt aber nichts desto
trotz hast du mit deiner Änderung die Logik verändert.
Code-Einrückung ist KEIN akademisches Gefasel, damit man Schüler quälen
kann! Code-Einrückung ist ein WErkzeug um die Struktur des Codes, seine
logische Struktur sehen zu können!
1
elseif(freq>=29.0&&freq<=31.0)
2
{
3
lcdUpdate("Schnellstart","Messung");
4
delay(1000);
5
6
if(duty_cycle>4.98&&duty_cycle<10.02)// FOR 5-10% duty cycle PWM
7
lcdUpdate("Isolation","OK");
8
9
elseif(duty_cycle>89.89&&duty_cycle<95.02)// FOR 90-95% duty cycle PWM
da stimmt was in der Einrückungshierarchie nicht!
Nach jeder öffnenden { wird der nachfolgende Code um 2 Zeichen
eingerückt. Bis zur schliessenden }. Diese wird wieder um 2 Zeichen
ausgerückt. Die letzte } einer Funktion muss wieder ganz am linken Rand
sein, sonst stimmt in der Einrückung etwas nicht. Und: 2 } können
niemals untereinander stehen.
Und? Funktioniert der Code noch?
Du testest hoffentlich regelmässig, ob noch alles geht?
Der Hauptpunkt war meiner Meinung nach das Umändern der Berechnung.
Danach hätte dein Programm schon funktionieren müssen. Die Schritte
danach sind Kosmetik um den Stil des Programmes zu verbessern. Aber sie
ändern nichts mehr an der Funktionalität.
Habe Ordnung in in den Code gebracht und die Klammern passen nun auch,
aber der Code funktioniert leider nicht mehr, bekomme einige Fehler
ausgegeben.
der Erste: ISO_neu1_2:56: error: invalid conversion from 'const char*'
to 'long int'
bezieht sich auf die Zeile:
lcdUpdate( "Status:", "Kein Fehler" );
Naja, ich hätte eigentlich gern direkt den vernünftigen Code zum Laufen
gebracht. Aber ich finde in angemessener Zeit nichtmal den ersten
Fehler. Daher werde ich nun mal versuchen, das Ganze mit der
modifizierten Berechnung zum Laufen zu bringen;)
M. N. schrieb:> der Erste: ISO_neu1_2:56: error: invalid conversion from 'const char*'> to 'long int'> bezieht sich auf die Zeile:>> lcdUpdate( "Status:", "Kein Fehler" );
Kann ja nicht so schwer sein.
So viele Funktionen lcdUpdate, die 2 Argumente nimmt hast du ja nicht
:-)
Also Funktionsdefinition der lcdUpdate Funktion suchen und nachsehen, wo
du das Argument verbummelt hast.
Wenn ich raten müsste, dann hast du wahrscheinlich hier
> Naja, ich hätte eigentlich gern direkt den vernünftigen Code> zum Laufen gebracht.
Tu das.
Es bringt nichts, an dem alten Code rumzuschnitzen, nur weil dir der
neue Probleme macht.
> Daher werde ich nun mal versuchen, das Ganze mit der> modifizierten Berechnung zum Laufen zu bringen;
Aha. Das heißt du hast den Fehler Nummero Due gemacht:
Zuviele Änderungen auf einmal, ohne jede einzelne zu testen.
OK. in dem Fall: Gehe zurück auf Start, ändere die Berechnung, und sieh
erst mal zu, dass du dein Programm in einen korrekten Zustand bringst.
Und dann geht die Aufräumaktion wieder von vorne los.
Lehrgeld - mussten wir alle zahlen
Im Ernst: Eines der Um und Aufs in der Softwareentwicklung ist das
Arbeiten in kleinen Schritten. Niemand, auch die Profis nicht, kann ein
hinreichend großes Programm in einem Zug schreiben. Das ist einfach ein
Trugschluss! Die Komplexität wächst mit der Codelänge schneller, als wir
Menschen sie überblicken können! Daher: kleine Schritte machen.
Zwischenziele stecken. Beim Erreichen des Zwischenziels: testen, testen,
testen. Dabei festgestellte Fehler erst korrigieren, ehe es dann weiter
geht zum nächsten Zwischenziel.
Der Unterschied zwischen dir und mir ist, dass meine Schritte größer
sind.
Und natürlich, dass ich mit Fehlermeldungen vom Compiler was anfangen
kann. Ein 'funktioniert nicht', ist bei mir immer eine Sache, das in der
Programmlogik was faul ist und nicht, dass ich die Syntax nicht
hinkriege.
Zweiteres kann man lernen, so wie man eine Fremdsprache an einer
Volkshochschule lernen kann. Aber ersteres ist dann die Fähigkeit einen
ansprechenden Roman in dieser Sprache zu schreiben. Natürlich geht das
nicht von heute auf morgen, aber eine ausreichende Kentniss vom ersteren
ist eigentlich Grundvoraussetzung, damit der Beginn eines Romans
überhaupt Sinn macht. Wer kein Englisch kann, hat nun mal schon von
vorneherein verloren, wenn er einen Krimi auf Englisch schreiben will.
Karl Heinz Buchegger schrieb:> M. N. schrieb:>>> der Erste: ISO_neu1_2:56: error: invalid conversion from 'const char*'>> to 'long int'>> bezieht sich auf die Zeile:>>>> lcdUpdate( "Status:", "Kein Fehler" );>> Kann ja nicht so schwer sein.
Aaahhh. Reihenfolge der Funktionen im Code!
Sie muss so sein
Einfaches Prinzip:
Lies den Code von oben nach unten (genau das macht der Compiler auch).
Bevor du eine Funktion verwenden kannst (also einen Aufruf machst), muss
die Funktion bekannt sein.
Damit ergibt sich im einfachsten Fall: Zieh die Funktion vor die erste
Verwendung, und alles ist in Butter.
Der Compiler sucht sich nicht kreuz und quer die Einzelteile zusammen.
Er liest den Code von oben nach unten. Und zwar nur ein einziges mal.
Villeicht sollte der TO Gebrauch von verschiedenen Hilfsmittels machen,
zB die automatische Einrückfunktion seiner IDE und der Gebrauch von
Assert und Debugausgaben.
Gruss
Robert
Soo... habe das Gerät am Laufen. Allerdings noch mit dem unaufgeräumten
Code. Werde das nun mal zusammenfrickeln.
Der Stratege von Elance hat es auch noch geschafft, den Duty-Cycle Wert
falsch zu berechnen. µs und s sollte man nicht in eine Gleichung
werfen^^.
Danke nochmal für die ganze Hilfe bisher:)
Achja, ich hatte gestern keinen Zugang mehr zum Arduino Board und dem
Isowächter, den es auswerten soll. Daher habe ich quasi auf "gut Glück"
losgelegt.
Hier nun der vorläufige, fast komplett funktionierende Code.
M. N. schrieb:> Nun muss ich nochmal schauen, warum die 5V 0Hz nicht erkannt werden.
Dann würde ich vorschlagen, du gibst dir erst mal hier
1
high=pulseIn(M_HS,HIGH,1000000);// Measuring high for 2 seconds max
2
low=pulseIn(M_HS,LOW,1000000);// Measuring low for 2 secs max
die gemessenen Werte aus. Dank deiner Codeaufräumaktion ist das ja jetzt
ein Klacks, weil du ja eine schöne Funktion hast, die du benutzen kannst
:-)
1
high=pulseIn(M_HS,HIGH,1000000);// Measuring high for 2 seconds max
2
low=pulseIn(M_HS,LOW,1000000);// Measuring low for 2 secs max
3
4
lcdUpdate("High ",high,"");
5
delay(1000);
6
lcdUpdate("Low ",low,"");
7
delay(1000);
und wenn du die konkreten Zahlen vor Augen hast, dann weiß man dann
meist auch schon mehr oder kriegt zumindest einen Hinweis.
:-)
Hat sich schon gelohnt, den Code aufzuräumen und zu strukturieren. Ab
jetzt arbeitet diese in die Vorleistung investierte Zeit für dich und
spielt sich sukzessive wieder rein, weil du in der Fehlersuche schneller
bist :-)
Karl Heinz Buchegger schrieb:> und wenn du die konkreten Zahlen vor Augen hast, dann weiß man dann> meist auch schon mehr oder kriegt zumindest einen Hinweis.
Aber ich schätze mal, das Problem wird sein, dass du bei konstantem
Eingangspegel hier
1
high=pulseIn(M_HS,HIGH,1000000);// Measuring high for 2 seconds max
2
low=pulseIn(M_HS,LOW,1000000);// Measuring low for 2 secs max
zwei mal eine 0 kriegen wirst. Die Funktion heißt nicht umsonst pulseIn.
Und wo kein Puls ist (wegen konstantem Pegel) kann man auch keinen Puls
messen.
Damit kann dann diese Asuwertung
1
if(high==0)// Means that f=0 Hz and the value is LOW
2
{
3
lcdtext("IMD aus oder","Kurzschl. Kl.31");
4
}
5
elseif(low==0)// Means that f=0 Hz and the value is HIGH
6
{
7
lcdtext("Kurzschluss zu","Ub+ / Kl.15");
8
delay(1500);
9
}
auch nicht funktionieren. Denn wenn high gleich 0 ist, dann wird ja
bereits das erste if genommen und das else hat keinen Effekt mehr.
D.h. die ganze Auswertung ist falsch. Anhand der high bzw. low Zeiten
alleine kannst du nicht feststellen, wie der Pegel an der Leitung ist.
Da musst du schon die Leitung selber befragen, welchen Pegel sie hat.
Ist aber alles geschätzt und abgeleitet davon, wie ich mir denke, wie
die pulseIn Funktion arbeitet.
Treffer -- Versenkt.
Nun funktioniert es.
Habe den Code geändert zu:
1
if(high==0&&M_HS_state==0)
2
{
3
lcdtext("IMD aus oder","Kurzschl. Kl.31");
4
}
5
elseif(low==0&&M_HS_state==1)
6
{
7
lcdtext("Kurzschluss zu","Ub+ / Kl.15");
8
delay(1500);
9
}
Gibt bestimmt einen eleganteren Weg, das zu lösen. Aber es funktioniert.
Danke nochmal für die Hilfe:)
Das nächste mal werde ich es versuchen, selbst zu machen. Wenn es dann
am Ende funktioniert, machts noch mehr Spaß:)
Kannst du eine gute Einsteigerlektüre empfehlen?
Macht es Sinn sich auf Arduino zu beschränken oder dann besser ein C
Buch zu nehmen?
Aber dazu findet sich bestimmt im Netz auch einiges.
Gruß,
Marco
M. N. schrieb:> Macht es Sinn sich auf Arduino zu beschränken oder dann besser ein C> Buch zu nehmen?
Du brauchst beides.
Erst mal ein gutes Verständnis der Grundlagen von C++ (du programmierst
C++ und nicht C. Auch wenn es so ähnlich aussieht).
Und dann darauf aufbauend die Spezialitäten der Programmierung auf dem
Arduino.
Die generelle Empfehlung ist, erst mal einen soliden Grundstock in
allgemeiner Programmierung zu erwerben und erst dann den Schritt auf die
Speizialitäten der µC-Programmierung zu gehen.
> Aber dazu findet sich bestimmt im Netz auch einiges.
mit Sicherheit.