mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PPM von RC-Empfänger einlesen in Mega8


Autor: Christian S. (snoopy88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich habe jetzt bereits einen Tag damit verbracht und komme nicht weiter. 
Leider hat mich auch die Suche nicht wirklich weiter gebracht.

Mein Ziel:
Ich habe vor das Summensignal (PPM) von einem standard-Empfänger 
einzulesen. IM moment teste ich das ganze an einem "Multiplex Pico 5/6". 
Leider ist meine Familie elektronisch nicht sonderlich vorbelastet, und 
so habe ich zwar einiges an RC-Equipment und fliege seit Jahren 
Modellflugzeuge, aber an Ausstattung für Elektrobasteleien mangelt es. 
Das Ansehen von Signalem mit einem Oszi o.ä. ist also nicht möglich und 
die meisten Bauteile muss ich auch jedes mal erst kaufen.

Ich arbeite daher momentan mit einem MyAVR-Board mit einem Mega8-16PU 
(wenn mir einer das 16PU in wenigen Worten erklären kann wäre das auch 
nett :)). Das PPM-Signal hängt an PIND2, um es über INT0 einzulesen. 
Dieser soll auf jede Taktflanke reagieren. Der nebenher laufende Timer0 
wird bei einer Taktfalnke 0->1 auf 0 gesetzt. Bei einer Taktfalnke 1->0 
wird er ausgelesen, sein Wert in einen array geschrieben, ein dirty-Bit 
gesetzt und der Index inkrementiert. Außerdem wird geprüft, ob es sich 
um einen langen Abstand gehandelt hat. Wenn das so ist, dann wird nur 
der Index auf 0 gesetzt.

Soweit zu meinem Vorhaben. Nur funktionieren tut es leider nicht. Da ich 
zu den Flanken im INternet unterschiedliche Angaben gefunden habe, habe 
ich auch schon die Reaktion auf die versch. Takflanken vertauscht, was 
aber auch keinen Erfolg brachte.


Mein Code sieht so aus:

ppm.c
//************************************************************************
// Note: This code was written for Mega8 at 4MHz
//       It reads in the Signal from standard RC-Transmitters with 8 Channels
//       The Signal from the reciever must be connected to PD2 (INT0)
//
// Current Counts per ms: 57.6
//
// TODO:
// * Currently there are no checks on array-borders
// * Automatic computeation of the prescaler would be nice

//************************************************************************

#include "ppm.h"

#include <avr/io.h>

#include <avr/interrupt.h>



extern void ppm_init()
{ 

//PD2 (INT0) as input with internal Pull-Up
  DDRD &= ~(1 << DDD2);
  DDRD |= (1 << PD2);

// enable Interupt INT0
  GIMSK |= (1 << INT0);

// Every change at INT0 triggers the Interupt
  MCUCR |= (1 << ISC00);
  MCUCR &= ~(1 << ISC01);

// Prescaler 64
  TCCR0 |= ((1 << CS00) | (1 << CS01));
  TCCR0 &= ~(1<<CS02);

// enable Timer-Interupt
//  TIMSK |= (1 << TOIE0);

  channels.dirty = 0;

  sei();
}

//ISR(TIMER0_OVF_vect)
//{
//  channels.overflow++;
//}

ISR(INT0_vect)
{
  if(PIND & (1 << PINC2)) { // High
    TCNT0 = 0;
  } else { // Low
    if (TCNT0 > LOW_MAX) { // all channels complete
      channels.counter = 0;
      channels.dirty   = 0;
    } else if (channels.counter < CHANNELS) { // write position after checking arraybounds
      channels.position[channels.counter] = TCNT0 - LOW_MIN;
      channels.dirty |= (1 << channels.counter);
      channels.counter++;
    }
  }
}

// Returns the position of the channel with a range between zero and 50.
// If the given channel doesn't exist, zero is returned.
uint8_t get_0_50 (uint8_t channel)
{
  if(channel => CHANNELS) {
    return 0;
  } else {
    return channels.position[channel] * (50/COUNTS_PER_MS);
  }
}

ppm.h
/*#######################################################################################

Reading the sum-Signal of normal RC-Recievers



Copyright (C) 2009 Christian Sachers

#######################################################################################*/



#include <avr/io.h>

#include <avr/interrupt.h>



#define CHANNELS  8

#define LOW_MIN    58  // = 1ms

#define LOW_MAX    130  // ~2.25ms

#define COUNTS_PER_MS  58


volatile struct {
  uint8_t position[CHANNELS];
  uint8_t counter;
  uint8_t dirty;  // every Bit represents one Channel
} channels;



extern void ppm_init(void);
extern uint8_t get_0_50 (uint8_t channel);

test.c
#include "ppm.h"
#include <avr/io.h> 

int main() {
  DDRC = 0xff;  // Port C ist Ausgang

  ppm_init();

  uint8_t position;
  while (1) {
    if (1 & channels.dirty) {
      position = get_0_50 (0);
      if (position < 17) {
        PORTC = 1;
      } else if (position < 33) {
        PORTC = 2;
      } else {
        PORTC = 4;
      }
    } else {
      PORTC = 7;
    }
  }
  return 1;
}


Ich habe im Internet auch eine Variante mit dem Timer1 und ICP gesehen. 
Aber den Timer1 würde ich mir gerne für PWM-Ausgabe freihalten.


Falls mir jemand von den Erfahrenen (oder gern auch Unerfahrene :)) 
einen Tip geben kann, was da der Fehler sein könnte, würde ich mich 
freuen.

Danke im Vorraus,
Christian

PS: Falls es nötig sein sollte, kann ich auch ein Photo des Aufbaus 
online stellen.

Autor: Christian S. (snoopy88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hochschiebt

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich habe im Internet auch eine Variante mit dem Timer1 und ICP gesehen.
>Aber den Timer1 würde ich mir gerne für PWM-Ausgabe freihalten.

Man kann ihn für beides benutzen.
Man muß nur erkennen, ob es einen Überlauf gab, wenn man den TOP-Wert 
des Timers verändert. Dann muss man die Differenz zu 65535 noch 
irgendwie dazupacken.

Autor: Michael K. (mmike)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau doch mal bei den Mikrocopter - Sourcen ...

http://svn.mikrokopter.de/mikrowebsvn/listing.php?...

da ist mit Sicherheit was dabei, wo man sich die Technik "anlernen" kann 
um dann das Ganze SELBST zu implementieren ! Einfach nur copy - paste 
hat keinen pädagogischen Nutzen ;-)

Grüße,
Michael

Edit: Bei V0.70d die Dateien rc.h und rc.c

Autor: Christian S. (snoopy88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.

Dass man beides (PPM einlesen und PWM ausgeben) mit einem Timer 
hinbekommen kann klingt schon logisch, aber wenn ich drei Timer zur 
Verfügung habe, kann ich diese ja auch verwenden. Besonders als Anfänger 
scheint mir das geeigneter, sonst werde ich nachher garantiert Probleme 
mit nicht bedachten Wechselwirkungen bekommen :).

Ich habe mir auch die Sourcen vom Mikrokopter gerade mal angesehen. Die 
verwenden ja leider auch den Timer1 mit Input-Capture.


Ich würde außerdem gerne verstehen, was ich bisher falsch gemacht habe. 
Meine Theorie sagt mir, dass es eigentlich funktionieren sollte, aber 
leider sieht die realität anders aus.

Einen meiner vermutlichen Fehler habe ich bereits gefunden: Ich habe die 
Overflows des Counters nicht mitgezählt, weswegen die Pausen zwischen 
den "Blöcken" nicht sicher erkannt werden. Leider funktioniert das ganze 
trotzdem noch nicht.


Christian

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.