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

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Doch, Timer0 des Mega16 kann vier Operationsmodi:
  • normaler Timer, single slope mit Überlauf 0xFF->0x00
  • phasenkorrekter PWM, dual slope 0x00->0xFF->0x00
  • CTC, "frequenzkorrigierter" Normalmodus, singleslope, das Output Compare Unit bestimmt den Überlauf nach 0x00
  • fastPWM, single slope, Überlauf 0xFF->0x00
Der Timer besitzt die diskreten Prescaler 0(*), 1, 8, 64, 256, 1024 und kann außerdem an Flanken eines externen Beines gekoppelt werden.
Es existiert nur ein OutputCompareUnit.

(*) Timer steht, ist weder an den Systemtakt, noch das externe Bein gekoppelt.

In der Bascom-Onlinehilfe ist das leider nicht ganz eindeutig, es sieht so aus, als wenn "Config Timer0" das nicht unterstützt, PWM taucht da absurderweise nur mit "Config Timer2" auf. Hat ja da eigentlich nix zu suchen...

Du kannst den Timer aber problemlos selbst einstellen - sind ja nur drei Register für den Timer selbst, und zwei weitere für die Interruptanbindung.
Ein Konfigurationsregister (TCCR0), ein Zählerregister (der eigentliche Timer, TCNT0), ein Compareregister (OCR0). Interrupt-Flags befinden sich im Timer Interrupt Flag Register (TIFR), die Enable-Bits im Timer Interrupt Mask Register (TIMSK) .

Beim Tiny24/44/84 besitzt Timer0 zwei OC-Units, kann damit zwei zusätzliche Operationsmodi (frequenzkorrigierter single-/dualslope-PWM, OutputCompare-Unit A legt dann den Überlaufs-/Umkehrpunkt fest, Unit B ist für PWM nutzbar).
Da der Timer mehr Konfigurationsmöglichkeiten bietet, benötigt er mehr Einstellbits, besitzt zwei Konfigurationsregister (TCCR0A, TCCR0B), außerdem besitzt jeder Timer ein eigenes TIFR und TIMSK.

Wie gesagt, wenn man sich mit de eigentlichen Hardware der Controller beschäftigt, ist es manchmal einfacher direkt die Register zu beschreiben, als herauszufinden welchen Config-Befehl man da verwenden muß, und welche Parameter da was bewirken.

Der Hintergrund ist hier konkret der, daß die älteren Controller an Timer0 teilweise gar kein PWM besaßen (ATtiny11, 12, 15, 26, beim 28 bin ich mir nicht sicher, ebenso bei den AT90... Dinosaurier halt). Also nur Timer/Counter mit Überlauf 0xFF->0x00 und Überlaufinterrupt.
Inzwischen gibt es deutlich mehr Variabilität zwischen den Controllern (ohne, mit einem, mit zwei, mit drei OC-Units, mit oder ohne IC-Unit, 8 oder 16Bit. Bei den neuen XTinies gibt es auch 12bit-Timer oder 16bit-Timer die in zwei 8bit-Timer gesplitted werden können).
Wenn man da alles mit einem Config-Befehl erschlagen will, wird dessen Parametrisierung komplexer als die Register eines einzelnen Controllers sind.
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hallo !

Okay - jetzt ist die Verwirrung so gross, dass ich nicht mehr durchblicke.
Könntest Du mir da bitte helfen, den Code in Bascom zu erstellen, bzg. des PWM mit TIMER0?

Bisher sah das so aus und hat perfekt funktioniert - ich übergebe für beide PWM-PINS Werte von 0-255 :
(bitte das ganze Drumherum mal nicht beachten, das ist zum Ausprobieren gewesen)
Ich bräuchte das auch wieder möglichst in der Form, so dass ich die Wert aus dem Impulsdetektor
direkt dort reinschreiben kann...



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

Dim Duty1 As Word , Duty2 As Word

Config Pind.7 = Input
Config Pind.2 = Input
Config Pind.3 = Input

Taster_li Alias Pind.2
Taster_re Alias Pind.3
Notaus Alias Pind.7

Portd.7 = 1
Portd.2 = 1
Portd.3 = 1

Duty1 = 1
Duty2 = 1

Config Pind.4 = Output
Config Pind.5 = Output
Config Timer1 = Pwm , Prescale = 1 , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down


Enable Interrupts

Pwm1a = Duty1
Pwm1b = Duty2                                               'Motor steht beim µC-Start

Doloop:

Do

    If Duty1 > 0 And Taster_re = 0 Then
       Decr Duty1

    End If

    If Duty1 = 0 And Taster_re = 0 Then
       Incr Duty2
       If Duty2 > 255 Then Duty2 = 255

    End If

    If Duty2 > 0 And Taster_li = 0 Then
       Decr Duty2

    End If

    If Duty2 = 0 And Taster_li = 0 Then
       Incr Duty1
       If Duty1 > 255 Then Duty1 = 255

    End If

    If Notaus = 0 Then
    Duty1 = 0
    Duty2 = 0
    End If

    Pwm1a = Duty1
    Pwm1b = Duty2
    Waitms 10

    'Print "1      " ; Duty1
    'Print "2      " ; Duty2

    Loop

End

Pwm_rechts:
Pwm1a = Duty1
Pwm1b = 0
Goto Doloop

End

Pwm_links:
Pwm1a = 0
Pwm1b = Duty2
Goto Doloop


Gruss Billy
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Schau Dir mal bitte im Datenblatt des Mega16 das Kapitel über Timer0 an. Das sind insgesamt nur16 Seiten. Ich schreib nachher mehr dazu...
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Ich wieder, hallo !

Sorry- ich blicke da nicht durch. Ich bin froh, dass ich jetzt mit dem Auslesen der Signale
soweit bin, dass ich Werte von 0-255 für beide Richtungen eines Kanales bekomme.
Das mit dem Timer0 und PWM verstehe ich nicht.
Ich brauche das wirklich so, wie mit dem Timer1 - Werte von 0-255 als Dutycycle einschreiben,
dann klappt das ...

Ich überlege ob ich einfach einen µC mit 2 16-Bit-Timern nehme ? Den 162 z.B.

Edit : hat sich erledigt - das Passt nicht mehr irgendwo rein...jedenfalls nicht mit
(Adapter-)Platine.

Gruss Billy
 
Zuletzt bearbeitet:

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Ich überlege ob ich einfach einen µC mit 2 16-Bit-Timern nehme ?
Das Problem ist nicht der 8Bit-Timer (im ersten Test hattest Du den 16er Timer ja auch nur als 8er laufen lassen), und auch nicht Bascom generell, sondern das "Config Timer0" kein PWM kennt. "Config Timer2" kennt PWM nur mit einem Output.
Das ist auch nicht Dein Problem - Du machst es erst zu Deinem, wenn Du darauf beharrst, den Timer mit "Config TimerN" zu konfigurieren...

Noch kurz was zum Programm in #42:
  • In den Zeilen 30, 31 willst sicherstellen, daß der Motor beim Start aus ist. Die beiden Duties hast Du aber in den Zeilen 20, 21 auf 1 gesetzt - die sind also minimal an. 0 wäre richtig.
  • Die Subroutinen Pwm_links und _rechts werden nie verwendet
  • Du scheinst keine Interrupts zu verwenden, brauchst die also nicht global freizugeben
  • Die Begrenzung der Duties nach oben (43,44 und 54,55) geht nur, weil die beiden Variablen Words sind. Besser wäre, daß andersrum zu realisieren ("If Duty2<255 Then Incr Duty2")
Soo...
Das mit dem Timer0 und PWM verstehe ich nicht.
Ich brauche das wirklich so, wie mit dem Timer1 - Werte von 0-255 als Dutycycle einschreiben,
Kannst Du ja machen, nur eben nicht mit Config Timer0.
Grundsätzlich hast Du am Mega16 bei Timer0 nur ein Compare-Unit, also für den Test nur eine Richtung. Dafür steht der UART fürs Debugging bereit. Wenn das Prinzip stimmt, kannst Du das für den Tiny24/44/84 übernehmen, bei dem Timer0 ähnlich aufgebaut ist, aber zwei Compare-Units besitzt (für zwei Richtungen).
Soweit klar?

Dann schau Dir mal gleich am Anfang des Timer0-Kapitels (Seite 71) Figure27 an. An den Datenbus des Controllers sind (hier) drei Register angebunden. Diese kannst Du (bzw Dein Bascom-Code) über den Datenbus auslesen oder beschreiben. Die Register sind:
  • TCNT0 - Timer Counter Register 0 - das ist der eigentliche Zähler, eine 8bit-Zahl. Diese kann durch die Kontrolllogik des Timers inkrementiert, dekrementiert oder gelöscht (auf 0x00 gesetzt) werden. Erreicht TCNT0 0x00 (Bottom) oder 0xFF (Top), wird die Kontrolllogik informiert, die daraufhin zB das TOV-Flag setzt.
  • OCR0 - Output Compare Register 0 - der Inhalt dieses Registers wird kontinuierlich mit TCNT0 verglichen, bei Gleichheit wird die Kontrolllogik informiert, außerdem wird das Compare match flag (OC0) gesetzt. Des weiteren wird die Waveform-Generation dadurch beeinflußt. OCR0 ist genau dasselbe wie Dein Pwm1a bzw Pwm1b in Deinem Programm. Nur eben für Timer0, und da der nur ein Compareunit hat, ohne a oder b.
  • TCCR0 - Timer Counter 0 Control Register - wie der Name sagt, kontrollieren die Bits dieses Registers den Timer. Sie wirken sich nicht nur auf die Kontrolllogik aus, sondern auch auf den Clock-Block (Flankendetektor, Prescaler) und den Waveform Generator.
  • (TIFR) - Timer Interrupt Flag Register - hier befinden sich (neben diversen anderen Bits der anderen Timer) die beiden Bits TOV0 und OC0, die einen IRQ anfordern können, wenn -> TIMSK
  • (TIMSK) - Timer Interrupt Mask Register - analog zu den Flags aus TIFR befinden sich hier die Interrupt-Enable Bits der jeweiligen Flags
TIFR und TIMSK sind in der Figure nicht explizit aufgeführt - brauchen wir auch nicht.

Auf den folgenden Seiten folgen dann 'ne Menge Erklärungen dazu, vieles hab ich hier bereits angerissen... konkret interessant wird's für uns wieder bei den Register Descriptions ab Seite 83. Zu TCNT0, OCR0, TIMSK und TIFR muß ich jetzt hoffentlich nichts mehr schreiben, in TCCR0 finden sich folgende Bits:

  • FOC0 - Force Output Compare - ist nur in nonPWM-Modi wirksam, und gaukelt dem Waveform Generator ein Compare Match vor. Brauchen wir nicht.
  • WGM01:00 - Waveform Generation Mode - diese beiden Bits legen bestimmen, in welchem der vier Operationsmodi der Timer laufen soll. Diese sind in Table38 aufgeführt.
  • COM01:00 - Compare Match Output Mode - diese beiden Bits bestimmen das Verhalten des Waveform Generators, in Abhängigkeit des gewählten Waveform Generation Modes. Tables 39, 40 und 41.
  • CS02:00 - Clock Select - diese drei Bits legen die konkrete Clock des Timers fest, also den Prescaler (aus dem Systemtakt), oder eine Flanke des T0-Beines. Hier hilft Table 42.
Zum Konfigurieren muß also "nur" TCCR0 mit einem sinnigen Wert beschrieben werden. Nichts anderes macht Config Timer1 mit den TCCR-Registern von Timer1:


CodeBox BascomAVR
Config Timer1 = Pwm , Prescale = 1 , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
Ok,
PWM=8 (Parameter 3) - Timer 0 ist eh auf 8bit beschränkt, entfällt (würde sonst bei den WGM-Bits mit auftauchen).
Mit Timer1=Pwm (Parameter 1) meint Bascom den phasenkorrekten PWM (fastPWM schein der Konfigurationsbefehl bei Timer 1 auch nicht zu kennen) - Dein Waveform Generation Mode ist also der phasenkorrekte PWM, und den findes Du (wie oben angedeutet in Table38. Mode1. WGM01=0, WGM00=1.
Prescale=1 (Parameter 2) legt, oh welch Überraschung, den Prescaler (die Anbindung an die Clock) fest. Das wären die CS-Bits mit Table42. Prescaler=1 entspricht CS02=0, CS01=0, CS00=1.
Compare A Pwm= Clear Down (Parameter 4) legt den Compare Output Mode von Kanal A fest. Clear Down bedeutet, daß das Bein genau dann "1" ist, wenn TCNT<OCR (der Zähler kleiner als der vorgegebene Comparewert). Den Compare Output Mode legen wie gesagt die COM-Bits fest, für den phasenkorrekten PWM gilt Table41. Clear Down entspricht Zeile3, also mußt Du COM01=1 und COM00=0 setzen.
FOC0 interessiert uns nicht, bleibt =0.

Zusammengebaut erhältst Du damit

CodeBox BascomAVR
TCCR0=&b01100001
oder

CodeBox BascomAVR
TCCR0=97
oder

CodeBox BascomAVR
TCCR0=&h61
Unter Assembler würde man die Konstante so verschlüsseln:

CodeBox Assembler
(1<<WGM00)|(1<<COM01)|(1<<CS00)

Dabei werden jeweils 'ne "1" entsprechend der Bitwertigkeit nach links geschoben (entspricht der Zweierpotenz), und das ganze dann verORrt. Bascom kennt diese Schreibweise nicht.
Prinzipiell müßte "2^WGM00+2^COM01+2^CS00" die richtige Zahl liefern aber das schluckt Bascom meiner Erinnerung nach nur in einem Inline-Assembler-Block.
Damit hast Du den Timer0 konfiguriert, statt Pwm1a verwendest Du OCR0 (Du mußt also auch das Bein wechseln - sowahl bei der Verdrahtung, als auch beim "zum Output machen" in Zeile 23, 24 (wie gesagt nur ein Output).

Zu den Frequenzen: Der Mega scheint mit einem Mhz getaktet zu sein - bei Prescaler=1 taktet auch der Timer mit 1. Damit ergibt sich im phasenkorrekten PWM (dual slope) 'ne PWM-Frequenz von 1000000Hz/1/510=1961Hz.
Hattest Du nicht eigentlich deutlich langsamere Frequenzen geplant??
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Prinzipiell müßte "2^WGM00+2^COM01+2^CS00" die richtige Zahl liefern aber das schluckt Bascom meiner Erinnerung nach nur in einem Inline-Assembler-Block.


CodeBox BascomAVR
TCCR0=2^WGM00+2^COM01+2^CS00
geht nicht, aber wenn man den Wert vorher als Konstante festlegen läßt, scheints zu klappen

CodeBox BascomAVR
Const Tccr0value = 2 ^ Wgm00 + 2 ^ Com01 + 2 ^ Cs00
'sonstiger Code
Tccr0 = Tccr0value
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hallo !

Sorry ...ich resigniere.
Ich verwerfe das ganze.
Ich verstehe nicht ein wort mehr.
Das bringt nichts, weil ich mit all den
Begriffen nicht zu recht komme.
-Sorry-

Trotzdem danke.

Gruss billy.
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
Hmm... es war nicht meine Absicht, Dich hier irgendwie zu vergraulen, oder zu verunsichern...
Wenn Du irgendwelche Begriffe oder Zusammenhänge (nochmal) näher erklärt haben willst, frag...
TCCR0=97 stellt Timer0 genau so ein, wie Du das in Deinem Code in Beitrag 42 in Zeile 25 mit Timer1 gemacht hast. Nur eben mit nur einem Ausgangskanal (für eine Richtung, weil Timer0 beim Mega16 eben nur einen hat.) Ob Du die 97 in dezimaler Form, oder in binärer (&b...), hexadezimaler (&h....) schreibst, oder Bascom das in einer Konstante selbst ausrechnen läßt, macht keinen Unterschied.
Du schriebst, daß der Code so mit Timer1 perfekt arbeitet. Dann versuch doch mal folgende Änderungen:


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

Dim Duty1 As Byte

Config Pind.7 = Input
Config Pind.2 = Input
Config Pind.3 = Input

Taster_li Alias Pind.2
Taster_re Alias Pind.3
Notaus Alias Pind.7

Portd.7 = 1     'Pullups aktiviert
Portd.2 = 1
Portd.3 = 1

Duty1 = 0    'nur ein PWM-Kanal

Config Pinb.3 = Output       'PWM-Ausgang=OC0
TCCR0=97  
'entspricht quasi "Config Timer0 = Pwm, Prescale=1, Pwm=8, Compare A Pwm = Clear Down"

OCR0 = Duty1                                              'Motor steht beim µC-Start

Do

    If Duty1 > 0 And Taster_re = 0 Then
       Decr Duty1
    End If

    If Duty1 < 255 And Taster_li = 0 Then
       Incr Duty1
    End If

    If Notaus = 0 Then
      Duty1 = 0
    End If

    OCR0 = Duty1
    Waitms 50

    'Print "1      " ; Duty1
    'Print "2      " ; Duty2

Loop

Sollte sich eigentlich genau so verhalten wie Dein Code, nur eben mit Timer0. Nur eben nur mit einer Richtung, die PWM-Ausgabe erfolgt an B3, OC0, dem PWM-Ausgang des Timer0
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hallo...

Du hast mich nicht vergrault- ich habe nur das Gefühl, ich schaffe das grade nicht.
Ich versuchs nochmal ...

Ich habe gesehen, dass noch ein Fehler drin ist - ich hatte das ganze mit 2.000.000 crystal, prescale 64
und nicht clear down , sondern "clear up" laufen. Falschen Code kopiert. Stimmt - die Unterroutinen "pwm_"
hatte ich vergessen zu löschen...Was muss ich dann ändern in dem Code von Dir, um das mal as zu probieren ?

PS: ich habe gesehen Timer 2 hat auch PWM (PIN OC2 ?) dann kann ich doch damit die andere Richtung
machen...

Gruss Billy
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
2.000.000 crystal, prescale 64
Ok, dann bist Du wieder bei 'ner PWM-Frequenz von 2000000/64/510=60Hz.
Einfacher als die Zahl (da oben die 97) jedesmal selbst auszurechnen ist, Bascom das über die Konstante machen zu lassen. Bascom kennt die Register und Bitnamen bzw die Zahlen dahinter. die stehen nämlich im, in Zeile 2 eingebundenen Regfile. Zum invertieren des PWM muß zusätzlich das COM00-Bit gesetzt werden (Table41), für den Prescaler=64 muß nach Table42 zusätzlich das CS01-Bit gesetzt sein.
Statt der Zeile 23 jetzt also:

CodeBox BascomAVR
Const Tccr0value = 2 ^ Wgm00 + 2 ^ Com01 + 2 ^ Com00 + 2 ^ Cs01 + 2 ^ Cs00
Tccr0 = Tccr0value

Für den Test reicht eine Richtung, der angestrebte Tins24/44/84 hat ja zwei PWM-Kanäle an seinem Timer0.
Grundsätzlich kann man natürlich mit Timer2 und der anderen Richtung ähnlich verfahren, da geh ich heute das/die Register nicht mehr durch. An dem OC2-Pin hast Du derzeit einen Deiner Taster, oder?
Wenn das mit Timer0 so paßt, wäre es interessanter mit Timer1 die Pulsweitendetektion anzugehen, und die gemessenen Rohwerte über den UART ausgeben zu lassen.
Wenn das erledigt ist, wäre die Umrechnung von den Zeiten auf den duty (mit beiden Richtungen) drann, Als letztes dann die Anpassung an den Tiny...

P.S.: mit clearup und cleardown gabs 'ne Zeitlang in Bascom mal'n Fehler...
Wie soll sich der Ausgang verhalten? Bei duty=0 low und bei duty=255 hi (so war's vorher), oder andersrum (so isses jetzt)?
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Guten Morgen.

Grundsätzlich kann man natürlich mit Timer2 und der anderen Richtung ähnlich verfahren, da geh ich heute das/die Register nicht mehr durch. An dem OC2-Pin hast Du derzeit einen Deiner Taster, oder?

Okay- ja, der Taster (die Taster) müssten eh geändert werden...war ja nur zum Testen. Die liegen auf dem Board so. Ich habe jetzt das
andere Board, da kann ich die frei wählen. Der PinD.3 ist sowieso der INT0 und den brauche ich ja bei der Impulslängen Detektion.

Wenn das mit Timer0 so paßt, wäre es interessanter mit Timer1 die Pulsweitendetektion anzugehen, und die gemessenen Rohwerte über den UART ausgeben zu lassen.

Das klappt soweit. Ist vieleicht nicht schön programmiert, aber für meine Verhältnisse okay, denke ich :



CodeBox BascomAVR
'Impulserfassung für 6-Kanal PPM nach Christoffer

$crystal = 2000000
$regfile "m16def.dat"
$framesize = 32
$swstack = 32
$hwstack = 64
$baud = 2400


Config Portd.4 = Output
Links_pin Alias Portd.4

Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Noise Cancel = 1

Enable Timer1
On Timer1 Pausedetect

Config Int0 = Rising

Enable Interrupts

Enable Int0
On Int0 Measure

Dim Empf(6) As Integer
Dim Stillstand(6) As Word
Dim Channel As Byte
Dim Wert As Word
Dim Li As Word , Re As Word
Dim Links As Single , Rechts As Single
Dim Links_out As Byte , Rechts_out As Byte

Stillstand(6) = 562

Do

    Empf(6) = Empf(6) - Stillstand(6)

    If Empf(6) < 0 Then

    Li = Abs(empf(6)) / 2
    Links = Li
    Links = Links / 1.099
    Links_out = Abs(links)

    Else

    Links_out = 0

    End If

    If Empf(6) > 0 Then

    Re = Empf(6) / 2
    Rechts = Re
    Rechts = Rechts / 1.099
    Rechts_out = Abs(rechts)

    Else

    Rechts_out = 0

    End If

    Print "" ; Rechts_out ; " : " ; Links_out ; "   " ; Chr(13) ;

    'Waitms 200

Loop

Measure:

If Channel > 0 And Channel < 7 Then
  Stop Timer1
  Wert = Timer1 - 64248
  Empf(channel) = Wert
End If
Timer1 = 62878                                             
Incr Channel
Start Timer1
Return

Pausedetect:

Channel = 0
Return

End


Es handelt sich hier explizit um den Kanal 6 (die anderen mal rausgelassen)
Zu der Rechnerei :

ich bekomme da Werte für die Impulse von 0 bis ca.1118 (schwankt immer etwas)
da es sich um Schiebepotis mit Mittelstellung handelt, brauche ich einmal Werte für
die eine Richtung und dann für die andere. Bei Mittelstellung ist (bei Kanal 6 !) der
Wert ca. 562. Dann habe ich die Werte-Reihe rechnerisch um genau diesen Wert nach unten
verschoben, damit dieser die Mitte dartsellt. Dann bekomme ich natürlich negative
Werte für eine Richtung. Diese habe ich dann wieder umgewandelt. Die Teilung (Faktor)
rührt daher, dass ich alles soweit runtergerechnet habe, dass ich auf 255 Teilungen pro
Richtung komme. Das klappt soweit ordentlich. Jetzt muss ich die je 255 Werte nur an den
jeweiligen PWM-Teil übermitteln und gucken , ob das klappt ...

Gruss Billy
 
Zuletzt bearbeitet:

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hi !

Ich habe mal versucht, das auf den Timer 2 zu übertragen, aber mit den Registern wohl noch
was falsch gemacht !? es passiert was , aber nicht richtig...



CodeBox BascomAVR
Config Pind.7 = Output                                      'PWM-Ausgang=OC2
Const Tccr2value = 2 ^ Wgm20 + 2 ^ Com20 + 2 ^ Com21 + _
2 ^ Cs20 + 2 ^ Cs21

Tccr2 = Tccr2value                                          'entspricht quasi "Config Timer0 = Pwm, Prescale=1, Pwm=8, Compare A Pwm = Clear Down"

Ocr2 = Duty1                                                'Motor steht beim µC-Start



Das hatte ich vergessen :

Wie soll sich der Ausgang verhalten? Bei duty=0 low und bei duty=255 hi (so war's vorher), oder andersrum (so isses jetzt)?

Bei 255 soll der Motor maximal AN sein !
Bei 0 AUS.

der angestrebte Tins24/44/84 hat ja zwei PWM-Kanäle an seinem Timer0.

Okay...dann sollte ich nicht mit dem Timer2 des ATmega16 versuchen, sondern direkt den ATtiny44 nehmen ?
Vergessen wir das oben mit Timer2.

Gruss Billy
 
Zuletzt bearbeitet:

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
mit den Registern wohl noch
was falsch gemacht !? es passiert was , aber nicht richtig...
Für Timer2 müßtest Du bei den Registern in die entsprechenden Tabellen schauen.
WGM20 paßt nach Table50, aber der Timer besitz zusätzlich Prescaler=32, und den hast Du gewählt, Damit wärst Du bei ca 120Hz PWM-Frequenz.
Für Prescaler=64 wäre nach Table54 nur CS22 zu setzen.
Bei 255 soll der Motor maximal AN sein !
Bei 0 AUS.
An entspricht Pin=Vcc, aus Pin=Gnd ?
Dann wäre für den Compare Output Mode (nach Table 53) nur COM21 zu setzen.


CodeBox BascomAVR
Const Tccr2value = 2 ^ Wgm20 + 2 ^ Com21 + 2 ^ Cs22

Wenn der Output invertiert sein soll, ist zusätzlich "2^Com20" zu addieren.

Aber mit Timer2 brauchst Du nichts anzufangen...
Deine Detektionsroutine wird recht umfangreich, wenn Du da Fließkommazahlen berechnen läßt. Ich schau mir das später mal an...
Wenn Du das in den Tiny bekommst, ok...
Ansonsten vereinfachen wir das...
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hallo.

Also ich habe Deinen Vorschlag/Code ja probiert, und der funktioniert auch gut, eben bis auf
"falschrum"... das hatte ich aber glaube ich auch nicht bedacht...also ich müsste das wie gesagt
so haben, dass Duty255 maximal Motor an ist und Duty0 Motor-Stillstand. Wie wäre dann die Zeile
zu ändern ?

Das mit Timer2 lasse ich mal erst...das war mir nur aufgefallen, dass es zumindest beim ATmega16
so gehen würde. Zum Versuchen/Testen.Aber wenn der Tiny44 ja wie ich jetzt auch gesehen habe einen
2. PWM Kanal für Timer0 hat, ist das ja super.

Das mit dem "Vereinfachen" ist schon gut gedacht, allerdings werde ich dann warscheinlich den Code
nicht mehr verstehen, was dann echt mies wäre. ich möchte das ja schon auch irgendwie noch ggf.
bearbeiten oder umstricken können, bzw. was dazu schreiben.Dann würde ich eher schauen es evtl. in
einen anderen µC zu packen, der dann nur minimal grösser ist. Z.B. SOIC24 Grösse-das ginge noch eben.
Aber schauen wir mal erst.

Gruss Billy
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Servus !

Ich hab doch was gelernt :)
Habs mir selber so gestrickt, dass es in beide Richtungen jetzt läuft (mit Verriegelung) :



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

Dim Duty1 As Word , Duty2 As Word

Config Pind.0 = Input
Config Pind.2 = Input
Config Pind.3 = Input

Taster_li Alias Pind.2
Taster_re Alias Pind.3
Notaus Alias Pind.0

Portd.0 = 1                                                 'Pullups aktiviert
Portd.2 = 1
Portd.3 = 1

Duty1 = 0
Duty2 = 0                                                   'nur ein PWM-Kanal

Config Pinb.3 = Output                                      'PWM-Ausgang=OC0
Const Tccr0value = 2 ^ Wgm00 + 2 ^ Com01 + 2 ^ Cs01 + 2 ^ Cs00

Config Pind.7 = Output                                      'PWM-Ausgang=OC0
Const Tccr2value = 2 ^ Wgm20 + 2 ^ Com21 + 2 ^ Cs22

Tccr0 = Tccr0value                                          'entspricht quasi "Config Timer0 = Pwm, Prescale=1, Pwm=8, Compare A Pwm = Clear Down"
Tccr2 = Tccr2value                                          
Ocr0 = Duty1
Ocr2 = Duty2

Do

    If Duty1 > 0 And Taster_re = 0 Then
       Decr Duty1

    End If

    If Duty1 = 0 And Taster_re = 0 Then
       Incr Duty2


    End If

    If Duty2 > 0 And Taster_li = 0 Then
       Decr Duty2

    End If

    If Duty2 = 0 And Taster_li = 0 Then
       Incr Duty1


    End If

    If Notaus = 0 Then
    Duty1 = 0
    Duty2 = 0
    End If

     If Duty2 > 254 Then Duty2 = 255
     If Duty1 > 254 Then Duty1 = 255

    Ocr0 = Duty1
    Ocr2 = Duty2

    'Print "   " ; Duty1 ; "  " ; Duty2 ; "   " ; Chr(13);

    Waitms 10

Loop

End


Jetzt muss ich es mit dem Impuls-PRG verhochzeiten...

Gruss Billy !
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
der funktioniert auch gut, eben bis auf
"falschrum"... das hatte ich aber glaube ich auch nicht bedacht...also ich müsste das wie gesagt
so haben, dass Duty255 maximal Motor an ist und Duty0 Motor-Stillstand.
Ich weiß nicht bei welchem Pegel am Bein der Motor läuft, und bei welchem nicht.
Wir haben den Timer (mithilfe der WGM-Bits) in den Modus "phasenkorrekter PWM" gesetzt. Dual slope. Das heißt, der Timer läuft zwischen 0 und 255 hin und her. Er zählt von null hoch bis 255, und dann wieder runter bis null und dann wider hoch bis 255 usw usw...
Jedesmal, wenn er dabei auf den Wert im Output Compare Register trifft (TCNT=OCR) wird ein Output Compare Match ausgelöst. Was da geschehen soll, haben wir mit den COM-Bits festgelegt. Ist nur COM01 gesetzt, wird das Bein beim Match beim Raufzählen auf Gnd geschaltet, und beim Runterzählen beim Match auf Vcc. Es ist also auf Vcc solange TCNT kleiner als der vorgegebene OCR-Wert ist, und Gnd, wenn TCNT größer als dieser ist. Wenn OCR 'ne Null vorgibt, ist TCNT immer größer(gleich), das Bein immer Gnd. Wenn OCR 'ne 255 vorgibt, ist TCNT immer kleiner(gleich), das Bein immer Vcc. Wird zusätzlich COM00 gesetzt, wird dasselbe Verhalten, nur eben invertiert bewirkt. Das Bein ist dann Gnd solange TCNT kleiner als OCR ist, und Vcc wenn TCNT größer als OCR ist.
Der Vorgabe-Vergleichswert im OCR, das ist Dein Duty.
"falschrum"[...]Wie wäre dann die Zeile zu ändern ?
Wenn der Output invertiert sein soll, ist zusätzlich "2^Com20" zu addieren.
Also statt:


CodeBox BascomAVR
Const Tccr2value = 2 ^ Wgm20 + 2 ^ Com21 + 2 ^ Cs22
das hier:


CodeBox BascomAVR
Const Tccr2value = 2 ^ Wgm20 + 2 ^ Com21 + 2 ^ Com20+ 2 ^ Cs22


Ok, zurück zu Timer0.
Das ganze läuft also ordentlich mit ca 60Hz PWM-Frequenz. Bisher mit 2MHz Systemtakt und Prescaler=64. Wegen der Genauigkeit der Pulsmessung vervierfachen wir den Systemtakt auf 8MHz. Gleichzeitig wird der Prescaler des PWM-Timers auch vervierfacht, hier ändert sich also die Frequenz nicht.
Prescaler auf 256 ändern:


CodeBox BascomAVR
Const Tccr0value = 2 ^ Wgm00 + 2 ^ Com01 +  2 ^ Cs02
Tccr0 = Tccr0value

Welche der COM-Bits Du nun konkret brauchst, ist mir nicht klar. Wenn Du den Controller auf 8MHz setzt, sollten das dieselben 60Hz sein.

Jetzt zur Erfassung:
Dein Code rechnet genau mit single-Zahlen, und rundet die dann zu weiterzuverarbeitenden Ganzzahlen. Bascom muß also extra single-genaue Divisionsroutinen einbinden.
Dasselbe Ergebnis kannst Du aber auch mit ganzzahliger Integerdivision erreichen. Viel schlanker und schneller.
Vorüberlegungen: Bei 8MHz dauert ein Takt 125ns. 1ms entspricht 8000 Takten. 1,5ms 12000 Takten. 2ms 16000 Takten. Ein Timer mit Prescaler=1 würde also in 1ms | 1,5ms | 2ms 8000 | 12000 | 16000 Schritte zählen.
Ein 16bit-Timer könnte mit 2^16 Schritten weiter als 8ms laufen - wir begrenzen ihn einfach mit dem CTC-Mode (Clear Timer on compare match) auf ... sagen wir 4ms. Im CTC läuft der Timer nicht von 0xFFFF (65535dezimal) auf 0x0000 über sondern bei dem Wert, den das verwendete Compare-Register vorgibt. Setzen wir das Compareregister auf 31999dezimal (0x7CFF), läuft der Timer immer nur von 0 bis 31999, und da nach 0 über. Also alle 32000 Takte ein Überlauf. Also alle 4ms.
Ok, dann mal den ersten Testcode (basierend auf Deinem Code aus #52:


CodeBox BascomAVR
'Impulserfassung für 6-Kanal PPM nach Christoffer

$crystal = 8000000
$regfile "m16def.dat"
$framesize = 32
$swstack = 32
$hwstack = 64
$baud = 2400

'es gibt hier sicher auch n Config Timer1=ctc... die Onlinehilfe sagt nichts dazu, also einfach direkt über die Register
'Wir verwenden den CTC mit OCR1A als Überlauf
OCR1A=31999  'Überlauf nach 4ms
'Waveform Generation Mode=4: WGM13=0, WGM12=1, WGM11=0, WGM10=0
'Output Compare Pins werden nicht verwendet, WGM11 und 10 befinden sich im TCCR1A und sind default 0
'WGM13 und 12 befinden sich neben dem Prescaler im TCCR1B
'TCCR1A muß nicht geändert werden.
'wir verwenden Prescaler=1: CS12=0, CS11=0, CS10=1
const TCCR1Bvalue = 2 ^ Wgm12 + 2 ^ Cs10  'CTC bis OCR1A, Prescaler=1
TCCR1B=TCCR1Bvalue


Config Int0 = Rising

Enable Interrupts

Enable Int0
On Int0 Measure

Dim Empf(6) As Word
Dim Channel As Byte

Do

    Print "Ch1:" ; Empf(1) ; "Ch2:" ; Empf(2) ; "Ch3:" ; Empf(3) ; "Ch4:" ; Empf(4) ; "Ch5: " ; Empf(5) ; "Ch6:" ; Empf(6) ; Chr(13) ;

    Waitms 500

Loop

Measure:
 If TIFR.OCF1A=1 then  'wenn Überlauf (über OCR1A)
  TIFR.OCF1A=1   'lösche Flag
  Channel=0   'synchronisiere Kanal-Array
 Else  'sonst
  Incr Channel 
  Empf(Channel)=Timer1  'lese Rohwert in Array ein
 End if
 Timer1=0 'Timer auf Flanke (annähernd) synchronisieren
Return

Es sollten zweimal pro Sekunde die gelesenen Rohdaten der sechs Kanäle ausgegeben werden - zu erwarten wären Werte zwischen 8000 und 16000, Mittelstellung je 12000
 
Zuletzt bearbeitet:

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
-Ich glaube, es hatte sich noch ein Beitrag von mir überschnitten-

Ein Problem sehe ich schon : ich verstehe den Code nicht mehr.
Was ich befürchtet hatte.

Das ist glaube ich nicht meine welt mit den Registern...sorry.
Mit den Bascom Sachen geht es gerade noch.

Werde es gleich mal eingeben und schauen, was der Code für Ergebnisse liefert.

Gruss Billy
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3,487
65
48
Marwitz
Sprachen
  1. BascomAVR
  2. Assembler
hab doch was gelernt :)
Habs mir selber so gestrickt, das
:good:

Bei meinem Code in #57 synchronisiert sich ja der Kanalzähler auf die erste Synchronisationslücke - mithilfe der Timerüberläufe. Erst nach der ersten erkannten Lücke werden die gemessenen Werte in die korrekte Array-Zelle geschrieben. erst nach der zweiten erkannten Lücke sind alle Zellen mit korrekten Werten gefüllt.
Wird im allgemeinen sicher keine Rolle spielen, ABER im worst case - wenn der Timer zufällig hinreichend kurz vor Ende einer Synchronisationslücke initialisiert wird (TCCR1B=blablub), wird diese Lücke mangels Überlauf nicht als solche erkannt, sondern als (erster) Kanal. Kanal6 wird dann nicht nach Array(6) geschrieben, sondern in die SRAM-Adresse dahinter - was auch immer Bascom eventuell in dieser Adresse abgelegt hat, wird überschrieben.
Um das zu verhindern, müßte man entweder auf die erste Lücke warten, und das bei jedr Flanke überprüfen (Performanceverlust), oder man spendiert dem Array in Zeile 29 einfach eine siebente Zelle:

CodeBox BascomAVR
Dim Empf(7) as Word
 

AVR-Billy

Mitglied
19 Jun 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Soooo...

Ergebnisse vom Impuls-Leser_test-Code :

Alle Mittelstellung




Alle max. vor




Alle max. rück





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)