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
1 | //************************************************************************
|
2 | // Note: This code was written for Mega8 at 4MHz
|
3 | // It reads in the Signal from standard RC-Transmitters with 8 Channels
|
4 | // The Signal from the reciever must be connected to PD2 (INT0)
|
5 | //
|
6 | // Current Counts per ms: 57.6
|
7 | //
|
8 | // TODO:
|
9 | // * Currently there are no checks on array-borders
|
10 | // * Automatic computeation of the prescaler would be nice
|
11 |
|
12 | //************************************************************************
|
13 |
|
14 | #include "ppm.h"
|
15 |
|
16 | #include <avr/io.h>
|
17 |
|
18 | #include <avr/interrupt.h>
|
19 |
|
20 |
|
21 |
|
22 | extern void ppm_init()
|
23 | {
|
24 |
|
25 | //PD2 (INT0) as input with internal Pull-Up
|
26 | DDRD &= ~(1 << DDD2);
|
27 | DDRD |= (1 << PD2);
|
28 |
|
29 | // enable Interupt INT0
|
30 | GIMSK |= (1 << INT0);
|
31 |
|
32 | // Every change at INT0 triggers the Interupt
|
33 | MCUCR |= (1 << ISC00);
|
34 | MCUCR &= ~(1 << ISC01);
|
35 |
|
36 | // Prescaler 64
|
37 | TCCR0 |= ((1 << CS00) | (1 << CS01));
|
38 | TCCR0 &= ~(1<<CS02);
|
39 |
|
40 | // enable Timer-Interupt
|
41 | // TIMSK |= (1 << TOIE0);
|
42 |
|
43 | channels.dirty = 0;
|
44 |
|
45 | sei();
|
46 | }
|
47 |
|
48 | //ISR(TIMER0_OVF_vect)
|
49 | //{
|
50 | // channels.overflow++;
|
51 | //}
|
52 |
|
53 | ISR(INT0_vect)
|
54 | {
|
55 | if(PIND & (1 << PINC2)) { // High
|
56 | TCNT0 = 0;
|
57 | } else { // Low
|
58 | if (TCNT0 > LOW_MAX) { // all channels complete
|
59 | channels.counter = 0;
|
60 | channels.dirty = 0;
|
61 | } else if (channels.counter < CHANNELS) { // write position after checking arraybounds
|
62 | channels.position[channels.counter] = TCNT0 - LOW_MIN;
|
63 | channels.dirty |= (1 << channels.counter);
|
64 | channels.counter++;
|
65 | }
|
66 | }
|
67 | }
|
68 |
|
69 | // Returns the position of the channel with a range between zero and 50.
|
70 | // If the given channel doesn't exist, zero is returned.
|
71 | uint8_t get_0_50 (uint8_t channel)
|
72 | {
|
73 | if(channel => CHANNELS) {
|
74 | return 0;
|
75 | } else {
|
76 | return channels.position[channel] * (50/COUNTS_PER_MS);
|
77 | }
|
78 | }
|
ppm.h
1 | /*#######################################################################################
|
2 |
|
3 | Reading the sum-Signal of normal RC-Recievers
|
4 |
|
5 |
|
6 |
|
7 | Copyright (C) 2009 Christian Sachers
|
8 |
|
9 | #######################################################################################*/
|
10 |
|
11 |
|
12 |
|
13 | #include <avr/io.h>
|
14 |
|
15 | #include <avr/interrupt.h>
|
16 |
|
17 |
|
18 |
|
19 | #define CHANNELS 8
|
20 |
|
21 | #define LOW_MIN 58 // = 1ms
|
22 |
|
23 | #define LOW_MAX 130 // ~2.25ms
|
24 |
|
25 | #define COUNTS_PER_MS 58
|
26 |
|
27 |
|
28 | volatile struct {
|
29 | uint8_t position[CHANNELS];
|
30 | uint8_t counter;
|
31 | uint8_t dirty; // every Bit represents one Channel
|
32 | } channels;
|
33 |
|
34 |
|
35 |
|
36 | extern void ppm_init(void);
|
37 | extern uint8_t get_0_50 (uint8_t channel);
|
test.c
1 | #include "ppm.h"
|
2 | #include <avr/io.h>
|
3 |
|
4 | int main() {
|
5 | DDRC = 0xff; // Port C ist Ausgang
|
6 |
|
7 | ppm_init();
|
8 |
|
9 | uint8_t position;
|
10 | while (1) {
|
11 | if (1 & channels.dirty) {
|
12 | position = get_0_50 (0);
|
13 | if (position < 17) {
|
14 | PORTC = 1;
|
15 | } else if (position < 33) {
|
16 | PORTC = 2;
|
17 | } else {
|
18 | PORTC = 4;
|
19 | }
|
20 | } else {
|
21 | PORTC = 7;
|
22 | }
|
23 | }
|
24 | return 1;
|
25 | }
|
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.