Pages: [1] 2 3   Go Down
Author Topic: RF12 Datenstruct senden, empfangen und wieder trennen  (Read 4085 times)
0 Members and 1 Guest are viewing this topic.
NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo zusammen,
ich brauche mal ein paar Tips.
Ich habe zwei RF12 Module.
Senden und empfangen geht schon mal  smiley

Nun habe ich mal wieder eine Wissenslücke.
Und zwar sammle ich an einem Modul verschiedene Daten. Diese wollte ich in einem Struct speichern.
Senden würde ich das ja in etwa so:
Code:
rf12_sendStart(0, &payload, sizeof payload);

Leider kann ich nicht ganz nachvollziehen was am ende raus kommt.
Wenn mein zusammengesetztes Payload eigentlich 12345 sein müsste
kommt komischer weise 12950 am anderen ende raus.
Ausgelesen wird das ganze ja durch folgenden code:
 
Code:
if (rf12_recvDone() && rf12_crc == 0) {
        for (byte i = 0; i < rf12_len; ++i) {
            Serial.print((int) rf12_data[i]);
 }

Deshalb zwei Fragen:
1. Wieso kommt so was komisches an? Übersehe ich etwas?
2. Wie kann ich am besten den Empfangenen String wider in das Construct bekommen.



Das Struct:
Code:
struct {
    byte t_id;
    byte light;     // light sensor: 0..255
    byte moved :1;  // motion detector: 0..1
    byte humi  :7;  // humidity: 0..100
    int temp   :10; // temperature: -500..+500 (tenths)
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;
Logged

Bavaria Germany
Offline Offline
Full Member
***
Karma: 0
Posts: 121
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Kommt auch bei mehreren Versuchen immer "12950" statt "12345" an ??
Falls ja, bitte den kompletten Programmcode für Sender und Empfänger zeigen.

Gruß, mmi.
« Last Edit: March 03, 2012, 12:33:04 am by mmi » Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ja es kommt immer 12950 an:
Code:
[crypRecv]
 31 =12950
 32 =12950
 33 =12950
 34 =12950
 35 =12950
 36 =12950
 37 =12950

Sender:
Code:
#include <RF12.h>
#include <Ports.h>
#define T_ID 10

MilliTimer sendTimer;
byte sendSize;
struct {
    byte t_id;
    byte light;     // light sensor: 0..255
    byte moved :1;  // motion detector: 0..1
    byte humi  :7;  // humidity: 0..100
    int temp   :10; // temperature: -500..+500 (tenths)
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;

void setup () {
    Serial.begin(57600);
    Serial.println("\n[crypSend]");
    rf12_initialize(T_ID, RF12_868MHZ, 47);
    rf12_encrypt(RF12_EEPROM_EKEY);
}

void loop () {
    rf12_recvDone();
    if (rf12_canSend() && sendTimer.poll(1000)) { // jede sekunde senden
        payload.t_id = 1;
        payload.light = 2;
        payload.moved = 3;
        payload.humi = 4;
        payload.temp =5;
       
        rf12_sendStart(0, &payload, sizeof payload);
     }
}

Empfänger:
Code:
#include <RF12.h>
#include <Ports.h>

struct {
  byte t_id;
    byte light;     // light sensor: 0..255
    byte moved :1;  // motion detector: 0..1
    byte humi  :7;  // humidity: 0..100
    int temp   :10; // temperature: -500..+500 (tenths)
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;

void setup () {
    Serial.begin(57600);
    Serial.println("\n[crypRecv]");
    rf12_initialize(1, RF12_868MHZ, 47);
    rf12_encrypt(RF12_EEPROM_EKEY);
}

void loop () {
    if (rf12_recvDone() && rf12_crc == 0) {
        // good packet received
        Serial.print(' ');
        Serial.print(rf12_seq);
        Serial.print(" =");
        for (byte i = 0; i < rf12_len; ++i) {
            Serial.print((int) rf12_data[i]);
        }
        Serial.println();
    }
}

Der Code soll noch nicht viel machen! Muss mich da jetzt erstmal einarbeiten und schritt für schritt erweitern.
Was hab ich für Möglichkeiten und so.
Möchte zb noch wissen ob ich die Versender-ID am Empfänger auslesen kann.
Dann würde ich die nicht im Payload mit senden sondern so erkennen, fände ich besser.

Was ich auch noch nicht verstehe (steht auch nicht in der Referenz :
Beim Struct
byte moved :1; <- was bedeutet die 1 oder die 7 oder die 10 bei meinem Struct
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo MueThoS,
(und hallo Forum, ich fange nach langem mitlesen mal an, mitzuschreiben)

Meine Vermutung:
Schau dir mal http://www.c-howto.de/tutorial-strukturierte-datentypen-bitfelder.html oder http://en.wikipedia.org/wiki/Bit_field an.

Dein Struct orientiert sich nicht an Bytegrenzen ... Und daher kommen beim byteorientierten Ausgeben (beim Serial.print) deines Empfangs-code auch komische Daten raus.

Versuche bei der Ausgabe auch wieder die Elemente des Structs zu verwenden und anzusprechen, wie du es beim befüllen machst ... Oder lasse die Doppelpunkt-angaben einfach weg (das macht aber deine Nachrichten unnötig groß).

Viele Grüße,
 Holger
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo MueThoS,

wie Holger schon richtig bemerkte, ist das eine Struktur mit Bitfeldern. Die Zahl hinter dem Doppelpunkt gibt an, wieviele Bits das Attribut  belegt.
Code:
struct {
    byte t_id;
    byte light;     // light sensor: 0..255
    byte moved :1;  // motion detector: 0..1
    byte humi  :7;  // humidity: 0..100
    int temp   :10; // temperature: -500..+500 (tenths)
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;

Das Attribut "moved" z. B. hat nur eine Länge von einem Bit, da versuchst du, den Wert 3 reinzuschreiben - bei einem Bit geht aber nur 0 oder 1.

Du solltest also erst mal da nur vernünftige Werte reinschreiben, die 3 kriegst du so nie wieder raus.
Auch ist es schwierig, die Werte direkt von der empfangenen Struktur so anzuzeigen, das stimmt ja vom Speicherlayout her nicht mit deiner Struktur "Payload" überein.

Die in meinen Augen einfachste Vorgehensweise wäre es, die empfangenen Bytes in einer eigenen Struktur zu übertragen (byte [5]) und dann die Daten in deine payload-Struktur zu kopieren, also z. B:

Code:
byte buffer[sizeof(payload)];
memcpy(&payload, &buffer, sizeof(payload));

Danach kannst du deine Daten aus der payload-Struktur ausgeben, indem du die einzelnen Attribute ansprichst, also z. B.

Code:
  Serial.println (payload.temp);
  Serial.println (payload.humi);

Ich hoffe, dass das dann bei dir so klappt.

Ciao,

Rudi

Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du brauchst die Daten nichtmal kopieren. Es reicht am Ende den Puffer auf den Datentyp "payload" zu casten.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du brauchst die Daten nichtmal kopieren. Es reicht am Ende den Puffer auf den Datentyp "payload" zu casten.

Daran hatte ich auch schon gedacht, aber payload ist kein Datentyp, sondern nur eine Struktur. Man kann natürlich mit typedef auch einen Typ daraus machen, aber dann braucht man wieder eine Variable mit diesem Typ,um diesen Cast durchführen zu können. Ob das für den TE einfacher zu durchschauen ist?

Rudi
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Erstmal natürlich Danke für die Antworten.
Mein Wunsch währe es es so zu machen wie rz259 vorgeschlagen hat.
Ich würde gerne über
Code:
Serial.println (payload.humi);
wieder drauf zugreifen können.
Zunächst die erste frage hierzu:
Ist es möglich dies noch als Array zu machen? Also so in etwa?
Code:
Serial.println (payload[0].humi);

Dann die Frage zu der Umsetzung:
Verstehe ich das richtig das ich meine Daten die ja in rf12_data mit der länge rf12_len
in eine zusammenhängende Variable bekommen muss?
Ich habe das schon mal gesehen verstehe aber noch nicht so ganz woher die Daten kommen für Buffer
Code:
byte buffer[sizeof(payload)];
Ist Buffer eine Variable von mir oder ist das etwas spezielles welches mir vom MC zur Verfügung gestellt wird?
Wenn es nur ein Platzhalter für eine von mir angelegte Variable sein soll müsste ich nun in dieser Schleife:
Code:
for (byte i = 0; i < rf12_len; ++i) {
           incomingByte = rf12_data[i];
        }
So etwas machen?
und danach
Code:
byte incomingByte[sizeof(payload)];
memcpy(&payload, &incomingByte, sizeof(payload));
So wie ich es jetzt hier geschrieben habe geht's natürlich nicht  smiley
Ich probiere weiter.

Das mit den Zahlen hinter dem : im Struct hab ich aber verstanden, Danke schon mal dafür.
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow, jetzt hatte ich einen Riesen Text geschrieben weil ich etwas weiter gekommen bin und es aber noch Probleme gab.
Und während ich so schrieb viel es mir ein!
Ich bin auf jeden Fall ein ganzes stück weiter:
Code:
#include <RF12.h>
#include <Ports.h>
char incomingByte;      // a variable to read incoming serial data into
struct {
    byte t_id:8;    //
    byte light:8;     // light sensor: 0..255
    byte moved :1;  // motion detector: 0..1
    byte humi  :7;  // humidity: 0..100
    int temp   :10; // temperature: -500..+500 (tenths)
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;

void setup () {
    Serial.begin(57600);
    Serial.println("\n[crypRecv]");
    rf12_initialize(1, RF12_868MHZ, 47);
    rf12_encrypt(RF12_EEPROM_EKEY);
}

void loop () {
    if (rf12_recvDone() && rf12_crc == 0) {           // good packet received
       memcpy(&payload, (byte*) rf12_data, sizeof payload); 
       debug();
    }
}


void debug(){
  Serial.print(rf12_seq);
  Serial.print(" =");
  Serial.print("T_ID: ");
  Serial.print((int) payload.t_id);
  Serial.print("  light: ");
  Serial.print((int) payload.light);
  Serial.print("  moved: ");
  Serial.print((int)payload.moved);
  Serial.print("  humi: ");
  Serial.print((int)payload.humi);
  Serial.print("  temp: ");
  Serial.print((int)payload.temp);
  Serial.print("  lowbat: ");
  Serial.println((int)payload.lobat);
}
Zeigt mir folgendes:
Code:
744 =T_ID: 111  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
745 =T_ID: 111  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
746 =T_ID: 111  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
747 =T_ID: 111  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Das gefällt mir schon mal ganz gut.
Damit kann ich jetzt weiter arbeiten....
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das sieht eigentlich ganz gut aus - aber ob die Daten stimmen, kann ich natürlich nicht beurteilen, das kannst nur du...


Rudi
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Die Daten stimmen so weit.
Zumindest in der aktuallen konfiguration klappt das wunderbar.
Eventuel muss ich noch Typen anpassen aber eins nach dem anderen.
Im groben bekomme ich die übertragung jetzt hin.
Jetzt schaue ich erstmal welche Daten ich an den standorten sammeln will/kann.
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Weiter geht's....
Folgendes Problem:
Ich möchte die Daten einzelne abholen. Deshalb versuche ich die einzelnen Stationen an zu funken und eine Antwort ab zu warten.
Deshalb habe ich im Sender/Zentrale folgendes gemacht:
Code:
void loop () {
   for(int i=1; i<2 ; i++){
      rf12_recvDone();
      if (rf12_canSend() && sendTimer.poll(2000)) {
         rf12_sendStart(i, "*", 1);
         Serial.println("Anforderung gesendet  ..  ");
      }
      if (rf12_recvDone() && rf12_crc == 0) {           // good packet received
         Serial.print("Daten wurden empfangen  ..  ");
         memcpy(&payload[i], (byte*) rf12_data, sizeof payload); 
         //debug();
      }
   }
}
Er sendet das *chen.
Das sehe ich daran das der Empfänger/Station etwas bekommt und auch seine Antwort gibt bzw hoffentlich gibt.
Der Empfänger/Station hat folgenden Code:
Code:
void loop () {
   if (rf12_recvDone() && rf12_crc == 0) {
      Serial.print("Anforderung erhalten  ..  ");
      rf12_recvDone();
      delay(100);
      if (rf12_canSend()) {
         payload.t_id = T_ID;
         payload.light = 222;
         payload.moved = 1;
         payload.humi = 33;
         payload.temp =444;
         payload.lobat =0;
         rf12_sendStart(10, &payload, sizeof payload);
         Serial.println("Daten gesendet");
      }
   }
}
Die Meldung "Anforderung erhalten" kommt und die Meldung "Daten gesendet" auch.
Ich gehe also mal davon aus das er auch sendet.
Nur leider bekomme ich laut Sender/Zentrale keine Antwort.

Ich habe hier irgendwie eine Blockade, da ich im Moment nicht weiß woran es liegen kann.

Hat da einer einen Tip für mich?
Oder vielleicht auch eine Möglichkeit wie ich einen request starten kann ohne so ein "*" oder sonst ein Zeichen zu schicken.
Ob meine Vorgehensweise so ideal ist.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hm,

da gibt es natürlich mehrere Möglichkeiten zur Fehlersuche:

a) Stimmt die Id der Basisstation (10)?
b) Kann es sein, dass du zu viele Daten sendest? Bevor du die Rückgabe entgegennimmst, schickst du schon wieder neue Anforderungen
c) Kommen überhaupt gültige Daten zurück? Du prüfst ja auf rf12_recvDone und crc == 0, kann es sein, dass zwar rf12_recvDone TRUE zurückliefert, aber der crc-Wert nicht passt?
d) evtl. mit ACKNOWLEDGE arbeiten und sehen, ob du das Ack-Signal zurückbekommst
e) Wenn du mit einem Empfänger anfangen und dort zuerst einen * senden, um zu sehen, ob das auch an der Basisstation ankommt

evtl. gibt's ja noch weitere Ursachen - einfach  mal prüfen...


Ciao,

Rudi
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 2
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, ich bin ein Stück weiter.
Aber ich kann nicht sagen das es Gut läuft.
Ich habe zumindest hin bekommen das Daten zurück kommen.
Sogar von zwei Modulen.
Nur die Auflösung ins Array funktioniert irgendwie nicht:
Code:
entrale
Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2  Empfang von 2  Daten: 802 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 813 =T_ID: 2  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 814 =T_ID: 2  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 818 =T_ID: 2  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 819 =T_ID: 2  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 809 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 810 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 813 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2   Sensor 2 antwortet nicht
Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2  Empfang von 2  Daten: 818 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2   Sensor 2 antwortet nicht
Anforderung senden an: 1  Empfang von 1  Daten: 821 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 822 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2  Empfang von 2  Daten: 824 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 826 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 827 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 831 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2  Empfang von 2  Daten: 842 =T_ID: 2  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 1  Empfang von 1  Daten: 833 =T_ID: 1  light: 222  moved: 1  humi: 33  temp: 444  lowbat: 0
Anforderung senden an: 2Anforderung senden an: 1   Sensor 1 antwortet nicht
Anforderung senden an: 2   Sensor 2 antwortet nicht
Anforderung senden an: 1   Sensor 1 antwortet nicht

Der Code:
Code:
void loop () {
   if (sendTimer.poll(3000)){
      for(int i=1; i<3 ; i++){
         rf12_recvDone();
         if (rf12_canSend()) {
            rf12_sendStart(i, "*", 1);
            Serial.print("Anforderung senden an: ");
            Serial.print(i);
           
         }
         warten=0;
         while (!rf12_recvDone()){
            warten++;
            delay(100);
            if (warten >= 20) {
               Serial.print("   Sensor ");
               Serial.print(i);
               Serial.println(" antwortet nicht");
               goto out;
            }
         }
         out:
         if (rf12_crc == 0)  {           // good packet received
            Serial.print("  Empfang von ");
            Serial.print(i);
            Serial.print("  Daten: ");
            memcpy(&payload[i], (byte*) rf12_data, sizeof payload); 
           debug(i);
         }
      }
       
   }   
}

void debug(int nr){
  Serial.print(rf12_seq);
  Serial.print(" =");
  Serial.print("T_ID: ");
  Serial.print((int) payload[nr].t_id);
  Serial.print("  light: ");
  Serial.print((int) payload[nr].light);
  Serial.print("  moved: ");
  Serial.print((int)payload[nr].moved);
  Serial.print("  humi: ");
  Serial.print((int)payload[nr].humi);
  Serial.print("  temp: ");
  Serial.print((int)payload[nr].temp);
  Serial.print("  lowbat: ");
  Serial.println((int)payload[nr].lobat);
 
}
Eigentlich sollte immer abwechselnd Sensor 1 und Sensor 2 ausgegeben werden aber naja das macht er irgendwie nicht.
Warum jetzt Daten kommen und vorher nicht liegt irgendwie an dem Teil:
Code:
warten=0;
         while (!rf12_recvDone()){
            warten++;
            delay(100);
            if (warten >= 20) {
               Serial.print("   Sensor ");
               Serial.print(i);
               Serial.println(" antwortet nicht");
               goto out;
            }
         }
Ich muss an der Stelle warten bis Daten auch da sind.
Allerdings will ich nicht ewig warten.
Hab jetzt keine schönere Variante hin bekommen als die Goto out.

Jetzt muss ich raus bekommen warum er die Daten nicht sauber ins Array schiebt.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Was meinst du damit, dass die Auflösung der Daten ins Array nicht richtigh funktioniert?


Dein Goto kannst du folgendermaßen elimieren:
<code>
boolean timeout = FALSE;
warten=0;
         while (!rf12_recvDone() && !timeout){
            warten++;
            delay(100);
            if (warten >= 20) {
               Serial.print("   Sensor ");
               Serial.print(i);
               Serial.println(" antwortet nicht");
               timeout = TRUE;
            }
         }
</code>
Logged

Pages: [1] 2 3   Go Up
Jump to: