Forum: Mikrocontroller und Digitale Elektronik Arduino zu schwach für RC5??


von Xaser (Gast)


Lesenswert?

Hallo!

Ich versuche derzeit mit meinem Arduino Duemilanove ein einfaches 
"Standby" signal mit dem Phillips RC5 Protokoll zu senden. Bisher habe 
ich das so einfach wie möglich gefasst:
1
#include <TimerOne.h>
2
3
#define IR 13
4
5
boolean bCommand[28] = { 0,1, 0,1, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 0,1, 0,1, 1,0, 1,0 };
6
int nPosition = 14;
7
8
void setup()
9
{ 
10
  Serial.begin(9600);
11
  pinMode(IR, OUTPUT);
12
  digitalWrite(IR, LOW);
13
  Timer1.initialize(8890);
14
  Timer1.attachInterrupt(SendBit);
15
}
16
17
void loop()                     
18
{
19
  if(nPosition > 28)
20
  {
21
    digitalWrite(IR, LOW);
22
    delayMicroseconds(500);
23
    nPosition = 0;
24
    Serial.println("Jump");
25
  }
26
}


Aber "JUMP" wird nie ausgegeben und die LED leuchtet auch nicht 
wirklich. und wenn dann nur sehr schwach, wie ein funke neben der Sonne 
wenn die LED direkt über eine Konstantstromquelle an eine Batterie 
angeschlossen ist.

Kann es sein, dass der Prozessor damit einfach nicht fertig wird?

Mfg Xaser

von Unbekannter (Gast)


Lesenswert?

Lern mal ne anständige programmiersprache wie Assembler oder C, dann 
klappt das schon.
Arduino ist wie VBasic für den PC: lahm und ressourcenhungrig.

von Adam (Gast)


Lesenswert?

Xaser schrieb:
> if(nPosition > 28)

nPosition wird aber nie > 28, folglich wird dieser IF-Zweig nie 
abgearbeitet.

Unbekannter schrieb:
> Lern mal ne anständige programmiersprache wie Assembler oder C, dann
> klappt das schon.
> Arduino ist wie VBasic für den PC: lahm und ressourcenhungrig.

Häh? Noch nie nen Arduino benutzt, was?
Der wird nämlich in C bzw. wahlweise auch in C++ programmiert. Es werden 
lediglich ein Paar Libs zur Vereinfachung mitgeliefert; aber niemand ist 
gezwungen diese zu benutzen.

von Xaser (Gast)


Lesenswert?

ups dem code oben fehlte natürlich was sorry
1
#include <TimerOne.h>
2
3
#define IR 13
4
5
boolean bCommand[28] = { 0,1, 0,1, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 0,1, 0,1, 1,0, 1,0 };
6
int nPosition = 14;
7
8
void setup()
9
{ 
10
  Serial.begin(9600);
11
  pinMode(IR, OUTPUT);
12
  digitalWrite(IR, LOW);
13
  Timer1.initialize(889);
14
  Timer1.attachInterrupt(SendBit);
15
}
16
17
void SendBit()
18
{
19
  Serial.println(nPosition);
20
      digitalWrite(IR, bCommand[nPosition]);
21
      ++nPosition;
22
}
23
24
void loop()                     
25
{
26
  if(nPosition > 28)
27
  {
28
    digitalWrite(IR, LOW);
29
    delayMicroseconds(500);
30
    nPosition = 0;
31
    Serial.println("Jump");
32
  }
33
}


Und dazu sei gesagt, dass ich sowohl ASM als auch C - C++ behersche

Ich versuche mich schon lange von dem Arduino Editor zu trennen, leider 
unterstützt der Code Composer aber noch keinen AVR compiler, und ich 
will nur 1 IDE für Microcontroller benutzen müssen..


PS: ich glaube die Arduino sprache wird auch als Processing bezeichnet. 
Lege mich da aber nicht fest.

von Thomas (Gast)


Lesenswert?

Mit einer Digicam sollte man die Diode deutlich sehen können. 
Kostantstrom brauchst du nicht, einfach Widerstand + LED reicht.

von Adam (Gast)


Lesenswert?

Xaser schrieb:
> int nPosition = 14;

Versuch mal:

volatile int nPosition = 14;

von Malte _. (malte) Benutzerseite


Lesenswert?

Ich würde in loop() noch einen SendBit() aufruf einbauen.
Hinterher wird dir noch das Serial.println(nPosition) das gewünschte 
500µs Timing verfälschen.

von Xaser (Gast)


Lesenswert?

Thomas schrieb:
> Mit einer Digicam sollte man die Diode deutlich sehen können.
> Kostantstrom brauchst du nicht, einfach Widerstand + LED reicht.

Warum keine Konstantstromquelle verwenden, wenn man schon eine hat, für 
die LED ist das am verträglichsten und man erzielt das beste Ergebnis 
damit!

Adam schrieb:
> volatile int nPosition = 14;

bringt auch nix



Vielleicht sollte ich mal erläutern warum ich denke das der Arduino 
dafür zu schwach ist!

Ganz einfach: bei einer Interrupt Period von 889 Microsekunden geht 
nPosition einfach immer weiter hoch

bei 8890 wird jump schon ausgeführt.

Ich schätze einfach mal, das das was in SendBit passiert länger als 889 
Microsekunden dauert.


Mfg

von Tishima (Gast)


Lesenswert?

Hallo!

Ich verstehe den Ardunio Code kaum, aber ich sehe nicht wo das Signal 
mit, ich glaube bei RC5 mit 38kHz moduliert wird.

gruß,
Bjoern

von spess53 (Gast)


Lesenswert?

Hi

>boolean bCommand[28] = { 0,1,....

Hat es eine besondere Bedeutung, das nur 26 Bits definiert werden?

MfG Spess

von Xaser (Gast)


Lesenswert?

Tishima schrieb:
> Ich verstehe den Ardunio Code kaum, aber ich sehe nicht wo das Signal
> mit, ich glaube bei RC5 mit 38kHz moduliert wird.

Es sind 36Khz

Hier ein bisschen Lektüre:

http://www.stefan-buchgeher.info/elektronik/rc5/rc5_doku.pdf
http://www.sbprojects.com/knowledge/ir/rc5.htm

hat man schnell durch

das wichtigstige ist eben, das alle 889 Mikrosekunden der Status der LED 
verändert werden muss. Damit kommt man auf ein Gesamt von 24.889 
Millisekunden

von Klaus Boenicke (Gast)


Lesenswert?

Also wenn etwas zu schwach ist, dann höchstens deine 
Programmierfähigkeiten. ;)

Zwei Dinge sind mir ins Auge gesprungen:

Erstens:
Xaser schrieb:
> boolean bCommand[28] = { 0,1, 0,1, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 1,0, 0,1, 0,1, 
1,0, 1,0 };

Du hast nur 26 Werte, also wäre wohl bCommand[25] richtiger.

Zweitens:
Xaser schrieb:
> Ich schätze einfach mal, das das was in SendBit passiert länger als 889
> Microsekunden dauert.

Das ist sehr wahrscheinlich. Das ist aber nicht ein Problem des 
Arduinos, sondern ist schlicht falsche Programmierung. Grundregel: 
Interruptroutinen so kurz wie möglich halten. Die Serielle Schnittstelle 
ist lahm, im Interrupt etwas über die Serielle auszugeben kostet zuviel 
Zeit. Zum ohnehin schon recht lansamen RS232-Timing kommen noch die 
Verluste der Seriell-USB-Wandlung dazu. Sowas macht man keinesfalls in 
der Interruptroutine.

von Maik F. (sabuty) Benutzerseite


Lesenswert?

Xaser schrieb:
> Tishima schrieb:
>> Ich verstehe den Ardunio Code kaum, aber ich sehe nicht wo das Signal
>> mit, ich glaube bei RC5 mit 38kHz moduliert wird.
>
> Es sind 36Khz

Das mag ja sein, aber trotzdem erzeugst du die nirgendwo.

Die '1' bei den vereinfachten Angaben für eine RC5-Übertragung bedeuten, 
dass da ein 36kHz Träger ausgesendet wird und nicht einfach nur die IR 
LED angeschaltet wird.

von Xaser (Gast)


Lesenswert?

Klaus Boenicke schrieb:
> Du hast nur 26 Werte, also wäre wohl bCommand[25] richtiger

2 Start Bits + 1 Toggle Bit + 5 Adress Bits + 6 Command Bits = 14

14 Bits * 2 Teile = 28
Habe lediglich in der Aufzählung eine 0 Vergessen, und solange ich das 
Array nicht überfülle kanns auch 1024 Elemente haben, das macht keinen 
Unterschied ;)

Klaus Boenicke schrieb:
> Sowas macht man keinesfalls in
> der Interruptroutine.

Hatte ich Ursprünglich auch nicht implementiert, erst als mir die Kamera 
sagte, dass die LED nicht leuchtet. Kurz gesagt, auch ohne Serial 
passiert nichts.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Es passiert nichts, weil du die 36 kHz Trägerfrequenz nicht erzeugst.

889 Mikrosekunden entspricht, wenn du im Timer die LED einfach nur 
toggeln würdest, etwa 562 Hz. Darauf wird kein IR-Empfänger reagieren.

Dann kann es auch noch sein, dass die Stromquelle zu langsam 
einschwingt. Für solche Frequenzen sollte man einfach Vorwiderstände 
verwenden.

Das Erzeugen der Trägerfrequenz kann man beispielsweise mit einem PWM 
Ausgang machen. In meiner Fernsteuerung mache ich das in Assembler auf 
einem ATtiny11 direkt mit Warteschleifen zyklusgenau - das geht auch.

Grüße,

Peter

von Xaser (Gast)


Lesenswert?

Das wars ja noch nicht einmal, die LED leuchtete überhaupt nicht, aber 
das konnte ich mittlerweile berichtigen.

Peter Diener schrieb:
> Das Erzeugen der Trägerfrequenz kann man beispielsweise mit einem PWM
> Ausgang machen. In meiner Fernsteuerung mache ich das in Assembler auf
> einem ATtiny11 direkt mit Warteschleifen zyklusgenau - das geht auch.

Der PWM des Arduinos arbeitet mit 500hz, definitiv zu wenig für mein 
Vorhaben, auf 36KHz zu kommen. Kann ich den PWM denn irgendwie 
einstellen?

Ich kann zwar ASM aber kenne mich mit den AMTEL Bausteinen absolut nicht 
aus, deswegen greife ich auf den Standartweg zurück.

von Peter D. (peda)


Lesenswert?

Xaser schrieb:
> Ich kann zwar ASM aber kenne mich mit den AMTEL Bausteinen absolut nicht
> aus, deswegen greife ich auf den Standartweg zurück.

"Stehende Arten" gibbet nicht.

Wenn ich was auf nem AVR einstellen will, gehe ich einfach ins 
Datenblatt, z.T. Timer1, Register Description und dann klappere ich alle 
Register durch, also setze die entsprechenden Bits darin. Fertig.

Ohne Datenblatt braucht man sich nicht zu wundern, daß man den Chip 
nicht kennt und das nix geht.


Ansonsten verstehe ich bei den Arduino-Befehlen auch nur Bahnhof.
Kann man auf den Arduino nicht ganz normale C-Programme laden, also mit 
main usw.?

Ne Stromquelle würde ich auch nicht nehmen, nicht jede Schaltung schafft 
36kHz. Ich sehe auch nirgends die 36kHz Erzeugung.

Ich würde nen 72kHz Interrupt mit Pin-Toggle nehmen und darin die Bits 
senden. Dann hat man keinen Jitter.
Bei 8MHz hat der Interrupt 111 Zyklen Zeit, das ist in C zu schaffen.
Alle anderen Interrupts müssen beim Senden gesperrt sein.


Peter

von Xaser (Gast)


Lesenswert?

Ich weiß echt nicht, was an einer Konstantstromquelle auszusetzen ist:

http://www.mikrocontroller.net/articles/Konstantstromquelle

das Ding wird lediglich zwischen LED und + - geklemmt, damit die 
Stromstärke für die LED optimal ist.

ich habe jetzt die ganze zeit gesucht und schon einiges rausgefunden:

Der ATMEGA328 hat 6 Pins die mit PWM verwendet werden können, jeweils 2 
teilen sich einen Timer/Counter Register: TCCR0B, TCCR1B, und TCCR2B.

Die letzten 3 Bits des Registers sind der Vorteiler, damit kann ich also 
für die Anschlüsse OC1A, OC1B, OC2A, OC2B (Pins 9, 10, 11 und 3) eine 
32KHz Frequenz modulieren.

ich brauche aber 36KHZ. Dass wird in einem Beispiel so gemacht:
1
TCCR2A = _BV(WGM21) | _BV(COM2A0);
2
TCCR2B = _BV(CS20);
3
// 36kHz carrier/timer
4
OCR2A = (F_CPU/(36000L*2L)-1);

TCCR2B und OCR2A sind geklärt. F_CPU ist beim ATMega328 16MHz 36000 ist 
die gewünschte Frequenz (36KHz) auch klar.

Bleibt über die -1, das L hinter den Werten (Long?) sowie TCCR2A und die 
_BV werte.

Dazu habe ich schon gewühlt aber noch nix gefunden was mich überzeugt 
hat.

von Peter D. (peda)


Lesenswert?

Xaser schrieb:
> Ich weiß echt nicht, was an einer Konstantstromquelle auszusetzen ist:

Welche der vielen Schaltungen denn?

Wie schon gesagt, sind Schaltungen nicht unendlich schnell, 36kHz ist 
schon ne ordentliche Hausnummer.


Peter

von Xaser (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Welche der vielen Schaltungen denn?
>
> Wie schon gesagt, sind Schaltungen nicht unendlich schnell, 36kHz ist
> schon ne ordentliche Hausnummer.

Eine ziemlich einfache, 2 dioden, 2 Wiederstände und ein Transistor, 
aber das tut nix zur sache, ich habe den Thread nicht zur Diskussion 
über eine Konstantstromquelle eröffnet^^, mich würde vielmehr die 
Bedeutung der oben stehenden Begriffe interessieren.


Mfg Xas

von Oskar (Gast)


Lesenswert?

Mann, du gehörst echt zu den lernresistenten Typen.

von Markus (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Ansonsten verstehe ich bei den Arduino-Befehlen auch nur Bahnhof.
> Kann man auf den Arduino nicht ganz normale C-Programme laden, also mit
> main usw.?

Klar kann man. Niemand wird dazu gezwungen die Arduino-Erweiterungen zu 
benutzen. Steht alles in der Doku zum Arduino. Allerdings gibts wohl 
immer Leute, die nichts von Doku-Lesen halten...

von Xaser (Gast)


Lesenswert?

Oskar schrieb:
> Mann, du gehörst echt zu den lernresistenten Typen.

Oh ja, solche Leute liebe ich, die durch Foren streifen nur auf der 
Suche nach Threads wo sie einen Klugscheißerkommentar loslassen können. 
Super.
Klar wer liebt denn nicht vollkommen unbegründete 2 Sekundenkommentare.



So wie ich das dem Datasheet entnehme hat WGM21 was mit dem Typ der 
Wavegenerierung zu tun sehe ich das richtig?

von Marcus M. (marcus67)


Lesenswert?

Moment mal, Peter wollte Euch helfen - jetzt werft Ihr ihm vor, daß er 
sich nicht durch die komplette Doku einer, vorsichtig gesagt, exotischen 
Entwicklungsumgebung wühlt ?

Gruß, Marcus

von Xaser (Gast)


Lesenswert?

Marcus Müller schrieb:
> Moment mal, Peter wollte Euch helfen - jetzt werft Ihr ihm vor, daß er
> sich nicht durch die komplette Doku einer, vorsichtig gesagt, exotischen
> Entwicklungsumgebung wühlt ?

Habe ich nie getan, von ihm stammen 90% der helfenden Antworten in 
diesem Thread. geärgert hat mich Oskar..

von Michael (Gast)


Lesenswert?

@Xaser: Ja, der Arduino ist dafür wirklich zu langsam!!
Und die einfache Konstantstromquelle ist schnell genug. Geht locker bis 
1MHz oder mehr, lass Dir da nicht reinquatschen - übrigens völlig egal 
welcher Transi da drin ist, das schaffen wirklich ALLE!!

Hoffe Dir geholfen zu haben indem ich das gesagt habe, was Du hören 
wolltest!

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Vielleicht kann man mit der Tone Library
http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation
36kHz erzeugen. Hab es nicht getestet, aber es sollte nichts dagegen 
sprechen.

Ansonsten kann man ja einfach eine eigene Bibliothek schreiben oder 
direkt auf die Hardware zugreifen.

Wenn es mein Projekt wäre, würde ich eine eigene Bibliothek schreiben, 
die einen der freien Timer zur PWM-Erzeugung benutzt. Die laufende PWM 
kann man einfach modulieren, in dem man die Pulsweite auf Null setzt 
(richtige waveform generation (up-down-mode) wählen, damit keine Spikes 
entstehen).
Das sollte bei doppelt gepufferten Compareregistern (wie z.B. beim Timer 
1) sogar richtig gut zu synchronisieren sein.

Die Modulation sollte dann entsprechend über den Overflowinterrupt des 
verwendeten Timers aufsynchronisiert werden.

Alternativ schätze ich, dass die "halb-software-PWM" (Vorschlag von 
Peter Dannegger) mit dem Toggeln des Pins im Interrupt genauso gut 
funktioniert. Das ist einfacher umzusetzen, dafür wird etwas mehr 
Rechenleistung verbraucht.

Grüße,

Peter

von Andreas L. (andi84)


Lesenswert?

Moin,

ein neues Bit kommt bei RC5 ja grad mal alle 1,778ms. Da jetzt jeden 
Toggle der IR-LED in nem IRQ zu machen ist mit kanonen auf spatzen.
Würde da eher den Wave Generator Mode des TImers nutzen, der toggled 
dann selbsttätig den ausgangspin und setzt den timer zurück - so kommt 
man dann zu den 36kHz, das passiert dabei alles im hintergrund in 
hardware.
Im original passiert ein umtasten alle 32 Perioden von 36kHz, da das 
aber eh immer von einem empfänger demoduliert wird bevors ausgewertet 
wird, muss man sich da jetzt keinen allzugroßen kopp machen, weil dass 
dann evtl nicht ganz stimmt vom timing her.
Den wave generator kann man ohne den timer zu stoppen vom pin 
trennen/damit verbinden. damit erzeugt man das nutzsignal 
(manchestercode für das RC5)

Also:
1) WGM nutzen für die 36kHz
2) mit Timer oder Delayloop alle 889µs den ausgang des WGM umschalten 
gemäß manchester
3) glücklich sein, dass das plötzlich alles geht

von Xaser (Gast)


Lesenswert?

Also vielen Dank für die vielen Beiträge (damit meine ich die nützlichen 
hust), aber ich denke ich habs jetzt durchschaut:

Ich habe mir diesen Codeschnitzel den ich gefunden hatte vorgenommen und 
dann mithilfe des Datasheets des ATMega328 entschlüsselt.
1
TCCR2A = _BV(WGM21) | _BV(COM2A0);
2
TCCR2B = _BV(CS20);
3
// 36kHz carrier/timer
4
OCR2A = (F_CPU/(36000L*2L)-1);

TCCR2A (Timer2 Counter Controll Register A?) wird neu beschrieben und 
dazu muss man wissen, dass _BV ein define für (1 << x) ist. WGM21 und 
COM2A0 sind dementsprechend Bits im Register.

Beide gesetzt heißt das soviel wie:
Toggle OC2A on Compare Match im Non-PWM Mode.
OC2A ist klar, Pin 11 des Arduino.
OCR2A (Output2 Control Register A?) beinhaltet dementsprechend den Wert 
der andauernd verglichen wird, in unserem Fall ein Wert der so gesetzt 
ist, dass er 72000x in der Sekunde zutrifft, also 36000 pro sekunde geht 
die LED ein und aus.

Wie ich das jetzt noch ein und ausschalte ist ja relativ klar, einfach 
andere Bits in TCCR2A setzen. Verbunden mit dem Timer1 der sich alle 
889mikrosekunden meldet wird das schon klappen hoffe ich

von weakbit (Gast)


Lesenswert?

Hallo,
ich verstehe auch nicht viel vom Arduino aber erstens warum sind da nur 
26bits wenn Dein Array mit [28] definiert ist?
Dann wo schaltest Du die LED ein und aus? Im ersten Code sehe ich nur 
LOW?
Der andere Kollege hat Recht wie kann es sein das man ohne Modulation 
der 36kHz mit dem PWM Register und keinem Zeitlichen Abstand überhaupt 
einen RC5 auftasten kann?

Das es funktioniert solltest Du die Startflanke der RC5 Pakete immer am 
gleichen Zeitpunkt haben.
Ein Timer der den Raster des Starts vorgibt mit 1,8ms OVF (overflow und 
timerint). Die PWM im Synchronmode mit 36kHz für die Bursts und wenn 
mich nicht alles täuscht hat der RC5 auch unterschiedlich lange Pakete. 
(das ist leider schon fast 20 Jahre her da haben wir einmal etwas für 
S**y mit RC5 gemacht - die wollten sich zu diesem Zeitpunkt am Phi***s 
immer mehr anpassen)

Interrupt Vektor:
12 0x0016 TIMER1 COMPA Timer /Counter1 Compare Match A
13 0x0018 TIMER1 COMPB Timer /Coutner1 Compare Match B
14 0x001A TIMER1 OVF Timer /Counter1 Overflow
Seite 65 im Datasheet

PWM - Output Compare Match:
OC0A
Seite 89 PortD.6
ist hier als Ausgang vorgesehen.
Seite 94 - 8bit PWM ebenfalls durchlesen hier wird erklärt das es 2 
Compare Match Register gibt.

Ach ja noch etwas ich glaube Niemanden der sagt er kenne sich mit C++ 
aus!
In den meisten Fällen ist es so das der Compiler auch C++ compilieren 
kann aber ich habe die letzten 30Jahre lediglich 3 Leute kennen gelernt 
die Bjarne Strostrup richtig schreiben können.

MfG
weakbit

von Oliver R. (orb)


Lesenswert?

Ich denke, daß  Xaser das Problem innerhalb der letzten dreieinhalb 
Jahre gelöst hat.
(und das ist ein Zeitraum in dem man C++ lernen könnte ohne Strostrup zu 
schreiben)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.