mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RFM12B Modul - Senden/Empfangen funktioniert nicht


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.
Autor: Florian S. (kingeldarion)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag,

Ich bin aktuell an einem Punkt wo ich nicht weiterkomme und hoffe ihr 
könnt mir helfen.

Folgende Ausgangssituation: Ich möchte in Zukunft ein paar Projekte 
umsetzen in denen ich Daten über Funk senden möchte. Daher habe ich mich 
in den letzten Wochen damit auseinandergesetzt und habe mir vor ca einem 
Monat RFM12B Module gekauft 
(https://www.amazon.de/gp/product/B00BTCUMP6/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1). 
Genau genommen die 868 Mhz Version.
Dazu folgende Antenne, da die Module keine eigene haben, wenn ich das 
richtig festgestellt habe?! Vielleicht könnte mich jemand bei diesem 
Punkt noch bestätigen oder widerlegen? 
(https://www.amazon.de/gp/product/B07DLR2BN2/ref=ppx_yo_dt_b_asin_title_o02_s03?ie=UTF8&psc=1)

Als Mikrocontroller dient mir momentan ein Elegoo Uno R3 und ich 
programmiere zum testen aktuell mittels Arduino IDE.

Jetzt bin ich seit ca 2,5 Wochen daran die Module dazu zu bringen Daten 
zu übertragen. Ich habe beide aktuell an den selben Mikrocontroller 
angeschlossen und nutze keine Hardware SPI.

Angeschlossen habe ich sie wie hier 
(https://lowpowerlab.com/2012/12/28/rfm12b-arduino-library/) im zweiten 
Schema zu sehen, also die Version mit den 4.7k Widerständen. In meinem 
Fall benutze ich jedoch 5.1k da ich nichts näheres hier hatte. Die 10k 
Widerstände sind bei mir auch 10k.

Generell habe ich versucht so viele Beispiele zu finden wie ich konnte 
und habe mich bisher auch glaube ich ganz gut daran heranarbeiten 
können.
Jetzt bin ich jedoch seit einigen Tagen an einem Punkt angekommen an dem 
ich keine Fortschritte mehr mache.

Nach dem was ich als Feedback (IRQ und SDO) bekomme, denke ich auch dass 
ich soweit fast alles richtig gemacht habe.
Der Sender scheint im Sendemodus zu sein. IRQ geht auf low sobald ich 
die Nachricht geschickt habe auf senden zu schalten und bleibt dort.
Der Receiver hat IRQ durchgehend auf HIGH.

Nun versuche ich mittels 0xB8 Befehl Daten zu senden. Mit einigen 0xAA 
zu Beginn oder ohne. Dann das Synchronisationsbyte 0xD4, auch mit einem 
0x2D davor, wie ich es ab und zu gesehen habe, dann ein paar zufällige 
Bytes als Nachricht und dann mit oder ohne ein Dummy Byte 0x00.

Zum einen geht während dessen der IRQ vom sender niemals auf HIGH. Nach 
meiner Recherche sollte er auf HIGH gehen während er sendet und wieder 
auf LOW sobald er bereit ist neue Daten zu senden, richtig?

Der Receiver ist ebenfalls unberührt von der ganzen Sache. IRQ bleibt 
bei ihm HIGH und wenn ich einfach versuche Datena us dem FIFO zu lesen, 
kommt dann halt auch nur immer 0 bei rum.


Die Status words der beiden bringen mich auch nicht weiter. Hier meine 
Referenz 
(https://www.mikrocontroller.net/articles/RFM12#Status_lesen_.28Status_Read_0000.29).
Der Sender hat das Flag 15 RGIT gesetzt, sowie 13 RGUR. Was ja im 
Endeffekt bedeutet dass ich Daten nachschieben kann bzw. soll.
Zudem ist Flag 8 ATS gesetzt. Hier werde ich nicht schlau raus?! Klingt 
für mich aber eher positiv?

Beim Receiver siehts folgendermaßen aus:
Bit 9 FFEM, bedeutet FIFO Empty, also keine empfangen Daten?!
Bit 8 RSSI, beduetet die Signalstärke ist über dem eingstellten Limit.
Klingt ja grundsätzlich nicht so toll. Ich habe versucht bei der 
Initialisierung des Empfängers mit dem Code 9xxx zu spielen. Und mal auf 
0x90 85 gestellt. Hat aber nichts genützt. Generell kann ich hierzu auch 
leider keine weiteren Infos finden.
Bit 7 DQD, bedeutet data quality detector. Keine Ahnung ob das gut oder 
schlecht ist?
Bit 6 CRL, bedeutet clock recovery locked. Auch hier keine Ahnung ob das 
gut oder schlecht ist!?


Generell sollte noch gesagt sein: Ich bin leider kein Elektrotechniker 
oder ähnliches. Mein Wissen ist eine Mischung aus Physik in der 
Mittelstufe und Hobbymäßig mit Mikrocontrollern basteln. Also bitte 
lyncht mich nicht wenn ich möglicherweise ziemlich simple Dinge nicht 
verstehe oder übersehe.
Ich bin aber gerne bereit neues zu lernen, darum mach ich das ja!
Also falls möglich bitte immer lieber die Variante für Dummies ;)

Hier mein Code:
const int PIN_OUT_SS = 12;
const int PIN_OUT_MOSI = 10;
const int PIN_OUT_MISO = 9;
const int PIN_OUT_SCK = 11;
const int PIN_OUT_IRQ = 8;

const int PIN_IN_SS = 2;
const int PIN_IN_MOSI = 4;
const int PIN_IN_MISO = 5;
const int PIN_IN_SCK = 3;
const int PIN_IN_IRQ = 6;

int abc = 0;

void irqchange(){

  abc ++;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
  if(digitalRead(PIN_OUT_IRQ) == 1){

    Serial.write("OUTIRQ\n");
  }

  if(digitalRead(PIN_IN_IRQ) == 1) {

    Serial.write("INIRQ\n");
  }
  
  pinMode(PIN_OUT_SS, OUTPUT);
  pinMode(PIN_OUT_MOSI, OUTPUT);
  pinMode(PIN_OUT_MISO, INPUT);
  pinMode(PIN_OUT_SCK, OUTPUT);
  pinMode(PIN_OUT_IRQ, INPUT);

  pinMode(PIN_IN_SS, OUTPUT);
  pinMode(PIN_IN_MOSI, OUTPUT);
  pinMode(PIN_IN_MISO, INPUT);
  pinMode(PIN_IN_SCK, OUTPUT);
  pinMode(PIN_IN_IRQ, INPUT);
  
  //attachInterrupt(digitalPinToInterrupt(PIN_OUT_IRQ), irqchange, CHANGE);
  //attachInterrupt(digitalPinToInterrupt(PIN_IN_IRQ), irqchange, CHANGE);
  
  digitalWrite(PIN_OUT_SS, HIGH);
  digitalWrite(PIN_IN_SS, HIGH);

  delay(5000);

  SendByte(0, 0x00, 0x00);
  SendByte(1, 0x00, 0x00);
  
  Serial.write("Begin Init\n");

  //Initialization
  //Sender
  SendByte(0, 0x80, 0xE8); //Set 868Mhz
  SendByte(0, 0xA6, 0x40); //Use the standart 868 Mhz Band
  SendByte(0, 0xC6, 0x23); //Bitrate
  SendByte(0, 0x90, 0x80); //?
  SendByte(0, 0xC2, 0x2C); //Empfangsdatenrekonstruktion
  SendByte(0, 0xCA, 0x81); //FIFO Empfängersteuerung -> Fifo leeren und sperren
  SendByte(0, 0xCA, 0xF3); //FIFO freigeben | evtl F3 oder 83?
  SendByte(0, 0xCE, 0xD4); //Wert der als Synchronisations-Byte verwendet werden soll. (Frei nach Schnauze einstellbar?)
  SendByte(0, 0xC4, 0x00); //AFC => Ist wohl unbrauchbar, daher abschalten
  SendByte(0, 0x98, 0x00); //Senderkonfiguration -> Möglicherweise 0x50 testen (Library)
  SendByte(0, 0xCC, 0x77); //Taktgenerator einstellungen
  SendByte(0, 0xE0, 0x00); //Disable Wakeup stuff
  SendByte(0, 0xC8, 0x00); //Wakeup stuff -> disbaled
  SendByte(0, 0xC0, 0x00); //Unterspannungsdetektor und Taktungsteiler?

  SendByte(0, 0x82, 0x28); //Enable Sender
  delayMicroseconds(4);
  SendByte(0, 0x82, 0x38);

  Serial.write("Initialized Sender\n");
  Serial.write("Initializing Receiver\n");

  //Receiver
  SendByte(1, 0x80, 0xE8); //Set 868Mhz
  SendByte(1, 0xA6, 0x40); //Use the standart 868 Mhz Band
  SendByte(1, 0xC6, 0x23); //Bitrate
  SendByte(1, 0x90, 0x80); //?
  SendByte(1, 0xC2, 0x2C); //Empfangsdatenrekonstruktion
  SendByte(1, 0xCA, 0x81); //FIFO Empfängersteuerung -> Fifo leeren und sperren
  SendByte(1, 0xCA, 0xF3); //FIFO freigeben | evtl F3 oder 83?
  SendByte(1, 0xCE, 0xD4); //Wert der als Synchronisations-Byte verwendet werden soll. (Frei nach Schnauze einstellbar?)
  SendByte(1, 0xC4, 0x00); //AFC => Ist wohl unbrauchbar, daher abschalten
  SendByte(1, 0x98, 0x00); //Senderkonfiguration -> Möglicherweise 0x50 testen (Library)
  SendByte(1, 0xCC, 0x77); //Taktgenerator einstellungen
  SendByte(1, 0xE0, 0x00); //Disable Wakeup stuff
  SendByte(1, 0xC8, 0x00); //Wakeup stuff -> disbaled
  SendByte(1, 0xC0, 0x00); //Unterspannungsdetektor und Taktungsteiler?

  //SendByte(1, 0x82, 0x3D); //Enable Sender
  SendByte(1, 0x82, 0xDD); //Enable Receiver

  Serial.write("Finished Init\n");
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.write("\n\n\n");
  
  //Serial.print("Interrupts: ");
  //Serial.print(abc);
  //Serial.write("\n");
  
  if(digitalRead(PIN_OUT_IRQ) == 1){

    Serial.write("OUTIRQ\n");
  }
  
  if(digitalRead(PIN_IN_IRQ) == 1) {

    Serial.write("INIRQ\n");
  }
  
  Serial.write("Status Sender: ");
  SendByte(0, 0x00, 0x00);
  SendByte(0, 0x00, 0x00);
  SendByte(0, 0x00, 0x00);
  
  Serial.write("Sending: ");
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0x2D);
  SendByte(0, 0xB8, 0xD4);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0xAA);
  SendByte(0, 0xB8, 0x00);
  
  delay(1);
  /*
  Serial.write("Receiving: ");
  SendByte(1, 0xB0, 0x00);

  Serial.write("Status Receiver: ");
  SendByte(1, 0x00, 0x00);
  SendByte(1, 0x00, 0x00);
  SendByte(1, 0x00, 0x00);*/
}

unsigned short SendByte(int _id, byte _cmd, byte _val) {

  int PIN_SS;
  int PIN_MOSI;
  int PIN_SCK;
  int PIN_MISO;
  int PIN_IRQ;

  if (_id == 0) {

    PIN_SS = PIN_OUT_SS;
    PIN_MOSI = PIN_OUT_MOSI;
    PIN_SCK = PIN_OUT_SCK;
    PIN_MISO = PIN_OUT_MISO;
    PIN_IRQ = PIN_OUT_IRQ;
  }
  else {

    PIN_SS = PIN_IN_SS;
    PIN_MOSI = PIN_IN_MOSI;
    PIN_SCK = PIN_IN_SCK;
    PIN_MISO = PIN_IN_MISO;
    PIN_IRQ = PIN_IN_IRQ;
  }
  
  digitalWrite(PIN_SCK, LOW);
  
  unsigned short read = 0;
  unsigned short value = _cmd;
  value = (value << 8) | _val;

  //delay a bit, just to be sure
  delayMicroseconds(10);

  //Start a command
  digitalWrite(PIN_SS, LOW);
  delayMicroseconds(1);
  for (int i = 0; i < 16; i ++) {

    //Write the bit
    digitalWrite(PIN_MOSI, (value >> 15 - i) & 0x0001);

    delayMicroseconds(10);
    
    //Clock high -> Read!
    digitalWrite(PIN_SCK, HIGH);

    read = (read << 1) | digitalRead(PIN_MISO);

    delayMicroseconds(10);

    //Clock low -> Write next bit or end (SS low)
    digitalWrite(PIN_SCK, LOW);
  }
  delayMicroseconds(1);
  digitalWrite(PIN_SS, HIGH);
  delayMicroseconds(10);

  Serial.write("Read: ");
  Serial.print(read);
  Serial.write("\n");

  return read;
}

Folgenden Output kann ich im Serial beobachten:

Setup Funktion:
INIRQ
OUTIRQ (Nur wenn nicht von vorheriger Session initialisiert)
Read: 41216
Read: 832
Begin Init
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Read: 65535
Initialized Sender
Initializing Receiver
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Read: 0
Finished Init


Bei allen loops kommt folgender output:
INIRQ
Status Sender: Read: 41216
Read: 41216
Read: 41216
Sending: Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Read: 65534
Receiving: Read: 0
Status Receiver: Read: 960
Read: 960
Read: 960


Ich hoffe ich habe keine Information ausgelassen. Falls doch, versuche 
ich schnellstmöglich nachzuliefern.

Mit freundlichen Grüßen
Florian

: Verschoben durch Moderator
Autor: Florian S. (kingeldarion)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Niemand der mir helfen kann?

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
falsches Unterforum.

Autor: John B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs doch mal mit Jeelib

https://jeelabs.net/projects/jeelib/wiki

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florian S. schrieb:

> Dazu folgende Antenne, da die Module keine eigene haben, wenn ich das
> richtig festgestellt habe?! Vielleicht könnte mich jemand bei diesem
> Punkt noch bestätigen oder widerlegen?

Kann ich einerseits bestätigen (die Module haben keine eigene Antenne), 
andererseits: man braucht auch echt keine kaufen. Ein paar Zentimeter 
stinknormaler Schaltdraht sind Antenne genug. Damit kann man Reichweiten 
von 100m und mehr erzielen...

> Als Mikrocontroller dient mir momentan ein Elegoo Uno R3 und ich
> programmiere zum testen aktuell mittels Arduino IDE.

Das ist der primäre Fehler.

> Jetzt bin ich seit ca 2,5 Wochen daran die Module dazu zu bringen Daten
> zu übertragen.

Du hättest die Zeit besser genutzt, indem du erstmal eine zuverlässige 
Kommunikation zwischen µC und RFM etabliert hättest.

> Nach dem was ich als Feedback (IRQ und SDO) bekomme, denke ich auch dass
> ich soweit fast alles richtig gemacht habe.

Nö, mit an Sicherheit grenzender Wahrscheinlichkeit nicht.

> Zum einen geht während dessen der IRQ vom sender niemals auf HIGH.

OMG. Einmal, wirklich nur einmal: DB lesen hätte dir diese Peinlichkeit 
von Aussage erspart...

Um dir das mal in einfachen Worten klarzumachen: der IRQ der RFM ist 
erstens Low-aktiv und zweitens ein "Level-IRQ". D.h.: dein RFM ist 
dauerhaft unzufrieden mit seiner Ansteuerung. Du hast auf irgendeine 
IRQ-Anforderung (der RFM hat MEHRERE, aber nur einen IRQ-Ausgang) 
nicht korrekt reagiert. Deswegen geht der Pegel niemals wieder auf High 
(also in den INAKTIVEN Zustand). Und deswegen kannst du auf weitere 
Änderungen seines Zustands garnicht mehr reagieren, weil er schon nicht 
mehr in der Lage ist, sie dir überhaupt zu signalisieren, denn sein 
Interrupt-Ausgang ist ja schon lange LOW also AKTIV, bloß du 
Dumpfbacke hast das bisher nicht korrekt behandelt...

Fazit: Typischer Arduidiot, der niemals ein Datenblatt auch nur zum 
Arschabwischen benutzt, geschweige denn, dass er es lesen würde...

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

c-hater schrieb:
> azit: Typischer Arduidiot, der niemals ein Datenblatt auch nur zum
> Arschabwischen benutzt, geschweige denn, dass er es lesen würde...

ein typischer Trottel, der unbedingt schlau sein will und sich mal 
wieder nicht benehmen kann oder was???

Man kann den RFM12 problemlos komplett ohne Interrupt per Polling 
bedienen.
Bitbanging ist für die Ansteuerung auch durchaus sinnvoll, ich weiß zwar 
nicht, ob die aktuellen RFM12B sich besser benehmen, die alten 
RFM01/02/12 machten damals mit Hardware-SPI gern seltsame Probleme.

Ich habe aus alten Zeiten nur noch eine Empangsroutine rumliegen, die 
ich mal in die ArduinoIDE getragen hatte:
Die RFM12.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "global.h"
#include "RFM12.h"

void RFM12_send_cmd(unsigned int command)
  {
  unsigned char i;
  RFM12_PORT &= ~(1<<RFM12_CS);        // CS auf L

  for (i=0; i<16; i++)
    {
      if (command & 0x8000)
        {
          RFM12_PORT |= (1<<RFM12_SDI);    // DATA auf H
        }
      else
        {
          RFM12_PORT &= ~(1<<RFM12_SDI);    // DATA auf L
        }
      asm("nop");
        RFM12_PORT |= (1<<RFM12_SCK);      // CLK auf H
      asm("nop");
      asm("nop");
        RFM12_PORT &= ~(1<<RFM12_SCK);      // CLK auf L
      command = (command << 1);        // nächstes Bit nach oben
    }
  RFM12_PORT |= (1<<RFM12_CS);          // CS auf H
  }

void RFM12_init(void)
  {
    RFM12_PORT = (1<<RFM12_CS);          // PullUp ein / Ausgang H  
    RFM12_DDR  = (1<<RFM12_SDI) | (1<<RFM12_SCK) | (1<<RFM12_CS);  // Ausgänge

    RFM12_send_cmd(0x0000);            // Status read

    RFM12_send_cmd(0xC080);            // CLK-Frequenz / Batterie-Level

    RFM12_send_cmd(0x80D7);            // FIFO ein, C = 11,5pF

    RFM12_send_cmd(0xC2AB);            // Thresold, Filter

    RFM12_send_cmd(0xCA81);            // FIFO-Level, 

    RFM12_send_cmd(0xE000);            // WakeUp aus 

    RFM12_send_cmd(0xC800);            // Low Duty Cycle aus, 

    RFM12_send_cmd(0xC4F3);            // AFC

    RFM12_send_cmd(0xA620);            // Frequenz

    RFM12_send_cmd(0x948C);            // Bandbreite

    RFM12_send_cmd(0xC610);            // Baudrate 19200
  }

void RFM12_read_fifo(char *data_buf, char len)
  {

    unsigned char byte = 0, i, j;

    RFM12_send_cmd(0x82C8);            // Empfänger ein

    RFM12_send_cmd(0xCA81);            // set FIFO mode

    RFM12_send_cmd(0xCA83);            // enable FIFO

      RFM12_PORT &= ~(1<<RFM12_SCK);        // CLK auf L
      RFM12_PORT &= ~(1<<RFM12_SDI);        // DATA auf L

    for (i=0; i<len; i++)
      {
        RFM12_PORT &= ~(1<<RFM12_CS);      // CS auf L
        asm("nop");
        asm("nop");
      while (!(RFM12_PIN & (1<<RFM12_SDO)))  // warten bis SDO 1 -> FFIL 
        {
        }
                
      byte = 0xB0;              // Receive FIFO

      for (j=0; j<8; j++)
        { 
        if (byte & 0x80)
            {
            RFM12_PORT |= (1<<RFM12_SDI);  // DATA auf H
            }
        else
            {
            RFM12_PORT &= ~(1<<RFM12_SDI);  // DATA auf L
            }
        asm("nop");
        asm("nop");
        asm("nop");
          RFM12_PORT |= (1<<RFM12_SCK);    // CLK auf H
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
          RFM12_PORT &= ~(1<<RFM12_SCK);    // CLK auf L
        byte = (byte << 1);          // nächstes Bit nach oben
        }

      byte = 0;

      for (j=0; j<8; j++)
        {     
        byte = (byte << 1);          // eins höher schieben
        if ((RFM12_PIN & (1<<RFM12_SDO)) == (1<<RFM12_SDO))  // Bit 1?
            {
            byte = (byte | 0x01);        // ja
            }
        asm("nop");
          RFM12_PORT |= (1<<RFM12_SCK);    // CLK auf H
        asm("nop");
        asm("nop");
          RFM12_PORT &= ~(1<<RFM12_SCK);    // CLK auf L
        }
      *data_buf++ = byte;
      RFM12_PORT |= (1<<RFM12_CS);      // CS auf H
    }

    RFM12_send_cmd(0x8208);            // Empfänger aus

  }

//------------------------------------------------------------------

uint16_t RFM12_read_status(void)
{
  uint16_t statusword = 0;
  unsigned char i = 0;

  RFM12_PORT &= ~(1<<RFM12_SCK);                 // CLK auf L
  RFM12_PORT &= ~(1<<RFM12_SDI);                 // DATA auf L

  RFM12_PORT &= ~(1<<RFM12_CS);                  // CS auf L

  for (i = 0; i < 16; i++)
  {
    statusword = (statusword << 1);             // eins höher schieben
    if ((RFM12_PIN & (1<<RFM12_SDO)) == (1<<RFM12_SDO))            // Bit 1?
    {
      statusword = (statusword | 0x0001);       // ja
    }
    asm("nop");
    RFM12_PORT |= (1<<RFM12_SCK);   // CLK auf H
    asm("nop");
    asm("nop");
    RFM12_PORT &= ~(1<<RFM12_SCK);    // CLK auf L
  }
  RFM12_PORT |= (1<<RFM12_CS);      // CS auf H

  return statusword;
}
und RFM12.h dazu:
#ifdef __cplusplus
extern "C" {
#endif

#define  RFM12_PORT  PORTB
#define  RFM12_DDR  DDRB
#define  RFM12_PIN  PINB

#define RFM12_CS   PB2
#define  RFM12_SDI   PB3
#define RFM12_SDO  PB4
#define  RFM12_SCK   PB5

#define  RFM12_IRQ_PIN  PIND
#define  RFM12_IRQ_IN  PD2

// nFFS: 1-10k Pullup an Vcc !!!

void RFM12_send_cmd(unsigned int command);
void RFM12_init(void);
void RFM12_read_fifo(char *data_buf, char len);
uint16_t RFM12_read_status(void);

#ifdef __cplusplus
} // extern "C"
#endif

keine Ahnung, ob das weiterhilft, ist alles Jahre her und läuft hier so 
immernoch...

Gruß aus Berlin
Michael

: Bearbeitet durch User
Autor: c-hater (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Michael U. schrieb:

> Man kann den RFM12 problemlos komplett ohne Interrupt per Polling
> bedienen.

Das kann man tatsächlich.

Nur hat es der TO halt nicht getan, wie jeder Nichtvollidiot anhand des 
OT sofort spielend leicht erkennen kann. Du hast es wohl nicht erkannt 
und bist damit vollkommen am Thema vorbei...

Das war nicht: wie mache ich das mit dümmlichen und 
resourcenverschwendendem Polling, sondern clever per Interrupt. Nunja: 
die Antwort ist (wie immer): mach' es einfach richtig. Und um es richtig 
machen zu können, muss man nunmal einfach wissen, wie sich das Teil 
verhält, was man da benutzen möchte, und dazu ist nunmal eine Lektüre 
des DB unverzichtbar, capisce?

Autor: Christian S. (roehrenvorheizer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

die speziellen Eigenheiten des RFM12 sind mir momentan nicht mehr 
gegenwärtig. Vor Jahren habe ich mal eines dieser Beispiele 
durchexerziert und konnte damit Daten übertragen, wenn auch immer mal 
wieder etwas klemmte nach längerem Testen. Aber grundsätzlich 
funktioniert es. Sogar eine Fehlerkorrektur ist dabei. Wenn Du alles 
liest, findest Du eine ausgereifte Version und kannst dort den Ablauf 
abschauen.

Bei meinem Aufbau habe ich ebenfalls den AVR auf 5 V laufen und das 
RFM12 über 2,2 kOhm an SPI angeschlossen. Ging bei mir auch ohne die 10k 
sehr gut.

Beitrag "bidirektionale RS232 Funkbrücke mit RFM12"

mfG

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

c-hater schrieb:
> Nur hat es der TO halt nicht getan, wie jeder Nichtvollidiot anhand des
> OT sofort spielend leicht erkennen kann. Du hast es wohl nicht erkannt
> und bist damit vollkommen am Thema vorbei...

ok. Dann fange ich mal an: ich würde nicht freiwillg versuchen, 2 
RFM-Module als Empfänger/Sender an einen AVR zu packen, schon garnicht 
im Interrupt, wenn ich nicht genau weiß, was ich da mache.
Das weiß der TO wohl nicht, da stimme ich Dir zu.
Es ist 10 jahre her, daß ich mit mit den Teilen befasst habe, da waren 
die Unterlagen von HopeRF mehr als fragwürdig und die Verwandtschaft zu 
den SiLabs Si4xxx hatte sich noch nicht rumgesprochen.
Das Zeug läuft huer heute noch, es macht aber vermutlich wenig Sinn, ihm 
die alten AVR-ASM-Sourcen vorzuwerfen.

Christian S. schrieb:
> Bei meinem Aufbau habe ich ebenfalls den AVR auf 5 V laufen und das
> RFM12 über 2,2 kOhm an SPI angeschlossen. Ging bei mir auch ohne die 10k
> sehr gut.

Die alten waren bis 5V, die neueren B-Typen nur noch 3,6V max.
Bei den alten brauchte man garnichts zum 5V AVR.

Gruß aus Berlin
Michael

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael U. schrieb:

> ok. Dann fange ich mal an: ich würde nicht freiwillg versuchen, 2
> RFM-Module als Empfänger/Sender an einen AVR zu packen

Warum nicht? SPI ist ein Bus. Der funktioniert mit einem RFM12 genauso 
wie mit zweien. Natürlich braucht man (bei Interruptsteuerung) zwei Pins 
mehr für zwei. Einen SlaveSelect und einen IRQ. Ansonsten gibt es keinen 
Unterschied, ob man nun nur einen oder zwei verwendet. Entweder man 
weiss, was man tut, oder man weiss es halt nicht. Dagegen hilft nur 
eins: LERNEN. Und das fängt an mit der Lektüre des DB.

> Das weiß der TO wohl nicht, da stimme ich Dir zu.

Das ist sehr offensichtlich so. Genau das war meine Kritik.

Autor: Florian S. (kingeldarion)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke für die Antworten. Ich habe es gerade eben endlich geschafft. Das 
Modul funktioniert wie ich es möchte, es werden alle bytes übertragen.

Am Ende war es dann vor allem dieser Beitrag 
(https://gobotronics.wordpress.com/2010/10/07/rfm12-programming/) der 
mir geholfen hat meine restlichen Fehler zu entdecken.

Problem war hauptsächlich das ich nicht verstanden hatte, dass ich den 
Transmitter für jedes Packet neu an und ausschalten musste.

Außerdem hat mir tatsächlich geholfen beide Module über einen seperaten 
Mikrocontroller anzusteuern.

Hier jetzt einmal mein Code mit dem ich erfolgreich war:
Sender:
const int PIN_SS = 12;
const int PIN_MOSI = 10;
const int PIN_MISO = 9;
const int PIN_SCK = 11;
const int PIN_IRQ = 8;

void irqchange(){

  Serial.write("IRQ: ");
  Serial.print(digitalRead(PIN_IRQ));
  Serial.write("\n");
}

void setup(){

  Serial.begin(9600);
  irqchange();
  attachInterrupt(digitalPinToInterrupt(PIN_IRQ), irqchange, CHANGE);
  
  pinMode(PIN_SS, OUTPUT);
  pinMode(PIN_MOSI, OUTPUT);
  pinMode(PIN_MISO, INPUT);
  pinMode(PIN_SCK, OUTPUT);
  pinMode(PIN_IRQ, INPUT);

  digitalWrite(PIN_SS, HIGH);

  delay(2000);
  PrintStatus();
  Serial.write("Begin Init\n");
  irqchange();
  //Sender
  SendByte(0x80, 0xE8); //Set 868Mhz
  PrintStatus();
  SendByte(0x82, 0x01); //Sleep Mode
  PrintStatus();
  SendByte(0xA6, 0x40); //Use the standart 868 Mhz Band
  PrintStatus();
  SendByte(0xC6, 0x23); //Bitrate
  PrintStatus();
  SendByte(0x90, 0x80); //?
  PrintStatus();
  SendByte(0xC2, 0x2C); //Empfangsdatenrekonstruktion
  PrintStatus();
  SendByte(0xCA, 0x81); //FIFO Empfängersteuerung -> Fifo leeren und sperren
  PrintStatus();
  SendByte(0xCA, 0xF3); //FIFO freigeben | evtl F3 oder 83?
  PrintStatus();
  SendByte(0xCE, 0xD4); //Wert der als Synchronisations-Byte verwendet werden soll. (Frei nach Schnauze einstellbar?)
  PrintStatus();
  SendByte(0xC4, 0x00); //AFC => Ist wohl unbrauchbar, daher abschalten
  PrintStatus();
  SendByte(0x98, 0x00); //Senderkonfiguration -> Möglicherweise 0x50 testen (Library)
  PrintStatus();
  SendByte(0xCC, 0x77); //Taktgenerator einstellungen
  PrintStatus();
  SendByte(0xE0, 0x00); //Disable Wakeup stuff
  PrintStatus();
  SendByte(0xC8, 0x00); //Wakeup stuff -> disbaled
  PrintStatus();
  SendByte(0xC0, 0x00); //Unterspannungsdetektor und Taktungsteiler?

  PrintStatus();
}

void SendMessage(){

  Serial.write("\n\nWrite Message:\n");
  
  SendByte(0xB8, 0xAA); //Fill FIFO with Preambel
  SendByte(0xB8, 0xAA); //Fill FIFO with Preambel

  PrintStatus(); //Status should be 0 now
  
  irqchange(); //IRQ should be 1 now

  int currentStep = 0;
  SendByte(0x82, 0x39); //Enter Transfer Mode
  //irqchange();
  //PrintStatus();

  while(currentStep < 12){

    if(digitalRead(PIN_IRQ) == 0){
      
      switch(currentStep){

        case 0:
          SendByte(0xB8, 0xAA);
          break;
        
        case 1:
          SendByte(0xB8, 0x2D);
          break;

        case 2:
          SendByte(0xB8, 0xD4);
          break;

        case 3:
          SendByte(0xB8, 0x1B);
          break;

        case 4:
          SendByte(0xB8, 0x12);
          break;

        case 5:
          SendByte(0xB8, 0x89);
          break;

        case 6:
          SendByte(0xB8, 0x4E);
          break;

        case 7:
          SendByte(0xB8, 0x4E);
          break;

        case 8:
          SendByte(0xB8, 0x4E);
          break;

        case 9:
          SendByte(0xB8, 0x00);
          break;

        case 10:
          SendByte(0xB8, 0x00);
          break;

        case 11:
          SendByte(0x82, 0x09);
          Serial.write("Aus\n");
          break;
      }

      currentStep ++;
      //PrintStatus();
    }
  }

  PrintStatus();
  irqchange();
}

void loop(){

  SendMessage();

  delay(1000);
}

void PrintStatus(){

  Serial.write("Status: ");
  Serial.print(SendByte(0x00, 0x00));
  Serial.write("\n");
}

unsigned short SendByte(byte _cmd, byte _val) {
  
  digitalWrite(PIN_SCK, LOW);
  
  unsigned short read = 0;
  unsigned short value = _cmd;
  value = (value << 8) | _val;

  //delay a bit, just to be sure

  //Start a command
  digitalWrite(PIN_SS, LOW);
  //delayMicroseconds(1);
  for (int i = 0; i < 16; i ++) {

    //Write the bit
    digitalWrite(PIN_MOSI, (value >> 15 - i) & 0x0001);

    //delayMicroseconds(1);
    
    //Clock high -> Read!
    digitalWrite(PIN_SCK, HIGH);

    read = (read << 1) | digitalRead(PIN_MISO);

    //delayMicroseconds(1);

    //Clock low -> Write next bit or end (SS low)
    digitalWrite(PIN_SCK, LOW);
  }
  //delayMicroseconds(1);
  digitalWrite(PIN_SS, HIGH);

  /*Serial.write("Read: ");
  Serial.print(read);
  Serial.write("\n");*/

  return read;
}


Empfänger
const int PIN_SS = 2;
const int PIN_MOSI = 4;
const int PIN_MISO = 5;
const int PIN_SCK = 3;
const int PIN_IRQ = 6;

void setup(){

  Serial.begin(9600);

  digitalWrite(PIN_SS, HIGH);

  delay(2000);
  PrintStatus();
  Serial.write("Begin Init\n");
  irqchange();
  pinMode(PIN_SS, OUTPUT);
  pinMode(PIN_MOSI, OUTPUT);
  pinMode(PIN_MISO, INPUT);
  pinMode(PIN_SCK, OUTPUT);
  pinMode(PIN_IRQ, INPUT);
  
  //Receiver
  SendByte(0x80, 0xE8); //Set 868Mhz
  SendByte(0x82, 0x01); //Sleep Mode
  SendByte(0xA6, 0x40); //Use the standart 868 Mhz Band
  SendByte(0xC6, 0x23); //Bitrate
  SendByte(0x90, 0x85); //?
  SendByte(0xC2, 0x2C); //Empfangsdatenrekonstruktion
  SendByte(0xCA, 0x81); //FIFO Empfängersteuerung -> Fifo leeren und sperren
  SendByte(0xCA, 0x83); //FIFO freigeben | nicht F3! Löst interrupt erst bei 2 vollen byte aus!
  SendByte(0xCE, 0xD4); //Wert der als Synchronisations-Byte verwendet werden soll. (Frei nach Schnauze einstellbar?)
  SendByte(0xC4, 0x00); //AFC => Ist wohl unbrauchbar, daher abschalten
  SendByte(0x98, 0x00); //Senderkonfiguration -> Möglicherweise 0x50 testen (Library)
  SendByte(0xCC, 0x77); //Taktgenerator einstellungen
  SendByte(0xE0, 0x00); //Disable Wakeup stuff
  SendByte(0xC8, 0x00); //Wakeup stuff -> disbaled
  SendByte(0xC0, 0x00); //Unterspannungsdetektor und Taktungsteiler?

  PrintStatus();
  irqchange();
  
  int i = 0;
  unsigned int* rec = new int[32];
  
  //SendByte(0xCA, 0x83);
  //SendByte(0xCA, 0x81);
  SendByte(0xCA, 0x81);
  SendByte(0xCA, 0x83); //Definitiv nicht F3  -> löst interrupt erst bei 2 vollen byte
  SendByte(0x82, 0xD9);
  
  //PrintStatus();

  //Serial.write("Starting read:\n");
  while(i < 6){

    if(digitalRead(PIN_IRQ) == 0){
      
      /*int rec = SendByte(0xB0, 0x00);

      if(rec == 0){

        Serial.print(rec);
        Serial.write("\n");
      }
      else{

        PrintStatus();
      }*/
      
      rec[i] = SendByte(0xB0, 0x00);
      i ++;
    }

    //Serial.write("A\n");
  }

  PrintStatus();
  
  for(int i = 0; i < 6; i ++){

    Serial.println(rec[i]);
  }
}

void loop(){

  
  Serial.write("Hallo\n");
  digitalWrite(7, HIGH);
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
}

void irqchange(){

  Serial.write("IRQ: ");
  Serial.print(digitalRead(PIN_IRQ));
  Serial.write("\n");
}

void PrintStatus(){

  Serial.write("Status: ");
  Serial.print(SendByte(0x00, 0x00));
  Serial.write("\n");
}

unsigned short SendByte(byte _cmd, byte _val) {
  
  digitalWrite(PIN_SCK, LOW);
  
  unsigned short read = 0;
  unsigned short value = _cmd;
  value = (value << 8) | _val;

  //delay a bit, just to be sure
  delayMilliseconds();

  //Start a command
  digitalWrite(PIN_SS, LOW);
  //delayMilliseconds();
  for (int i = 0; i < 16; i ++) {

    //Write the bit
    digitalWrite(PIN_MOSI, (value >> 15 - i) & 0x0001);

    //delayMilliseconds();
    
    //Clock high -> Read!
    digitalWrite(PIN_SCK, HIGH);

    read = (read << 1) | digitalRead(PIN_MISO);

    //delayMilliseconds();

    //Clock low -> Write next bit or end (SS low)
    digitalWrite(PIN_SCK, LOW);
  }
  //delayMilliseconds();
  digitalWrite(PIN_SS, HIGH);
  //delayMilliseconds();

  /*Serial.write("Read: ");
  Serial.print(read);
  Serial.write("\n");*/

  return read;
}

void delayMilliseconds(){

  
}

Dann würde ich gerne noch was zu Herrn c-hater sagen:

Zum einen verstehe ich diese Abneigung gegenüber Arduino nicht. Klar ist 
das nicht das gleiche wie wenn man mit C oder Assembler programmiert und 
sehr stark vereinfacht. Aber genau dass ist ja das schöne jeder kann 
damit was machen, egal wie sehr er sich mit der Materie auskennt.

Wie ich auch geschrieben habe, benutze ich Arduino auch nur zum testen. 
Wenn ich dann final die Projekte umsetze entwickle ich meistens in C, 
bei kleinen Projekten spaßeshalber mit Assembler.

Das schöne an Arduino ist einfach dass man mit wenig Aufwand viel 
erreichen kann. Und vor allem zum testen und ausprobieren möchte ich 
nicht viel Aufwand betreiben.
Allein das ich mit einer Zeile meine Serial Monitor ansprechen kann und 
Text übertragen kann, ist hier schon große Hilfe.

Wer Arduino nicht mag schön und gut, aber bitte urteile nicht über 
andere die eine andere Meinung hierzu haben.

Zum Thema Datenblatt lesen. Wie ich bereits geschrieben hatte, bin ich 
halt kein Elektrotechniker oder ähnliches. Ich HABE die Datenblätter 
gelesen und dies nicht nur einmal, wie gesagt, habe ich jetzt fast einen 
Monat gebraucht um die Module zum laufen zu bekommen und ich habe fast 
20 Lesezeichen zum Thema im Firefox abgelegt.
Als "Laie" ist es für mich halt nicht immer so einfach alles zu 
verstehen und es ist oft viel kompakte Info die in den Datenblättern 
steht, ohne viel Kontextwissen.
Also wenn du aus dem Datenblatt direkt alles verstehst und es umsetzen 
kannst, freut mich das für dich. Aber ich kann es nicht.

Ich habe diesen Forenbeitrag auch nur eröffnet, weil ich eine Woche lang 
nicht mehr weitergekommen bin, OBWOHL ich weiter recherchiert habe und 
keine neuen Informationen entdeckt habe.

Und am Ende waren es jetzt keine großen Veränderungen mehr, also hatte 
ich es tatsächlich geschafft einiges richtig zu machen, ohne Hilfe von 
anderen sondern nur mittels Lektüre. Also sei ein wenig konstruktiver 
und stelle andere nicht in Frage sondern versuche ihnen zu helfen auf 
die richtige Spur zu kommen. Es haben halt nicht alle den gleichen 
Wissensstand wie du.

So wie in deinem erstem Beitrag der Part mit den einfachen Worten. Der 
hat mir tatsächlich geholfen. Ein wenig netter formuliert und ich wäre 
dir wirklich dankbar dafür gewesen.

Mit freundlichen Grüßen
Florian

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.