Go Down

Topic: Programm läuft von alleine los - LED glimmt - geht es schneller ? (Read 2 times) previous topic - next topic

DrThunderhell

Apr 20, 2013, 11:08 pm Last Edit: Apr 21, 2013, 02:01 pm by DrThunderhell Reason: 1
Kann mir jemand mal helfen und bitte über meinen Quellcode schauen,
ich bin total neu in der Materie und kenn mich noch kaum aus. Hab einen Arduino Mega 2560.

Manchmal Funktioniert es manchmal nicht. Aber nach einem reset/oder upload läuft es immer von alleine los.

Die Funktion des Programms sollte sein:
Nach betätigen eines Tasters und einer Wartezeit werden 4 Schritte durchlaufen die jeweils den Ausgang für eine bestimmt Zeit ein- oder Ausschalten.
Währenddessen sollen 3 Analogeingänge und ein Digitaler eingelesen werden und der Taster nicht betätigt werden können.


Probleme:
- nach Aufspielen des Programms läuft es los ohne das ich auf den Taster drücke.
- manchmal kann ich mit dem Taster starten, manchmal nicht.
- wenn der Zyklus einmal durchlaufen ist glimmt die LED noch und schaltet nicht komplett ab. (Habs auch mit der Internen an PIN13 versucht, selbes Phänomen)

Zusatz Fragen:
- warum hab ich eine steigende Analoge Spannung von 1-2V obwohl ich noch keine Spannung angelegt habe? oder ist genau das der Grund?
- Die Programmlaufzeit ist laut dem Logfile ca 30ms, geht das nicht schneller?


Als Anlage hab ich mein Programm, den Aufbau und das Logfile hinzugefügt.

Wär schön wenn sich jemand findet der mir helfen könnte.
gruß Jens

t3d_et

Läuft das Programm denn ansonsten normal ab? Wäre zur Sicherheit noch interessant, auch mal den "Zustand" zu loggen und natürlich den Ausgang an dem die LED angeschlossen ist.

Dass du an den analogen Eingängen Blödsinn misst, wenn nichts angeschlossen ist, ist normal.

Ein vorprogrammiertes Problem wirst du früher oder später mit der Zeitsteuerung haben. Integer gehen nur bis 32'768, dann überlaufen sie, das sind in ms also ca. 30 Sekunden. Mit unsigned long hast du ein bisschen mehr Luft.


J3RE

Du hast break; in den einzelnen case-Abfragen vergessen. Bei dir werden alle "cases" schon beim ersten Programmdurchlauf abgearbeitet.

Code: [Select]
switch (Zustand)
  {
  case 0:  //waiting for start
    digitalWrite(FGL1, LOW);
    if (WertTaster == HIGH)
    {
      Starttime=millis();
      Zustand = 1;
    }
    break;
  case 1:  //Startdelay
    if ((millis()-Starttime)>=Startdelay)
    {
      digitalWrite(FGL1, HIGH);
      Zustand = 2;
    } 
    break;
...


Ein freier/unbeschalteter Analogeingang wir immer irgendetwas anzeigen, weil das Potential nicht definiert ist, d.h. Es wird zwischen 0 und 5V liegen.

Die Variable Starttime muss unsigned long sein, wie t3d_et schon erwähnt hat.

Grüße,
J3RE

DrThunderhell

Ok Danke, hat prima funktioniert.

Die breaks hab ich total vergessen^^ aber nachdem sie gesetzt wurden hat auch das glimmen der led aufgehört und es läuft auch nicht mehr von selber an.
Das mit den Int, unsigned Long wusst ich nicht.


was mich noch interessieren würde:
- die Zykluszeit der Messungen sind laut logfile immer noch ca 40ms, kann man das Programm noch irgendwie schneller machen? was schluckt soviel Zeit?

Klaus_ww

Baudrate der seriellen Ausgabe auf Maximum bringt noch was.

DrThunderhell

Was ist denn maximal möglich ?

es wird doch vorgeschlagen mit 9600 zu arbeiten, kann da nichts kaputt gehen?

Eisebaer

hi,

nein, mit der baudrate kannst Du nichts kaputtmachen, da wird kein strom zu hoch oder so...

es kann nur passieren, daß bei zu langem kabel oder schlechtem kabel die kommunikation nicht mehr zuverlässig ist.

gruß stefan

DrThunderhell

ok, hab sie jetzt mal auf 115200 gesetzt, da gehts schon anders ab.
Zykluszeit 4ms.
Der Serialmonitor in dem Arduino Programm lässt sich nicht höher einstellen.


Geht noch mehr? wenn ja wie?
Sehr geil wär es wenn eine kontinuierliche Zykluszeit von 100ns oder so machbar wäre.

Marcus W

#8
Apr 21, 2013, 02:56 pm Last Edit: Apr 21, 2013, 03:04 pm by Marcus W Reason: 1
100ns sind 10-7 Sekunden oder 0,0000001 Sekunden. Der Takt deines Arduinos ist maximal 16Mhz also 106 Hertz oder 16.000.000 Zyklen pro sekunde... also 62.5ns pro Zyklus. In den 100ns Bereich wirst du fast unmöglich vordringen, da das Programm auch noch Laufzeit benötigt.

DrThunderhell

hm ok, klingt eindeutig.
Aber ist es nicht trotzdem irgendwie möglich das Programm schneller zu machen oder noch abzuspecken?

Ich hab auch was von nem prescaler gelesen, habs aber nicht ganz geschnallt, was macht dieser?

Wärs möglich die Werte permanent über nen Timer interrupt auszulesen? Das Programm kann ja "langsamer" laufen

guntherb

#10
Apr 21, 2013, 05:29 pm Last Edit: Apr 21, 2013, 05:41 pm by guntherb Reason: 1
welchen Teil genau willst du denn schneller haben?

Man kann Programmteile, die nur seltener gebraucht werden in Zeitscheiben auslagern, dann bleibt die eigentliche loop() schlanker und schneller.

Code: [Select]
if (millis()> Zeitscheibe_1sek )    // Zeitscheibe wird alle 1000ms aufgerufen
 { Zeitscheibe_1sek  = millis()+1000;  
  // mach was, was nur jede Sekunde erledigt werden muß
} // end Zeitscheibe_1sek


Allerdings wird die Ausführung der Loop bei der Zeitscheibe jedesmal kurz unterbrochen.

die Zeile
Code: [Select]
float VoltageA0 = WertA0*(5.0/1023.0); könntest du ändern in
Code: [Select]
float VoltageA0 = WertA0 / 204.6

das spart eine floating point multiplikation.

Um zu sehen, wie schnell dein Code wirklich ist, ohne Serial.print, kannst du an Anfang der loop() einen befehl setzen
Code: [Select]
Timestamp0 = micros() dann, vor Beginn der Ausgabe
Code: [Select]
Timestamp1 = micros() und in der Ausgabe dann
Code: [Select]
Serial.print(Timestamp1 - Timestamp0).

Gunther
Grüße
Gunther

DrThunderhell

Merci gunther für den Tip, hab ich gleich mal gemacht.
Wenn ich nur die Loopschleife messe hab ich 8-16 µs.
Kommt aber die Serielle Ausgabe hinzu sind es 2000-4000µs je Zyklus.

d.h. die Ausgabe bremst aus.

Ist es denn nicht möglich mit einem serial.print Befehl mehrere Variablen zu schicken. Evtl als Array oder so?
Oder kann ich die Baudrate noch mehr erhöhen als 115200? Wie kann ich es dann lesen, der Serial Monitor kann ja nur bis 115200.

Gruß Jens

michael_x

@Gunther:
Quote
das spart eine floating point multiplikation.

Mein (und dein) avr-gcc Compiler ist so schlau, dass er das selber merkt:

Code: [Select]
void setup() {
float VoltageA0 = analogRead(A0)*(5.0/1023.0);
//float VoltageA0 = analogRead(A0) / 204.6;
Serial.begin(115200);
Serial.print(VoltageA0);
}
void loop() {}

Übersetzen für einen Uno liefert:
Binäre Sketchgröße: 3.932 Bytes (von einem Maximum von 32.256 Bytes)
Wenn ich den Kommentar in die obere Zeile setze, kommt der gleiche Sketch von 3.932 Bytes raus.
Aber ganz auf float verzichten bringt was...

Es gibt andere Terminal-Programme, die evtl. auf mehr als 115200 eingestellt werden können.
Ein 16MHz Arduino sollte auch noch 230400, 250000 oder noch mehr können, schau dir mal diesen Thread an.

Aber, als Mensch mitlesen geht etwa bis 9600, darüber brauchst du auf der PC-Seite sowieso ein Empfangsprogramm, dass die vielen Daten weiterverarbeitet (wie z.B. das erwähnte "Oszilloskop")





DrThunderhell

Mitlesen brauch ich es ja nicht, meine Messung startet und wird einfach mitgeloggt.

Das Ergebniss lass ich mir nacher irgendwo Grafisch darstellen zum Auswerten.
Aber es wär halt schöner, wenn es noch nen ticken schneller gienge als derzeit ~3ms/Zyklus. kontinuierlich (Beziehungsweise für einen variablen Messbereich zwischen 1 und 30 Sekunden).

michael_x

#14
Apr 21, 2013, 07:37 pm Last Edit: Apr 22, 2013, 12:11 am by michael_x Reason: 1
Wenn es eh kein Mensch direkt lesen soll:

Eine Zahl im Bereich 0 .. 256255 kann man mit 4 Buchstaben, z.B.  "255," oder binär als 1 Zeichen übertragen.
Dadurch kriegst du statt 3 ms z.B. 1 ms hin.

Mit anderen Daten bringt Binär statt Text nicht ganz so große, aber auch deutliche Verbesserungen.

Edit: 0...256 wären 257 verschiedene Werte, also einer zuviel. Sorry

Go Up