PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 4 kanal fernsteuerung für tiny13



Nerb
26.05.2008, 22:15
hallo zusammen,
ich habe vor einiger Zeit den code für eine 4 Kanal Fernbedienung mit Tiny13 porgrammiert. Da ich das ganze erst in geraumer Zeit testen kann, wollte ich hier den code mal in die Runde werfen, in der Hoffnung das eventuelle Fehler aufgedeckt werden.
Nun ein paar Daten zum selbstausgedachten code:
Der 8 bit Timer (einziger timer im Tiny13) erzeugt die Trägerfrequenz von 38khz. An Pin PB2 ist eine IR Leuchtdiode über Vorwiderstand und Treiber angeschlossen.
Als Taster werden normale 2 Schließer benutzt. Je ein Schließer eines Tasters hängt an PB0,PB3,PB4 und PB5. Der zweite Schließer jedes Tasters hängt zusammen mit den anderen an PB1 dem externen Interrupt, was den avr aus dem Sleep modus aufwecken soll.
Gesendet wird zuerst ein 3 Bit Header, dann ein 4 Bit Befehlsschlüssel. Alles wäre natürlich auch mit weniger Bits ausgekommen, aber so ist das Ganze meines Erachtens störsicherer. Der Zeitabstand zwischen jedem gesendeten Bit ist 2ms. Dazu wird die delay Funktion benutzt. Ob die Genauigkeit dazu ausreicht, weiß ich nicht. Nach jedem Bitblock wird 160ms gewartet.



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define F_CPU 1000000UL
#include <util/delay.h>

int main (void) {
DDRB|=(1<<PB2);
PORTB=0x3b; //Pullups an (außer PB2)
TIMSK0 |= (1<<TOIE0); //Timer Overflow Interrupt freischalten
ACSR = 0x80; //Analog Comparator ausschalten
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sei();
while(1) { //Hauptschleife,
do { //Interrupt pin gedrückt (low)
//header 101
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1
TCCR0B = 0; //Timer stoppen
_delay_ms(2); //0
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1

if ((PINB & (1<<PINB0))==0) { //code 1: 1010
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
}
if ((PINB & (1<<PINB3))==0) { //code 2: 1101
_delay_ms(4); //11
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
}
if ((PINB & (1<<PINB4))==0) { //code 3: 0101
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1

}
if ((PINB & (1<<PINB5))==0) { //code 4: 1011
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(4); //11

}
TCCR0B = 0;
_delay_ms(160);
} while((PINB & (1<<PINB1))==0);

PORTB &= ~(1<<PB2); //IR LED ausschalten
sleep_mode(); //in den Schlafmodus wechseln



}
}

ISR (INT0_vect) {
_delay_ms(50); //Tasten entprellen
}

ISR (TIM0_OVF_vect ) { //Erzeugung der 38Khz Trägerfrequenz
cli();
PORTB ^= (1<<PB2); //PB2 toggeln
TCNT0 = 0xe5; //Vorladen auf 229 -> 26 Schritte
sei();
}

mfg Philip

Gock
26.05.2008, 23:29
Keine Ahnung, mit was Du progst, aber in meinem WinAVR sehen die ISR-Namen (TIM0_OVF_vect) etwas anders aus.
Schön und portabel ist der Progstil nicht (PORTB=0x3b), aber das weißt Du wahrscheinlich auch.
Auf die Schnelle kann ich Dir nur sagen, dass Du in der ISR die sei und cli nicht brauchst, weil der Controller das eh' macht.
Für den Rest ist es zu spät...

Nerb
27.05.2008, 14:06
Danke für die Antwort.
Das mit dem 0x03 ist zwar unübersichtlich, aber stört mich nicht sonderlich.
Das einzige was ich befürchte ist, dass sich irgendwo ein logischer Fehler eingeschlichen hat oder eine der If- Abfragen falsch ist.
Ich benutze Avr Studio zum proggen. Der Code compiliert ohne Warnungen, also sollte auch der TIM0_OVF_vect passen. (steht ja auch so im Datenblatt vom Tiny13).

Kann man den code noch effizienter gestalten bzw hat jemand eine Idee wie ich eine Funktion schreibe die die bits sendet, die ich per parameter übergebe: zb: void sende(0b1110) ?

mfg

radbruch
27.05.2008, 16:08
Hallo

Einen RC5-Sender (IR-Fernbedienungen) mit dem tiny13 in Bascom haben wir hier entwickelt: Link (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=36253). Anwendungen mit 4 Knöpfen finden sich gegen Ende des Threads. RC5 ist ein Quasistandart der sehr gut dokumentiert ist. Bei deiner "Insellösung" können etliche Probleme auftreten die man dem nacken Code auf den ersten Blick nicht ansieht.

Kritisch scheint mir das Timeing per _msdelay zu sein. Wenn du schon mit 38kHz toggelst (die Umschaltfrequenz muss natürlich doppelt so hoch sein und kann im CTC-Mode des Timers viel einfacher erzeugt werden) könnest du diesen Takt auch als Basis deiner Bitlängen verwenden (und die Daten mit der 38kHz-ISR rausschieben). ( Datenblatt (http://atmel.com/dyn/resources/prod_documents/doc2535.pdf)(1,7MB) S. 60ff. "Output Compare Unit")

Läuft der tiny13 wirklich mit 1MHz-Takt?. Meine Tests mit den internen 9,6MHz liefen problemlos, du könntest dir den externen Takt sparen. Oder meinst du vielleicht den 1,2MHz-Defaulttakt der tiny13? ( Datenblatt (http://atmel.com/dyn/resources/prod_documents/doc2535.pdf)(1,7MB) S. 22. "Default Clock Source")

Gruß

mic

Nerb
27.05.2008, 21:12
Hallo,
mit dem Takt meinte ich eigentlich den internen Takt es Tiny13. Ich dachte immer alle avrs laufen defaultmäßig auf 1Mhz.
Die Umschaltfrequenz ist auch nicht doppelt... das werde ich aber ändern.


Kritisch scheint mir das Timeing per _msdelay zu sein. Wenn du schon mit 38kHz toggelst (die Umschaltfrequenz muss natürlich doppelt so hoch sein und kann im CTC-Mode des Timers viel einfacher erzeugt werden) könnest du diesen Takt auch als Basis deiner Bitlängen verwenden (und die Daten mit der 38kHz-ISR rausschieben). ( Datenblatt(1,7MB) S. 60ff. "Output Compare Unit")


Wie sieht so eine Lösung codemäßig aus? Ich bin noch recht unerfahren im Thema µC. Ich bräuchte da eine starthilfe (in c natürlich).

mfg