Aus RN-Wissen.de
Wechseln zu: Navigation, Suche


Dieser Artikel ist noch lange nicht vollständig. Der Auto/Initiator hofft das sich weitere User am Ausbau des Artikels beteiligen.

Das Ergänzen ist also ausdrücklich gewünscht! Besonders folgende Dinge würden noch fehlen:

Mehr Grundlagen/ Erklärungen, und Code Beispiele in C


Vorwort

Um einen RC-Empfänger mit einem ATmega auszuwerten, bedient man sich am besten des Summensignals. Im Wiki von Mikrokopter.de findet sich eine Liste mit getesteten Empfängern und kurzen Anleitungen, wie man an das Signal kommt. Die Quellcode Beispiele in diesem Artikel funktionieren mit einen Atmel ATmega32 der mit einem 16Mhz Quarz betrieben wird. Werden andere µC's oder andere Quarze verwendet ändern sich natürlich einige Zeilen. Besonders bei Verwendung eines anderen Quarzes müssen die Zeilen "preload für 4ms" auf den entsprechend richtigen Preload geändert werden! Evtl. muss auch der Prescaler angepasst werden.

Für BASCOM kann man mit folgendem Code die Kanäle 1-6 auslesen (atmega32, 16Mhz Quarz - bei Bedarf anpassen):

Auslesen mit Timer0

$baud = 9600
$crystal = 16000000
$regfile "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 64
Config Timer0 = Timer , Prescale = 256
Enable Timer0
On Timer0 Pausedetected
Config Int1 = Falling                             'Summensignal an int1 (am Mega32: Port D3), Reaktion auf fallende Flanke
Enable Interrupts
Enable Int1                                       'einschalten Int1
On Int1 Measure                                   'springe zum Interrupt von Timer0
Dim Empf(6) As Word
Dim Channel As Byte

Do                                'Main Loop gibt Signale per UART aus
    Print Empf(1) ; " CH1"
    Print Empf(2) ; " CH2"
    Print Empf(3) ; " CH3"
    Print Empf(4) ; " CH4"
    Print Empf(5) ; " CH5"
    Print Empf(6) ; " CH6"
    Print " "
    Waitms 500
Loop

Measure:                               'Reaktion auf fallende Flanke

If Channel > 0 And Channel < 7 Then
  Empf(channel) = Timer0 - 6
End If

Timer0 = 6                                        'preload für 4ms
Incr Channel
Return

Pausedetected:
Channel = 0
Return

End

Auslesen mit Timer1

Alternativ kann man den Empfänger natürlich auch mit Timer1 auslesen. Hier ist die Auflösung höher:

$baud = 9600
$crystal = 16000000
$regfile "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 64
Config Timer1 = Timer , Prescale = 8 , Capture Edge = Falling , Noise Cancel = 1
Enable Timer1
On Timer1 PauseDetect
Config Int1 = Falling
Enable Interrupts
Enable Int1    
On Int1 Measure
Dim Empf(6) As Word
Dim Channel As Byte
Do
    Print Empf(1) ; " CH1"
    Print Empf(2) ; " CH2"
    Print Empf(3) ; " CH3"
    Print Empf(4) ; " CH4"
    Print Empf(5) ; " CH5"
    Print Empf(6) ; " CH6"
    Print " "
    Waitms 500
Loop

Measure:
If Channel > 0 And Channel < 7 Then
  Empf(channel) = Timer1 - 57536 
End If
Timer1 = 57536                                    'preload für 4ms
Incr Channel
Return

PauseDetect:
Channel = 0
Return
End

C-Programmbeispiel (Auslesen mit Timer0)

Dieses Beispiel ist für einen ATMega128 mit 14,745600MHz und funktioniert für alle 8 möglichen Kanäle.

Wichtig ist es den Overflow des Counters zwischen 2ms und 4ms zu setzen, damit der Controller den Anfang des Signals erkennen kann. Die einzelnen Servosignale sind dann in cSumSig[] zu finden.

#ifndef RC_SUM_H
#define RC_SUM_H

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

volatile unsigned char cSumSig[8];
volatile uint8_t iCounter=0,iValid=0;

ISR(TIMER0_OVF_vect) {
  iCounter=0;					// Bei Overflow den Channel Counter zurücksetzen
  iValid=0;					// Messung bis zum ersten Puls blockieren
}

ISR(INT0_vect) {
  if(iValid==1) {				// Nicht vor dem ersten Puls das zählen beginnen
    cSumSig[iCounter] = TCNT0;			// Pulslänge im Array speichern
	iCounter++;				// Counter für nächsten Puls erhöhen
  } else {
    iValid = 1;					// Messung bei erstem Puls freigeben
  }
  TCNT0 = 0;					// Counter zurücksetzen
}

void RC_SUM_init(void) {		
  TIMSK |= (1<<TOIE0);				// Overflow Interrupt einschalten
  TCCR0 |= ((1<<CS00) | (1<<CS02));		// Prescaler 128
  TCNT0 = 0;					// Overflow zwischen 2,2ms & 3,8ms
  EIMSK |= (1<<INT0);				// INT0 enable
  EICRA |= ((1<<ISC01) | (1<<ISC00));	        // Externer Interrupt bei steigender Flanke an Pin INT0
  sei();					// Globale Interrupts erlauben
}
#endif

Autoren

Siehe auch