Forum: HF, Funk und Felder 433 Funksteckdose mit RFM69 steuern


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von David M. (thenetstriker)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche mit einem RFM69 (Adafruit Featherwing) 433 MHz 
Funksteckdosen zu steuern und auch die Signale der original 
Fernsteuerung empfangen zu können. Ich verwende dazu aktuell die 
RadioHead Library die ich noch etwas modifizieren musste da die Library 
nicht für diese Art Kommunikation ausgelegt ist. Ich verwende aktuell 
den das "Unlimited Length Packet Format" um die Daten zu senden und zu 
empfangen.

Ich habe auch bereis die korrekte Bitrate herausgefunden und auch das 
eine 0 als 1000 und eine 1 als 1110 geschickt wird. Mit diesen 
Informationen habe ich es auch bereits geschafft die Funksteckdose zu 
schalten. Beim Empfang habe ich aber noch Probleme. Aus irgendeinem 
Grund erhalte ich nicht die gleichen Bit's von der original 
Fernbedienung.

Ich habe die Signale von der original Fernbedienung und vom RFM69 mit 
einem HackRF One analysiert und habe im Anhang zwei Screenshots abgelegt 
wo die Signale zu sehen sind. Seltsamerweise ist das erste Bit des RFM69 
immer 1100 statt 1000, aber die Funksteckdose akzeptiert das Signal 
trotzdem. Ausserdem ist der Delay zwischen den Signalen etwas grösser. 
Das liegt wohl auch noch an der RadioHead library die zu lange wartet. 
Aber auch das schein kein Problem für die Funksteckdose zu sein. Hier 
ist mein aktueller Code um das Funksignal zu schicken:
#include <Arduino.h>
#include <SPI.h>
#include <RH_RF69.h>

#define RFM69_CS  14   // "E"
#define RFM69_RST 32   // "D"
#define RFM69_INT 33   // "B"

RH_RF69 rf69(RFM69_CS, RFM69_INT);

#define CONFIG_OOK (RH_RF69_DATAMODUL_DATAMODE_PACKET | RH_RF69_DATAMODUL_MODULATIONTYPE_OOK | RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE)
#define CONFIG_NOWHITE_NOCRC_FIXED (RH_RF69_PACKETCONFIG1_DCFREE_NONE | RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE)

const uint8_t kbps_msb_3_0_5_5 = 0x28; // 3.055 kbps
const uint8_t kbps_lsb_3_0_5_5 = 0xEB; // 3.055 kbps
const uint8_t bandwidth_1 = 0x88; // Rx Bandwidth = 1kHz.

const uint8_t dataON[] = {
  B10001000, B10001000, B10001000, B10001000, B10001000, B10001110, B10001000, B10001110, B10001110, B10001110, B10001000, B10001110, B10000000, B00000000, B00000000, B00000000,
  };

const uint8_t dataOFF[] = {
  B10001000, B10001000, B10001000, B10001000, B10001000, B10001110, B10001000, B10001110, B10001110, B10001110, B10001110, B10001000, B10000000, B00000000, B00000000, B00000000,
  };

void setup() 
{
  Serial.begin(115200);
  while (!Serial);

  pinMode(RFM69_RST, OUTPUT);

  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);

  if (!rf69.init())
    Serial.println("init failed");

  if (!rf69.setFrequency(433.85))
    Serial.println("setFrequency failed");

  rf69.setTxPower(20, true);

  RH_RF69::ModemConfig config = {
    CONFIG_OOK,                                           ///< Value for register RH_RF69_REG_02_DATAMODUL "ModulationType"
    kbps_msb_3_0_5_5,                                     ///< Value for register RH_RF69_REG_03_BITRATEMSB "Datarate" 20.0
    kbps_lsb_3_0_5_5,                                     ///< Value for register RH_RF69_REG_04_BITRATELSB not used, default value 0x0B
    0x00,                                                 ///< Value for register RH_RF69_REG_05_FDEVMSB "Deviation" not used, default value
    0x52,                                                 ///< Value for register RH_RF69_REG_06_FDEVLSB not used, default value
    bandwidth_1,                                          ///< Value for register RH_RF69_REG_19_RXBW "Bandwidth"
    0x8B,                                                 ///< Value for register RH_RF69_REG_1A_AFCBW "AfcBandwidth" default value
    CONFIG_NOWHITE_NOCRC_FIXED};                          ///< Value for register RH_RF69_REG_37_PACKETCONFIG1

  rf69.setModemRegisters(&config);

  // Disable preamble
  rf69.spiWrite(RH_RF69_REG_2C_PREAMBLEMSB, 0x00);
  rf69.spiWrite(RH_RF69_REG_2D_PREAMBLELSB, 0x00);

  // Disable sync words
  rf69.spiWrite(RH_RF69_REG_2E_SYNCCONFIG, B01000000);

  // Set payload length to our packet size
  rf69.spiWrite(RH_RF69_REG_38_PAYLOADLENGTH, 0);
}

void loop()
{
  rf69.sendRaw(dataON, sizeof(dataON));
  rf69.waitPacketSent();
}

Die SendRaw Funktion habe ich selber in die RadioHead Library eingebaut 
und sieht so aus:
bool RH_RF69::sendRaw(const uint8_t* data, uint8_t len)
{
    if (len > RH_RF69_MAX_MESSAGE_LEN)
  return false;

    waitPacketSent(); // Make sure we dont interrupt an outgoing message
    setModeIdle(); // Prevent RX while filling the fifo

    if (!waitCAD()) 
  return false;  // Check channel activity

    ATOMIC_BLOCK_START;
    digitalWrite(_slaveSelectPin, LOW);
    _spi.transfer(RH_RF69_REG_00_FIFO | RH_RF69_SPI_WRITE_MASK); // Send the start address with the write mask on
    // Now the payload
    while (len--)
  _spi.transfer(*data++);
    digitalWrite(_slaveSelectPin, HIGH);
    ATOMIC_BLOCK_END;

    setModeTx(); // Start the transmitter
    return true;
}

Für den Empfang verwende ich folgend Code im loop:
    setOpMode(RH_RF69_OPMODE_MODE_RX);
    uint8_t buf[sizeof(RH_RF69_MAX_MESSAGE_LEN)]; // RH_RF69_MAX_MESSAGE_LEN
    uint8_t len = sizeof(buf);

    uint8_t readLength = rf69.readFifoTest(buf, len);
    //Serial.print("got reply: ");
    for (int i = 0; i < readLength; i++) {
      if (buf[i] != 255)
        Serial.print(buf[i], BIN);
    }

Die readFifoTest methode habe ich wieder selber in die RadioHead Library 
eingebaut:
uint8_t RH_RF69::readFifoTest(uint8_t* buffer, uint8_t length) {
    uint8_t bufferLength = 0;

    while (length > 0) {
        uint8_t irqflags2 = spiRead(RH_RF69_REG_28_IRQFLAGS2);

        if (irqflags2 & RH_RF69_IRQFLAGS2_FIFONOTEMPTY)
        {
            digitalWrite(_slaveSelectPin, LOW);

            _spi.beginTransaction();
            _spi.transfer(RH_RF69_REG_00_FIFO); // Send the start address with the write mask off

            buffer[bufferLength] = _spi.transfer(0);
            bufferLength++;
            length -= 1;

            _spi.endTransaction();
            digitalWrite(_slaveSelectPin, HIGH);
        }

        YIELD;
    }

    return bufferLength;
}

Hat mir vielleicht jemand einen Tipp was ich hier falsch mache?

von Christian S. (roehrenvorheizer)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,


ich möchte mal hier aus meinem virtuellen Elfenbeinturm heraus kund tun, 
was mir einfällt:

Wir haben es wie öfter mal mit einer Frage zu einem gängigen Funkmodul 
zu tun, die auf wenig/gar keine Resonanz stößt. Die Frage ist bereits 
ziemlich ausführlich formuliert und mit Codebeispiel angereichert. 
Zusätzlich wird der Datenstrom gezeigt. Trotzdem hat niemand eine Idee 
dazu.

Ich selbst kann mit dem Arduino-Code nicht viel anfangen, da ich die 
Arduino-Welt nicht kenne. Leider fehlen Kommentare hinter den 
Codezeilen, die anderen verdeutlichen können, was die einzelnen Zeilen 
bewirken sollen. Nützlich wäre vielleicht auch, die eingestellten 
Registerwerte separat binär oder als hex anzugeben, am besten gleich mit 
verbaler Erklärung, was eingestellt wurde. Hilfreich wäre noch eine 
kurze Beschreibung der Funktionsweise, also hier unbegrenzte Paketlänge 
zusammen mit Fifo-Benutzung.

MfG

von Gehirnchirurg (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bei diesen Funkasics die auch OOK können und per Registereinstellungen 
konfiguriert werden hat das bei mir auch nie hingehauen. Schaut man sich 
genauer an was die senden ist es ein Pulsetrain, lauter kleine Pulse, 
die ein HIGH "nachbilden". Manche Empfänger kommen damit nicht zurecht. 
Ich glaube in einem Datenblatt von einem Silabs, TI oder Hope steht das 
auch drinn, dieser OOK Modus in diesen Funkasics ist eher mit Vorsicht 
zu geniesen. Manche haben einen RAW-Modus, der der sich dann wie die 
Primitivmodule verhält, da gab es glaube ich aber auch Einschränkungen, 
dient nur zum Testen nicht zur Datenübertragung.

Mit den Primitivmodulen die nur einen TX-Pin haben den man HIGH und LOW 
schaltet ging es immer auf Anhieb. Die schalten einfach die 
Trägerfreuquenz ein solange der Pin HIGH ist, Pulsetrains gibts dort 
nicht.


Vielleicht hast du das Modul auch nicht sauber konfiguriert, ich bin 
jetzt zu faul nachzuschauen aber manchen haben noch Datawhitening, 
kleben nen CRC automatisch ran, machen Manchester,... Das meiste davon 
ist im OOK-Modus sowieso nicht verfügbar aber schau trtzdem mal ins 
Datenblatt.

Wenn am Anfang das Bit nicht ankommt stimmt evt. was mit dem timing 
nicht oder off-by-one Fehler, hatte ich auch schon.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe sowohl mit RFM12 als auch RFM69 FS20 Code gesendet und 
empfangen, das geht. Beim RFM69 habe ich das über einen Datenpin des 
Moduls gemacht, für nur über SW hatte ich keine Möglichkeit gesehen. 
Bzw. nur wie vom Vorredner genannt diese ähnliche Modulation.
Code für MBed, müsste ich nochmal raussuchen.

von Stefan S. (energizer)


Bewertung
0 lesenswert
nicht lesenswert
Hallo David,

ich habe mich mit genau diesem Thema vor einiger Zeit recht intensiv 
befasst; der Empfang solcher Signale klappt gut mit dem RFM69, wenn man 
einige Gegebenheiten beachtet:
- Man muss "oversamplen", d. h. mit deutlich größerer Bitrate abtasten 
so dass die kürzesten Impulse mindestens 4 Bit lang sind. Ich verwende 
20 kbit/s.
- Die Bandbreite sollte relativ groß gewählt werden weil die 
Fernbedienungen in der Frequenz stark schwanken. Ich verwende 300 kHz.
- Der OOK Decoder muss passend parametriert werden. Ich verwende 
Threshtype peak, Threashstep 0,5 dB, und ThreashDec once every 8 chips

Ich empfange durchgehend und suche in den empfangenen Daten nach einer 
ausreichend langen Folge von 0en die den Syncpulse darstellen.

P. S. Das dargestellte Protokoll scheint zu den Logilight oder emylo 
Systemen zu gehören, also Bit0 = 1000, Bit1 = 1110. 24 Bit und ein 
Syncpulse ergeben ein ganzes Frame.

Schöne Grüße
Stefan

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.