Go Down

Topic: RFM12B Arduino (Read 6420 times) previous topic - next topic


Schachmann

Hallo,

der Anschlussplan in Deinem zweiten Link scheint mir für ein 3,3 V-Modul schon plausibel zu sein. Im ersten Plan hast Du ja keine Verbindung zum SPI-Port und keine Anpassung an 3,3 V.

Gruß,
Ralf

Snoops

Hallo,

zur Verschaltung steht hier was:
http://openenergymonitor.org/emon/buildingblocks/rfm12b-wireless

Und als Library kann man bspw. folgende nehmen:
http://jeelabs.net/pub/docs/jeelib/index.html

Gruß
Snoops

emilio20

Hallo
ok gibt es ein fertiges bord mit den Wiederstanden ? Möchte ungerne die schaltung so aufbauen.

erni-berni

Hallo emilio,
das RFM12B ist eigentlich nicht für OOK (On-Off-Keying), also eine An/Aus Trägermodulation gedacht, sondern für FSK (Frequenz-Shift-Keying).  Für das Senden/Empfamgen von OOK Codes ist in der Jeelabs Lib ein Beispiel ->   RFM12B_OOK. In diesem Beispiel wird auch ein Link auf ein Projekt angegeben. http://jeelabs.net/projects/cafe/wiki/Receiving_OOKASK_with_a_modified_RFM12B
Mit den Initialisierungsparameter aus dem Link habe ich das allerdings nicht geschafft, das ans laufen zu bekommen. Mit hat dieser Link sehr geholfen http://www.mikrocontroller.net/topic/161885#1761752. Die Initialisierungsequenz sieht bei mir so aus:
Code: [Select]
  rf12_control(0x8017); // 8027    Configuration Settings: 433 Mhz; !TX; !RX FIFO; 12pF
  rf12_control(0x82D8); // 82C0    Power Management: enable receiver; enable basebandblock; enable synth; en cryst osc
  rf12_control(0xA608); // A68A    Frequency Setting: Fc =430+ F x0.0025MHz; F = 1544; 433,86 MHz
  rf12_control(0xC623); // C691    Data Rate: 9579 kbps 
  rf12_control(0x94c2); // 9489    Receiver Control: LNA Gain max; Pin VDI; RX BW 67kHz; VDI fast; DRSSI -91 db
  rf12_control(0xC220); // C220    Data Filter & Clock Recovery:  ** not documented cmd
  rf12_control(0xCA00); // CA00    FIFO and Reset Mode: FIFO full disabled
  rf12_control(0xC431); // C473    Automatic Frequency Control: AFC Auto OFF; enable AFC; offset register; +3 -4
  rf12_control(0xCC67); // CC67    PLL Settings: Clock rise low; PLL Band 256 kbps; !Dither;

Der RFM12B hat für 433MHz auf jeden Fall eine höhere Empfindlichkeit und damit eine höhere Reichweite. Für Senden oder Empfangen aus einigen Metern Sichtweite würde ich aber weiterhin die billigen 433MHz Module empfehlen.

Gruß
Reinhard

emilio20

#5
Mar 15, 2014, 06:23 pm Last Edit: Mar 15, 2014, 06:26 pm by emilio20 Reason: 1
Hallo
vielen Dank erst mal.

Ich möchte im ersten Schritt meine Funksteckdosen schalten und im zweiten Schritt Daten einer z,B Wetterstation auswerten.

Für mich wäre erst mal wichtig wie ich das Modul verdrahten, so wie im oberen Beitrag oder ?

Hir zu  benötige ich erst mal die Wiederstande.


emilio20


erni-berni

Hallo,

Nathan Chantrell gibt ja auf seiner Seite eine Empfehlung http://nathan.chantrell.net/tinytx-wireless-sensor/
Quote
If you want to get PCBs made up I can recommend the Chinese site SeeedStudio, for 10 boards in green (other colours are more expensive) it costs 9.90 USD + shipping

Wir könnten uns zusammen tun, ich würde 5 Boards nehmen. PN, wenn du Interesse hast. Die Lieferung von Seeedstudio dauert aber min. 4 Wochen.

Gruß
Reinhard

Spexx

Die Platinen sind aber für einen ATtiny, willst du den denn benutzen? Dann brauchst du zumindest noch einen ISP-Programmer. Die Platinen haben auch keinen Anschluss für den Programmer, Nathan hat dafür einen "Testclip" verwendet, wie auf seiner Seite beschrieben. Die RFM12B-Module vertragen keine 5V, daher benötigst du die Widerstände für den Spannungsteiler.

Wenn du keine größere Stückzahl von den Platinen brauchst, könntest du auch 1-2 von mir haben. Ich persönlich würde aber lieber ein Board mit Atmega328 bevorzugen, welches dann wie ein UNO angesprochen werden kann. Also zum Beispiel ein Jeenode (http://www.digitalsmarties.net/products/jeenode) oder wenn du es kleiner haben möchtest, ein Moteino von LowPowerLabs http://lowpowerlab.com/moteino/ (mein Favorit :)).

Das Beispiel aus der Jeelib Library mit dem OOK-Modus hat bei mir nicht funktioniert, habe mich aber auch nicht intensiv damit beschäftigt.

erni-berni

#9
Mar 17, 2014, 06:05 pm Last Edit: Mar 17, 2014, 06:16 pm by erni-berni Reason: 1
Quote
Die Platinen sind aber für einen ATtiny, willst du den denn benutzen?

Ich schon. Die Platinen wären aber auch als Breakout zu benutzen, wenn man statt des ATTiny eine Steckleiste einsetzt. Platz für die Spannungsteiler wäre sicher auch noch auf dem Lochrasterfeld.
Quote
Das Beispiel aus der Jeelib Library mit dem OOK-Modus hat bei mir nicht funktioniert, habe mich aber auch nicht intensiv damit beschäftigt.

Ich habe das für dieses Projekt genutzt http://forum.arduino.cc/index.php?topic=136836.msg1536416#msg1536416 Empfang von Wetterdaten von einem Conrad KW9010 Sensor. Ich habe den Sketch aus dem Post entsprechend für RFM12B OOK angepasst.
Bei Interesse kann ich den Sketch posten.

Spexx

Es gibt von JeeLabs auch Breakout-Platinen für das RFM12B-Modul, siehe http://jeelabs.net/projects/hardware/wiki/RFM12B_Board
Hatte mir vor einiger Zeit mal welche mitbestellt aber nie benötigt, also falls jemand daran Interesse hätte...
https://www.dropbox.com/s/thqnt81wcd13ybj/RFM12B-Breakout.jpg

@erni-berni
Du hast den OOK-Modus aber nur zum Empfang genutzt, oder hast du auch gesendet? Hatte versucht, eine Funksteckdose einzuschalten, hatte aber einfach nicht darauf reagiert. Bin ja noch auf der Suche nach einer Funksteckdose, die mir auch eine Rückmeldung gibt ob sie an ist oder nicht bzw. suche eine Lösung, direkt ein RFM-Modul einzubauen :)

JoWiemann

Quote
Ich habe das für dieses Projekt genutzt http://forum.arduino.cc/index.php?topic=136836.msg1536416#msg1536416 Empfang von Wetterdaten von einem Conrad KW9010 Sensor. Ich habe den Sketch aus dem Post entsprechend für RFM12B OOK angepasst.
Bei Interesse kann ich den Sketch posten.


Hallo,

ich würde mich über ein Posting des Codes sehr freuen. Schon mal vielen Dank.

Grüße Jörg

erni-berni

Hallo Jörg,
ist schon etwas her, aber das müsste der Sketch sein
Code: [Select]

/// Receive / decode OOK signals using a RFM12B as 434 MHz OOK receiver for K9010 temp/humidity sensor
//
// Adapted from the experiments and code by JGJ Veken, as posted on the wiki at:
// http://jeelabs.net/projects/cafe/wiki/Receiving_OOKASK_with_a_modified_RFM12B 
// and  Arduino sketch to receive KW9010 temperature/humidity RF sensor telegrams
// Written by 'jurs' for German Arduino Forum

#include <JeeLib.h>


#define RX433DATA 3       // receive pin for hardware interrupts
#define RX433INTERRUPT 1  // interrupt number for receive pin

#define KW9010_SYNC 8900  // length in µs of starting pulse
#define KW9010_ONE 4020   // length in µs of ONE pulse
#define KW9010_ZERO 1950  // length in µs of ZERO pulse
#define KW9010_GLITCH 350 // pulse length variation for ONE and ZERO pulses
#define KW9010_MESSAGELEN 36  // number of bits in one message



static void rf12_init_OOK ()
{
  /*0x8017,   http://www.mikrocontroller.net/attachment/80918/main.c
   0xC431,
   0xa608,
   0x94c2,
   0xC220,
   0x82D8,
   0xCA00,
   0xCC67,
   0xC623,
   0,
   0*/
  rf12_control(0x8017); // 8027    Configuration Settings: 433 Mhz; !TX; !RX FIFO; 12pF
  rf12_control(0x82D8); // 82C0    Power Management: enable receiver; enable basebandblock; enable synth; en cryst osc
  rf12_control(0xA608); // A68A    Frequency Setting: Fc =430+ F x0.0025MHz; F = 1544; 433,86 MHz
  rf12_control(0xC623); // C691    Data Rate: 9579 kbps 
  rf12_control(0x94c2); // 9489    Receiver Control: LNA Gain max; Pin VDI; RX BW 67kHz; VDI fast; DRSSI -91 db
  rf12_control(0xC220); // C220    Data Filter & Clock Recovery:  ** not documented cmd
  rf12_control(0xCA00); // CA00    FIFO and Reset Mode: FIFO full disabled
  rf12_control(0xC431); // C473    Automatic Frequency Control: AFC Auto OFF; enable AFC; offset register; +3 -4
  rf12_control(0xCC67); // CC67    PLL Settings: Clock rise low; PLL Band 256 kbps; !Dither;
  // rf12_control(0xB800); // TX register write command not used
  // rf12_control(0xC800); // Low Duty-Cycle: disable low dutycycle
  // rf12_control(0xC040); // Low Battery Detect and µC Clock: 1.66MHz, 2.2V not used see 82c0 
  // register calculator: http://tools.jeelabs.org/rfm12b.html
}


void setup () {
  Serial.begin(115200);
  pinMode(RX433DATA, INPUT);
  Serial.println(F("Sec\tCRC\tPak\tID\tChan\tTemp C\tTrend\trH %\tLowBat\tForced send"));
  rf12_initialize(0, RF12_868MHZ);
  rf12_init_OOK();
  attachInterrupt(RX433INTERRUPT, rx433Handler, CHANGE);
}

unsigned long lastread;
boolean pending=false;
unsigned long lastData;
int dataCounter=0;

void loop () {
  if (pending && millis()-lastread > 500) {   // es ist noch was zu drucken
    if (lastData!=0)         // letzten Datensatz drucken
    {
      Serial.print(millis()/1000);
      Serial.print(F("\tOK"));
      Serial.print(F("\t"));
      Serial.print(dataCounter);
      printResults(lastData);
      Serial.println(); 
      dataCounter=0;
      lastData=0;
    } 
    else
    { 
      Serial.print(F("F"));
      Serial.println(); 
    } 
    pending = false;
    lastData=0;
  }   
  if (fifoAvailable())  // es sind neue Daten da
  {
    unsigned long dataReceived=fifoRead();
    lastread=millis();              // Zeitpunkt des letzten Datensatzes
    if (dataReceived==lastData) {   // gleicher Datensatz
      dataCounter++;             // Anzahl gleicher Pakete
      pending=true;
    }
    else {                        //                           
      if (pending) {             // ungleicher Datensatz kam innerhalb 500ms und da war noch was zum printen
        if (lastData!=0)
        {
          Serial.print(millis()/1000);
          Serial.print(F("\tOK"));
          Serial.print(F("\t"));
          Serial.print(dataCounter);
          printResults(lastData);
          Serial.println(); 
          dataCounter=0;
          lastData=0;
        } 
        else
        { 
          Serial.print(F("F"));
          Serial.println(); 
        } 
        pending = false;
      }
      lastData=dataReceived;
      dataCounter++;
      pending=true;
    }
  }
}

void printResults(unsigned long value)
{
  // Sensor ID
  byte id = value & 0b11001111; // bit 0, 1, 2, 3, 6, 7, random change bits when battery is changed
  Serial.print('\t');
  Serial.print(id);
  // Channel (as set on sensor)
  byte channel = 2*bitRead(value,4)+bitRead(value,5); // bit 4, 5 are channel number
  Serial.print('\t');
  Serial.print(channel);
  // Temperature
  int temperature = value>>12 & 0b111111111111;  // bit 12..23
  // if sign bit is set, adjust two's complement to fit a 16-bit number
  if (bitRead(temperature,11)) temperature= temperature | 0b1111000000000000;
  Serial.print('\t');
  Serial.print(temperature/10.0,1);
  // temperature tendency
  byte trend = value>>9 &0b11; // bit 9, 10
  Serial.print('\t');
  if (trend==0) Serial.print('=');       // temp tendency steady
  else if (trend==1) Serial.print('-');  // temp tendency falling
  else if (trend==2) Serial.print('+');  // temp tendency rising
  // Humidity
  byte humidity = (value>>24 & 0b11111111) - 156; // bit 24..31
  Serial.print('\t');
  Serial.print(humidity);
  // Battery State
  bool lowBat = value>>8 & 0b1;      // bit 8 is set if battery voltage is low
  Serial.print('\t');
  Serial.print(lowBat);
  // Trigger
  bool forcedSend = value>>11 &0b1;  // bit 11 is set if manual send button was pressed
  Serial.print('\t');
  Serial.print(forcedSend);
}

boolean crcValid(unsigned long value, byte checksum)
// check if received crc is correct for received value
{
  byte calculatedChecksum = 0;
  for (int i = 0 ; i < 8 ; i++) calculatedChecksum +=(byte)(value >> (i*4));
  calculatedChecksum &= 0xF;
  return calculatedChecksum == checksum;
}

void rx433Handler()
{
  static long rx433LineUp, rx433LineDown;
  static unsigned long rxBits=0;
  static byte crcBits=0;
  static byte bitsCounted=0;
  long LowVal, HighVal;
  byte rx433State = digitalRead(RX433DATA); // current pin state
  if (rx433State) // pin is now HIGH
  {
    rx433LineUp=micros(); // line went HIGH after being LOW at this time
    LowVal=rx433LineUp - rx433LineDown; // calculate the LOW pulse time
    if (LowVal>KW9010_SYNC-2*KW9010_GLITCH && LowVal<KW9010_SYNC+2*KW9010_GLITCH)
    {
      rxBits=0;
      crcBits=0;
      bitsCounted=0;
    }
    else if (LowVal>KW9010_ONE-KW9010_GLITCH && LowVal<KW9010_ONE+KW9010_GLITCH)
    { // set the one bits
      if (bitsCounted<32)
        bitSet(rxBits,bitsCounted);
      else 
        bitSet(crcBits,bitsCounted-32);
      bitsCounted++;
    }
    else if (LowVal>KW9010_ZERO-KW9010_GLITCH && LowVal<KW9010_ZERO+KW9010_GLITCH)
    { // setting zero bits is not necessary, but count them
      bitsCounted++;
    }
    else // received bit is not a SYNC, ONE or ZERO bit, so restart
    {
      rxBits=0;
      crcBits=0;
      bitsCounted=0;
    }
    if (bitsCounted>=KW9010_MESSAGELEN) // all bits received
    {
      if (crcValid(rxBits,crcBits)) fifoWrite(rxBits); // write valid value to FIFO buffer
      else fifoWrite(0);  // write 0 to FIFO buffer (0 = invalid value received)
      rxBits=0;
      crcBits=0;
      bitsCounted=0;
    }
  }
  else
  { // High values have no information with them
    rx433LineDown=micros(); // line went LOW after being HIGH
    HighVal=rx433LineDown - rx433LineUp; // calculate the HIGH pulse time
  }
}


#define FIFOSIZE 8  // Fifo Buffer size 8 can hold up to 7 items
volatile long fifoBuf[FIFOSIZE]; // ring buffer
volatile byte fifoReadIndex,fifoWriteIndex;  // read and write index into ring buffer

void fifoWrite(long item)
// write item into ring buffer
{
  fifoBuf[fifoWriteIndex]=item; // store the item
  if (!(fifoWriteIndex+1==fifoReadIndex || (fifoWriteIndex+1>=FIFOSIZE && fifoReadIndex==0)))
    fifoWriteIndex++;  // advance write pointer in ringbuffer
  if (fifoWriteIndex>=FIFOSIZE) fifoWriteIndex=0; // ring buffer is at its end
}


unsigned long fifoRead()
// always check first if item is available with fifoAvailable()
// before reading the ring buffer using this function
{
  unsigned long item;
  item=fifoBuf[fifoReadIndex];
  cli(); // Interrupts off while changing the read pointer for the ringbuffer
  fifoReadIndex++;
  if (fifoReadIndex>=FIFOSIZE) fifoReadIndex=0;
  sei(); // Interrupts on again
  return(item);


boolean fifoAvailable()
// item is available for reading if (fifoReadIndex!=fifoWriteIndex)
{
  return (fifoReadIndex!=fifoWriteIndex);
}


Gruß
Reinhard

Go Up