Hallo,
Ich habe vor einigen Wochen drei Funkchips RFM12B-868-D gekauft und
versuche seither erfolglos, die Chips (die ja für 3.3V Stromkreise
ausgelegt sind) in einem 5V Stromkreis zum Laufen zu bekommen. Die
Übersetzungslogik zwischen den Spannungen funktioniert inzwischen
zuverlässig, die Software-Seite gestaltet sich jedoch schwierig.
Da das Datasheet an einigen Stellen fehlerhaft / ungenau ist, habe ich
noch andere Quellen hinzugezogen und versucht, mir einen eigenen Code zu
schreiben, der sich einfach auf andere Szenarien portieren lässt:
Mein Problem ist, dass die testweise Kommunikation zwischen zwei µCs
(ein ATtiny45 bei 3.3V mit einem Funkchip und diesem Code und ein
ATmega32 bei 5V mit Pegelkonverter und Funkchip) nicht funktioniert. Auf
der Receiver-Seite wird nie ein Interrupt ausgelöst und auch das
abgefragte Interrupt-Bit im Statusregister bei "RFM12B_get()" ist nie
gesetzt, obwohl in unmittelbarer Nähe der andere Funkchip wie wild
sendet/senden sollte. Nichtmal irgendwelcher "Müll" kommt an.
Meine Fragen sind folgende:
1. Hat jemand den Chip RFM12B schonmal erfolgreich zum Laufen gebracht?
2. Welcher Code wurde verwendet?
3. Vielleicht hat jemand ähnliche Probleme gehabt und kann mir ein wenig
auf die Sprünge helfen.
Vielen Dank im Voraus!
CRT
War bei deinen "anderen Quellen" bereits die Elektor Januar 2009 dabei?
Dort ist ein längerer Artikel von B. Kainka zu diesen Modulen sogar
speziell auf 868 MHz. Programmiersprache ist allerdings BASCOM AVR.
Vielen Dank für die schnellen Antworten.
@Analog: Ich habe mir den Link angesehen und werde es in der nächsten
Zeit mit der dort verwendeten SPI Implementation versuchen. Was mir
immernoch etwas schleierhaft ist: Laut dem Datasheet des Controllers
überträgt dieser das erste Bit des Statusregisters bereits mit dem
ersten Bit des "Commands" - ich frage mich, wie bei einer syncronen
Datenübertragung möglich ist, dass der Slave schon weiß, was er mir
schicken soll, bevor der Master die Übertragung des ersten Bits beendet
hat. Weißt du dazu Genaueres?
@Stefan B.: Ich kannte die Elektor bisher noch nicht, entsprechend
gehörte sie noch nicht zu meinen Quellen. Ich werde aber versuchen, sie
in den nächsten Tagen irgendwo aufzutreiben. Zu Rate gezogen habe ich
bisher v.A. das Datasheet des Herstellers (weitestgehend unbrauchbar),
das Code-Example des Herstellers (ebenso unbenutzbar) und diese
Quickstart-Anleitung:
http://zenburn.net/~goroux/rfm12b/rfm12b_and_avr-%20quick_start.pdf
Außerdem habe ich einen kurzen Blick auf den Code bei
http://www.das-labor.org/ geworfen. An allen Implementationen hat mich
gestört, dass man nicht vollständig frei definieren könnte, welche Pins
man verwenden möchte, sondern dass es immer Randbedingungen gab (meist,
dass sie im gleichen Port sein müssen). Störend ist natürlich auch, wenn
die Implementationen schlicht fehlerhaft sind.
CRT wrote:
> Was mir> immernoch etwas schleierhaft ist: Laut dem Datasheet des Controllers> überträgt dieser das erste Bit des Statusregisters bereits mit dem> ersten Bit des "Commands" - ich frage mich, wie bei einer syncronen> Datenübertragung möglich ist, dass der Slave schon weiß, was er mir> schicken soll, bevor der Master die Übertragung des ersten Bits beendet> hat.
Sobald CS auf Low geht, gibt der RF12 das FFIT Bit aus.
Das Datenblatt ist etwas uneindeutig was das Statusregister angeht:
Version 1:
Parallel zum Senden eines (beliebigen) Befehls, wird das Statusregister
ausgegeben. Dies sieht man auch im Timingdiagramm auf Seite 13 des
Datenblatts.
Version 2:
Nur das FFIT Bit wird ausgegeben, was danach kommt ist sonst was. Wenn
man das Statusregister komplett lesen möchte, muss man den Befehl 0x0000
senden. Dies steht auf Seite 23.
Beides kann in die Angaben aus dem Datenblatt hineininterpretieren.
Welche Version richtig ist, habe ich noch nicht ausprobiert. Mit Version
2 ist man aber auf der sicheren Seite.
> Ich kannte die Elektor bisher noch nicht, entsprechend> gehörte sie noch nicht zu meinen Quellen. Ich werde aber versuchen, sie> in den nächsten Tagen irgendwo aufzutreiben.
Schau aber erst rein ehe du die kaufst. Da wurde im Prinzip nur das
Datenblatt wiedergegeben und ein paar Bascom Beispiele gezeigt. Nichts
was man nicht auch kostenlos und besser im Internet finden kann.
Vielen Dank auch dir, Benedikt K., für deine schnelle und hilfreiche
Antwort!
Ich habe die von mir verwendete Implementation mit der in dem anderen
Beitrag und der von Wikipedia
(http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Example_of_bit-banging_the_SPI_Master_protocol)
verglichen und musste feststellen, dass es auch hier wieder Unterschiede
gibt, wobei die von mir verwendete Implementation näher an dem
Wikipedia-Beispielcode ist. Da der Funkchip aber vermutlich nach dem
Heruntersetzen der Clock schnell genug sein nächstes Bit auf den Bus
schaufelt, bevor der Atmel es lesen möchte und du außerdem den Code
erfolgreich verwendest, muss es wohl ebenso funktionieren. Dass ich
dennoch bisher bei meinem Receiver das erste Bit nie gesetzt bekam, bei
meinem Chip im Transmitter-Modus aber halbwegs sinnvolle Werte beim
Status-Read-Command rauskamen (0xA040, 0xE040 bei der ersten Abfrage),
muss ich nun davon ausgehen, dass meine SPI-Implementation zwar stimmt,
mein Chip aber schlicht und einfach nichts empfängt, was er mir liefern
könnte.
@Benedikt K.: Warum hast du SPI so implementiert, wie du es
implementiert hast? Hast du außerdem detailierte Informationen bezüglich
des nFFS-Pins? Du schreibst in deinem Post, man möge ihn mit 10 kOhm auf
Vdd pullen, das habe ich auch getan. Im Datasheet des auf elektor
verlinkten Si4420
(https://www.silabs.com/Support%20Documents/TechnicalDocs/Si4420.pdf)
steht auf Seite 4 "nFFS | FIFO select input (active low) In FIFO mode,
when bit ef is set in Configuration Setting Command"; "ef" ist sowohl in
deiner alsauch meiner Implementation auf 1, müsste dann nicht nFFS auf
logisch high, also physisch low sein, um den FIFO zu verwenden?
CRT wrote:
> Warum hast du SPI so implementiert, wie du es> implementiert hast?
Weil es so dem Timing aus dem Datenblatt entspricht.
> Hast du außerdem detailierte Informationen bezüglich> des nFFS-Pins? Du schreibst in deinem Post, man möge ihn mit 10 kOhm auf> Vdd pullen, das habe ich auch getan. Im Datasheet des auf elektor> verlinkten Si4420> (https://www.silabs.com/Support%20Documents/TechnicalDocs/Si4420.pdf)> steht auf Seite 4 "nFFS | FIFO select input (active low) In FIFO mode,> when bit ef is set in Configuration Setting Command"; "ef" ist sowohl in> deiner alsauch meiner Implementation auf 1, müsste dann nicht nFFS auf> logisch high, also physisch low sein, um den FIFO zu verwenden?
Datenblatt RF12, Seite 14: Bit ef enables FIFO mode. -> ef muss 1 sein
wenn man das FIFO verwendet. Gleichzeitig wird nFFS auch ein eigener
Chipselect für das FIFO, man kann dann ohne Befehle zu senden, direkt
die Daten auslesen, wenn man nFFS auf Low zieht anstelle von nSEL. Da
ich dies aber nicht mache, muss nFFS deaktiviert werden, daher der
Pullup.
Nochmals vielen Dank für all eure Hilfe! Ich habe es nun geschafft,
einen Transmitter so zu programmieren, dass er auf die Flags im
Status-Register Rücksicht nimmt und wartet, bis der Chip bereit ist, die
nächsten Daten zu verarbeiten.
Ich werde mich nun wieder an einem Receiver versuchen und weitere
Ergebnisse und Fragen hier posten. Mein Quellcode sieht inzwischen so
aus:
Die Software-Initialisierung muss ich nochmal durchgehen, damit ich sie
verstehe.
Wenn jemand einen Fehler findet oder Denkanstöße in irgendeine Richtung
für mich hat, immer her damit! :)
Mein RFM12B-Treiber funktioniert nun! Ich arbeite gerade noch daran, ihn
an einigen Stellen zu überarbeiten, außerdem versuche ich mich an der
Interrupt-Implementation und gehe nochmal die Initialisierung durch.
Wenn er tadellos funktioniert werde ich ihn hier als Code-Schnipsel zur
freien Verwendung durch andere verlinken.
Eine Frage kam mir noch bzgl. Frequenzen: Das 868 MHz-Band ist relativ
restriktiv limitiert (Quellen:
http://de.wikipedia.org/wiki/Short_Range_Devices und
http://www.roboternetz.de/wissen/index.php/Funkmodule). Stellenweise
darf man nur mit Duty Cycle 0,1% oder 1% senden, hier sind offenbar auch
kritische Funkdienste wie sogenannte "Social Alarms" unterwegs, deren
Störung unbedingt vermieden werden muss.
Aus diesem Grund würde es mich freuen, wenn möglichst viele Augen den
folgenden Gedankengang und die Rechnung nachvollziehen und ihre
Meinung/Bedenken darüber äußern würden:
Laut Wikipedia (http://de.wikipedia.org/wiki/Short_Range_Devices) und
RoboterNetz (http://www.roboternetz.de/wissen/index.php/Funkmodule) ist
der Bereich 869,3 - 869,4 MHz im 868 MHz-Band "offen"; ich kenne mich
mit der Terminologie nicht aus, nehme aber an, dass das bedeutet, dass
hier keine Duty Cycle und Nutzungseinschränkungen gemacht werden. Ist
das richtig?
Das Code-Datensheet sagt auf Seite 2 zum Frequency Setting Command, die
Frequenz berechne sich über Fc = 860 + F * 0.0050 MHz; möchte ich nun
also auf 869,3 MHz senden, muss ich nach F auflösen, Fc einsetzen und
bekomme dann für F (also den Wert von f11..f0) 1860 oder 0x744. Ist das
richtig?
Was bedeuten die Frequenzangaben beim AFC Command (Seite 5) und TX
Configuration Control Command (Seite 6)?
Die Einschränkung der 10mW sollte nicht überschritten werden, denn: Laut
Datasheet Seite 5 beträgt die "Max. available output power" im 868
MHz-Band typischerweise 4 dBm; laut Wikipedia
(http://en.wikipedia.org/wiki/DBm#Unit_conversions) entspricht das
2,5mW; ist das richtig?
Ich hätte nun, davon ausgehend, dass ich die Basis-Frequenz einstellen
muss und der Funkchip dann die Basisfrequenz +- die Frequency Deviation
besendet, folgende Einstellungen vorgenommen:
Frequency Setting Command (0xA74E): Fc = 869,350 MHz (Mitte des
Bereiches 869,300 - 869,400 MHz) => F = 1870 = 0x74E
TX Configuration Control Command (0x9820): p = 000b (Output Power:
0dBm), m = 0010b (Frequency Deviation: 45kHz)
AFC und den Receiver Control Command hätte ich außenvor gelassen, da sie
scheinbar nur beim Empfangen der Signale eine Rolle spielen.
Hey,
habe mir soeben auch diese Module zugelegt und würde mich für deine
Implementierung interessieren. Die Ansätze hier sind schon sehr
hilfreich!
Hast du weiter gearbeitet oder ist das Projekt tot?
Würde mich über jeden Codefetzen freuen ;)
Danke...
Hallo.
Entschuldige, dass ich mich erst so spät melde, ich wollte eigendlich
den Code noch überarbeiten und dann hier hochladen. Dabei ist mir aber
der normale Alltag dazwischengekommen und ich habe das ganze aus den
Augen verloren.
Meine bisherige unbereinigte (!!!) Version habe ich hier online
gestellt: http://www.joachim-neu.de/index.php?lang=1&id=102
Dort werde ich auch Änderungen einpflegen und den Code falls nötig
aktualisieren.
Ich möchte mich nochmal für die Hilfe aus dem Forum hier bedanken,
namentlich bei Benedikt K., Stefan B. und Analog. Ich hoffe der Code
hilft anderen bei der Ansteuerung ihrer Funkmodule!
CRT