PPM Signale auswerten, bzw. 6-Kanal Empfänger ?

Aber generell war der Ansatz auch nicht verkehrt, vom Prinzip her ?
Die erste Idee war von zwei Flanken für die Messung ausgegangan. die erste Flanke startet den Timer (mit Zählerstand 0), die zweite stopt den Timer und liest den Zählerstand aus. Außerdem wird das Überlaufflag des Timers ausgewertet, welches der Timer automatisch beim Überlauf setzt. Dieses Flag wurde sofort beim Überlauf den Interrupt triggern, aber der Interrupt wird hier gar nicht verwendet. Am Flag erkennst Du nur, daß der Timer mindestens einmal übergelaufen sein muß, seit dem letzten Zurücksetzen mindestens 2ms vergangen sein müssen - klar?

Wenn man genauer drüber nachdenkt, ist das mit den zwei Flanken Quatsch - man kann auch eine Flanke nehmen.

Und jetzt vergiß mal die Impulsdauer. Du willst die Zeit zwischen zwei aufeinanderfolgenden steigenden (oder fallenden) Flanken wissen. Beziehungsweise die entsprechende Anzahl der Timer-Inkrements. Die bekommst Du, wenn Du nach jeder steigenden (oder fallenden) Flanke den Timer ausliest, und dann sofort nullst. Wie in der ersten Variante informiert Dich auch hier das TOV-Flag über einen etwaigen Überlauf.

Ich bin mir jetzt nicht sicher, aber meiner Meinung nach wartet Pulsein auf die entsprechenden Flanken. Es blockiert also das Programm des Controllers solange, bis ein entsprechender Pulse fertig erfaßt wurde (oder irgendein Timeout erreicht wurde).
Irgendwie wurden da Schleifendurchläufe mit bekannter Tacktzahl (=Zeit) runtergezählt, bis der Startpegel kommt (oder der Zähler 0 erreicht=Timeout), und dann Schleifendurchläufe (mit bekannter Dauer) gezählt, bis der andere Pegel kommt (auch hier mit Timeout).
Wenn Du Pulsein nutzen willst, brauchst Du den Timer nicht. Du mußt dann quasi ununterbrochen mit Pulsein die Dauer eines Low-Pegels erfassen, diesen dann in der kurzen (ok, gut dreitausend Takte bei 8MHz) Hi-Phase verarbeiten, und Pulsein zur Erfassung der nächsten Low-Phase starten/scharfmachen.


Meine Vorschläge nutzen einen Timer und einen externen IRQ, die Erfassung kostet dann regelmäßig etwas Zeit in den IRQs, dazwischen kann der Controller was anderes machen.
 
Hallo , guten Abend !

Ich habe jetzt mal ein wenig mit PWM, dem Treiber und dem Motor der Lok experimentiert.
Mit Taktfrequenzen von 8 oder 4 MHz kann man dem Motor leider nicht kommen. Er fiepst dann
nur im unteren Bereich und eine vernünftige Feineinstellung des Motorlaufes ist nicht möglich.
Bei 255 Werten für den Dutycycle passiert dann nur in den oberen 10-15 Werten etwas und der
Motor läuft auch nach, bzw. pulsiert. Bei 1MHz für den (internen) Crystal und einem prescaler von
64 für den Timer 1, bekomme ich über PWM1a und PWM1b vernüntige Frequenzen für den Motor.
Damit kann ich von 0-255 (Duty) den Motor super ansteuern

Das Testprogramm war:



CodeBox BascomAVR
'Bascom Hardware-PWM
$regfile = "m16def.dat"
$crystal = 1000000
$baud = 2400

Dim Duty1 As Word

Config Pind.4 = Output
Config Portd.5 = Output
Config Timer1 = Pwm , Prescale = 64 , Pwm = 8 , Compare A Pwm = Clear Up

Portd.5 = 0                                                 'dafür,damit der andere Anschluss d. Treibers nicht aktiv ist beim Test

Enable Interrupts

Pwm1a = 0                                                   'Motor steht beim µC-Start

Do
    Input "Datenbyte PWM-1 (0-255): " , Duty1
    Print "Duty1 = " ; Duty1
    Pwm1a = Duty1

Loop

End


Die Märklin Allstrom-Motoren kommen offensichtlich mit den hohen Frequenzen nicht klar.
Die originale Anwendung arbeitet ja auch im Bereich von 50Hz am Motor, bzw die Trafos
sowieso.

Gruss Billy
 
Bei 1MHz für den (internen) Crystal
Du hast mit den CKSEL-Fuses als Taktquelle den internen 1MHz-RC-Oszillator gewählt, und das Bascom mit der $Crystal-Direktive mitgeteilt, korrekt?
(sicherheitshalber nachgefragt - gab hier schon ... Anfänger, die der Meinung waren, die Direktive würde dn tatsächlichen Takt einstellen)

Ok, Du setzt den Prescaler auf 64, der Timer taktet also mit 1MHz/64=15,625kHz. Du verwendest den Timer als 8-Bit-Timer, mMn wählt Bascom als PWM einen phasenkorrekten PWM-Modus. Dual slope. in einer Periode zählt der Timer 0->255->0, die Ausgabe kippt je im Compare-Event, hin und her.
Also 510 Timertakte entsprechen einer Periode. Daraus folgt eine PWM-Frequenz von 15,625kHz/510 von gut 30Hz.

Mit Taktfrequenzen von 8 oder 4 MHz kann man dem Motor leider nicht kommen.
Wenn Du den Prescaler auf 256 setzt, sollte bei 4MHz-Takt genau dasselbe rauskommen.
Was ist mit 8MHz Systemtakt und Prescaler=1024? Wären rechnerisch 15Hz PWM-Frequenz.

Beim Tiny25/45/85 besitzt Timer1 auch einen 512-Prescaler, da könnte man aus 8MHz dann auch 30Hz-PWM (dual slope) ableiten.

Die originale Anwendung arbeitet ja auch im Bereich von 50Hz am Motor
8MHz über einen 256er Prescaler liefern bei einem 8bit-dual-slope-PWM 60Hz PWM-Frequenz. Hast Du das mal getestet?
 
Hallo !
Danke für Deine Mühe. Also :

8MHz über einen 256er Prescaler liefern bei einem 8bit-dual-slope-PWM 60Hz PWM-Frequenz. Hast Du das mal getestet?

Ist in Arbeit. Melde später das Ergebnis.

Du hast mit den CKSEL-Fuses als Taktquelle den internen 1MHz-RC-Oszillator gewählt, und das Bascom mit der $Crystal-Direktive mitgeteilt, korrekt?

Ja, habe ich natürlich, sonst bekäme ich ja falsche Werte. Das entsprechende Fuse-Bit ist gesetzt und geschrieben.

Du willst die Zeit zwischen zwei aufeinanderfolgenden steigenden (oder fallenden) Flanken wissen. Beziehungsweise die entsprechende Anzahl der Timer-Inkrements. Die bekommst Du, wenn Du nach jeder steigenden (oder fallenden) Flanke den Timer ausliest, und dann sofort nullst. Wie in der ersten Variante informiert Dich auch hier das TOV-Flag über einen etwaigen Überlauf.

Ich verstehe zwar das Prinzip, aber ich kriege das nicht in Befehlszeilen verpackt : "Timer auslesen" welcher Befehl ist das denn ? Oder das TOV ?
Sorry - ich verstehe die Zusammenhänge nicht bezogen auf Bascom Befehle, bzw. kann das nicht zuordnen. Kannst Du mir bitte dazu sagen, welche
Befehle da hinterstecken ? Bitte versuche mir das mal als Anfänger zu verpacken. Ich hangele mich mit Buch noch parallel immer an den Ideen hier
mit entlang...

Ich versuche jetzt mal die anderen Frequenzen/prescaler Einstellungen.
In Bezug auf was ist es denn so wichtig, den µC so schnell laufen zu lassen ?
Wäre es nicht egal, ob er auf 1MHz oder 8Mhz läuft, wenn die Impulse doch eh nur mit 50Hz reinkommen ?
Oder hat es damit zu tun, dass ich bei einem schneller laufendem µC mit dem Timer weiter/öfter zähle und
dann eine Bessere Auflösung bekomme ?

Gruss & Dank- Billy

EDIT : Das beste Ergebnis im Bezug auf den Motor (Lauf und Leistung/Geräusch) erziele
ich bei 4MHz und prescaler 256...
 
Zuletzt bearbeitet:
Ja, habe ich natürlich
:good: Wie gesagt... wir hatte hier schon "Spezialisten"...
ich verstehe die Zusammenhänge nicht bezogen auf Bascom Befehle, bzw. kann das nicht zuordnen. Kannst Du mir bitte dazu sagen, welche Befehle da hinterstecken ?
Das hat eigentlich nichts mit Bascom-Befehlen selbst zu tun, sondern mit dem Controller selbst.
*aushol*
Der Zugriff auf die periphäre Hardware eines AVR erfolgt über so genannte I/O-Register. Die kannst Du Dir als speziellen Speicher vorstellen, auf den Du (also Dein Programm) und die jeweilige Hardware Zugriff haben. Wenn Du ein Bein auf "Ausgang" setzt, wird ein Bit im entsprechenden Datenrichtungsregister (DDRx.n) gesetzt. Der tatsächliche Pegel an diesem Bein ist im Port Input Register (PINx.n) auslesbar.
Bei 'nem komplexeren Modul wie zB einigen Timern, kommen da dann mehrere Register (Bytes in diesem "speziellen Speicher") zusammen. Für den Mega8 hab ich das mal hier versucht zu erklären...
(die wesentlichen Infos kommen dann in #19 und #27)

Bascom bietet Dir selbst mehrere Wege, die periphäre Hardware einzustellen. Dabei sollen die Befehle (Config Timer blablub) natürlich bei allen Controllern gleich handhabbar sein. Bei sehr komplexen oder speziellen Timern (koppelbar an eine High-speed-PLL, PWM-6, zerlegbare Timer) würde der Config-Befehl selbst sehr unübersichtlich werden - oder er ermöglicht nicht alle Eventualitäten.
Grundsätzlich erlaubt Dir Bascom aber den direkten Zugriff auf die I/O-Register. Die konkreten Adressen stehen im eingebundenen regfile. Du kannst Die Register benutzen, als wenn es Byte-Variablen wären. Bei 16bit-Werten, die in zwei Registern abgelegt sind, kannst Du meines erachtens sogar als word drauf zugreifen.
"Timer auslesen" welcher Befehl ist das denn ?
Der Zählerstand, der eigentliche Wert, ist das "Timer/Counter n Register", Timer1 -> n=1. TCNT1 (bei einem 16bit-Timer besteht das aus zwei Bytes, man kann auf TCNT1L und TCNT1H zugreifen, Bascom kennt aber auch TCNT1 nimmt Dir das zusammenfassen ab). Alternativ kannst Du auch Timer1 als Variable nerwenden.
Um den Zählerstand in das Array zu übernehmen, kannst Du also einfach schreiben "Array(index)=TCNT1" oder "Array(index)=Timer1". Bascom läd dann den wert aus dem/n TCNT-Register/n, und speichert sie im Array (SRAM) ab.
Um den Zählerzustand auf einen bestimmten Wert zu setzen (hier null), kannst Du schreiben "TCNT1=0" (oder "Timer1=0"), Bascom schreibt dann 'ne null in das/die TCNT-Register.
TOV (eigentlich TOVn, n=Timernummer) ist das Overflow-Flag des Timers. Ein Bit in einem der Register (variiert bei den Controllern -> Datenblatt). Es wird bei jedem Überlauf auf 1 gesetzt. Wenn der entsprechende Interrupt enabled ist (TOIEn-Bit (Timer Counter n Overflow Interrupt Enable)) und die IRQs global scharf, löst dieses Flag den Overflow-Interrupt aus. Man kann das Bit auch selbst auslesen oder zurücksetzen. Bei älteren Controllern findet man alle Interrupt-Flags aller Timer im TIFR (Timer Counter Interrupt Flag Register). Bei moderneren/Controllern bzw welchen mit komplexeren Modulen reichen 8 bit, 8 Flags nicht mehr. Da hat dann jeder Timer ein eigenes Flag Register.
Beim Mega8 und Mega16 ist es das TIFR, Bascom kennt das Register und die Bits (aus dem Regfile), Du kannst die Bits also also Bitvariable lesen oder schreiben (TIFR.TOVn). ("If TIFR.TOVn=1 then..."
Beim Zurücksetzen des Flags ist folgendes zu beachten (Zitat aus dem Datenblatt):
TOV1 is automatically cleared when the Timer/Counter1 Overflow interrupt vector is executed. Alternatively, TOV1 can be cleared by writing a logic one to its bit location.
Um das Flag zu löschen, muß eine "1" geschrieben werden. In Bascom also ganz einfach mit "TIFR.TOVn=1". Wahrscheinlich geht auch "Set TIFR.TOVn" (n=Timernummer)
hangele mich mit Buch
Welches haste denn?
Wäre es nicht egal, ob er auf 1MHz oder 8Mhz läuft, wenn die Impulse doch eh nur mit 50Hz reinkommen ?
Du hattest geschrieben, daß Du mit acht bzw vier MHz kein verwertbares PWM erreichst. Mit 'nem entsprechenden Prescaler sollte es aber doch gehen. Die Impulse kommen/wiederholen sich zwar nur alle 20ms (50Hz), aber du willst ja die Längen erfassen (1..2ms), und mit 'nem langsameren Systemtakt wirds im Programm selbst ggf enger.
Es geht erstmal nur darum harauszufinden, welche PWM-Frequenz anzustreben ist (30Hz geht, 50Hz wären von der Originalschaltung logisch, was ist mit 60Hz?)
Danach kann man dann sehen, welchen Kompromiß man für den letztendlich verwendeten Controller bezüglich Takt, Prescaler, PWM-Ausgabe und Pulslängenerfassung sucht. Ein langsamerer Takt würde außerdem die Stromaufnahme des Controllers senken - ist hier aber sicher nicht relevant...
 
Hallo !

Okay- Check !
Langsam wird ein Schuh draus. Mich verwirrt immer ein bisschen das Hardware/Software geswitche.
Aber das kommt langsam. Ich habe das Buch aus dem Franzis Verlag (Ulli Sommer) "Microcontroller
programmieren in Bascom Basic" ... finde ich nicht schlecht. Allerdings braucht es eine Zeit, bis das alles
sitzt. Beim Dimmer war das (mit Hilfe - danke Markus ! ) noch machbar. Da konnte ich das dann auch gut
nachvollziehen mit dem Timer/Nulldurchgang/Zündung d. Triac. Aber hier komme ich irgendwie nicht so
schnell dahinter. wird aber sicher noch...

Ich setze mich gleich wieder dran.

Gruss
-Billy
 
Mich verwirrt immer ein bisschen das Hardware/Software geswitche.
Ich hab damals mit dem "Kühnel" (Programmieren der AVR RISC Mikrocontroller mit BASCOM-AVR) angefangen. Da wird zwar auch auf die interne Hardware eingegangen, aber trotzdem war mir als Anfänger nicht immer so recht klar, ob das dann in Hard- oder Software realisiert wird. Gerade bei den Kommunikationsschnittstellen zB....
Print "Text"
Je nachdem, was in den defaults eingestellt ist, oder ob da ggf irgendein Config steht, kann des Hard- oder Software nutzen.
Zur Hardware selbst: Du hast neben dem eigentlichen Rechenkern (ALU, Program-Flash+Kontrolllogik, SRAM) je nach Controller noch diverse Hardware-Module dazu, die vom Rechenkern (weitgehend) unabhängig sind. Diese werden in den Datenblättern am Anfang als peripheral Features erwähnt, und später im Datenblatt detailiert erklärt.
Ein Timer/Counter zählt einmal eingestellt, entsprechend seiner Clock-Source sein Zählerregister rauf/runter, und läßt ggf die Output-Compare-Beine zappeln - ohne daß dabei weiteres Eingreifen des Rechenkernes nötig wird.
Der ADC digitalisiert, einmal angestoßen, eine irgendwie anliegende analoge Spannung in eine digitale Zahl, und legt das Ergebnis anschließend im entsprechenden Conversion Result Register ab.
Die Kommunikationsschnittstellen senden/empfangen weitgehend unabhängig Bytes.
Der Rechenkern (Dein Programm) steuert und kontrolliert die Hardware über die genannten I/O-Register, Du kannst dann zB regelmäßig nachfragen, obe der Timer übergelaufen ist, oder der ADC endlich fertig hat, oder vom UART ein Byte eingetrudelt ist, ob an einem Bein ein Pegelwechsel erfolgte usw. Viele dieser Ereignisse können auch so eingestellt werden, daß sie den Rechenkern unterbrechen, um eine "sofortige" Behandling zu "erzwingen"
Natürlich kannst Du viele dieser Funktionen auch komplett in Software erledigen, aber das kostet eben mehr Rechenzeit, als wenn man die Hardware anstupst.
Was die Hardwaremodule können, und wie sie einzustellen sind, sagt Dir das jeweilige Controllerdatenblatt besser, als BASCOM.
Wenn Du Dir mit den Konfigurationsmöglichkeiten eines Bascom-Configs nicht sicher bist, kannst Du immer direkt über die I/O-Register direkt gehen. Basom macht auch nix anderes, als die entsprechenden Zahlen in die Register zu stopfen (oder da rauszulesen)
 
Halllo !

Ich hätte da mal noch eine Frage :

anbei ein Bild vom original Decoder. An pin 14 (CL) des 4022 (Zähler IC) kommen die
Impulse von T1 invertiert an. An pin 15 (Reset) kommt die Pausenerkenung an !
Hardwaremässig über R4,C3 und D2. Wenn ich mir das auch erstmal so baue und nutze,
kann ich mir ja erstmal einen oder 2 Knoten im Kopf wegen des Programms sparen ?
Ich hätte also ein konkretes Pausensignal, das ich einem Pin zuführen kann.
(Später kann ich ja dann mal ein Programm versuchen, wo dies in der Software erfolgt.)
Momentan bin ich mehr irritiert als im Bilde. Wenn ich mir also was erleichtern kann...

Wenn du mir bitte hier nochmal genau in Ablauf sagen könntest , was ich nun dann genau
im µC machen muss - Schritt für Schritt und abfolgend. Dann kann ich mir da mal einen
Bascom-Code drauf reimen.

Das wir mal ein bisschen sortieren...

Gruss Billy

PPM-Decoder.jpg
 
Wenn ich mir das auch erstmal so baue und nutze,
kann ich mir ja erstmal einen oder 2 Knoten im Kopf wegen des Programms sparen ?
Nur, wenn Dich nur Kanal-1 interessiert.
WAS willst Du/kannst Du damit einsparen?
IC2 macht ja eigentlich zwei Sachen: es trennt die Kanäle, und es "sortiert" die, stellt sicher, daß Kanal-1 an Pin1 kommt, Kanal-2 an Pin3 usw.
Natürlich kannst Du auch ein zusätzliches (Hardware) Reset-Signal verwenden, und weißt dann, daß der folgende Kanal Kanal-1 ist, aber wenn Du Kanal-4 nutzen willst, mußt Du doch eh die Flanken zählen.
Der Timerüberlauf ist nichts anderes, als Dein extern aufgelegtes Reset (des Zählers), nur eben intern, das fällt beim Timer nebenbei mit ab...
Ob Du den Impulszähler durch ein externes Event (Reset-Signal) oder ein internes Event (TOV-Flag des Timers) zurücksetzt, macht im Programm keinen Unterschied. Reagieren mußt Du eben entweder auf das eine, oder das andere.
Wenn du mir bitte hier nochmal genau in Ablauf sagen könntest
Du legst (global) ein Array an, das die Ergebnisse aufnehmen soll (bei einem 8bit-Timer und sechs Kanälen also sechs Byte).
Du dimensionierst (global) eine Variable für den Kanalzähler.
Im Array sollten erstmal sinnigerweise die Werte für den Stillstand stehen, der Kanalzähler sollte mit "0" initialisiert werden.
Du initialisierst den Signaleingangspin mit Interrupt auf ... steigende Flanken.
Du initialisierst einen Timer so, daß er innerhalb von 2ms nicht überlaufen kann, aber in 8ms sicher (mindestens ein mal) überläuft (und startest diesen).
Interrupts aktivieren.
Hauptprogrammschleife mit sonstigem Programm...

In der ISR des Flanken-Interruptes:
  1. Wenn der Timer übergelaufen ist (also das TOV-Flag=eins ist)
    1. TOV-Flag zurücksetzen (Das Bit im Register mit "1" beschreiben
    2. Den Kanalzähler auf "0" setzen
  2. sonst
    1. den Kanalzähler inkrementieren
    2. den Timerstand nach Array(Kanalzähler) speichern
  3. Timerstand auf "0" setzen
"1" synchronisiert den Kanalzähler (jedesmal) auf die Pause (genauer: auf das Ende der Pause bzw die erste steigende Flanke nach der Pause)
"2" sortiert die Impulslängen (Timertakt-Anzahl) in das Array
"3" synchronisiert den Timer (jedesmal) auf die steigende Flanke.

Welcher Punkt ist Dir jetzt noch unklar?
 
Morgen !

Ja klasse - danke - ich werde dann mal werkeln. Kann ein bisschen dauern. Mit kurz vor 50 dauert das ein bisschen ;-)
Stimmt, das Signal spart mir quasi nix, aber Platz würde ich ohne die Bauteile sparen und das wäre in der Lok sehr
wertvoll...

Gruss Billy
 
Du legst (global) ein Array an, das die Ergebnisse aufnehmen soll (bei einem 8bit-Timer und sechs Kanälen also sechs Byte).
Du dimensionierst (global) eine Variable für den Kanalzähler.
Im Array sollten erstmal sinnigerweise die Werte für den Stillstand stehen, der Kanalzähler sollte mit "0" initialisiert werden.
Du initialisierst den Signaleingangspin mit Interrupt auf ... steigende Flanken.
Du initialisierst einen Timer so, daß er innerhalb von 2ms nicht überlaufen kann, aber in 8ms sicher (mindestens ein mal) überläuft (und startest diesen).
Interrupts aktivieren.
Hauptprogrammschleife mit sonstigem Programm...

In der ISR des Flanken-Interruptes:
  1. Wenn der Timer übergelaufen ist (also das TOV-Flag=eins ist)
    1. TOV-Flag zurücksetzen (Das Bit im Register mit "1" beschreiben
    2. Den Kanalzähler auf "0" setzen
  2. sonst
    1. den Kanalzähler inkrementieren
    2. den Timerstand nach Array(Kanalzähler) speichern
  3. Timerstand auf "0" setzen
"1" synchronisiert den Kanalzähler (jedesmal) auf die Pause (genauer: auf das Ende der Pause bzw die erste steigende Flanke nach der Pause)
"2" sortiert die Impulslängen (Timertakt-Anzahl) in das Array
"3" synchronisiert den Timer (jedesmal) auf die steigende Flanke.

Welcher Punkt ist Dir jetzt noch unklar?

Anbei mal ein Bild vom Signal an den Ausgängen der Schaltung

1.bmp


Auf geht's - jetzt wieder mit meinen Worten / Zeilen

Folgendes vorweg :

Ich habe jetzt mal nachgesehen - das mit dem "TOV auslesen/setzen" ist in Bascom der Befehl "ON TIMERX ISR_TIMERX"
also "bei TIMERX -Überlauf die ISR dazu ausführen" !? DAs kann ich doch dann nutzen ?

weiter...

Da meine PWM-Motor-Routine mit Werten von 0-255 (für jede Richtung) arbeitet, wäre es ja sinnvoll, wenn mir
die Impuls-Auslese-Routine Werte bis 510 +/- liefert, damit ich das gut verarbeiten kann. Ich habe dann mal ein
Bisschen gerechnet und kam auf brauchbare Werte bei einem Takt von 2MHz für den µC, weil dann

-der Timer bei 2ms (= längster Impuls) bis 500 zählt. Also brauche ich einen µC mit 16-Bit-Timer (richtig ?)

aber :

-dann habe ich aber das Problem, dass der bei 8-14ms Pause nicht überläuft, weil er ja bis 65.536 zählt.
-also müsste ich ihn preloaden , dann bekomme ich aber wieder andere Werte für den abgelegten Wert ?
Oder ist genau das der Punkt ? Also auf 65.036 laden ? Dann läuft er bei über 2ms sicher über und die Werte
bis 2ms passen dann ?

Ich blicke das nicht - sorry. Das macht mich fertig...mir brummt der Schädel.

Ich glaube ich bin zu dumm/mathe oder logikschwach dafür :-(

Gruss Billy
 
Zuletzt bearbeitet:
das mit dem "TOV auslesen/setzen" ist in Bascom der Befehl "ON TIMERX ISR_TIMERX"
also "bei TIMERX -Überlauf die ISR dazu ausführen" !? DAs kann ich doch dann nutzen ?
Nein, nicht ganz.
Bleib nicht an dem Timer-Interrupt kleben...
Kleiner Exkurs Interrupts:
Die meisten periphären Hardwaremodule besitzen die Möglichkeit, das laufende Programm zu unterbrechen (interrupt). Dazu gibt es meist ein ... Flag, ein Fähnchen, das in irgendeiner Weise das Event erstmal anzeigt. Das kann unabhängig davon geschehen, ob der Interrupt überhaupt aktiviert ist. Jedesmal, wenn der Timer überläuft, wird das TOV-Flag (auf "1") gesetzt. War er vorher schon gesetzt, bleibt es gesetzt.
Aktiviert wird jeder Interrupt für sich mit einem eigenen Interrupt-Enable-Bit. Außerdem müssen die Interrupts global aktiviert sein.
Wenn also der TOV-IRQ enabled ist (und die Interrupts global), löst das ein gesetztes TOV-Flag einen Interrupt aus. Dabei wird der aktuelle (Maschinencode-) Befehl abgearbeitet/beendet, die Adresse des nächsten Befehls abgespeichert (Rücksprungadresse), Danach wird eine spezielle Adresse am Anfang des Programmspeichers angesprungen - der Interruptvektor (des konkreten TOV-IRQs). Außerdem werden die Interrupts global gesperrt.
In der Interruptvektortabelle muß jetzt die weitere Behandlung des Interruptes erfolgen, üblicherweise ein Sprung in eine entsprechende Interrupt Service Routine (ISR). "On Timerx Isr_timerx" macht nichts anderes, als in der Interruptvektortabelle (IVT) beim TOV-Vektor einen Sprung zu der genannten Routine einzutragen. Mit "On Int0 Routinenname" hast Du dasselbe mit dem externen Interrupt gemacht.
Am Ende der ISR erfolgt dann ein Return (genauer: ein Return from Interrupt), dabei wird die abgespeicherte Adresse im Programmspeicher wieder geladen (da gehts weiter), und die Interrupts global wieder freigegeben.

Mein Vorschlag war nicht, den Überlaufsinterrupt des Timers zu verwenden, sondern nur das Überlaufsflag auszuwerten, welches automatisch bei jedem Überlauf gesetzt wird. Ohne den Interrupt zu aktivieren. Ohne dafür 'ne ISR zu implementieren. Ohne einen Sprung in die IVT schreiben zu lassen (On Timerx...).
Klar?
dann habe ich aber das Problem, dass der bei 8-14ms Pause nicht überläuft, weil er ja bis 65.536 zählt.[...]also müsste ich ihn preloaden
Nicht unbedingt preloaden - Du kannst Ihn auch "oben abschneiden", also die Reichweite begrenzen. Den Punkt, wo er überläuft. Üblicherweise kann man einen 16bit-Timer, zumindest im PWM/fastPWM (man muß die OutputsCompares ja nicht nutzen) auch auf 8, 9 oder 10 Bit vorgeben. Außerdem gibt es oft die Möglichkeit, den Überlauf durch den Vergleich (automatisch bei jedem Timerinkrement) mit einem bestimmten Register Durchzuführen. Oft das CaptureUnit A, wenn vorhanden das Input Capture Register, einige Timer bieten auch ein extra-Register für sowas an (der Tiny25/45/85 hat zB bei Timer1 ein drittes Capture Unit (C) ohne PWM-Output dafür). Die entsprechenden Timermodi heißen dann CTC (Clear Timer on Compare Match) oder frequenzkorrigiert.
Allerdings hat der vorgeschlagene Tiny25/45/85 nur zwei 8bit-Timer. Laut meiner Übersicht hätte der Tiny24/44/84 einen achter und einen sechzehner, der ist aber auch schon größer. Wie's mit dem Tiny102 aussieht, weiß ich grad nicht aus dem Kopf, aber der wird eh schwerer zu beschaffen sein, der kleine XTiny wird noch gar nicht auf dem Markt sein (muß die Übersicht irgendwann mal weitermachen).
wie dem auch sei...
Da meine PWM-Motor-Routine mit Werten von 0-255 (für jede Richtung) arbeitet, wäre es ja sinnvoll, wenn mir die Impuls-Auslese-Routine Werte bis 510 +/- liefert, damit ich das gut verarbeiten kann.
Du wirst eh rechnen lassen müssen, da die erste ms ja auch immer mitgezählt wird.
Die Frage ist also auch, welche Auflösung Du hier haben willst.
Man könnte beim Tiny85 zB für die Pulslängenerfassung Timer1 mit Prescaler=128 am 8MHz-Systemtakt wählen. Der ist dann nach 1ms bei 63, nach 1,5ms bei 94, nach 2ms bei 125. Nach gut 4ms kommt das TOV, wenn der Timer nicht vorher zurückgesetzt wurde.
Wären 31 Schritte pro Richtung.
Mit Prescaler 64 wäre es überall das doppelte.
Die Werte landen also in dem Array, Du ziehst vom Ergebnis den Null-wert (94 bzw 188) ab. Anhand des Vorzeichens kannst Du die Richtung (also den PWM-Kanal) festlegen; die negative Zahl machst Du danach positiv (Komplement). Anschließend mit 8 multiplizieren (viermal linksschieben, bei Prescaler=64 nur mit 4 multiplizieren, also zweimal linksschieben). Damit kämest Du von 0..248 was in das korrespondierende Compare-Register zu schreiben wäre. Alles mit einfacher Bitpopelei...
Bei den beiden Kanälen mußt Du sicherstellen, daß immer nur ein Kanal gleichzeitig aktiv ist. Bei Phasenkorrekten Modi scheint es zu genügen, den Compare-wert auf "0" zu setzen, sicher bist Du immer, wenn Du den Compare Output Mode des anderen Kanales abschaltest.
Klar könnte man das auch sauber bis 255 hochmultiplizieren, oder mit etwas Bitgeschubse schummeln...

Wenn Du das mit den PWM-Frequenzen bei der PWM-Ausgabe fertig getestet hast (gehen die 60Hz nun?), würde ich erstmal ein Testprogramm für die Pulslängenerfassung testen. Du nutzt für die Tests einen Mega16 und da insbesondere auch den UART?
 
Hallo !

hat sich überschnitten - ich versuche es doch mal - so würde ich das bislang schreiben. (µC auf 2MHz, Motortreiber läuft ordentlich)
Ja- momeentan ein ATmega16, ich habe aber auch ATiny2313A, ATmega 8L, ATiny44,45...
Der kleinstmögliche nutzbare µC soll es werden.
UART hatte ich nur jetzt bei der Ansteuerung für den Treiber genutzt. Brauche ich jetzt nicht mehr.

Oben natürlich im PRG Kopf alles entsprechend

dann

Dim Kanal as Byte
Dim Kanal_wert as Word

Kanal=0

Config INT0 = Rising
Config TIMER1 = Timer, Prescale 8
TIMER1 = 65036
ON TIMER1 Sync_detected
ON INT0 Measure

Enable TIMER1
Enable INT0
Enable Interrupts

Do
nope
Loop

End

Measure:
Stop TIMER1
Kanal=Kanal+1 ( oder INCR Kanal)
Kanal_wert (Kanal) = TIMER1
TIMER1 = 65036
Start TIMER1
Return

Sync_detected
Kanal = 0
Return

Gruss Billy
 
µC auf 2MHz, Motortreiber läuft ordentlich
Welche PWM-Frequenz ist das dann? 2MHz/Prescaler des Timers/510
Der kleinstmögliche nutzbare µC soll es werden.
Wäre dann der Tiny25/45/85, also nur 8bit-Timer

"Kanal_wert" soll ein Array sein, kannst Du mMn so anlegen: "Dim Kanal_wert(6) as byte/word"
Ich würde wie gesagt nicht den TOV-IRQ verwenden, sondern das Flag in der Measure-ISR mitabfragen. Und die beiden Fälle (Kanal oder Pause) in einer If...Then...Else erschlagen.
Und den Timer anschließend auf 0 setzen.
Starten und stoppen brauchst Du den Timer auch nicht (mehr).
Ich würde das ganze auf einen 8bit-Timer auslegen (wegen dem Tiny25/45/85), aber mit dem Mega16 erstmal testen.
Als erstes mit 'ner effektiven Timer-Takt-Frequenz von 62,5kHz (8MHz und Prescaler 128 oder 4MHz und Prescaler 64, ...)
Wenn das Gerüst steht, könnte man im Hauptprogramm die Kanal-Rohwerte dann mal im Sekundentakt über den UART rausjagen.
Und ggf als zweitenTest den effektiven Timertakt verdoppeln.

P.S.: nutz mal bitte die BASCOM-Code-Tags da oben, ist besser lesbar...
 
Also wenn Du den 25/45/85 da hast, würd ich's mit dem machen. Die gibt's, wie auch die 24/44/84 also SOIC150.
Den ATtiny45 bekommst Du allerdings auch als TSSOP.
Ich hätte auch noch'n ATtiny20 als WLCSP hier, der hat auch 'n 16er Timer, und sollte definitiv nicht zu groß sein...

Zum Testen dann erstmal den Mega mit UART...
 
Also wenn Du den 25/45/85 da hast, würd ich's mit dem machen. Die gibt's, wie auch die 24/44/84 also SOIC150.
Den ATtiny45 bekommst Du allerdings auch als TSSOP.
Ich hätte auch noch'n ATtiny20 als WLCSP hier, der hat auch 'n 16er Timer, und sollte definitiv nicht zu groß sein...

Zum Testen dann erstmal den Mega mit UART...

Hab den ATiny44 auch...spricht doch nix dagegen, oder.
Hätte ich noch Beinchen frei für andere Dinge.

Gruss Billy
 
Ok, wenn's der sein soll, würde ich den 8Bit-Timer mit seinen beiden Compare-Units die PWM-Ausgabe machen lassen.
Da wäre immer noch als erstes zu klären, ob die 60Hz PWM-Frequenz passen, oder ob Du bei 30Hz bleiben willst.
Dann stehen mit dem 16Bit-Timer wesentlich bessere Möglichkeiten der Anpassung (1ms abschneiden, Überlauf deutlich nach 2ms) zur Verfügung...
 
Das wäre dann TIMER0 , oder ?
Ich habe gerade versucht, beim ATmega16 den Timer0 als PWM zu nutzen, da bekomme ich
eine Fehlermeldung - geht nicht !?

Gruss Billy
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)