Servus , in meinem Programm nutze ich einen Timer zum Ansteuerung von 2 Schrittmotoren. Nun würde ich gerne einen zweiten Timer nutzen um in einen festen Zeitintervall Wetre auszulesen. Das Programm zum auslesen der Werte über einen Timer hab ich geschrieben und Funktioniert auch blendend. Das Problem ist jetzt folgendes, wenn ich beide Programme "verheirate" funktioniert das Auslesen der Werte ohne problme aber der Schrittmotor rattert und läuft nicht rund, bzw. nicht so wie er sollte. Ich hab darauf geachtet die Timerinterrupt-Routine so kurz wie möglich zu halten. Die ganze Rechnenroutine hab ich in die main() verlagert die Interrupts holen sich nur die Varibale. Aber es funktionert torzdem nicht. Die beiden Programme für sich allein Funktionieren einwandfrei, nachdem "verheiraten" wird auch keine fehlermeldung angezeift weswegen ich ziemlich ratlos bin. Spaßes halber habe ich das ganze auch ohne den zweiten timer probiert, sondern hiermit: void loop() { int AktuelleZeit = millis(); if(AktuelleZeit - VergangeZeit >= Zeitintervall) { VergangeZeit = AktuelleZeit; // macht irendwas..... } } So Funktionieren es, ich würde es tortzdem ganz gerne über die Timer zum laufen kreigen.
@Ahmet D. (closed_loop_stepper) >Das Problem ist jetzt folgendes, wenn ich beide Programme "verheirate" >funktioniert das Auslesen der Werte ohne problme aber der Schrittmotor >rattert und läuft nicht rund, bzw. nicht so wie er sollte. Dann stimmt wohl dein Konzept nicht. Oder dessen Umsetzung. >Interrupts holen sich nur die Varibale. Aber es funktionert torzdem >nicht. Zeige uns deinen VOLLSTÄNDIGEN Quelltext als Anhang.
Beitrag #5504330 wurde von einem Moderator gelöscht.
Ahmet D. schrieb: > Das Problem ist jetzt folgendes, wenn ich beide Programme "verheirate" > funktioniert das Auslesen der Werte ohne problme aber der Schrittmotor > rattert und läuft nicht rund, bzw. nicht so wie er sollte. Entweder semantischer Fehler oder Verlassen der Echtzeit. Ergo ist die Fehlersuchstrategie entweder: 1) Prüfung, dass das Geschriebene jederzeit passieren darf, ohne dass dadurch die Echtzeit verlassen werden muss. Geht diese Prüfung positiv aus->semantischer Fehler. 2) Prüfung der Programmlogik. Geht diese Prüfung positiv aus->Verlassen der Echtzeit Man darf auch gerne beide Prüfungen anwenden. Wenn man was im Kopp hat, wird man das bei dem beschriebenen Fehlerbild sogar ganz sicher tun... Wenn man noch mehr im Kopp hat: dann hätte man die Echtzeit-Constraints vorher geprüft, bevor man den zweiten Programmteil überhaupt angefangen hätte zu schreiben und man bräuchte dann nur noch nach semantischen Fehlern zu suchen... > Ich hab darauf geachtet die Timerinterrupt-Routine so kurz wie möglich > zu halten. Drauf' geschissen. "So kurz wie möglich" bedeutet halt niemals: "sicher kurz genug". Wenn's so einfach wäre, könnte man ja wirklich alles einfach in VB.net, C#, JavaScript oder Python schreiben und bräuchte sich niemals Gedanken um die Laufzeit von Code zu machen. So isses aber eben nicht...
@Ahmet D. (closed_loop_stepper) Naja. 1.) in eine.h Datei (AMS5812.h) gehört KEIN ausführbarer Code, sondern nur #defines, Deklarationen, Funktionsprototypen etc. 2.) Die Abfrage deines Sensor AMSSensor() in ISR(TIMER5_COMPA_vect) ist wahrscheinlich zu langsam. Denn dort ist nicht nur eine Menge I2C-Kram (wire) drin, auch viele Fließkommaberechnungen und Divisionen. Das alles kostet Zeit. Zeit, in der der andere Interrupt nicht bedient wird. Lösung. Die Abfrage deines Sensor aus der ISR entfernen und in die Hauptschleife (Loop() ) verlagern. GGf. von Fließkomma auf Festkommaarithmetik umbauen, denn Fließkomma brauchst du hier nicht wirklich. 3.) Auch wenn du die ganzen UART-Ausgaben auskommentiert hast, sie gehören nicht in dieser Funktion. Schreibe eine 2. Funktion nur zur Ausgabe der Rohdaten bzw. Zwischenergebnisse. Das ist auch praktischer für die Fehlersuche. 4.) Der Reset der Timer5 Register ist Unsinn, die haben definierte Resetwerte. Außerdem kann man die normal setzen, als mit TCCR5B = ... 5.) Wo ist die Initialisierung von Timer 1 und des Interrupts?
Hallo, eine Anmerkung. Beim Arduino wie hier, müsste ein Mega2560 sein, muss man von selbst genutzten Timern die Register manuell reseten. Die sind durch PWM Funktionen wie analogWrite oder Zeitfunktionen wie millis vorbelegt. Gültig wenn man in der Arduino IDE oder Atmel Studio mit Plugin programmiert. Also die Arduino IDE Ressourcen nutzt. Programmiert man klassisch muss man das nicht machen. Klassisch geht auch in der Arduino IDE ohne setup/loop mit main und while. Nur fehlen einem dann die fertigen Komfortfunktionen. Das so nebenbei.
Hallo c-hater, c-hater schrieb: > Entweder semantischer Fehler oder Verlassen der Echtzeit. semantischer Fehler sind klar, aber was mienst du mit verlassen der Echtzeit. ich nehme mal an das du damit meintst das die Hardware nicht hinterher kommt. Zu dem Punkt hab ich mir mal gedanken gemacht wie schnell der Timer für den Schrittmottor ausschlägt. Der Timer hat keinen vorteiler aktive und braucht zwischen 833 und 5000 takte. Mit 16MHZ also 62,5 Nano Sekunden pro Takt, bedeutet das der Timmer alle 52000 bis 312.500 Nano Sekunden braucht. Der zweite Timer schlägt soll jede 1/10 Sekunde ausschlgen. und meinst du mit: c-hater schrieb: > Wenn man noch mehr im Kopp hat: dann hätte man die Echtzeit-Constraints > vorher geprüft, Was meinst du mit Kopp und Echtzeit-Constraints. Wenn du mit Kopp, Kopf meinst machts Sinn, sonst wäre eine Erklärung sehr schön. vielen Dank im Voraus
Ahmet D. schrieb: > semantischer Fehler sind klar, aber was mienst du mit verlassen der > Echtzeit. > ich nehme mal an das du damit meintst das die Hardware nicht hinterher > kommt. Eher: das Programm (bzw. der Programmteil) ist zu langsam. Die Hardware ist niemals Schuld, denn deren Eigenschaften sind immer vorab bekannt. Es ist also Aufgabe des Programms, jederzeit schnell genug zu sein. Genauer: Es ist Aufgabe des Programmierers, dafür zu sorgen, dass sein Programm das ist... > Wenn du mit Kopp, Kopf meinst machts Sinn Ja, ich bin mitteldeutsch->Kopp=Kopf. Scheint aber fast deutschlandweit durchzugehen. Sogar die Migranten in Berlin-Kreuzberg und anderswo verstehen auf Anhieb, was "Kopp" bedeutet, benutzen das Wort teilweise sogar aktiv selber. Aber: Ist natürlich kein klassisch geprägtes Oberschichten-Schul-Deutsch. Nächstes Mal werde ich die sechs Zentimeter bis zur "f"-Taste zurücklegen, damit es auch für Neudeutsche völlig unmissverständlich wird...
Hallo Falk, und zu deinem zweiten Punkt Falk B. schrieb: > 2.) Die Abfrage deines Sensor AMSSensor() in ISR(TIMER5_COMPA_vect) ist > wahrscheinlich zu langsam. Denn dort ist nicht nur eine Menge I2C-Kram > (wire) drin, auch viele Fließkommaberechnungen und Divisionen. Das alles > kostet Zeit. Zeit, in der der andere Interrupt nicht bedient wird. Die Berechung habe ich in einer Funktion ausgeglidert. Auf gerufen wird sie aber in der main(). Das ergeniss der Brechnung speicher ich in einer globalen Variable. Der Timer macht nichts anderes als sich die Variable zu ziehen. In der TimerRoutine wird nichts berechnet. Deswegen weiß ich nicht was du mit in die main() verlagern meinst.
@ Ahmet D. (closed_loop_stepper) >> 2.) Die Abfrage deines Sensor AMSSensor() in ISR(TIMER5_COMPA_vect) ist >> wahrscheinlich zu langsam. Denn dort ist nicht nur eine Menge I2C-Kram >> (wire) drin, auch viele Fließkommaberechnungen und Divisionen. Das alles <> kostet Zeit. Zeit, in der der andere Interrupt nicht bedient wird. >Die Berechung habe ich in einer Funktion ausgeglidert. Nö. Ich rede von ISR(TIMER5_COMPA_vect) > Auf gerufen wird >sie aber in der main(). Das ergeniss der Brechnung speicher ich in einer >globalen Variable. Der Timer macht nichts anderes als sich die Variable >zu ziehen. In der TimerRoutine wird nichts berechnet. Doch >Deswegen weiß ich nicht was du mit in die main() verlagern meinst. Das was ich oben geschrieben habe. Die Rede ist von ISR(TIMER5_COMPA_vect). Du aber redest von ISR(TIMER1_COMPA_vect).
Falk B. schrieb: > Nö. Ich rede von > > ISR(TIMER5_COMPA_vect) > >> Auf gerufen wird >>sie aber in der main(). Das ergeniss der Brechnung speicher ich in einer >>globalen Variable. Der Timer macht nichts anderes als sich die Variable >>zu ziehen. In der TimerRoutine wird nichts berechnet. > > Doch > >>Deswegen weiß ich nicht was du mit in die main() verlagern meinst. > > Das was ich oben geschrieben habe. Die Rede ist von > ISR(TIMER5_COMPA_vect). Du aber redest von ISR(TIMER1_COMPA_vect). endweder stehe ich auf dem schlau oder ich verstehs nicht. ISR(TIMER5_COMPA_vect) { // für den sensor AMS5812 // ISR_NOBLOCK vlt int Druck = GetAMSSensor(); } int GetAMSSensor() { return GetWert; } Also ich sehe hier einfach nur wie der Timer in int Druck den Wert der variable GetWert setzt. Das aht dich mit dem I2C nichts zu tun oder ?
@Ahmet D. (closed_loop_stepper) >endweder stehe ich auf dem schlau oder ich verstehs nicht. >ISR(TIMER5_COMPA_vect) { // für den sensor AMS5812 // ISR_NOBLOCK vlt > int Druck = GetAMSSensor(); >} Ok, mein Fehler! Ich habe die beiden Funktionen verwechselt, weil sie sehr ähnlich heißen. Aber damit ist die Anweisung sinnlos, denn du machst nichts mit dem Wert in der ISR. Was passiert, wenn du die Zeile auskommentierst, die ISR also leer ist?
Kein Ding ^^ Ich will später die in der variable Druck gespeicherten werte als Regelgröße für die anstehende regelung verwenden Aber wie war das mit reset von TCCR5B = ... Am integer und I2C hat nicht gelegen
Hallo, Beitrag "Re: Mehrfachnutzung Timer" sind dir die Unterschiede klar?
1 | Bsp. |
2 | |
3 | TCCR5A = 0; |
4 | TCCR5A = (1<<COM1B1); |
5 | TCCR5A |= (1<<COM1B1); |
Du programmierst doch in der Arduino IDE oder? Edit: diese muss man selbst behandeln bzw. reseten TCCR5A TCCR5B TCCR5C TIMSK5 diese bei Bedarf wenn man sie benutzt, dann erfolgt sowieso eine Grundeinstellung OCR5A OCR5B OCR5C TCNT5 kann man nullen, muss man nicht, man macht es aus Gewohnheit Wie gesagt, muss man im Zusammenhang mit oben geschriebenen sehen.
:
Bearbeitet durch User
Als erstes ich hab doch noch zum laufen gebracht. Ja mit dem Arduino Mega2560. Veit D. schrieb: > Hallo, > > Beitrag "Re: Mehrfachnutzung Timer" > > sind dir die Unterschiede klar?Bsp. > > TCCR5A = 0; > TCCR5A = (1<<COM1B1); > TCCR5A |= (1<<COM1B1); > > Du programmierst doch in der Arduino IDE oder? ich denke eher unzureichend. TCCR5A ist ein Kontrollregister "timer control register A" ^^. Druch das setzen von bits kann man dan bestimmte Funktionen aktiverien (00; 01; 10; 11) die dan so tolle namen wie COM1B1 haben. Eine Frage müsste es nicht COM1"A"1 sein? > TCCR5A = (1<<COM1A1); > TCCR5A |= (1<<COM1A1); https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR Wäre cool wenn du es mir in deinen Worten erklären könntest.
Hi
>Eine Frage müsste es nicht COM1"A"1 sein?
Kommt darauf an, welche Kanäle du in TCCR5A ansprechen willst:
Bit 7:6 – COM5A1:0 Compare Output Mode for Channel A
Bit 5:4 – COM5B1:0 Compare Output Mode for Channel B
Bit 3:2 – COM5C1:0 Compare Output Mode for Channel C
MfG Spess
Ahmet D. schrieb: > Also gings nur darum das, > >> TCCR5A = 0; > > unprofessionell aussieht ? Nein! > TCCR5A = (1<<COM1A1); Vollkommener Stuss. Unsinnig, und damit ein gefährlicher Irrtum. Du meinst: >TCCR5A = (1<<COM5A1) Wenn es auch bei diesen konkreten Timer gerade klappt, dann wirst du bei anderen Timern/µC mit einer solchen Schlampigkeit auf die Nase fallen. Entschuldige bitte, die harten Worte. Ich möchte bei dir den "Finger auf Herdplatte Effekt", also das "lernen" daraus, anstoßen. Denn nach solchen Fehlern, kann man sich dull und dusselig suchen, da es ja plausibel aussieht, keine Meldungen wirft, und das eigene Hirn es gerade bügelt. Der Fehler liegt gerne außerhalb des Fokus.
Hallo, ja war ein Tippfehler mit der 1 statt 5. Entschuldigung. War nur ein Bsp. für das Verständnis / Unterschied von = 0 oder = bestimmtes Bit oder |= also was mit dem Inhalt des Registers dabei passiert. Ich empfehle dir einmal in aller Ruhe die Timerregister im Datenblatt anzuschauen. Die Namen sind eindeutig. Die der Register und dessen Bits. Bei allen anderen Unklarheiten fehlt mir die konkrete Frage um darauf eindeutig antworten zu können. Eine Frage an dich habe ich noch die du dir selbst beantwortest. Die Timerregister werden durch die Arduino IDE vorbelegt. Wenn du nun einen Timer selbst verwendest und die Register die du für deine Verwendung nicht benötigst nicht nullst, was passiert dann mit dem Timer im Gesamten? Also wie verhält er sich? Macht er das was du möchtest oder macht er was anderes?
Veit D. schrieb: > Eine Frage an dich habe ich noch die du dir selbst beantwortest. Also mit dem Nullen läufts defenetiv besser.
Leute ich hätte ein Weiters Problem das eure Hilfe benötigt. ich will jetet eine Regelung drauf setzen. Nun wie ich mir das ganze Vorstelle. Ich will die Drezhal der Schrittmotoren über den Druck reglen. Dazu hab ich ein Array in dem ich bestimmte Schwelllenwerte deklariert habe. Die Drezahl soll sich so lange erhöhen oder verringen bis der Schwellenwert erreicht wurde. Ist der Schwellenwert erreicht worden wird das nächst Schwellenwert vom Array hergezogen und das ganze geht von vorne los. Wenn der letzte Wert vom Array heranggezogen wird, soll der Feldzähler des Arrays wieder auf das erste Feld zeigen, damit das ganze von vorn los geht. Den Druckwert der von Sensor gelsen wird stelle ich über den Barometer ein den ich mittel Silikonschläuchen und einer Großen Sprizte einstelle. Barometer und Sensor sind mit der Sprizte parallel verzeigt verbunden, deswengen stellt sich bei beiden der gleiche Druck ein Die Drehzahl beeinfluss über den Timer, oder genauer über die Funktion Setspeed(). Der Timer zieht sich nur den Wert aus der Funktion Setspeed() ins Regsiter und löst danach aus und macht dan eine Step für beide Motoren. Der Wert den sich der Timer zieht liegt zwischen 3200 bis 22.400. Der Code steht nocht nicht so wie oben beschreiben und befindet sich noch in der entwicklungspahse aber es gint schon erste probleme Meine erste Frage: Also ich lasse in der Main die unten genannte Funktion laufen. Mein Problem wenn ich am Barometer den gewünschten Druck einstelle, ziehn die motoren die Drehzahl an bis sie hangen bleiben egal on sie Unterhalb, Oberhalb oder genau im Druckberech liegen. Wenn ich aber die ber die Auskommentierten Prints einkommentire sehe ich am Seriellem monitor das, er Arduino genau das macht was er machen soll. leigt darüber runterzählen... liegt darunter hoch zählen ..... .... void ReglerStellen() { if(InputDruck <= (SetponitArray[Setpointzeahler]-15)) // SetponitArray[Setpointzeahler] entspricht 100. { Steller= Steller + 50; // Steller wird der Funktion Setspeed() über geben. //Serial.println("Hochzählen"); } if(InputDruck >= (SetponitArray[Setpointzeahler]+15)) // SetponitArray[Setpointzeahler] entspricht 100. { Steller = Steller - 50; // Steller wird mit 3200 deklaiert,Steller hat sollte nicht weit über unter 3200 und 22400 liegen. //Serial.println("Runterzählen"); } if( (InputDruck >= (SetponitArray[Setpointzeahler]-15) ) && (InputDruck <= (SetponitArray[Setpointzeahler]+15) ) ) { //Serial.println("Eingependelt"); } } ich verstehe nicht warum das so ist ??? echt ratlos?? vlt ist es auch was einfachs und ich sehs nur net, HOFFENTLICH :) Meine zweite frage: ich hab nach PID Libraries gesucht und keine passenden gefunden der von Brett Beauregard <PID_v1_h> ist zwar genial aber der geeignet sich nicht , weil dieser ja so Funktionert das er einen Inpunt einen einliest und versucht einen Output entsprechend dem Setpoint zu reglen...... Mein Output der zu Regeln ist ist ein interner rechneter wert von Setpeed. Und so weit ich den jetzt einschätzen drufte bracht die Libraries einen PIN als Output. An dieser Stelle wen iht eine Libraries kennt die dazu passt bitte nennen. Oder hab ich Bertts Librarie falsch genutzt. ich hoffe ihr könnt mir weiter helfen. Und sorry für die Schlechte Darstellung ist das erste mal das ich was hier Poste
https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h Habe mir gerade mal das Interface angesehen... Da wird kein Pin genutzt/übergeben. Du siehst Geister.
Arduino Fanboy D. schrieb: > Habe mir gerade mal das Interface angesehen... > Da wird kein Pin genutzt/übergeben. > > Du siehst Geister. zu dieser späten Stunde kann gut möglich sein ^^ ich hab eher mit dem Beispiel Basic getestet und da hab er mir den wert 0 oder 255 ausgegeben. dait nicht viel anfangen. es sei den mann kann den Output auf einen Werteberetch begrenzen das wäre gigantisch
Beitrag #5508590 wurde von einem Moderator gelöscht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.