Hallo,
ich versuche seit einer weile eine gute Lösung für mein Projekt zu
finden.
Projektziel:
- Auswerten eines 6 Kanal RC Empfängers ohne Summensignal
- Interne Verarbeitung, Modifikation, etc
- Ausgabe von Mindestens 4 Kanälen, besser 4 Analog Servo Kanälen und
zusätzliche Schaltausgänge für Licht, Blinker, etc
- Licht mit PWM um die Helligkeit einstellen zu können. Schön wäre noch
eine Konstantstromquelle und ein integriertes Soundmodul, aber das geht
aus Speicher gründen nicht.
Mein bisheriger Testaufbau mit einem ATmega16 sieht wie folgt aus:
- Timer CTC mode. Im Interrupt wird ein Port gesampelt und je nach
Bitzustand dann die Bitlängen Zähler hochgezählt. Wurden alle gezählt
(Austastlücke) wir ein Flag gesetzt und die mainline wertet die Daten
aus.
- Im Timer werden auch die Servo Ausgänge gesetzt.
Problem, das kostet zu viel Rechenzeit, die Auflösung ist sehr gering
und ich habe einen Jitter von +-1 auf dem Signal bei einem Signal von
+-16.
Mein Gedanke war nun Externe Interrupts zu benutzen, aber hier finde ich
nicht die richtige CPU. zudem bin ich mir nicht sicher ob es das ganze
"schneller" macht.
Ich habe auch schon versucht im Interrupt alles schrittweise zu machen.
- Sampeln
- Warten bis Mainline fertig
- Ausgänge setzen
Allerdings ist die Ausgaberate dann sehr gering der Servosignale
Ich denke ich habe mich verrannt und hoffe jemand hat eine Creative
Idee.
Das ganze soll und ist mit AVR und GCC gelösst werden.
Die bisherige Bastellösung sieht so aus (Sampelt nur einen Servo vom
Empfänger):
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
#include"usart.h"
5
6
#define MAX_CHANNELS (6)
7
8
9
#define CH_IN1 PD3
10
#define CH_IN2 PD3
11
#define CH_IN3 PD3
12
#define CH_IN4 PD3
13
#define CH_IN5 PD3
14
#define CH_IN6 PD3
15
16
#define CH_OUT1 PD6
17
#define CH_OUT2 PD7
18
#define CH_OUT3 PD7
19
#define CH_OUT4 PD7
20
#define CH_OUT5 PD7
21
#define CH_OUT6 PD7
22
23
volatileuint8_tch_data_in[MAX_CHANNELS];
24
volatileuint8_tch_data_out[MAX_CHANNELS];
25
volatileuint8_tch_ready=3;
26
27
volatileuint8_treward=0;
28
volatileuint8_trewardold=1;
29
30
voidinitTimer()
31
{
32
// Timer 0 konfigurieren
33
TCCR1B=_BV(WGM12);// CTC Modus
34
TCCR1B|=_BV(CS10);// Prescaler 1
35
// ((1000000/8)/1000) = 125
36
OCR1A=0xaF;
37
38
// Compare Interrupt erlauben
39
TIMSK|=_BV(OCIE1A);
40
41
// Global Interrupts aktivieren
42
sei();
43
44
}
45
46
intmain()
47
{
48
ch_ready=0;
49
DDRD=_BV(PD6)|_BV(PD5);
50
usart_init(9600);
51
initTimer();
52
sei();
53
54
while(1)
55
{/*
56
*/
57
58
// Serial output is control/test only
59
//PORTD^=_BV(PD5);
60
if(ch_ready==1)
61
{
62
// Normal control stuff
63
if(ch_data_in[0]<60)
64
{
65
if(reward!=rewardold)
66
{
67
reward=~reward;
68
rewardold=reward;
69
}
70
}
71
elseif(ch_data_in[0]>60)
72
rewardold=~reward;
73
74
75
76
77
usart_write("data=");
78
for(uint8_ti=0;i<MAX_CHANNELS;i++)
79
{
80
usart_write("%i,",ch_data_in[i]);
81
ch_data_out[i]=ch_data_in[i];
82
ch_data_in[i]=0;
83
}
84
usart_write("\r\n");
85
ch_ready=2;
86
87
88
89
90
}
91
}
92
}
93
94
ISR(TIMER1_COMPA_vect)
95
{
96
uint8_tpin=PIND;
97
uint8_tout=0x00;
98
uint8_tch_cnt;
99
100
volatilestaticuint8_toutput_cnt;
101
102
// sample if last value already read
103
if(ch_ready==0)
104
{
105
ch_cnt=0;// count how many channels we finished sampling
106
107
if(pin&_BV(CH_IN1))
108
ch_data_in[0]++;
109
else
110
if(ch_data_in[0]>0)ch_cnt++;
111
112
if(pin&_BV(CH_IN2))
113
ch_data_in[1]++;
114
else
115
if(ch_data_in[1]>0)ch_cnt++;
116
117
if(pin&_BV(CH_IN3))
118
ch_data_in[2]++;
119
else
120
if(ch_data_in[2]>0)ch_cnt++;
121
122
if(pin&_BV(CH_IN4))
123
ch_data_in[3]++;
124
else
125
if(ch_data_in[3]>0)ch_cnt++;
126
127
if(pin&_BV(CH_IN5))
128
ch_data_in[4]++;
129
else
130
if(ch_data_in[4]>0)ch_cnt++;
131
132
if(pin&_BV(CH_IN6))
133
ch_data_in[5]++;
134
else
135
if(ch_data_in[5]>0)ch_cnt++;
136
137
// if all sampled, mark as ready
138
if(ch_cnt==MAX_CHANNELS)
139
ch_ready=1;
140
}
141
// make sure we do not start sample in the midle of a bit
Viel weniger Rechenzeit wirst du auch mit anderen Ansätzen nicht
verbrauchen, denn viel mehr als die Eingänge abzufragen machst du ja in
der ISR nicht. Optimierung eingeschaltet, 16MHz-Quarz, Assembler-Listing
auf Auffälligkeiten geprüft?
Die neueren Megas bieten zwar die Möglichkeit, 6 Eingänge mit externem
Interrupt abzufragen, aber auch da musst du dann erst noch den Pin
abfragen, um rauszufinden, welcher jetzt den Interrupt ausgelöst hat.
Oliver
Doch Oliver, Jürgen kann mit anderen Ansätzen viel Rechenzeit sparen!
Und zwar wenn er versteht, dass es eine Welt außerhalb des
Mikrocontrollers gibt. ;-)
Die einzelnen PLM codierten Kanäle sind (auch heute noch bei den meisten
digitalen RC Empfängern) Zeit-gemultiplext. Sprich die einzelnen Kanäle
kann man einfach per Logikschaltung zum Summensignal zusammensetzten.
Ein einfaches 6x ODER aus Dioden genügt da vollkommen.
Dann brauch nur noch das Summensignal ausgewertet werden. Das geht dann
recht effektiv mit dem Controller.
Geht eben nicht! Das "Summensignal" über ein OR-Gatter ist dann einfach
nur über die Zeit aller Impulse High und während der Synchronpause Low!
Nur wenn die Flanken der einzelnen Impulse stark verschliffen sind,
entsteht ein ganz kurzer Einbruch des High-Pegels.
Das echte Summensignal aus dem Empfäger (vor dem Decoder) hat jedoch ein
Austast-Low-Signal von ca. 0,4ms. Dieses in jedem einzelnen Impuls. Das
ist aber Bestandteil des Impulses!.
Der Decoder braucht diesen Austast-Impuls, um das Schieberegister
weiterschalten zu können. Damit wird klar, das dieser Austast-Impuls
Bestandteil des ganzen Impulses sein muß, egal wie lang der
Austastimpuls auch war. Früher (vor der "Schmalband"-HF-Zeit) waren
diese Austastimpulse 0,2ms lang. Dann paßten die Fernsteuerkanäle aber
nicht mehr in das neue 10kHz-Raster. Deshalb die Vergrößerung auf 0,4ms.
Gilt alles nur für herkömmliche PPM-Anlagen, die etwas älter sind.
Blackbird.
Blackbird schrieb:> Geht eben nicht!
Geht schon, man braucht halt noch ein Monoflop dazu. Das funktioniert
aber nur, wenn der Empfänger die einzelnen Servokanäle tatsächlich nach
althergebrachter Art nacheinander im PPM-Summensignalzeitraster ausgibt.
Das ist bei aktuellen 2.4Ghz-Systemen nicht immer so.
Oliver
das ist das (echte) Summensignal vom Empfängerausgang VOR dem Decoder
--- ---- ---
---- - - -------------
das sind die einzelnen Servo-Impulse aus dem Schieberegister:
----
--- ----------------------
-----
------- -----------------
----
------------ -------------
das ist ein "ORed" Summensignal von den Schieberegisterausgängen:
-------------
--- -------------
wie soll das ein Monoflop was triggern?
Blackbird
Tobyas schrieb:> Doch Oliver, Jürgen kann mit anderen Ansätzen viel Rechenzeit sparen!> Und zwar wenn er versteht, dass es eine Welt außerhalb des> Mikrocontrollers gibt. ;-)>> Die einzelnen PLM codierten Kanäle sind (auch heute noch bei den meisten> digitalen RC Empfängern) Zeit-gemultiplext. Sprich die einzelnen Kanäle> kann man einfach per Logikschaltung zum Summensignal zusammensetzten.> Ein einfaches 6x ODER aus Dioden genügt da vollkommen.>> Dann brauch nur noch das Summensignal ausgewertet werden. Das geht dann> recht effektiv mit dem Controller.
Das habe ich schon versucht. Wie später auch erwähnt wird, ist bei
heutigen Epfängern das nicht einfach zu verknüpfen. Meiner hat auch kein
Summensignal (Siehe anderen Post von mir...) Die Signal von einigen
Kanälen kommen gleichzeitig.
Daher der Ansatz alle einzeln zu sampeln.
@Blackbird: Zum echten Summensignal kann ich leider keine Aussagen
machen, da sich eh keiner der RC Empfänger Hersteller je an eine Spec
gehalten hat...
Ich kann nur zu allen hier rumliegenden Empfängern (klassisch und
2.4GHz) feststellen, dass sie entweder direkt das Summensignal liefern
oder zeitgemultiplexte PLM Signale mit signifikanten Austastlücken
liefern.
@Jürgen: Wie ich ja schrieb ist das nicht immer so...
Es ist auf jeden Fall immer Wert sich die Signale vorher mal
anzuschauen. Entschuldige ich hatte dein anderes Posting nicht gesehen.
Wenn dein Empfänger die Kanäle gleichzeitig bzw. überlappend liefert ist
dein Ansatz schon der richtige.
Allerdings halten sich alte Konzepte ziemlich lange. Mein 2.4 GHz
RC Sender / Empfänger benutzt (intern) Telegramme, welche timing-genau
das Summensignal codieren. ;-)
@Tobyas: Ich habe auf mein anderes Posting auch nicht hingewiesen, kein
Problem :-)
Was für einen Empfänger hast Du den ? Ich kann zwar intern an diesem
EMpfänger auch an eine SPI Schnittstelle, aber dann müsste ich dort die
ganze Kommunikation mithören. Zwischen der "CPU" und dem Funkmodul. Das
ist mir doch etwas zu heftig... :-)
Dann könnte ich gleich die CPU im Empfänger und im Sender ersetzen...
Würde ich aber nur tun, wenn ich von den Funkmodulen noch ein paar über
hätte, falls was kaputt geht.
Um mal wieder aufs Thema zurückzukommen:
Wenn du den Servoimpuls in 256 Schritte auflöst (was eigentlich
ausreicht), müsste deine ISR mit 256KHz aufgerufen werden. Bei 16MHz
CPU-Takt bleiben dir da brutto 62 Zyklen, netto sind es dann einige
weniger, da der ganze ISR-Aufruf-Overhead noch davon abgeht.
Da kann man sich die ISR auch ganz sparen, und einfach eine Schleife zur
Datenerfassung in main laufen lassen. In dieser liest du den Port, auf
dem die 6 Eingänge liegen, und den Wert des frei durchlaufenden Timer1.
Wenn sich der Portzustand gegenüber dem vorherigen Schleifendurchlauf
geändert hat, speicherst du den Portwert und den dazugehörigen
Zählerstand in je einem Feld ab. Dazu noch eine Zeitüberwachung, die die
Schleife nach 1.5ms beendet.
Danach hast du gut 18ms Zeit, die Daten auszuwerten, Ausgänge zu setzen,
etc. Dann alle Daten in den Feldern löschen, und wieder von vorn.
Mit etwas Optimierung solllte die Schleife mit 62 Zyklen machbar sein.
Wenn dir die Verzögerung von einem Frame bei den Kanälen, die du nur
durchreichen willst, zu viel ist, kannst du die auch direkt in der
Schleife ausgeben.
Oliver
Hallo Jürgen, der genannte 2.4 GHz Empfänger sollte ein AR6100E
(Spectrum) sein. Habe zwar nachgeschaut kann aber meine Aufzeichnungen
leider nicht finden. Ich hatte mir den Empfänger vor ca. 2 Jahre mal
angeschaut und mich dann für das wired OR mit Dioden entschieden...
Dann halte dich mal an die Tips aus Olivers letztem Posting. Damit
solltest du zum Ziel kommen.
Viel Erfolg!
Ich bin im Moment am überlegen das Rad neu zu erfinden.
BTM-222 Bluetooth modul an beiden enden und mit rs232 vom Controller
füttern. Dann muss ich eben meine Funke umbauen.
In etwa so wie die "Blauzahn" (Für Insider)
Das Problem ist hierbei die Rechenzeit die man benötigt wenn man alle 6
Eingänge gleichzeitig sampled. Da sind einfach nicht genug CPU Zyklen
frei um noch mehr zu tun.
Wie gesagt überlege ich im moment das Problem (erneut) neu anzugehen mit
eine Bluetooth Funkstrecke und BTM-222 Modul. Da sist eine Transparente
RS232 mit ein paar AT Befehlen und gut ist...
Und ich habe volle Felxibilität was über die Leitung geht. Digital von A
bis Z :-)
Hallo Zusammen,
für das Problem gibt es durchaus sehr effektive Routinen auf PCINT Basis
die auch auf nem ollen Atmega8 mit 16MHz mehr als genug Rechenzeit
lassen um alles mögliche zu machen. Jürgen, sehe dich mal bei dmn
Multicopter-Volk um. Als ein Beispiel, z.B. den MultiWii-Copter, da gibt
es den C Code für Arduino frei verfügbar, und wenn du da reinsiehst
findest du eine gute Lösung. (du kannst dir z.B. den zugehörigen Thread
bei rcgroups ansehen, der Autor heisst alexinparis und der Thread ist
immer oben und daher leicht zu finden, es gibt auch eine Wikiseite auf
der du dir die ganzen Codes runterladen kannst).
Olli
PS: beim den "einfachereren" Spektrum Empfängern (wie dem AR61XXx) ist
es tatsächlich so dass zwischen den PPM-Servo Impulsen eine Lücke von ca
70us kommt, so dass das or-Ding geht, leider aber scheint's nicht bei
Jürgen's Empfänger
Mit 6 ExtInt wäre ja auch mehr Rechenzeit frei.
Ich muss dann nicht alle 6 Eingänge Sampeln und "Zählen", sondern nur
bei einer Änderung agieren, z.B. den Timer speichern.
Das war mein Ursprungsgedanke, allerdings tue ich mir noch schwer einen
Atmel zu finden den ich bei "R" oder "C" bekomme... 100.000 Pins haben
soll er dann auch ned. ATmega32 mit 6-8 Ext Int wäre Supper...
Humm.
Anderer Seits bekommt man das BTM-222 Modul für so um die 15€.
Ich muss da über Ostern mal etwas dran arbeiten.
Gruss
Jürgen
Jürgen Sachs schrieb:> allerdings tue ich mir noch schwer einen> Atmel zu finden den ich bei "R" oder "C" bekomme...
Beim "C" kuft man keine Atmels.
Schau dich mal hier um:
www.csd-electronics.de
Oliver
mache ich auch nicht. ist mir zu teuer.
Aber wegen ein oder zwei atmels wo bestellen. neues konto etc. ist mir
dann doch zuviel aufwand ...
wie gesagt sehe ich mir noch mehr optionen an.
Juergen