Das Problem hatten doch sicher schon viele: Kann man TCNT0 irgendwie anhalten? Ich meine nicht den Überlauf-Interrupt, den kann ich ja disablen. Aber soweit ich es gesehen habe, wird TCNT0 IMMER hochgezählt, egal ob der Interrupt anabled ist oder nicht. Warum das Ganze? Weil ich gerne bei Eintritt in eine bestimmte Interruptroutine den Zustand des Zählers einfrieren würde. Denn während ich in der ISR rumhantiere, verändert sich ja ständig TCNT0, und was am schlimmsten ist: er kann auch überlaufen, und ist dann null oder vier oder sowas, obwohl er auf z.B. auf 252 stand, als die ISR begann. Andere Timer etc. kann ich nicht nehmen, werden für was anders gebraucht. Wie löst man sowas? e.
im TCCR0 Register die Bits 2,1 und 0 löschen. Das hält den Timer an: Prescaler = 0 -> Timer gestoppt alten Prescaler wieder laden: Timer läuft weiter in R16, TCCR0 andi R16,0b11111000 out TCCR0,r16 Ich weiß jetzt nicht, mit welchem Prescaler dein Timer0 arbeitet, aber mit in R16, TCCR0 ori R16, 0b00000001 ;läuft der Timer volle Kanne weiter out TCCR0,r16 mit oriR16,0b00000010 ;prescaler von 8 ,0b00000011 ;--''-- 64 ,0b00000100 ;256 ,0b00000101 ;1024 du liesst das Timercontrolregister ein und setzt die PrescalerBit's entsprechend wieder, ohne die anderen Bits zu beeinflussen. Zum stoppen löscht Du mit Bitweiser UND Verknüpfung alle Prescaler Bits, ebenfalls ohne die anderen evtl. gesetzten Bits zu stören. Ich hoffe mein Assemblercode ist von der Syntax her richtig... @ALL Berichtigt mich, wenn ich falsch liege Gruß und schönen Abend noch Axel
eine der Standardantworten: wennst schreibst welchen Prozessor du nimmst wird man dir sicher helfen können. Ich tipp mal auf avr: Clock Source auf null setzen (CS02=0,CS01=0,CS00=0 im TCRR0) grüsse leo9
Jou, hast Recht leo: AT90S8535 Aber die Antworten haben mir schon geholfen, Danke. Ein Problem bleibt trotzdem: auch wenn ich die Registerorgie durchziehe, und den Timer einfriere: überlaufen kann er bis zu diesem Moment trotzdem noch. Hat da einer ne Idee? Oder könnte man in der ISR einfach ungefähr sowas machen: SIGNAL (blabla) { if (TCNT0 <=4) { // Timerüberlauf .... foo(); } ... }
Warum stört das Überlaufen so? mir fällt beim besten Willen nichts ein warum er nicht weiterlaufen soll (Eigentlich ist ja das der große Vorteil von Timern dass sie zählen, egal was der uP sonst macht). Vielleicht könntest du das Gesamtproblem skizzieren, ich denke da dann findet sich sicher eine Lösung. grüsse leo9
Weil ich den Timer in eben dieser ISR auswerte. Ich habe einen Timer0 mit Vorteiler 8 laufen. In der Überlauf-ISR (OVERFLOW0) addiere ich die Überläufe. Wenn nun ein bestimmtes Ereignis eintritt (Flanke an int1), dann messe ich die zeit: PulseLen = Overflows * 256 + TCNT0. Wenn nun JUST IN DIESER ISR der Timer überläuft, dann stimmt die ganze Arie nicht nicht mehr. Denn erstens wird dann NACH der ISR die OVERFLOW0 Routine ausgeführt, und somit "Overflows" hochgezählt. Das wäre aber (in dieser Anwendung) falsch. Und zweitens kann es natürlich passieren, das bei meiner Berechnung von "PulseLen" der Wert von TCNT0 nicht mehr 250 (o.ä.) war, wie zum Zeitpunkt der Flanke, sondern mittlerweile übergelaufen ist, und dehalb z.B. nur den Wert 8 hat. Und das ist erst recht falsch. Ein echtes Dilemma. Deshalb habe ich die Hoffnung, das irgend jemand iese Nuss schon geknackt hat.
Hi, ich zähle eine integer variable hoch. bei steigender flanke setze ich diese Variable auf null, bei fallender flanke werte ich die variable aus. Ist für meinen Fahrregler. Der mega8 kann ja beim Interrupt0 bei jedem flankenwechsel einen Interrupt auslösen. Ich programmiere mit FastAVR... Gruß axel
@Axel Wir lösen, wie scheint, das gleiche Problem. Ich möchte eine 4-8 KHz PWM zur Steuerung mehrerer BUZ o.ä verwenden, um 50V bei bis zu 80A zu regeln. Das Eingangssignal kommt von einer Fernsteuerung, die üblichen 0,8 bis max. 2 Millisekunden. Das Hochzählen der Int-Variable ist aber genau das Problem: wo zählst Du die denn hoch? Ich mach das mit dem erwähnten 8-Bit Timer und einem Überlaufzähler. Genau wie Du setze ich bei steigender Flanke die Werte auf Null, und werte das bei fallender Flanke aus. Läuft während dieser Aktion der Timer über, stimmt das Ganze nicht mehr. Hier die geschilderte Routine: /*----------------------------------- Interrupt bei steigender/fallender Flanke an PD3 (int1) -----------------------------------*/ SIGNAL (SIG_INTERRUPT1) // vector 2 { if (bit_is_set(MCUCR, ISC10)) // rising edge { TCNT0 = 6; // 6 where lost up to here SET_INT1_FALLING_EDGE(); // set int1 to falling edge OverFlows = 0; } else // we are at falling edge { Pulse = OverFlows * 256 + TCNT0; SET_INT1_RISING_EDGE(); // set int1 to rising edge } } Und hier das Routinchen für den 8-Bit Timer: SIGNAL (SIG_OVERFLOW0) // vector 9 { // diser 8-Bit timer läuft immer nach (Vorteiler * 256) Clocks über OverFlow++; } // SIGNAL(SIG_OVERFLOW0)
beim eintrit in die interruptroutine einfach erst den letzen timerwert sichern (tmp1) und hier kann der überlaufzähler ja nicht verändert werden, weil man ja schon im interrupt ist. ich messe erst x ms nach der hiflanke, da mich der bereich ja nicht interessiert (immer hi). habe meinen T0 aber ebenfalls auf Fosc/8 laufen lassen und maximal einen überlauf dabei -> das overflowflag flag abfragen und gut is. Besser: (um auch vor störimpulsen gewappnet zu sein) wie ihr das ganze schon hab mit überlaufzähler. Die aus den 8bit überlauf und 8bit timer bestehende 16bit zahl einfach einen nach rechts schieben ( /2 ) und die unteren 8bit enthalten den wert. vorher testen ob der überlaufzähler nen wert über 1 hat und dann nichts tuen, ausser eben wieder die fehlerzahl zählen und ggf. abschalten. ganz ideal passt das ganze allerdings nich zu meinem empfängersignal, aber ich habe in den grenzen einen bereich von 10 einheiten als vollgas, und den unteren bereich, so das es passt (rund 30 einheiten) als stillstand akzeptiert. so ist der untere berreich, in dem der motor nur brummen würde auch ausgeblendet. die fets schalte ich per PWM bei etwa 1,8 kHz hab das ganze in asm gemacht, mit einem 2313 zum testen. bin auch vorgestern schonmal damit gefahren. mich würde eure fet-ansteurung interessieren: ich treibe im mom 3 parallele buz11 mit jeweil einem 56R gate widerstand und einem gemeinsamen treibertransistor davor. Freilaufdiode am ausgang und das wars auch schon. muss man noch mehr zum entstören machen?! (ausser die 3 C´s am motor direkt) hab einen 0,22uF Folienkondi (1000V) parallel zur Freilaufdiode gepackt aber trotzdem ist die ausgangsspannung ganzschön zerhackt (vom wechsel auf das nächste kollektorfeld (?)), hat also scheinbar nix geholfen.
Timer anhalten bringt Dir nur eine Verfälschung der Zeitmessung. Das ist doch der Witz daran, daß die Timer durchlaufen und damit exakt und unabhängig von der Software arbeiten. Das Kaskadieren per Software ist einfach: Du liest zuerst den Timer und dann das Overflow-Bit. Wenn das Overflow-Bit gesetzt ist, heißt daß, der Timer ist übergelaufen, aber der Timerinterrupt hat noch nicht das High-Byte hochzählen können. Also prüfst Du noch das Bit7 des gerade gelesenen Timerwertes. Ist es 1, dann hast Du es vor dem Überlauf gelesen. Ist es aber 0, dann hast Du es nach dem Überlauf gelesen, d.h. Du must das High-Byte nach dem Lesen einmal hochzählen und alles stimmt wieder. Peter
Hi, ohoo, auf dem linken Fuß erwischt, ich probier mal in C, mache ja eigentlich mit FastAVR-Basic. Ich verwende einen Mega8 im MCUCR das Bit2(ISC10) setzen : Interrupt1 bei jedem Flankenwechsel SIGNAL (SIG_INTERRUPT1) // vector 2 { if (pind.3) //steigende flanke löste int1 aus { pulscounter=0; } else //fallende Flanke löste Interrupt1 aus { pwm_accl_tabl_index = pulscounter // steht bei mir so zwischen 247 und 350 wert der Tabelle entnehmen und dem linken oder rechten PWM-kanal zuweisen. In Abhängigkeit davon die oberen gegenüberliegenden P-Mos setzen. } } soviel zum Interrupt; ich weiß leider nicht, wie man in C den Portpin d.3 abfragt, in FastAVR geht das jedenfalls so. Hier in der else schleife erledige ich alles andere gleich mit. Mittelwert bilden, selbstlernfunktion, störimpulsausblendung (sender aus->motor aus) Bremslicht, Bremse, Rücklicht. Zeit ist ja genug da. Timer0 OHNE Vorteiler benutzen! overflow als Integer deklarieren, (wie auch immer das in C geht) int overflow , glaube ich. SIGNAL (SIG_OVERFLOW0) // vector 9 { OverFlow++; } // SIGNAL(SIG_OVERFLOW0) Soo, ich habe auch schon an anderen Stellen im Forum berichtet. Noch mal ein Bild gefällig?( ich will niemenden langweilen) Gruß AxelR.
@Henning "beim eintrit in die interruptroutine einfach erst den letzen timerwert sichern (tmp1) und hier kann der überlaufzähler ja nicht verändert werden, weil man ja schon im interrupt ist." Zwar nicht der Überlaufzähler, aber der Timer. Der läuft nämlich erst mal weiter und kann deshalb überlaufen. Schau oben mal genauer hin: der Wert könnte zum Zeitpunkt der Flanke z.B. 0xFE gewesen sein, und in der Routine dann mit 0x02 ankommen. Der Überlaufzähler macht an dieser Stelle zwar noch keine Probleme, aber wenn die Routine fertig ist, wird der T0 overflow nachgeholt, und dann der Überlaufzähler erhöht. Das wäre aber falsch, da die ISR (je nach Flanke) eine NEUE Zählung starten soll, und deshalb auch den Overflow-Zähler zurücksetzt. Wenn der unmittelbar nach dem Ende der Routine inkrementiert wird, stimmts dann nicht. "mich würde eure fet-ansteurung interessieren:" Da ists bei mir noch zappenduster, ich verstehe von Analogtechnik nicht sehr viel. Muss mir dass zu gegebener Zeit zusammensuchen. @Peter "Timer anhalten bringt Dir nur eine Verfälschung der Zeitmessung. Das ist doch der Witz daran, daß die Timer durchlaufen und damit exakt und unabhängig von der Software arbeiten." Stimmt im reinen Timerfall sicher, aber hier messe ich ja nur die Zeit zwischen zwei Flanken (hi/lo). Wenn die HiFlanke kommt, wird sowiso der Rimer auf Null gesetzt. Wenn dann die fallende Flanke kommt, dann isses im Moment des Aufrufs der ISR ja bereits passiert. Ich möchte ja genau bis zur Flanke zählen, und nicht weiter. Für die Folgemessungen ist es eh wurscht, ob der Timer erst mal gestoppt ist, oder nicht: da ich nur die High-Zeiten messen möchte, und nicht die Lowzeiten, ist im Ablauf also ohnehin eine Messlücke, in der ich dem Timer gar nicht brauche. "Du liest zuerst den Timer und dann das Overflow-Bit. Wenn das Overflow-Bit gesetzt ist, heißt daß, der Timer ist übergelaufen, aber der Timerinterrupt hat noch nicht das High-Byte hochzählen können" Diese Idee ist solange praktikabel. wie man keine PWM einsetzt. Wie oben bereits geschrieben habe, möchte ich aber genau das nutzen: PWM. Im AT90S8535-Manual heisst es dazu auf Seite 28: "Bit 0 TOV0: Timer/Counter0 Overflow Flag The bit TOV0 is set (one) when an overflow occurs in Timer/Counter0." Das hört sich zunächst gut an. Aber zwei Sätze weiter heisst es: "In up/down PWM mode, this bit is set when Timer/Counter1 advances from $0000." Und das finde ich oberblöd. Wundert mich eh: was hat das TOV0 Bit mit der PWM zu tun? Oder ist das ein Manual-Bug, oder hab ich was falsch verstanden? @Axel "pulscounter // steht bei mir so zwischen 247 und 350" Ich komme mit 8MHz und einem t0-prescaler von 8 auf Werte zwischen 819 und 2120. Das entspricht fast genau den Microsekunden der Pulse, die mein Servotester generiert (ist bei einem 8MHz Quarz und einem Vorteiler von 8 eigentlich auch logisch...). Ich kann also etwa 1200 Schritte abbilden, und so für diesen Bereich ganz wunderbar eine 10Bit PWM realisieren. Die Anlagen im richtigen Leben arbeiten allerdings nur zwischen 830 und 1500 microsekunden, Eigentlich reicht Deine Genauigkeit aber aus. Aber die Modellfuzzis (ich bin auch einer) stehen nun mal auf solche "Genauigkeit", wenns im Grunde auch Blödsinn ist. Wie sind Deine Erfahrungen in der Praxis: Braucht man eine nichtlineare Tabelle mit Regelwerten, oder kann man die Messwerte einfach linear umgesetzt in die PWM übergeben? Also z.B. bei einem Messbereich von 1024 Schritten (z.B. 850-1873) den Messwert (Value - 850) einfach der 10Bit-PWM übergeben? e.
da alle meine Variablen im SRAM stehen, brauchst bei mir etwas mehr zeit, bis alles umgeschaufelt ist. so ist mein relativ kleiner zählerwert zu erklären. Die genauigkeit reicht allemale aus. Ich habe zwei tabellen: eine für vorwärts und eine für rückwärts. Fährt sich besser, hängt auch viel vom Motor und vom Getriebe ab. so habe ich (nach abzug der Totzone um die Mittelstellung herum) 40 Stufen für vorwärts und 40 für rückwärts. den unteren Bereich habe ich gedehnt. Ich hab's ja gut: mein Meag8 hat zwei PWM-Kanäle (timer0), die kann ich direkt auf die N-MOSFET's packen. 2 Portpins schalten dann die P-MOSFETS. Sieht in FastAVR auch alles ganz einfach aus, sind keine 200Zeilen Quelltext. PWMA = Acc_table(pulscounter),PWMB = 0. oder eben umgekehrt. Aufpassen muss man aber, das nicht der 'linke' PMOS und die'linke'PWM gleichzeitig an ist. axel
"oder hab ich was falsch verstanden?" Ja, T0 hat gar keine PWM ! "aber hier messe ich ja nur die Zeit zwischen zwei Flanken (hi/lo)" Dann ist doch die Capture-Funktion von T1 die erste Wahl. Warum die Umstände mit T0 ? Capture und PWM gehen doch gleichzeitig. Peter
Hi! @Peter: na weil er mit T1 die PWM macht und da geht das mit dem IC nicht. @Axel: Du verwechselst was! TOV1 wird nur von T1 gesetzt, nicht T0! Es sollte also kein Problem sein das TOV0 Flag auszuwerten und es dann auch noch zu löschen(verhindert TOV0-Int.) MFG Uwe
@peter "Ja, T0 hat gar keine PWM !" Na eben, genau das sag ich doch: deshalb verstehe ich ja genau nicht, warum im Handbuch über das TOV0 (!) Bit: steht: ------------------------------------------------------------------ "In up/down PWM mode, this bit is set when Timer/Counter1 advances from $0000." ------------------------------------------------------------------ "Dann ist doch die Capture-Funktion von T1 die erste Wahl." Die werd ich mir sicher mal genauer anschauen, nützen tut sie mir in diesem Fall aber trotzdem nichts. Ich möchte doch PWM einsetzen, und da ist T1 dann belegt. @Uwe "Du verwechselst was! TOV1 wird nur von T1 gesetzt, nicht T0! Es sollte also kein Problem sein das TOV0 Flag auszuwerten und es dann auch noch zu löschen(verhindert TOV0-Int.)" Siehste, das wäre auch logisch. Aber nochmal: im Handbuch steht was anderes: TOV0 wird angeblich bei PWM gesetzt, wenn der Zähler bei $00 umkehrt. Das steht übrigens so nicht nur im AT90S8535 - Handbuch, sondern auch im Handbuch des ATMega128 .... e.
@Uwe "na weil er mit T1 die PWM macht und da geht das mit dem IC nicht." ??? Und wo steht das ? Beide Funktionen haben doch ihre eigenen Bits und Register. Peter
Im Handbuch steht: "Timer/Counter1 can also be used as an 8-, 9- or 10-bit Pulse Width Modulator. In this mode the counter and the OCR1A/OCR1B registers serve as a dual glitch-free standalone PWM with centered pulses." Ich verstehe "in this mode" so, dass man nur eine von beiden Betriebsarten zur gleichen Zeit nutzen kann? Korrigiert mich, wenn das falsch ist. Aber auch wenn man beides gleichzeitig nutzen kann: Der Timer kann nicht mit zwei verschiedenen Geschwindikeiten gleichzeitig laufen. Ist es nicht so, dass ich dann mit Timer1 zwangsweise den Vorteiler benutzen muss, den ich für die PWM eingestell habe? Im Handbuch steht für die 8Bit PWM Ftck/510, für 9Bit Ftck/1022 und für 10Bit Ftck/2046 Allerdings ist mir nicht so ganz klar, welche Frequenz nun Ftck ist - wenn ich es richtig verstanden habe, dann ist das bereits eine vorgeteilte Frequenz. Wie könnte sowas denn aussehen?
Hi Leute, ...Zitat den unteren Bereich habe ich gedehnt. Ich hab's ja gut: mein Meag8 hat zwei PWM-Kanäle (timer0), die kann ich direkt auf die N-MOSFET's packen. ...Zitat ende muss natürlich (timer1) heißen, sorry. Axel
das mit dem vorteiler (bei 2 Funktionen 1 Timer) kann man noch ausgleichen, aber der Tackt der fernsteuerung (wann die Hi flanke kommt) ist nicht die selbe wie die des PWM timers. ausserdem zählt der PWM hoch und wieder runter, was das wohl so umständlich macht, das mans auch lassen kann und gar per polling die impulse messen könnte. zu den fets gibt´s (nich brandaktuelle aber ganz gute) infos bei www.nessel.info hat sich schonmal jemand bei den Brushless Motoren versucht? Gibt nen selbstbau projekt Speedy-BL aber den kann man nur als bausatz kaufen für ~75Euro. http://www.megra-elektronik.de/html/speedy_bl.html
@Emax, hast recht, der T1 wechselt im PWM-Mode ständig die Richtung und damit ist dann die Capture-Funktion witzlos. Peter
Hi! Du kannst schreiben was du willst, ich finde die von dir erwähnte Zeile nicht.Bei mir steht: Bit 0 - TOV0: Timer/Counter0 Overflow Flag The bit TOV0 is set (one) when an overflow occurs in Timer/Counter0. TOV0 is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, TOV0 is cleared by writing a logic one to the flag. When the SREG Ibit, and TOIE0 (Timer/Counter0 Overflow Interrupt Enable), and TOV0 are set (one), the Timer/Counter0 Overflow interrupt is executed. Entweder habe ich ein anderes Manual oder ich bin zu blöde es zu finden.Eigentlich ist es ja auch unsinnig mit PWM in T1 das TOV0 zu setzen. das versaut ja einen ganzen Timer. Ich vermute mal einen Manual-Bug. MFG Uwe
Original Atmel-PDF: http://www.atmel.com/dyn/resources/prod_documents/DOC1041.PDF Seite 28 unten, Absatz "Bit 0-TOV0".
ok, es steht da, aber der absatz ist fast exakt gleich mit dem 2 höher: Handbuchfehler. in meinem buch AVR-risc mikrocontroller steht es nich (muss aber ja nix heissen). trotzdem währe die funktion unlogisch... probier´s doch mal in avr studio aus, da wird man das sicherlich bestätigt finden.
Das werd ich wohl auch machen. Was mich verunsichert hatte war, dass dieser Text auch im ATMega128-PDF so drin steht. Allerdings habe ich die Errata noch nicht konsultiert, auf die Idee komme ich grade eben...
Hi! Das ist tatsache ein anderes Manual un ich behaupte das ist ein Schreibfehler. Der selbe Satz steht ja auch bei TOV1. Noch deutlicher wird es wenn man sich das Blockdiagramm T1 anschaut. Ganz deutlich wird es auf Seite 42 unter Tab 16: In PWM mode, the Timer Overflow Flag1 (TOV1) is set when the counter advances from $0000. Timer Overflow Interrupt1 operates exactly as in normal Timer/Counter mode,i.e., it is executed when TOV1 is set, provided that Timer Overflow Interrupt1 and global interrupts are enabled. This also applies to the Timer Output Compare1 flags and interrupts. Wäre ja auch Mist wenn ich mir T0 mit T1 versaue! MFG Uwe
Woher hast Du denn Deins? Vielleicht lad ich mir das auch runter? Schau doch mal nach dem Auflage-Datum oder so. Vielleicht sind im ATMEL-PDF noch mehr Bugs.
Hi! Auflage? Das einzige was ich finde ist: Rev 1041A-05/96. Es ist also schon recht alt und den Namen habe ich natürlich geändert. Da aber 2,6MB, ist es als Anhang leider zu gross. MFG Uwe
Na ist nicht weiter schlimm. Ist ja wohl auch ein Atmel-Pdf, die Revisionsnr. ist genauso aufgebaut. Bei mir steht Rev. 1041H 11/01 drauf. Also neuer, dafür MIT Fehler ... Gut zu wissen, dass man die Handbücher ruhig auch mal in Frage stellen kann. bis denne e.
Hi leutz, hi emax, ich gehe nochmal ein Stück zurück, emax schrieb: --schnnipp else // we are at falling edge { Pulse = OverFlows * 256 + TCNT0; SET_INT1_RISING_EDGE(); // set int1 to rising edge } --schnipp ende wenn du den Timer nun ohne vorteiler laufen lassen würdest, kommen deine overflows in den zeitbereich hinein, wie jetzt deine tcnt0 takte kommen. die TCNT0-Takte beachte ich garnicht!! du brauchst also dann nur die overflows zählen. Ein Overflow mehr oder weniger, ist egal, merkt kein mensch. nimmst du die overflows mal 256, da fällts dann schon auf. Oder du lässt den Vorteiler auf 8, um dann ,wie du ja schon geschrieben hast, mikrosekundenimpulse hast. von 0.8ms bis 2ms sind's 1200us. Der Knüppel in Mittelstellung liegt bei -sagen wir- 1450us, dann hast du 650 Stufen nach hinten und 550Stufen nach vorn. Viiel zu viele! Stell deinen Timer, wie ich, auf 10us, dann kommt das besser: 55 Stufen nach vorn und 65 nach hinten. hängt ja immer vom Trimming des Knüppels ab. KOmmt ja noch der Totbreich von +-5 Stufen rein. Dann passt das. eine 8Bit-PWM im Fastpwm-Mode, und eine kleine Tabelle im Flash zum zuordnen der Beschleunigungswerte. Die Motorleistung steigt sonst nicht linear, sondern Quadratisch an, wenn man keine Tabelle nimmt. Fährt sich eher doof. den timer1 lasse ich, wie gesagt, im fast-pwm mode laufen. er zählt also nur nach oben. Darüber habe ich mir aber auch überhaupt keine Gedanken gemacht. die Motorfrequenz kann ich zwar nur grob über den Prescaler vom Timer1 einstellen, kommt aber genau hin, hab'szwar nicht gemessen, aber der Motor pfeift vor sich hin (3-4Khz?). Grüße aus Potsdam AxelR Auf die Manual-Diskussion gehe ich mal nicht ein, man weiss doch, was man macht. die Registerdefinitionen sind doch logisch angelegt, naja...
Mit den Fahrstufen hast Du völlig recht, es sind natürlich viel zu viele. Aber ich wollte einfach mal das Machbare testen, und das Ergebnis ist erstaunlich: Ich kann (immer mit 8MHz Clock) 4Khz bei 10Bit, 8KHz bei 9 Bit und 16KHz bei 8 Bit Auflösung realisieren. D.h, ich kann eine Schaltfrequenz z.B. von 16KHz fahren (genau sind es 8MHz/510 = 15,68KHz), und dabei immer noch 256 Fahrstufen unterscheiden, das ist enorm. Ausserdem betreibe ich nebenher (auf dem Entwqicklungsboard) noch noch mein HD44780 und die Dekodierung der Fernbedienung, weil ich damit zu Testzwecken alle möglichen Bits interaktiv ein und ausschalten kann, und zeige die Ergbenisse noch als Klartext an. Dabei ist der Prozessor hauptsächlich immer noch gelangweilt. PWM ist echt ne dolle Sache. Hardware ist eben nur durch Hardware zu ersetzen, genau wie der Hubraum beim Auto. Was heisst das für mein Projekt? Dass ich mir genau das gleiche überlegt habe wie Du: das Ding ist Overpowered. Deshalb kann ich das ganze sicher mit viel langsamerer Clock fahren, und so auch noch Strom sparen (und der ist bei z.B. Flugreglern ein echtes Thema). Ich muss mal nachsehen welche AVRs auch mit internem Quarz -1MHz wird reichen- betrieben werden können, da spart man dann gleich wieder ein paar Bauteile ein. Zu lösen ist jetzt noch die Frage der Nullpunktprogrammierung und die MIN/MAX Erkennung der Empfänger-Impulse.
Hm, weiss nicht, ob mans unbedingt braucht, aber ich nehme nicht an, dass alle Fernsteuerungen exakt gleiche Impulslängen liefern. Und das Ding soll ja universell funktionieren. Auch die Nullpunkteinstellung möchte ich "intelligent" machen. Nicht fix im Programm, sondern Benutzer-einstellbar. Der kann dann selber entscheiden, wieviel Rückärts und wieviel Vorwärts-Regelweg er hat. Muss ich noch ein bischen drüber grübeln. Vielleicht mit Jumper, oder aber auch mit einer bestimmten Steuerknüppel-Sequenz.... Es gibt noch mehr Gimmicks, die man machen kann: SENDER AUS/MOTOR AUS, zum Beipiel. Oder Überlastschutz bei zu hoehen Strömen (blockierte Räder, oder im Schlamm eingegrabener Propeller). Die Strombegrenzung könnte man auch wiederum Benutzer-programmierbar machen, z.B. Abschaltung nach 3 Sekunden, oder Abschaltung bei mehr als 30 Ampere, oder beides: 30 Ampere für nicht mehr als 3 Sekunden .... Ausserdem kann man noch eine Spannungsüberwachung für die Akkus einbauen: wenn die Spoannung unter 5,5 Volt sinkt, liesse sich die Leistung des Motors soweit reduzieren, dass wieder genug Spannung für Servos etc. vorhanden ist. Ach ich hab noch viele Ideen.... Man kann sich an so was "trivialem" wie eine Fahrtregler schon ganz schön verausgaben... e.
@emax: naa, weitergekommen mit deinem Vorhaben? ICh muss jetzt tatsächlich Min und max ermitteln, die fahrstufen dynamisch im SRAM linear oder logaritmisch verteilen und vorhalten, keine Ahnung, wie ich das machen soll. Ich will doch keinen Setup-Knopf anbauen. Ausserdem habe ich keine Idee, wie die Formel aussehen muss. max-min/anzahl der fahrstufen= schrittweite Motorpower = schrittweite* messwert der letzten Pulsmessung. oder wie? Gruß Axel
Hi Axel, > ICh muss jetzt tatsächlich Min und max ermitteln wie kommts denn? Bislang warst Du doch auch ohne zufrieden? Ich hab' mein Projekt ein ganzes Stück weiter gebracht, im Moment liegt es aber auf Eis - zuviel anderes zu tun. Min/Max-Ermittlung - das ist ein ziemlich wüstes Thema gewesen. Genau wie Du wollte ich ja keinen Setup-Knopf oder sowas haben. Deshalb hab ich mir einfach mal angesehen, wie die "grossen" Hersteller das machen. Und siehe da - die kochen auch nur mit Wasser: Die ermitteln hierzu aus den "Benutzereingaben", was passieren soll, und zwar mit dem Steuerknüppel. Ich hab' das so gelöst: 1. beim Einschalten mach ich erst mal gar nix: könnte ja ein Versehen sein, und deshalb wird der Motor nicht hochgefahren. 2. nun warte ich zu allererst auf ein Sendesignal. Bis dahin ist weiterhin Ruhe. 3. Wenn das da ist, dan warte ich, bis der Knüppel überhaupt mal für "längere Zeit" bewegt wird, bis dahin passiert also immer noch nix. 4. Wenn endlich eine Signaländerung eintritt, dann werden eine Reihe von Entscheidungen getroffen: a) Ist im eeprom eine gültige Konfiguration ? Wenn ja, dann nimm die als Grundlage für die Ermittlung des Steuerknüppelzustandes. b) wenn nicht, dann wird alles unter 1,3ms als NULL/Neutral und alles über 1,6ms als EINS angenommen. Ausserdem gehe ich in diesem Falls zwangsweise ins Setup. 5. Auf Grund der unter Punkt 4 getätigten Entscheidungen kann ich nun feststellen: Gibt der User NULL-Gas? Dann gehts los - normaler Fahrtreglerbetrieb. Gibt der User Vollgas (Stellung EINS) - dann ist das Setup aufzurufen. Warum das Ganze? Weil so sichergestellt ist, dass bei versehentlichem Vollgas kein Unheil geschieht. Der User MUSS für Normalbetrieb zuerst mal auf Leerlauf gehen. Oder, wenn er beim Einschalten schon auf NULL war, mindestens ein mal "kurz" auf EINS und dann auf NULL gehen. Ich nehme als Feedback eine LED, die blinkt je nach Zustand meiner "Statemachine" unterschiedlich schnell und oft auf. Geht der User also ins Setup, dann blinkt die LED schnell. Geht er versehentlich ins Setup, dann geht mein Regler nach 8 Sekunden ohne Steuerknüppel-Kommando automatisch in den Normalzustand, und wartet auf NULL-Stellung (wieder anderes Blinken der LED) Diese Zustände (NULL oder EINS) müssen natürlich über einen gewissen Zeitraum anliegen - eine oder mehrere Sekunden - damit macht man die Sache ruhiger und sicherer, auch bei Fehlsignalen. Im Setup passieren nun die komplizierteren Sachen. 1. muss man sich eine Art "Dialog" ausdenken, der nur durch NULL und EINS - Knüppelstellungen und die LED stattfindet: der User macht Eingaben (z.B: 0,0,1 - Knüppel auf NULL/MITTE/NULL/MITTE/EINS/MITTE), und man reagiert darauf. Als Bestätigung blinkt die LED unterschiedlich oft oder lang. 2. muss man sich ein Timing überlegen, innerhalb dessen der User diese Eingaben machen kann oder muss. 3. Man braucht auch ein ENDE Kommando, also z.B. 1,1,1 (Knüppel drei Mal auf EINS und wieder in die Mitte. Jedes dieser "Kommandos" entspricht einem Befehl. Z.B.: 001 - Strombegrenzung eingeben 010 - Nullstellung festlegen 011 - Schaltfrequenz festlegen 100 - MIN und MAX ermitteln usw... 111 - Ende und Speichern Gibt der User nun 010 ein, also "Nullstellung festlegen", dann blinkt die LED schnell, und die Software wartet, bis der Steuerknüppel sich z.B. 2 Sekunden lang nicht mehr bewegt (plus-minus Toleranz von z.B. xyz-Mikrosekunden oder xyz-Prozent). Der User kann also in Ruhe seine Position festlegen. Hat er das endlich getan, so leuchtet als Bestätigung die LED beständig für sagen wir 4 Sekunden, und man speichert die ermittelte Knüppelstellung als neuen Leerlaufwert. Und so gehts weiter für alle Werte. Wenn der User sich unsicher ist, und abbrechen will, so drückt er Reset oder schaltet aus. Anderfalls kann er mit 1,1,1 bestätigen, und alles wird im Eeprom gespeichert. Alles in allem ziemlich aufwändig. In meiner Version nimmt alleine die Setup-Routine mit den Knnüppel-Abfragen 80% des Programms in Anspruch - und ich bin mit den "Feeling" für den User immer noch nicht zufrieden.... Einfacherer Weg: Setup über serielle und PC. Nur hat den auf dem Flugfeld keiner dabei. Kontronik (glaube ich) gibt Rückmeldungen nicht über eine LED, sondern lässt als Antwort den Motor "brummen" (vibrieren), was ich allerdings für Blödsinn halte: erstens hat man vielleicht gerade gar keinen Motor dran, und zweitens hört man's nicht, wenn nebenan gerade einer an seinem OS-MAX die Vollgasstellung sucht. Du brauchst vor allem ein paar Routinen, die verlässlich die Knüppelaktivitäten feststellen - warte, bis Knüppel für n Zehntelsekunden stillsteht - warte, bis Knüppel sich mindestens n Zehntelsekunden lang bewegt usw. Wenn Du nun MIN und MAX auf diese Art ermittelt hast, und ausserdem die Null-Stellung (Leerlauf) kennst, dann musst Du Dir überlegen, was Du damit anstellst. Soll heissen, Du musst Dir einfach überlegen, wie Deine Software mit diesen Werten umgeht. Ich selber hab mir ein Excel-Sheet gebastelt, in dem ich meine Steuerroutine simuliere. Und warum das Ganze? Weil ich im Programm keinesfalls mit Float-Variablen arbeiten wollte (viel zu langsam), sondern alles mit Integern gelöst habe. Also alles in Excel mit INT(Wert) verarbeiten. Du wirst dann ziemlich schnell feststellen, wie bockig deine Regelei wird, weil sie nicht genau genug ist - es geht einfach zuviel verloren. Ein Beispiel: Sechs geteilt durch sieben ist schlicht NULL - wenn mans in Integern macht. Dabei müsste es eigentlich etwa 0,86 sein, was eben 86 Prozent (von irgendwas) wären. Was also tun? Die Antwort heisst: Skalieren ..... Soll heissen: 60/7 ist (in Integern) immerhin schon 8. Also wesentlich genauer. Und wenn man ein bischen nachdenkt, und seine Skalierungen richtig wählt (immer an den Wertebereich denken :-)), dann kann man auch mit Integern saumässig genau werden. Ich habs auf 0,5 Prozent Rechen-Genauigkeit gebracht, und dabei nur schnelle Integer-Berechnungen gewählt. Im Beispiel "60/7" würde ich kaufmännisch runden, und auf die "60" zum Beispiel 5 draufaddieren: 65/7 .... und siehe da: das ergibt 9, was exakt kaufmännischer Rundung entspricht, und damit genauer ist. Achja: gerundet wird IMMER NUR AM SCHLUSS ... Das ganze ist (immer) ein ziemlich aufwändiger Prozess, aber er führt zu sehr grundsätzlichen Erkenntnissen der µP-Programmierung. In meinem Programm gebe ich zur Kontrolle alles auf mein LCD-Display aus. Die Knüppelstellung, die Millisekunden, den prozentualen Vorwärts- oder Rückwärts-Gasweg usw. Erst dann, wenn Du diese Werte richtig ermitteln kannst, ist es sinnvoll, an eine Regel-Kurve zu denken. Und ob die nun linear oder logarithmisch ist, ist völlig wurst: sie wird ohnehin als Zahlenreihe im eeprom abgelegt - alles andere wäre zu langsam. Diese Kurve zu ermitteln ist reine Erfahrungssache: wenn Deine Software läuft, dann regel einfach mal linear drauflos (PWM natürlich), und Du wirst schon selber merken, wo Du ab und zu geben musst. Dieses "ab und zu geben" ist das, was die Hersteller als ihr KnowHow bezeichnen, und dürfte bei Car-Reglern z.B. anders ausfallen, als bei Flugreglern. Diese Abweichungen kannst Du nun in ein Array eintragen und fertig ist deine Regelkurve. Macht halt a bisserl Arbeit .... Wenns ganz super sein soll, dann kann man im Setup noch erlauben, aus verschiedenen solchen Kurven auszuwählen (Car-Charakteristik, oder Flugregler...), und ggf. noch eigene Mutliplikatoren festlegen lassen - sagen wir mal "Rally" und "Omnibus" - Variante. Das wär dann schon fast ne echte Kennfeld-Regelung, geil was? Tja, und damit wären dann in der Marketingabteilung angelangt.... So, ich denke, da kannste jetzt erst mal verdauen. Beste Grüsse e.
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.