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:

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:
1
#include <Arduino.h>
2
#include <SPI.h>
3
#include <RH_RF69.h>
4
5
#define RFM69_CS  14   // "E"
6
#define RFM69_RST 32   // "D"
7
#define RFM69_INT 33   // "B"
8
9
RH_RF69 rf69(RFM69_CS, RFM69_INT);
10
11
#define CONFIG_OOK (RH_RF69_DATAMODUL_DATAMODE_PACKET | RH_RF69_DATAMODUL_MODULATIONTYPE_OOK | RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE)
12
#define CONFIG_NOWHITE_NOCRC_FIXED (RH_RF69_PACKETCONFIG1_DCFREE_NONE | RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE)
13
14
const uint8_t kbps_msb_3_0_5_5 = 0x28; // 3.055 kbps
15
const uint8_t kbps_lsb_3_0_5_5 = 0xEB; // 3.055 kbps
16
const uint8_t bandwidth_1 = 0x88; // Rx Bandwidth = 1kHz.
17
18
const uint8_t dataON[] = {
19
  B10001000, B10001000, B10001000, B10001000, B10001000, B10001110, B10001000, B10001110, B10001110, B10001110, B10001000, B10001110, B10000000, B00000000, B00000000, B00000000,
20
  };
21
22
const uint8_t dataOFF[] = {
23
  B10001000, B10001000, B10001000, B10001000, B10001000, B10001110, B10001000, B10001110, B10001110, B10001110, B10001110, B10001000, B10000000, B00000000, B00000000, B00000000,
24
  };
25
26
void setup() 
27
{
28
  Serial.begin(115200);
29
  while (!Serial);
30
31
  pinMode(RFM69_RST, OUTPUT);
32
33
  // manual reset
34
  digitalWrite(RFM69_RST, HIGH);
35
  delay(10);
36
  digitalWrite(RFM69_RST, LOW);
37
  delay(10);
38
39
  if (!rf69.init())
40
    Serial.println("init failed");
41
42
  if (!rf69.setFrequency(433.85))
43
    Serial.println("setFrequency failed");
44
45
  rf69.setTxPower(20, true);
46
47
  RH_RF69::ModemConfig config = {
48
    CONFIG_OOK,                                           ///< Value for register RH_RF69_REG_02_DATAMODUL "ModulationType"
49
    kbps_msb_3_0_5_5,                                     ///< Value for register RH_RF69_REG_03_BITRATEMSB "Datarate" 20.0
50
    kbps_lsb_3_0_5_5,                                     ///< Value for register RH_RF69_REG_04_BITRATELSB not used, default value 0x0B
51
    0x00,                                                 ///< Value for register RH_RF69_REG_05_FDEVMSB "Deviation" not used, default value
52
    0x52,                                                 ///< Value for register RH_RF69_REG_06_FDEVLSB not used, default value
53
    bandwidth_1,                                          ///< Value for register RH_RF69_REG_19_RXBW "Bandwidth"
54
    0x8B,                                                 ///< Value for register RH_RF69_REG_1A_AFCBW "AfcBandwidth" default value
55
    CONFIG_NOWHITE_NOCRC_FIXED};                          ///< Value for register RH_RF69_REG_37_PACKETCONFIG1
56
57
  rf69.setModemRegisters(&config);
58
59
  // Disable preamble
60
  rf69.spiWrite(RH_RF69_REG_2C_PREAMBLEMSB, 0x00);
61
  rf69.spiWrite(RH_RF69_REG_2D_PREAMBLELSB, 0x00);
62
63
  // Disable sync words
64
  rf69.spiWrite(RH_RF69_REG_2E_SYNCCONFIG, B01000000);
65
66
  // Set payload length to our packet size
67
  rf69.spiWrite(RH_RF69_REG_38_PAYLOADLENGTH, 0);
68
}
69
70
void loop()
71
{
72
  rf69.sendRaw(dataON, sizeof(dataON));
73
  rf69.waitPacketSent();
74
}

Die SendRaw Funktion habe ich selber in die RadioHead Library eingebaut 
und sieht so aus:
1
bool RH_RF69::sendRaw(const uint8_t* data, uint8_t len)
2
{
3
    if (len > RH_RF69_MAX_MESSAGE_LEN)
4
  return false;
5
6
    waitPacketSent(); // Make sure we dont interrupt an outgoing message
7
    setModeIdle(); // Prevent RX while filling the fifo
8
9
    if (!waitCAD()) 
10
  return false;  // Check channel activity
11
12
    ATOMIC_BLOCK_START;
13
    digitalWrite(_slaveSelectPin, LOW);
14
    _spi.transfer(RH_RF69_REG_00_FIFO | RH_RF69_SPI_WRITE_MASK); // Send the start address with the write mask on
15
    // Now the payload
16
    while (len--)
17
  _spi.transfer(*data++);
18
    digitalWrite(_slaveSelectPin, HIGH);
19
    ATOMIC_BLOCK_END;
20
21
    setModeTx(); // Start the transmitter
22
    return true;
23
}

Für den Empfang verwende ich folgend Code im loop:
1
    setOpMode(RH_RF69_OPMODE_MODE_RX);
2
    uint8_t buf[sizeof(RH_RF69_MAX_MESSAGE_LEN)]; // RH_RF69_MAX_MESSAGE_LEN
3
    uint8_t len = sizeof(buf);
4
5
    uint8_t readLength = rf69.readFifoTest(buf, len);
6
    //Serial.print("got reply: ");
7
    for (int i = 0; i < readLength; i++) {
8
      if (buf[i] != 255)
9
        Serial.print(buf[i], BIN);
10
    }

Die readFifoTest methode habe ich wieder selber in die RadioHead Library 
eingebaut:
1
uint8_t RH_RF69::readFifoTest(uint8_t* buffer, uint8_t length) {
2
    uint8_t bufferLength = 0;
3
4
    while (length > 0) {
5
        uint8_t irqflags2 = spiRead(RH_RF69_REG_28_IRQFLAGS2);
6
7
        if (irqflags2 & RH_RF69_IRQFLAGS2_FIFONOTEMPTY)
8
        {
9
            digitalWrite(_slaveSelectPin, LOW);
10
11
            _spi.beginTransaction();
12
            _spi.transfer(RH_RF69_REG_00_FIFO); // Send the start address with the write mask off
13
14
            buffer[bufferLength] = _spi.transfer(0);
15
            bufferLength++;
16
            length -= 1;
17
18
            _spi.endTransaction();
19
            digitalWrite(_slaveSelectPin, HIGH);
20
        }
21
22
        YIELD;
23
    }
24
25
    return bufferLength;
26
}

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

von Christian S. (roehrenvorheizer)


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)


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)


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)


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
von David M. (thenetstriker)


Lesenswert?

Danke für die vielen Rückmeldungen. Den CRC check, Datawhitening und 
Machchester habe ich bereits deaktiviert. Daran kann es eigentlich nicht 
liegen. Ich habe nun noch die Bandbreite auf 255 khz erhöht (Scheint das 
maximum zu sein bei OOK) und habe die Threshold decay time auf once 
every 8 chips gestellt. Leider erhalte ich aber immer noch nicht die 
korrekten bytes. Ich habe auch versucht die Bitrate 4 mal höher 
einzustellen, aber leider gibt auch das keine brauchbaren Resultate. 
Hier sind meine aktuellen Registereinstellungen:
1
00 00
2
01 04
3
02 08
4
03 28
5
04 EB
6
05 00
7
06 52
8
07 6C
9
08 76
10
09 66
11
0A 41
12
0B 40
13
0C 02
14
0D 92
15
0E F5
16
0F 20
17
10 24
18
11 7F
19
12 09
20
13 1A
21
14 40
22
15 B0
23
16 7B
24
17 9B
25
18 08
26
19 81
27
1A 8B
28
1B 43
29
1C 80
30
1D 06
31
1E 10
32
1F 00
33
20 00
34
21 00
35
22 00
36
23 02
37
24 FF
38
25 00
39
26 05
40
27 80
41
28 00
42
29 FF
43
2A 00
44
2B 00
45
2C 00
46
2D 00
47
2E 40
48
2F 2D
49
30 D4
50
31 00
51
32 00
52
33 00
53
34 00
54
35 00
55
36 00
56
37 00
57
38 00
58
39 00
59
3A 00
60
3B 00
61
3C 8F
62
3D 02
63
3E 00
64
3F 00
65
40 00
66
41 00
67
42 00
68
43 00
69
44 00
70
45 00
71
46 00
72
47 00
73
48 00
74
49 00
75
4A 00
76
4B 00
77
4C 00
78
4D 00
79
4E 01
80
4F 00
81
58 1B
82
6F 30
83
71 00

Die Registereinstellungen können auf dieser Seite übersetzt und geändert 
werden: https://dimhoff.github.io/sx1231_calculator.html
Die Werte können einfach unten in das Textfeld eingegeben werden und 
dann importiert werden. Was könnte ich hier noch anpassen um den Empfang 
zu verbessern?

von Wolle G. (wolleg)


Lesenswert?

Christian S. schrieb:
> Leider fehlen Kommentare hinter den  Codezeilen, die anderen verdeutlichen
> können, was die einzelnen Zeilen bewirken sollen.
Sehe ich auch so. (für mich vorzugsweise auf deutsch)
Da ich gerade angefangen habe, mich mit RFM69 zu beschäftigen und zu 
programmieren, bin ich besonders scharf auf Beispiele. RFM69 soll mit µC 
MSP430Fxxxx angesteuert werden.
Vielleicht fällt auch noch für mich etwas ab, falls jemand ein 
funktionstüchtiges Beispiel übrig hat.

Beitrag #6330469 wurde von einem Moderator gelöscht.

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]
  • [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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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