38 kHz met Arduino hardware

Over het maken van een (al dan niet gemoduleerde) 38 kHz blokgolf m.b.v. Arduino is e.e.a te vinden op het web. Ik besloot het zelf maar even van scratch op te zetten in Bascom. Simpel dingetje, zonder te hoeven leunen op Arduino libs waarvan je nooit weet wat die precies doen...

Mijn aanpak: Configureer de 16 bits timer (Timer1) als counter die zonder prescaler klokpulsen telt. De cpu klok is 16 MHz, dus moet die door 421 gedeeld worden om op 38 kHz uit te komen. Ik gebruik voor de deling de compare registers.
OCR1A stel ik in op 421/2=210 (halve periodetijd) en OCR1B op 421 (einde van hele periode). Wanneer de 'count' van de timer/counter gelijk is aan een van beide compare registers komt er een interrupt.
In de eerste interrupt routine (count=210) toggle ik een pin. In de tweede interrupt routine reset ik eerst de counter (TCOUNT=0) en toggle daarna de pin. Het weer op nul zetten van de counter kost natuurlijk een paar klok-cycli, dus dat moet eerst gebeuren.

Vreemd genoeg meet ik op de output pin geen 38 kHz maar een lagere frequentie (~36 kHz).

Een tweede Pro-Mini deed hetzelfde. De klokfrequenties van beide exemplaren zijn 15,99 MHz of daaromtrent
Ik weet dat je moet 'delen' door n-1 (gewenste pulstijd/klokperiode) als je een bepaalde pulsduur wil maken omdat het resetten van de timer/counter ook een klokperiode kost, maar in dit geval kom ik (empirisch bepaald) ergens uit op 354/177 i.p.v 421/210. Kennelijk mis ik ongeveer 65/ klokpulsen....

Dit was al zo toen ik de SW de eerste keer 'kaal' zonder andere functies en interrupts (seriele communicatie bijv.) ging testen.

Heb ik misschien te maken met een chinese kloon AVR of snap ik niet hoe de timer/counters werken. Bij vorige projectjes klopten de sommetjes wel....

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.
Arco

Special Member

De timers in een Arduino zullen toch wel een auto-reload functie hebben? Dan hoef je maar 1 keer in te stellen...
(hardware pwm kan trouwens ook)

[Bericht gewijzigd door Arco op vrijdag 15 juli 2022 19:56:03 (13%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 15 juli 2022 19:19:42 schreef soldeersmurf:
In de tweede interrupt routine reset ik eerst de counter (TCOUNT=0) en toggle daarna de pin. Het weer op nul zetten van de counter kost natuurlijk een paar klok-cycli, dus dat moet eerst gebeuren.

OCR1B op 421 met een prescaler van 1 geeft een frequentie van 16e6/(421+1) = 37,9e3 Hz. Je ziet in werkelijkheid 36 kHz, dus 16e6 / 36e3 = 444 klokcycli per ronde van de timer. Je mist dus 444 - 422 = 22 klokcycli, niet 65. En het is niet zo gek om te denken dat het 22 klokcycli kost van het moment van de OCR1B-interrupt tot het moment dat de timer gereset is en weer loopt. In die tijd moet de ISR aangeroepen worden (minimaal 4 klokcycli), moeten de cpu registers veiliggesteld worden en moeten er 2 geheugenregisters opgeslagen worden (TCNT1 is 16 bits!). Kortom: gebruik de pwm feature van de timer.

@ Deskinspin
Ik had me vergist w.b.t. de 36 kHz bij een deelfactor van 421. Ik kwam daarmee op ~33 kHz terecht, waarmee het sommetje wel op 484-422=62 uitkomt. Dat is ook de waarde er nu 38 kHz uitkomt.

Volgens de datasheet kost de jump naar de isr minimaal 4 clokcycli. o.a. afhankelijk van de instructie die de cpu aan het uitvoeren was.

Registers worden niet automatisch op de stack gesaved. Alleen de stackpointer. dus ik 'schrok' wel van die 62 cycli.
Inmiddels ben ik erachter dat Bascom wel bijna alle registers saved tenzij je de optie NOSAVE gebruikt... dat was ik dus vergeten.

Ik zal je suggestie om de PWM mode te gebruiken ook eens uitproberen.

In ieder geval weer wat geleerd (of weer aan herinnerd).

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.

Het is nooit handig om te vertrouwen op een specifieke interrupt latency, want als je nog een andere interrupt in je programma hebt, kan die latency opeens veel langer zijn dan je verwacht.

Die timer kan prima zelf resetten op een compare match, dan heb je de hele interrupt niet nodig.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 19 juli 2022 15:26:13 schreef soldeersmurf:
Registers worden niet automatisch op de stack gesaved. Alleen de stackpointer.

Er zijn CPUs die om die interrupt latency omlaag te krijgen gewoon een hele registerset paraat houden, en dus vanzelf switchen naar de andere registerset als er een interrupt komt. Gewoon om te leren wat voor truuks gebruikt worden om dat wel snel te krijgen.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Arco

Special Member

De enhanced PIC16F1xxx gebruiken maar 1 instructieclock cycle om alle werkregisters te saven (+2 clocks om naar de interrupt te jumpen)
Dat scheelt echt ontzettend veel tijd als je met 38kHz een interrupt aanroept...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 19 juli 2022 16:25:19 schreef SparkyGSX:

Die timer kan prima zelf resetten op een compare match, dan heb je de hele interrupt niet nodig.

Ik heb dat interrupt wel nodig. In ieder geval het tweede omdat ik ook bij wil houden hoeveel perioden er al voorbij zijn. Ik moet namelijk bursts van bepaalde lengte maken en dus kunnen meetellen.

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.
Arco

Special Member

De interrupt heb je toch altijd (anders is het geen interrupt... ;) )
Wat tellertjes bijhouden is dan ook geen probleem, maar een autoreload bespaart je veel werk.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

En zorgt er voor dat je timer gewoon doorloopt ook al is de interrupt routine voor 20-40-60 of misschien wel 200 cyclces uitgesteld.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/