PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 72kHz / 32kHz



t1001hh
16.08.2011, 12:06
Moin, Ich habe hier mal eine Frage wie man auf die 32 / 72 kHz kommt ich verstehe die Einstellung der Timer noch nicht so recht kann mir das hier mal wer vorrechnen oder einen guten Link schicken?

noch eine Frage, hat irgendwer Erfahrungswerte mit einen ATtiny13? So fern ich das richtig verstanden haben laut Datenblatt kann der keine externe Taktung annehmen oder? Und wie genau ist denn die interne Taktung? Kann man damit einen genau 70kHz Impuls mittels PWM erzeugen?
danke im Voraus
Gruß aus Hamburg

radbruch
16.08.2011, 12:46
Hallo

36kHz wäre richtiger, denn das ist die Trägerfrequenz des IR-Signals und auch die des SFH5110-36.

In der orginalen CD-Version der asuro-Library wurde diese Trägerfrequenz über den Timer2 im normalen Modus erzeugt. Beim Überlauf wurde der OC2-Ausgang getoggelt und das Zählregister TCNT2 mit einem Startwert für 72kHz geladen. Bei den späteren Libs wurde das zur CTC-Betriebsart geändert. Dadurch wurde die Timer2-ISR nur noch mit 36kHz aufgerufen. Da die ISR aber auch die Zeitbasis für die Sleep()-Funktionen liefert, dauert eine Millisekunde bei der orginalen Lib 72 Sleep()s und bei den neueren Lib nur 36 Sleep()s. Grundsätzlich, weil die Änderung und Erweiterung gleichzeitig stattfand, funktionieren alle Libs die Msleep() kennen mit 36kHz.

Wirklich clever wurde die Erzeugung der Trägerfrequenz mit den Änderungen von Waste im Rahmen der IR-Abstandsmessung. Jetzt war es möglich, die Hell- und Dunkelanteile des IR-Signals zu beeinflußen. Dieses Timersetup wird auch in der aktuellen Version der Library verwendet, weil sie auch die IR-Abstandmessung unterstützt.

Wie das Timersetup genau funktioniert hatte ich hier mal beschrieben:
https://www.roboternetz.de/community/threads/45551-Verst%C3%A4ndnisproblem-beim-IRCollisionTest-Testprogramm?p=436695&viewfull=1#post436695

Gruß

mic

Zitat aus dem Beitrag:
Dieser Absatz erklärt, wie das Timersetup funktioniert, das ist für das Verständniss der IR-Abstandsmessung nicht so wichtig: Beim Start des Counters wird der OC2-Pin auf low gesetzt, beim Erreichen des Wertes im OCR2-Register wird der OC2-Pin nach high umgeschaltet. Der Counter zählt dann weiter bis zum Überlauf, dann wird das Zählregister wieder auf null gesetzt und die Overflow-ISR angesprungen. Bei 8MHz dauert eine 36Khz-Periode ca. 222 Zähltakte, wenn man für den Counter keinen Prescaler verwendet. Beim Berechen des Counterstartwertes und des Umschaltpunktes setzt man nun am Besten am Ende einer Periode beim Überlauf des Zählregisters an. Für 111 Takte vor dem Überlauf muss man den Wert im OCR2-Register auf 256-111=145 oder 0x91 setzen, 222 Takte davor muss das Zählregister starten. Für das Laden des Zählregisters braucht man noch zusätzliche drei Takte: 256-222+3=37 oder 0x25. Die betreffenden Zeilen im Timersetup in asuro.c:

Im Init():

OCR2 = 0x91; // duty cycle for 36kHz

In der ISR:

SIGNAL (SIG_OVERFLOW2)
{
TCNT2 += 0x25;
...
Das += bewirkt, dass inzwischen schon erfolgte Zähltakte nicht ignoriert werden.


[Edit]
Noch 'ne Info zum Tiny13: Der läuft im Auslieferzustand mit 1,2MHz, ohne internen Vorteiler /8 (Fuses) mit 9,6MHz, mit interner Taktquelle. Hier erzeugt mein 1,2MHz-Tiny13 Servoimpulse mit einer 10kHz-Basis:
https://www.roboternetz.de/community/threads/31035-monoleg-Der-einbeinige-Roboter?p=298095&viewfull=1#post298095

Bei einem umgefuseten 9,6MHz-Tiny wären das ca. 80kHz. Das Feintuning der Frequenz müßte man am OCR0A einstellen.

t1001hh
16.08.2011, 13:39
super klasse!!! genau was ich brauchte:)

nur mal so aus neugier... das mit der sleep und Msleep Funktion habe ich verstanden, jedoch ist dem Prozessor ja auch die Taktung bekannt also wieso nimmt man nicht gleich die Funktion delay oder gäbe es da keinen unterschied?

radbruch
16.08.2011, 14:21
Bei delay muss die Dauer der Verzögerung zur Kompilezeit bekannt sein. Nun könnte man auch auf Basis von delay auch eine variable Verzögerung konstruieren, aber dann ist der Aufwand nicht mehr kleiner als wenn man es gleich selbst auf der Basis der eigenen Lib umsetzt. Hier steht wohl der Lerneffekt im Vordergrund.

Was sich die Macher des asuro damals, als sie das asuro-Konzept erbrütet haben, so alles gedacht haben, kann ich heute nur erahnen. Sowohl hard- wie auch softwaretechnisch eine echte Meisterleistung.

t1001hh
30.08.2011, 09:20
Moin ich nochmal zu diesem Thema,
kannst du mir dies nochmal genauer erklären??

Bei einem umgefuseten 9,6MHz-Tiny wären das ca. 80kHz. Das Feintuning der Frequenz müßte man am OCR0A einstellen.
wi ekommt man da auf 80 kHz?

Wenn ich den Tiny mit 9,2 MHz betreibe und durch 72kHz teile bekomme ich ca 128 und wenn ich den Zähler als CTC-Betriebsart programmiere dauert eine Periode 255-128=127 Takte wenn ich also OCR0A auf 127 einstelle, bekomme ich so die 72kHz? oder bin ich völlig auf dem falschen Dampfer?

danke im Vorraus

Gruß aus Hamburg

radbruch
30.08.2011, 10:10
Hallo

Oje, frag mich nicht, was mich da geritten hat. Der Tiny im Beispielprogramm erzeugt die Servosignale mit 24kHz (1,2MHz/50) und deshalb sind das bei 9,2MHz keine 80kHz. Entschuldigung.

Deine Berechnung ist fast richtig. Beim CTC-Mode zählt der Timer von 0 bis OCR0X, beim Match beginnt er wieder bei null und führt die ISR aus. Deshalb kannst du die 127,7 direkt ins OCR0X schreiben. Die Berechnung 256-128 gehört zum Overflow-Mode. Man berechnet so den Vorladewert des OCR0X um nach der gewünschten Zählertaktzahl einen Überlauf zu erhalten.

Gruß

mic

t1001hh
30.08.2011, 13:14
so ein mist der Tiny 13 hat ja 9,6MHz... also stimmt die Rechnung ja nicht dann muss ich den Zähler im CTC-Modus betreiben und rechne:
9,6MHz durch 72kHz = 133,3333-> dies Teile ich durch 2 -> 66,5 sprich 67 also ziehe ich 67 von 256 ab und erhalte
189 oder oxBD die ich im OCR0A/B Register schreibe
bei 123 oder ox7B muss ich starten, also schreibe ich im Interrupt

SIGNAL (SIG_OVERFLOW0)
{
TCNT0 += 0x7B;
....
}

bin ich soweit richtig? würde ich so 72kHz bekommen?
Gruß aus Hamburg und nochmals vielen dank:)

radbruch
31.08.2011, 16:08
Hallo

CTC-Mode ohne Prescaler, die ISR wird alle 1/72000 Sekunde aufgerufen:

#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIM0_COMPA_vect)
{
}

int main(void)
{
TCCR0A = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0A |= (0 << COM0A0) | (0 << COM0A1); // ohne OCR-Pin
TCCR0B = (0 << CS02) | (0 << CS01) | (1 << CS00); // kein prescaler!
TIMSK0 = (1 << OCIE0A); // Interrupt ein
OCR0A = 9600/72; // 9,6MHz/72kHz = 133,3
sei();

while(1)
{
}
return(0);
}

Genau sind es 9600/133=72,18kHz.

Gruß

mic


btw.:
"9,6MHz durch 72kHz = 133,3333-> dies Teile ich durch 2" Wieso denn /2?

Und dann noch ne Frage: Was willst eigentlich du anstellen mit den 36/72kHz?

t1001hh
01.09.2011, 08:21
erstmal vielen dank für die immer sehr hilreiche Antwort:)

durch 2 deshalb, weil ich am Ausgang ein Signal von 72khz benötige und der Ausgang doch bei der hälfte umschalten muss oder nicht???, bei deinem Vorschlag bekomme ich doch am Ausgang keine 72khz oder nicht? also ist der CTC Mode dann doch falsch?

sollte man dann 36kHz nehmen und den Ausgang dann dabei toggeln? oder einen anderen Mode?
Entschuldigung das ich mit der PWM ein wenig schwer tue :rolleyes:


72kHz benötige ich für die Schaltung für die Erweiterung Minesweeper, die ich auf einer extra Platine dazu gebaut habe und wollte dies mittels eigenen Controller umsetzen, der dann nur ein Signal an den ASURO sendet. Da die erweiterte lib mit 36kHz arbeitet und ich die Option für die IR Abstandsmessung offen lassen wollte habe ich mich für einen zusätzlichen Controller entschieden.

radbruch
01.09.2011, 09:56
Hallo

Danke für die Erklärungen. Aber was brauchst du nun wirklich? 36kHz, 72kHz oder gar 144kHz?

Beim oben gezeigten Grundgerüst wird der Interrupt 72000 mal in der Sekunde ausgelöst und die ISR angeprungen. 72000 mal, weil eine Periode des 36kHz-Signals aus zwei Halbwellen besteht und der erzeugende Ausgang deshalb doppelt so schnell angesteuert werden muss. Hier die passende Erweiterung die den Pin5 oder PB0 ansteuert:

#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIM0_COMPA_vect)
{
// PB0 einlesen und invertiert wieder ausgeben
if(PINB & (1<<PB0)) PORTB &= ~(1<<PB0); else PORTB |= (1<<PB0);
}

int main(void)
{
TCCR0A = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0A |= (0 << COM0A0) | (0 << COM0A1); // ohne OCR-Pin
TCCR0B = (0 << CS02) | (0 << CS01) | (1 << CS00); // kein prescaler!
TIMSK0 = (1 << OCIE0A); // Interrupt ein
OCR0A = 9600/72; // 9,6MHz/72kHz = 133,3
sei();

DDRB |= (1<<PB0); // PB0/Pin5 als Ausgang betreiben
while(1)
{
}
return(0);
}(ungetestet)

Bei der PWM-Betriebsart, wie beim asuro, läuft der Timer von 0 bis 255 und startet dann wieder bei 0. Die Periodendauer wird über das OCRx-Register erzeugt. Immer wenn der Zählerwert dem Inhalt dieses Registers entspricht wird der OCx-Ausgang des Timers geschaltet. Details werden über die Parametrierung des Timers eingestellt. Beim asuro wird der Ausgang immer gesetzt wenn der Timer nach dem Überlauf bei 0 neu startet, wenn OCRx erreicht wird, wird der Ausgang wieder ausgeschaltet. Dadurch werden pro Timerdurchlauf beide Periodenhäflten erzeugt. Ein Durchlauf dauert 8MHz/36kHz=222 Takte, jede Halbwelle also ca. 111 Takte. Für ein symetrisches Signal muss der Ausschaltpunkt deshalb 111 Takte vor dem Überlauf sein, deshalb wird das OCRx-Register mit 256-111=145 oder 0x91 geladen.

Nun muss man noch die Takte pro Periode von 256 auf 222 kürzen. Da der Timer beim Überlauf nach 0 springt und erst dann die Überlauf-ISR aufgerufen wird, kann man hier den Zählerstand manipulieren. Das Zählregister des Timers muss um die zuvielen Takte erhöht werden. Dazu wird der aktuelle Zählerstand eingelesen, die Korrektur dazugerechnet und alles zusammen wieder in das Zählregister zurückgeschrieben. Der Korrekturwert errechnet sich aus der Differenz von 222 zu 256 und zusätzlichen(!) 3 Takten fürs Laden, Rechnen und Zurückschreiben: 256-222+3=37 oder 0x25. Deshalb findet man in der asuro-Lib in der ISR folgende Zeile:

TNCT2 += 0x25;

Beim Tiny mit 9,6MHz klappt das nicht so einfach: 9600000/36000=266. Leider zuviel für den 8-Bit-Timer.

Gruß

mic

t1001hh
01.09.2011, 10:59
Beim Tiny mit 9,6MHz klappt das nicht so einfach: 9600000/36000=266. Leider zuviel für den 8-Bit-Timer.

das habe ich mir schon gedacht,

ich habe mir wieder gedanken gemacht und rum gerechnet und mal sehen ob ich es richtig verstanden habe,
folgendes kam raus:

nehme ich die interne Taktfrequenz von 4,8kHz

rechne ich 1,2MHz/72kHz =66 oder 67
1,2Mhz durch 66 ergibt 72,7Hz die sollten für die Minesweeper Erweitung in Ordnung sein

der Zähler wird wieder im CTC Betrieb betrieben und
OCRA0= 256-(66:2)=223
TCNT0=256-66+3("Für das Laden des Zählregisters")

haut das so hin?
Gruß aus Hamburg

radbruch
01.09.2011, 12:15
Aha, es lichtet sich. Ich habe nun deinen Spulenthread (https://www.roboternetz.de/community/threads/53991-Mine-Sweeper-Spule) gefunden und das von Manf verlinkte PDF gelesen:
http://www.produktinfo.conrad.com/datenblaetter/175000-199999/191555-as-01-de-ASURO_MINESWEEPER_BAUSATZ.pdf

Grundsätzlich sind wir auf dem richtigen Weg, denn die Variable count72kHz zeigt eindeutig, dass es sich um die 72kHz-Lib des asuro von der CD handelt. Diese Version 2.1 kann man hier runterladen: http://sourceforge.net/projects/asuro/files/AsuroLib/

Daraus nun der Ausschnitt mit der Timerparametrierung und der ISR:

volatile unsigned char count72kHz;

/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
}

/* Init function Processor will be initalized to work correctly */
void Init (void)
{
//-------- seriell interface programmed in boot routine and already running -------
// prepare 36kHz for IR - Communication
TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS20);
OCR2 = 0x6E; // 36kHz @8MHz
TIMSK |= (1 << OCIE2); // 36kHz counter for sleep


WGM21 gesetzt bedeutet CTC, COM20 bedeutet "Toggle OC2 on Compare Match", also Ausgangspin umschalten bei Match. CS20 schaltet den Prescaler aus, somit ergeben 0x6e oder 110 im OCR2-Register etwa 8000000/110= 72727 Matches pro Sekunde und ebensoviele Aufrufe der ISR. Da bei jedem Match der Ausgang getogglet wird, ergeben sich am OC2-Pin 36kHz.

Hier mal ein Testprogramm, keine Ahnung ob das so funktioniert:

// Ansteuerung der Minesweeper-Erweiterung für den asuro mit einem Tiny13 1.9.2011 mic
// Basis ist das Testprogramm aus der Anleitung Seite 10

// Asuro: Tiny13:
// Ausgang der 36kHz (OC2): PB1 (OC0B, Pin6)
// Eingang für das Signal (INT0): PB0 (PCINT0, Pin5)
// Ausgang für LED (PD6): PB2 (Pin7)

// Der Eingang ist wie beim asuro interruptfähig.

#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned char count72kHz;
ISR(TIM0_COMPB_vect)
{
count72kHz ++;
}

int main(void)
{
TCCR0A = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0A |= (1 << COM0B0) | (0 << COM0B1); // Toggle OC0B on Compare Match
TCCR0B = (0 << CS02) | (0 << CS01) | (1 << CS00); // kein prescaler!
TIMSK0 = (1 << OCIE0B); // Interrupt ein
OCR0B = 9600/72; // 9,6MHz/72kHz = 133,3
sei();

DDRB |= (1<<PB2) | (1<<PB1); // LED und 36kHz sind Ausgänge

unsigned char oscillation;

PORTB &= ~(1<<PB2); // LED aus
while(1)
{
count72kHz=0;
oscillation = 0;
while (count72kHz<100) {
// Detect low level
if ((PINB & (1<<PB0)) == 0) oscillation = 1;}
// If oscillator is running, no metal object is within
// range, so LED should be off
if (oscillation) PORTB &= ~(1<<PB2); else PORTB |= (1<<PB2); // LED schalten
}
return(0);
}

Gruß

mic

t1001hh
01.09.2011, 12:42
super klasse:) das muss ich erstmal alles nach vollziehen und dann werde ich die Spule wickeln und alles mal Testen und messen und werde dann mal am Ende Bereicht erstatten wenns erwünscht ist:)
aber vielen Dank war eine riesen Hilfe! wenn ich Fragen habe melde ich moch noch mal
Gruß aus Hamburg

radbruch
01.09.2011, 13:22
Na dann: Viel Erfolg.


der Zähler wird wieder im CTC Betrieb betrieben und
OCRA0= 256-(66:2)=223
TCNT0=256-66+3("Für das Laden des Zählregisters")

CTC bedeutet, der Timer zählt von 0 bis zu dem Wert in OCR0X. Beim Erreichen von OCR0X startet er wieder bei 0 und der Interrupt wird ausgelöst. Das Zählregister TCNT0 muss dabei nicht korrigiert werden!

Im normalen Modus (und auch im PWM-Mode) zählt der Timer bis zum Überlauf und startet dann wieder bei 0. Hier muss man die Anzahl der Zähltakte bis zum Überlauf berechen und gegebenfalls auch das Zählregister korrigieren. Diese Betriebsart verwenden wir aber nicht.

Gruß

mic

t1001hh
01.09.2011, 13:38
CTC bedeutet, der Timer zählt von 0 bis zu dem Wert in OCR0X. Beim Erreichen von OCR0X startet er wieder bei 0 und der Interrupt wird ausgelöst. Das Zählregister TCNT0 muss dabei nicht korrigiert werden!
also wenn der Zähler von dem Wert OCR0X auf 0 springt toggelt er den Ausgang und löst den Interrupt aus oder? aber da dies mit 72kHz getoggelt wird habe ich dann nicht 36kHz? ich brauche aber 72kHz oder wird der Minesweeper-Schwingkreis mit 36kHz betrieben?
gruß aus Hamburg

radbruch
01.09.2011, 14:02
Hallo

Der Schwingkreis wird mit 36kHz betrieben, da auch die 72kHz-Library des asuro am OC2-Pin 36kHz ausgibt. Normalerweise ist das ja die Trägerfrequenz für die IR-Kommunikation. Deshalb wird im Testprogramm aus der Anleitung der Timer beim asuro ganz normal mit Init() parametriert.

Der Zugriff auf count72kHz gibt zwar bei neueren Libs (ab v2.3) eine Fehlermeldung, aber da sie im Testprogramm nur sicherstellt, das 100 Halbwellen erzeugt wurden um den Schwingkreis anzuregen, sollte auch ein schlichtes Sleep(100) bei der 72kHz-Variante ausreichen. Bei den aktuellen Libs wäre es entsprechend Sleep(50) für 100 Halbwellen. Da wir aber beim Tiny kein Sleep() haben, zählen wir die Halbwellen selbst mit unserem count72kHz. Die erzeugte Frequenz am OC0X bleibt aber in allen Fällen 36kHz.

Gruß

mic

[Edit]
Im asurowiki wurde der Code stillschweigend an die aktuellen Libs angepasst:
http://www.asurowiki.de/pmwiki/pmwiki.php/Main/MineSweeper

Die Schaltung wird definitiv mit 36kHz betrieben. Leider hat sich aber ein Denkfehler eingeschlichen:

while (count36kHz<200)

count36kHz zählt zwei Halbwellen, die Wartezeit fürs Einschwingen beträgt deshalb in dieser Version 400 Halbwellen. Richtiger, aber vielleicht nicht wirklich besser, wäre:

while (count36kHz<50)

t1001hh
01.09.2011, 14:57
ahhhh nun macht das ganze doch alles Sinn:D natoll dann habe ich ja die ganze Zeit was falsches gedacht undnun verstehe ich:D besten Dank für die doch so schwere Geburt:D
Grußs aus Hamburg

radbruch
01.09.2011, 15:32
Also ganz ehrlich, der ganze Aufwand bisher hat sich eigentlich nicht gelohnt:

Der linke Teil der Schaltung aus Dioden und Kondensatoren dient zur Erzeugung einer (bezogen
auf die Masse der Schaltung) negativen Versorgungsspannung. Das ist erforderlich, da die
Spannung am Schwingkreis um Masse herum schwingt und damit sowohl positiv als auch negativ
werden kann.Aha! Deshalb auch der gigantische C2 mit 100µF zwischen Vss und GND (mit + an GND!). Da kommt von den 36kHz gar nichts mehr an!

Der Schwingkreis um die Spule/Kondensator steuert sich selbst:

Aber wie beim Anschubsen einer Schaukel muss das zum richtigen Zeitpunkt passieren, sonst funktioniert es
nicht. Die hier verwendete Schaltung macht das dadurch, dass sie proportional zur Spannung am Kondensator Strom in den Kondensator schiebt.(Alle Zitate aus der Anleitung.)

Trotzdem was gelernt.

[Edit]
Einen ähnlichen "Trick" gibts auch beim SnakeVision. Dort wird aus den 36kHz per Ladungspumpe die Eingangsspannung für einen 5V-Spannungsregler (IC2, 78L05Z) erzeugt:
http://www.produktinfo.conrad.com/datenblaetter/175000-199999/191374-as-01-de-ASURO_SNAKE_VISION_fuer_ARX_03.pdf