433Mhz Daten Übertragung - Zeichenkette verändern

Hallo.

Ich möchte per 433Mhz Temperatur und Feuchtigkeit übertragen (Attiny85) und das mit einem anderen Arduino Nano empfangen.
Das ganze funktioniert auch, nur würde ich gerne die Zeichenkette die übertragen wird verändern.

Es soll so oder ähnlich übertragen werden:
$22%55#

 char msg[5] = {'1','2','3','4','#'};
  msg[0] = 37;
  msg[1] = temp;
  msg[2] = 36;
  msg[3] = hum;
  msg[4] = 35;
  
  vw_send((uint8_t *)msg, 5);

So was ähnliches habe ich in einem Beispiel gesehen, da wurde aber nur eine Zahlen ersetzt.
Das hier funktioniert auch, auf der Empfängerseite erhalte ich aber nur Zahlen, was natürlich richtig ist, wegen dem HEX.

 Serial.print(buf[i], HEX);

Ändere ich es auf:

 Serial.print(char(buf[i]));

um, werden die Sonderzeichen zwar angezeigt, heißt ich kann so Text ausgeben, aber die Zahlen für Temperatur werden dann als wirre Zeichen angezeigt.
Später soll da auch ein Display ran, sollte dann ja sicher ähnlich funktionieren wie mit serial.print...also das Ausgabeformat müsste dann ja ähnlich sein.

Ich möchte nicht einfach nur die Zahlen übertragen, sondern Zeichen dazwischen haben, sollte es mal zu Störungen in der Übertragung kommen und die fest definierten Zeichen sind nicht Ok, weiß man das etwas nicht stimmt. Nichts genaues, aber etwas sicherer.

Ich versuche das nun schon seit Stunden das ich das so ausgebe wie ich es gerne hätte...es geht nicht.
Ok, hab den Arduino auch wieder ne ganze weile hier liegen gehabt...ich weiß gar nichts mehr :confused:
Das nervt mich total !
Kann mir jemand helfen ?

Es gibt sicher viele Wege wie man es machen kann, ich nutze diesen Code, um meine Daten per 433 MHZ zu übertragen und das funktioniert prima.

// In der Deklaration

char Sensor1Msg[5];      
char Sensor2Msg[5];      
char Sender_Msg[20];     

const char Trenner[] = {":"}; 


// In der Loop

  strcat(Sender_Msg, Trenner);                                    
  strcat(Sender_Msg, Sensor1Msg);                                 
  strcat(Sender_Msg, Trenner);                                    
  strcat(Sender_Msg, Sensor2Msg);                                 
  strcat(Sender_Msg, Trenner);                                    

  vw_send((uint8_t *)Sender_Msg, strlen(Sender_Msg));

Dies ist Beispielcode und nicht vollständig!

Im Empfänger verwende ich dann die im Beispiel gezeigte Zeile.

  if (vw_get_message(buf, &buflen)) {             // überprüfen ob eine Nachricht eingegangen ist
    for (i = 0; i < buflen; i++) {
      StringReceived[i] = char(buf[i]);

Der darin empfangene Text (StringReceived) wird anschließend wieder getrennt und angezeigt.

Captain-DJ:
So was ähnliches habe ich in einem Beispiel gesehen, da wurde aber nur eine Zahlen ersetzt.
Das hier funktioniert auch, auf der Empfängerseite erhalte ich aber nur Zahlen, was natürlich richtig ist, wegen dem HEX.

 Serial.print(buf[i], HEX);

Ändere ich es auf:

 Serial.print(char(buf[i]));

um, werden die Sonderzeichen zwar angezeigt, heißt ich kann so Text ausgeben, aber die Zahlen für Temperatur werden dann als wirre Zeichen angezeigt.

Du hast vermutlich eine Vermischung der Variablenformate. Du sendest die Daten als Bytes. Das eine mal interpretierst du das als Zahlen, dann stimmt die Temperatur, aber das Trennzeichen wird auch zur Zahl oder du interpretierst das als Char, dann stimmen die Trennzeichen, aber die Temp./Hum. siehst du als wirre Ascii-Zeichen. Du musst entweder die Temperatur vorm Senden auch zu Ascii-Zeichen wandeln oder du Unterscheidest beim Empfang die Zeichen. Du solltest Trennzeichen nehmen, die nicht mit einer Temperatur verwechselt werden kann.

so wie du sendest, kannst du nur ganzzahlige Werte von 0 bis 255 übertragen

Verstehe nicht, was der TE mit Beispielen meint. Entweder mach ich es mit der Printf Klasse oder ebend nicht. Wenn du auf der Empfängerseite "nur" Zahlen erhälst, dann machst du beim Einlesen was falsch! Zeige bitte beide Sketche.

@sschultewolter
Ich habe beide Seiten gezeigt.
Der erste Code ist der Sender, der zweite und dritte Code der Empfänger...steht doch da.

@Theseus
Ich habe mir schon gedacht, das mit unterschiedlichen Variablenformaten gearbeitet wird.
Leider habe ich aber keine Befehle gefunden, mit denen ich das so umgewandelt bekommen habe, das was brauchbares raus kam.
Ich habe die Arduino Hilfe danach durchsucht, aber wenn man nicht weiß was man sucht ist das immer etwas schwierig.

@HotSystems
Ja danke für das Beispiel, das werde ich mal direkt versuchen.
Aber was ist denn STRCAT ? Setzt man damit Strings zusammen (sind das überhaupt strings?)
So was findet man ja nicht in der Hilfe...die ist eh sehr dünn.

Kennt jemand eine bessere Hilfe mit allen Befehlen die es so in der Arduino Software gibt ?

Captain-DJ:
Ich habe die Arduino Hilfe danach durchsucht, aber wenn man nicht weiß was man sucht ist das immer etwas schwierig.

Das hat nichts speziell mit dem Arduino zu tun, sondern ist grundlegendes C. Deshalb taucht es auch in der Arduino Referenz nicht auf.

Die Arduino Software ist nur eine Art API die in C/C++ geschrieben sind.

Ja,mit "strcat" setzt du die Strings zusammen.
In Google mit "arduino strcat c++" findest du einiges an infos.

Captain-DJ:
Ich habe beide Seiten gezeigt.
Der erste Code ist der Sender, der zweite und dritte Code der Empfänger...steht doch da.

Sorry, aber in den meisten Fällen reicht das so nicht.
Wir benötigen den kompletten Sketch um auch die Deklaration zu sehen.
Nur kurze Auszüge helfen da nicht.
Oft stecken die Fehler auch wo anders.

schau einmal hier: strcat

Außerdem bräuchte man sehr wahrscheinlich noch eine Konvertierungsfunktion um Integer in Strings zu wandeln. Dann geht es auch ohne strcat():

void setup() 
{
  Serial.begin(9600);

  float temp = 23.5;
  int hum = 45;

  char buffer[20];
  itoa(temp * 100, buffer, 10);
  int length = strlen(buffer);
  buffer[length] = ',';
  itoa(hum, &buffer[length + 1], 10);
  Serial.println(buffer);

  float t = atoi(strtok(buffer, ",")) / 100.0;
  int h = atoi(strtok(NULL, ","));
  Serial.println(t, 1);
  Serial.println(h);
}

itoa() = integer to ascii. Nach der ersten Konvertierung bestimmt man das Ende mit strlen(). Dadurch weiß man genau wo man den Rest hinschreiben muss.

Der Block am Ende ist für die Rückwandlung des Strings in Zahlen. atoi() = ascii to integer. strtok() = string tokenizer

Generell gibt es aber mehrere Wege sowas zu erschlagen :slight_smile:

@HotSystems
Das hier lag ja eindeutig an den Variablen Arten.
Dein gezeigtes Beispiel funktioniert so...na fast jedenfalls.
Also ich hab als Sender einen Attiny85. Senden funktioniert mit der virtualwire Library.
Nur das Senden hört nach zwei mal einfach auf. Ich hab eine LED die durch blinken zeigt, das gesendet wurde.
Die blinkt nach zwei mal nicht mehr, bedeutet das es irgendwo hängt.

Schon mal auf einem Attiny85 diese Library laufen gehabt ?
Wenn der Attiny85 auf 8Mhz läuft, funktioniert das gar nicht. Auf 1Mhz ging es die ganze Zeit, aber auch nur wenn ich die Übertragungsrate auf 1000 bit/s einstelle.

Mal sehen ob ich da irgendwo einen Fehler eingebaut habe durch das ganze rum probieren.

Danke schon mal !

Captain-DJ:
@HotSystems
Das hier lag ja eindeutig an den Variablen Arten.
Dein gezeigtes Beispiel funktioniert so...na fast jedenfalls.
Also ich hab als Sender einen Attiny85. Senden funktioniert mit der virtualwire Library.
Nur das Senden hört nach zwei mal einfach auf. Ich hab eine LED die durch blinken zeigt, das gesendet wurde.
Die blinkt nach zwei mal nicht mehr, bedeutet das es irgendwo hängt.
D
Schon mal auf einem Attiny85 diese Library laufen gehabt ?
Wenn der Attiny85 auf 8Mhz läuft, funktioniert das gar nicht. Auf 1Mhz ging es die ganze Zeit, aber auch nur wenn ich die Übertragungsrate auf 1000 bit/s einstelle.

Mal sehen ob ich da irgendwo einen Fehler eingebaut habe durch das ganze rum probieren.

Danke schon mal !

Dann hast du einen Fehler in der Deklaration gemacht, da läuft was über.
Da konnen wir ohne den Sketch wiedermal nichts sagen.
Du musst vermutlich die Char Variable leeren.

Ich würde eine IF-Abfrage im Empfänger machen.

if ((int(buf[i]>=35)||int(buf[i])<=37))
                {Serial.print(char(buf[i]));}
           else Serial.print(int(buf[i]));

Deine Trennzeichen zwischen 35 und 37 sind etwas ungeschickt, da sie mit einer Temperatur verwechselt werden können. Besser wären z.B. zwischen 135 und 137, und zur Ausgabe einfach 100 abzuziehen.

Hm, ok auf 8Mhz läuft es nun doch...keine Ahnung was das damals war.

#include <VirtualWire.h>
#include <dht11.h>

int led_pin = 0;
int transmit_pin = 3;
dht11 DHT11;
#define DHT11PIN 4
char temp[]="22";
char hum[]="55";
char msg[5];

void setup()
{
    // Initialise the IO and ISR
    vw_set_tx_pin(transmit_pin);
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(1000);       // Bits per sec
    pinMode(led_pin, OUTPUT);
  }


void loop()
{
 int chk = DHT11.read(DHT11PIN); //chk enthällt dann ok oder fehler wird sonst nicht gebraucht
 
 strcat(msg, "X");
 strcat(msg, temp);
 strcat(msg, "Y"); 
 strcat(msg, hum);
 strcat(msg, "#");
 
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  vw_send((uint8_t *)msg, strlen(msg) );
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(led_pin, LOW);
  char msg[] = {""};
  delay(500);
  
}

Das letzte char msg[] = "" bzw. mit {} habe ich gerade versucht um den String zu löschen.
Sendet zwei malund bleibt dann stehen.

EDIT:
Da ich anscheinend zu doof bin um den String zu löschen, habe ich einfach den Zeiger ganz nach vorne gesetzt
msg[0] ='\0';
Habe das gerade in einer Hilfe für C gefunden.
Was ist denn an msg[]=""; falsch ?
Ich kann doch keine Zahl in die eckige Klammer setzten, der ganze String soll doch gelöscht werden.

Lerne bitte C Grundlagen!

Du musst beachten dass C Strings Null-terminiert sind. Die sind eins größer als die Anzahl der sichtbaren Zeichen. Eine Größe von 5 reicht also nur für 4 Zeichen! Mehr verursacht einen Puffer-Überlauf. Du kannst das Array ruhig 10 groß machen und weniger verwenden.

Dann ist das zweite msg ist nur eine lokale Variable gleichen Namens! Zweitens werden C Strings so nicht gelöscht. Sondern so:

*msg = '\0';

Oder:

msg[0] = '\0';

Das terminiert einfach den String gleich am Anfang

Ich sehe auch gar nicht wozu du hier Anfangs-und Endzeichen brauchst wenn du das am anderen Ende durch die gleiche Library empfängst. Zwei Werte mit einem Komma getrennt sollten hier doch reichen.

Die Variable char msg musst du größer setzen und du kannst die char variable so nicht löschen.

Das löschen ist hier

https://www.c-plusplus.net/forum/115373-full

beschrieben.

Du brauchst hier aber nichts löschen, da die Variable übergelaufen ist.

Bis jetzt habe ich in C noch gar nichts gemacht.
Auch wusste ich nicht wirklich, das C hier eine Rolle spielt.
Warum sollte ich mir dann C anschauen ... will doch nur am Arduino rum machen :wink:

Jetzt weiß ich aber das beides zusammen gehört, was bei einer Suche schon etwas hilfreich ist.
Auch habe ich eben C-HowTo gefunden, das hilft auf jeden Fall.

Das mit dem msg '\0' habe ich schon gefunden.
Da war mein EDIT doch etwas zu langsam.

Die Anfangs und Endzeichen brauche ich so direkt erst mal nicht.
Ich hatte zuerst ohne die Library eine Datenübertragung versucht. Dazu habe ich ein Beispiel gesehen, das einfach ein Zeichen in Signale umwandelt die dann per serial.write in Millisekunden übertragen werden.
Dort wurde extrem viel Müll übertragen, am Anfang und am Ende. Die Daten an sich waren meist ok.
Deshalb hatte ich mir überlegt, das wenn die Start, Mitten und Endzeichen ok, sind, es sehr wahrscheinlich ist, das auch die Daten OK sind.

Damals wusste ich, das diese VirtualWire.h nicht auf einem Attiny läuft...aber nur als Empfänger !
Als Sender geht das sehr wohl und damit war die "Eigenbau" Variante hinfällig.
Aber ich möchte auch noch Text übertragen, deshalb ist das gut das es so funktioniert.
Wie ich das am anderen Ende nun noch auseinander kriege wird sich zeigen.

@HotSystems
Wenn ich das mit dem strcat mache, wird das nun eben immer länger, deshalb bringt es ja nichts wenn ich die Variable auf 200 setzte, die wird trotzdem immer länger und läuft über und dann stoppt alles.
Dem Nano macht das anscheinend nichts, mit dem ich das ganze per serieller Ausgabe grad getestet habe.
Das Programm fängt dann einfach von vorne an. Der Attiny bleibt stehen und das wars.

Aber es funktioniert jetzt so !

Danke für eure Hilfe !!!

Captain-DJ:
Dem Nano macht das anscheinend nichts, mit dem ich das ganze per serieller Ausgabe grad getestet habe.
Das Programm fängt dann einfach von vorne an.

Der Nano ist intelligenter :slight_smile: :slight_smile:

Ist aber reiner Zufall, dass er resettet.

Ok falsch ausgedrückt, die Variable wird wieder auf den richtigen Wert gesetzt und das Programm läuft ohne Unterbrechung weiter...das nur damithier nichts falsches steht :slight_smile: