Jeti
17.04.2013, 22:03
Hallo an Alle!
wie manche ja vielleicht schon wissen bin ich in letzter Zeit stark am rumprobieren um mehr Verständniss für die Mikroelektronik zu bekommen. Nun wollte ich einmal einen standard RC-Empfänger durch einen ATMega16 auswerten lassen. Dazu habe ich mir folgendes Prinzip überlegt/abgeschaut:
Timer1 soll genau 10µs brauchen um einen Überlauf zu erzeugen. Wenn nun eine positive Taktflanke vom Empfänger kommt soll der Mikrocontroller die Überläufte zählen die bis zur nächsten negativen Taktflanke auftreten und daraus auf die Pulsweite schließen. Die Pulsweite soll nun über ein LCD-Display ausgegeben werden.
Zur Schaltung kann ich noch ergänzen das ich die GND´s der Batterie die den Empfänger antreibt mit dem GND der Platine verbunden habe (ein Fehler den ich sonst immer falsch gemacht habe).
Nun möchte ich vor dem Code noch das Problem beschreiben:
Der Zählerstand ändert sich nicht wenn ich den Stick der Fernbedingung verschiebe. Dazu folgt das die Zahl ein Zufallswert ist, der jedoch konstant bleibt und entweder im Bereich von 600 oder 2230 liegt. Ein Signal vom Empfänger kommt aber denn wenn ich die Fernbedinung ausschalte dann beginnt der Zahlen-Wert durch das Rauschen im Empfänger an zu springen.
Das Projekt arbeitet mit 8MHz... jetzt der Code (dazu sei Gesagt das die LCD-Befehle in anderen Projekten funktionieren)
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd_tools.h"
#include <util/delay.h>
volatile int inizialisierung;
volatile uint16_t counter=0;
volatile int posneg;
volatile uint16_t Zeit=0;
//LCD Ausgabe
void ausgabe()
{
char Z[10];
lcd_gotoline(1);
lcd_writetext("Kanal 1:");
lcd_cls_line(2);
lcd_gotoline(2);
itoa(Zeit,Z,10);
lcd_writetext(Z);
}
// Timer/Counter1 Start und Ende
ISR (TIMER1_CAPT_vect)
{
if (posneg<1)
{
counter=0; //counter zurücksetzen
TCCR1B&=~ (1<<ICES1); //auf fallende Flanke triggern
posneg=1;
}
else
{
cli();
Zeit=counter; // Zeit im µs berechnen
TCCR1B|= (1<<ICES1); //auf steigende Flanke triggern
ausgabe (); // Ausgabe auf Display
posneg=0;
sei();
}
}
// Timer/Counter1 Vergleichszähler
ISR (TIMER1_COMPA_vect) // je 10µs einmal
{
counter++; // Überläufe zählen
}
int main(void)
{
lcd_ini();
TIMSK |= (1 << TICIE1) | (1 << OCIE1A); // Input Capture Interrupt Enable+Output Compare A Match Interrupt Enable
OCR1A = (uint16_t)(0x50); // Vergleichswert 10µ Sekunden
TCCR1B |= (1 << WGM12); // CTC Modus
TCCR1B |= (1 << ICNC1) | (1 << ICES1); // Noise Canceler + steigende Flanke an ICP1
TCCR1B |= (1 << CS10); // Prescaler: 1
lcd_gotoline(1);
lcd_writetext ("Kalibrierung");
_delay_ms(1000);
inizialisierung=0; // Kalibrierung erforderlich
posneg=0; // warten auf positive Flanke
lcd_cls();
sei(); // IRQs enable
while(1)
{
}
}
Die Variable "inizialisierung" soll später für weitere Funktionen genutzt werden.Im Moment ist sie nutzlos. Genauso wie die Ausgabe "Kalibrierung" auf dem LCD.
Danke schon mal für die Hilfe und den Hirnschmalz.
Viele liebe Grüße
Jeti
wie manche ja vielleicht schon wissen bin ich in letzter Zeit stark am rumprobieren um mehr Verständniss für die Mikroelektronik zu bekommen. Nun wollte ich einmal einen standard RC-Empfänger durch einen ATMega16 auswerten lassen. Dazu habe ich mir folgendes Prinzip überlegt/abgeschaut:
Timer1 soll genau 10µs brauchen um einen Überlauf zu erzeugen. Wenn nun eine positive Taktflanke vom Empfänger kommt soll der Mikrocontroller die Überläufte zählen die bis zur nächsten negativen Taktflanke auftreten und daraus auf die Pulsweite schließen. Die Pulsweite soll nun über ein LCD-Display ausgegeben werden.
Zur Schaltung kann ich noch ergänzen das ich die GND´s der Batterie die den Empfänger antreibt mit dem GND der Platine verbunden habe (ein Fehler den ich sonst immer falsch gemacht habe).
Nun möchte ich vor dem Code noch das Problem beschreiben:
Der Zählerstand ändert sich nicht wenn ich den Stick der Fernbedingung verschiebe. Dazu folgt das die Zahl ein Zufallswert ist, der jedoch konstant bleibt und entweder im Bereich von 600 oder 2230 liegt. Ein Signal vom Empfänger kommt aber denn wenn ich die Fernbedinung ausschalte dann beginnt der Zahlen-Wert durch das Rauschen im Empfänger an zu springen.
Das Projekt arbeitet mit 8MHz... jetzt der Code (dazu sei Gesagt das die LCD-Befehle in anderen Projekten funktionieren)
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "lcd_tools.h"
#include <util/delay.h>
volatile int inizialisierung;
volatile uint16_t counter=0;
volatile int posneg;
volatile uint16_t Zeit=0;
//LCD Ausgabe
void ausgabe()
{
char Z[10];
lcd_gotoline(1);
lcd_writetext("Kanal 1:");
lcd_cls_line(2);
lcd_gotoline(2);
itoa(Zeit,Z,10);
lcd_writetext(Z);
}
// Timer/Counter1 Start und Ende
ISR (TIMER1_CAPT_vect)
{
if (posneg<1)
{
counter=0; //counter zurücksetzen
TCCR1B&=~ (1<<ICES1); //auf fallende Flanke triggern
posneg=1;
}
else
{
cli();
Zeit=counter; // Zeit im µs berechnen
TCCR1B|= (1<<ICES1); //auf steigende Flanke triggern
ausgabe (); // Ausgabe auf Display
posneg=0;
sei();
}
}
// Timer/Counter1 Vergleichszähler
ISR (TIMER1_COMPA_vect) // je 10µs einmal
{
counter++; // Überläufe zählen
}
int main(void)
{
lcd_ini();
TIMSK |= (1 << TICIE1) | (1 << OCIE1A); // Input Capture Interrupt Enable+Output Compare A Match Interrupt Enable
OCR1A = (uint16_t)(0x50); // Vergleichswert 10µ Sekunden
TCCR1B |= (1 << WGM12); // CTC Modus
TCCR1B |= (1 << ICNC1) | (1 << ICES1); // Noise Canceler + steigende Flanke an ICP1
TCCR1B |= (1 << CS10); // Prescaler: 1
lcd_gotoline(1);
lcd_writetext ("Kalibrierung");
_delay_ms(1000);
inizialisierung=0; // Kalibrierung erforderlich
posneg=0; // warten auf positive Flanke
lcd_cls();
sei(); // IRQs enable
while(1)
{
}
}
Die Variable "inizialisierung" soll später für weitere Funktionen genutzt werden.Im Moment ist sie nutzlos. Genauso wie die Ausgabe "Kalibrierung" auf dem LCD.
Danke schon mal für die Hilfe und den Hirnschmalz.
Viele liebe Grüße
Jeti