Go Down

Topic: Arduino und der Sparkfun Transceiver nRF2401A ??? (Read 7638 times) previous topic - next topic

bohne

Das ist gefährlich, Du wirst unter Garantie die entscheidenden Pin level changes verpassen, da der Prozessor gerade etwas anderes abarbeitet. Besser, Du bemühst die Hardware Interrupts...

Es gibt im Endeffekt zwei Arten von Interrupts, die Dich interessieren könnten:
Pin Change Interrupt Request und
External Interrupt Request
guck mal im Datenblatt vom ATmega168 nach, welchen Du verwenden magst und was das bedeutet, konkret wird es ab Seite 65 spannend.

Das Wesentliche für EXTERNE INTERRUPTS (davon hat der Chip nur zwei Stück) wurde schon für Dich implementiert, guck mal in diese Datei:
http://code.google.com/p/arduino/source/browse/tags/0015/hardware/cores/arduino/WInterrupts.c

Du musst also den DR1 Pin an den digitalen Pin 2 bzw. 3 des Arduino anschließen. Das sind die Pins PD2 und PD3 im ATMega168 Datenblatt (dort werden sie dann auch INT0 bzw. INT1 genannt).

Probier doch mal das Beispiel aus dem Playground aus (http://www.arduino.cc/en/Reference/AttachInterrupt), indem Du einen Taster an digital Pin 2 des Arduinos hängst... die LED sollte dann blinken wenn Du einen pinchange an diesem Schalter vornimmst. Eigentlich sehr einfach.

Wenn Du so weit bist musst Du die blink() Funktion austauschen gegen die Programmlogik, die Du eigentlich benötigst und dann muss eben der DR1 Pin vom Transceiver an den digital Pin 2 vom Arduino angeschlossen werden und es wird dann funktionieren :)


http://www.dorkbot.de
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236434254
http://www.luminet.cc

kimmi

Netterweise hängt der DR1 schon am Pin2,der Hardware Interrupt müsste sich also direkt einfügen lassen. Ich nehme an, der Interrupt setzt an der Stelle ein, wo er abgefragt wird? Der Interrupt bewirkt keinen Reset?

bohne

Der Interrupt ruft nur die Funktion auf, die Du angibst, im Beispielcode wäre das blink()... ein Reset wird nicht ausgeührt.
http://www.dorkbot.de
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236434254
http://www.luminet.cc

kimmi

Ok, Danke, dass sollte dann funktionieren.

kimmi

#94
May 16, 2009, 11:32 pm Last Edit: May 16, 2009, 11:33 pm by oren Reason: 1
Wo wird den in dem Beipiel hier http://www.arduino.cc/en/Reference/AttachInterrupt spezifiziert welcher Interrupt Pin abgefragt wird? Es gibt ja zwei, Pin2 und Pin 3? Ich möchte ja vielleicht einen der beiden als normalen Pin fü anderes benutzen.

Code: [Select]
int pin = 13;
volatile int state = LOW;

void setup()
{
 pinMode(pin, OUTPUT);
 attachInterrupt(0, blink, CHANGE);
}

void loop()
{
 digitalWrite(pin, state);
}

void blink()
{
 state = !state;
}

Schwarzfuss

Ohne groß Ahnung zu haben, deutlicher wirds wohl hier erklärt:
AVR-Tutorial:_Interrupts
INT0 reagiert auf Änderung an PD2
INT1 auf PD3
Gruß Peter

kimmi

#96
May 17, 2009, 09:51 am Last Edit: May 17, 2009, 09:52 am by oren Reason: 1
Danke aber.... die Erklärung im Link ist in Assembler.. in ASSEMBLER !!! Ich kann doch kaum Arduino !!!!

Ich frage mich vorallem wo die Pin auswahl in dem obenstehenden Arduino Programm zu finden ist und wo der Interrupt-Punkt.

Schwarzfuss

Ich kann weder Assembler noch Arduino, trotzdem find ich es im o.g. Link gut erklärt.
Die Interrupt-Funktionen sind fest im Chip integriert, man muß nur wissen wie man drankommt.
Dein Prg.-Beispiel hab ich mal nachvollzogen,
einmal mit
Code: [Select]
attachInterrupt(0, blink, CHANGE);
und dann mit
Code: [Select]
attachInterrupt(1, blink, CHANGE);
Im ersten Fall wechselt der Zustand der LED bei Änderung an Pin 2,
im zweitem bei Änderung an Pin 3, deutlicher kann ichs leider nicht beschreiben... :-[
Gruß Peter

dh1ao

#98
May 17, 2009, 05:03 pm Last Edit: May 17, 2009, 05:25 pm by dh1ao Reason: 1
Hallo kimmi

ich habe so den Verdacht, dass Dir die Interruptsachen nicht ganz klar sind? Mir kommt es so vor, dass wir alle manchmal aneinander vorbei"schreiben"...

Ich beschreibe mal auf Verdacht etwas die Funktionsweise ja? Und wenn es allzu großer Unsinn sein sollte werden die Kollegen hier es sicher schnell korrigieren  8-) Im wiki ist es zwar beschrieben, aber es tauchen doch viele wahrscheinlich verwirrende Begriffe auf...

Es gibt im wesentlichen zwei Möglichkeiten einen Controller auf Signale der realen physikalischen Welt reagieren zu lassen. Signale der Umwelt werden immer als Spannungspegel oder Spannungsänderung an einem Pin des Controllers angelegt.

Die erste Methode kennst Du ja schon. In einer while-Schleife einen Pin nach seinem Spannungspegel abfragen.

Im wesentlichen macht Radio.available() so etwas. Man läßt also sein Hauptprogramm so vor sich hinwerkeln und fragt dabei einen interessanten Pin nach seinem Pegel.

Je nachdem welcher Pegel anliegt macht dein Hauptprogramm wie gewohnt weiter oder behandelt das Eingangssignal. Dieses Verfahren nennt man auch polling.



Die andere Methode die Umwelt zu erfassen sind Interrupts!
Interrupt kann man ja als "unterbrechen" beschreiben/übersetzen. Genau das ist es auch.

Hier übernimmt die Hardware das Erkennen einer Änderung an einem Eingangspin des Controllers.
Du bastelst Dir eine Funktion, die nur dann ausgeführt werden soll, wenn sich an Pin 2 z.B. der Pegel ändert. In den Beispielen hier war es die Funktion void blink(void). Du sagst dem Controller ganz zu Anfang in deinem Programm

"Wenn an Pin 2 etwas wackelt, dann führe blink aus
Code: [Select]
attachInterrupt(0,blink)

Nun fängt dein eigentliches Hauptprogramm an zu werkeln. Schön einen Befehl nach dem anderen.
Irgendwann, ganz plötzlich und unerwartet passiert an Pin2 etwas. Und jetzt das schöne! Ohne das Du noch etwas abfragen musst unterbricht der Controller dein normales Hauptprogramm. Irgendwo, wo es halt gerade war.

Zusätzlich merkt sich der Controller, wo er Dein Hauptprogramm unterbrochen hat.

Dann ab zu der vorher für diesen Fall bekannt gemachten Funktion blink (Du erinnerst Dich: attachInterrupt(0,blink) )

blink ist ein Beispiel für die von Bohne angesprochenen ISRs
(Interrupt Service Routine). Wenn blink jetzt abgearbeitet ist, erinnert sich die Hardware, wo sie dein Hauptprogramm unterbrochen hat und macht dann da weiter als wäre nix geschehen.

Der kleine Atmel kann Interrupts erzeugen, wenn außen etwas passiert (das kann er an Pin2 oder Pin3) oder Timer abgelaufen sind oder der A/D Wandler fertig ist usf.

Zusatz: (muss man nicht direkt verstehen, schadet aber auch nix :D)
Für jeden Interrupt gibt es einen Eintrag im RAM an einer speziellen, vom Hersteller festgelegten Adresse. Das ist die Interrupt Vektor Tabelle. Wenn nun an Pin 2 etwas passiert schaut die Hardware in dieser Tabelle nach, wohin verzweigt werden soll.

Quote
.org 0x000                    ; kommt ganz an den Anfang des Speichers
        rjmp RESET           ; Interruptvektoren überspringen
                             ; und zum Hauptprogramm
        rjmp EXT_INT0        ; IRQ0 Handler <- Pin 2
        rjmp EXT_INT1        ; IRQ1 Handler
        rjmp TIM2_COMP
        rjmp TIM2_OVF
        rjmp TIM1_CAPT       ; Timer1 Capture Handler
        rjmp TIM1_COMPA      ; Timer1 CompareA Handler
        rjmp TIM1_COMPB      ; Timer1 CompareB Handler
        rjmp TIM1_OVF        ; Timer1 Overflow Handler
        rjmp TIM0_OVF        ; Timer0 Overflow Handler
        rjmp SPI_STC         ; SPI Transfer Complete Handler
        rjmp USART_RXC       ; USART RX Complete Handler
        rjmp USART_DRE       ; UDR Empty Handler
        rjmp USART_TXC       ; USART TX Complete Handler
        rjmp ADC             ; ADC Conversion Complete Interrupthandler
        rjmp EE_RDY          ; EEPROM Ready Handler
        rjmp ANA_COMP        ; Analog Comparator Handler
        rjmp TWSI            ; Two-wire Serial Interface Handler
        rjmp SPM_RDY         ; Store Program Memory Ready Handler


Vorteil: Du verpasst kein Ereignis, weil die Hardware drauf achtet und Du verschwendest keine Rechenzeit durch pollen, wenn nix passiert.

Vielleicht ist der Unterschied Pollen und Interrupt etwas klarer geworden?

Und sorry für langen Text....
Erkläre es mir, ich werde es vergessen. Zeige es mir, ich werde es vielleicht behalten. Lass es mich tun, und ich werde es können. Indisches

kimmi

#99
May 17, 2009, 07:19 pm Last Edit: May 17, 2009, 08:06 pm by oren Reason: 1
Die Funktionsweise eines Interrupts war mir schon klar aber ich konnte mit der Codezeile aus dem Beispielprogramm nicht richtig was anfangen, aber jetzt ist alles klar, danke schön!!!

Was ja jetzt noch richtig klasse ist, dass der Transceiver2 Kanäle hat und der Arduino 2 Interrupt Pins, man kann also sogar zwei unabhängige Interrupts anlegen jit zwei verschiedenen Funktionen, zum Beipiel einen für den normalen Datenverkehr und einen für den Notfall. Wunderbar, da hab ich alles was ich bracuhe zusammen!!

Vielen Dank allen die hier gepostet und geholfen haben!!

australopitecus

Ok. Hab ich alles verstanden.

Aber woher weiß ich, dass
"rjmp EXT_INT0    ; IRQ0 Handler"    für Pin2 steht,
"rjmp EXT_INT1    ; IRQ1 Handler"    für Pin 3 usw. ?

Ich hab das Arduino Mega Board, da stehen noch einige mehr drin.

Und kann ich auch aufgrund von Signalen an Analogeingängen Interrupts starten?

Vielen Dank im voraus.

Go Up