Forum: PC-Programmierung Hilfe beim Code für den Tiny84 (C++)


von Kolja L. (kolja82)


Lesenswert?

Hallo

Das Skript soll auf einem Tiny84 dafür sorgen,
das empfangene Daten weitergesendet werden.

Nur leider schaffen wir es nicht, die Daten im gänze zu senden.
Es werden nur die ersten beiden Zeichen des Strings übertragen.

Kann von euch jemand sehen, ob wir den String so richtig zusammen bauen?

Danke und Gruß

Kolja

Hier die vermeintlich problematische Stelle:
1
// Buffer to store incoming data
2
      const char* inData;
3
      int i;
4
      for (byte i = 0; i < *radio.DataLen; i++) //can also use radio.GetDataLen() if you don't like pointers
5
        #ifdef DEBUG
6
          mySerial.print((char) radio.Data[i]);
7
        #endif
8
        inData += (char) radio.Data[i];
9
10
      if (LEDpin) {
11
        blink(LEDpin, 2);
12
      }
13
      if (radio.ACKRequested()) {
14
        radio.SendACK();
15
        #ifdef DEBUG
16
          mySerial.print(" - ACK sent");
17
        #endif
18
      }

Und hier nochmal der Code im Ganzen:
1
void loop() {
2
  if (radio.ReceiveComplete()) {
3
    if (radio.CRCPass()) {
4
      int supplyV = readVcc(); // Get supply voltage
5
      //node ID of TX, extracted from RF datapacket. Not transmitted as part of structure
6
      byte theNodeID = radio.GetSender();
7
      // Buffer to store incoming data
8
      const char* inData;
9
      int i;
10
      for (byte i = 0; i < *radio.DataLen; i++) { //can also use radio.GetDataLen() if you don't like pointers
11
        inData += (char) radio.Data[i];
12
      }
13
      if (radio.ACKRequested()) {
14
        radio.SendACK();
15
      }
16
      // Send received data to PI
17
      setupTransmit();
18
      radio.Send(T_GATEWAYID, (uint8_t *)inData, strlen(inData), requestACK);
19
      radio.SendWait(2);    //wait for RF to finish sending (2=standby mode, 3=power down)
20
      setupReceive();
21
      if (LEDpin) {
22
        blink(LEDpin, 2);
23
      }
24
    } else {
25
      if (LEDpin) {
26
        activityLED(1); // LED on
27
        delay(1000);
28
        activityLED(0); // LED off
29
      }
30
    }
31
  }
32
}

von Tom K. (ez81)


Lesenswert?

1
const char* inData;
2
//...
3
inData += (char) radio.Data[i];
Das funktioniert so nicht. Lest Euch mal in Strings in C ein. Ein 
char-Pointer funktioniert  nicht so einfach wie ein String in 
zivilisierten Programmiersprachen.

Erst legt ihr einen Zeiger an, der irgendwo hin zeigt, dann 
inkrementiert ihr ihn abhängig vom Inhalt der empfangenen Daten, so dass 
er sonstwo hin zeigt, dan sendet ihr die Daten, die an dieser (halbwegs 
zufälligen) Stelle im RAM stehen.

: Bearbeitet durch User
von Kolja L. (kolja82)


Lesenswert?

Nabend Tom

Dann liegt das Problem ja wirklich da wo wir es vermuteten.


Kostet das was wir zum Auslesen des Strings machen müssen
viel Platz auf dem Tiny?
Wenn noch eine library hinzugefügt werden muss,
müssten wir uns nach einer anderen Lösung umschauen...

Der String sieht in etwa so aus:
v=4321_0079=2409_0a28=2343
und wir bräuchten ihn schon im Ganzen.

Gruß Kolja

von Thorsten H. (lordvader91)


Lesenswert?

Probiert es mal mit:
1
#define MAX_LENGTH 27
2
// Buffer to store incoming data
3
char inData[MAX_LENGTH];
4
int i;
5
for (i = 0; i < *radio.DataLen; i++) //can also use radio.GetDataLen() if you don't like pointers
6
    inData[i] = (char) radio.Data[i];
7
inData[*radio.DataLen] = '\0'; // nötig, sofern das Nullzeichnen nicht in der empfangenen Zeichenkette schon vorkommt

MAX_LENGTH sollte dabei die maximal zu erwartende Länge des Strings + 1 
sein. Strings werden in C mit 0 terminiert. Die strlen()-Funktion sucht 
das Nullzeichen um das Ende des Strings zu finden und damit die Länge zu 
berechnen.

Das Konstrukt *radio.DataLen sieht auch ziemlich komisch aus. Sicher, 
dass das nicht radio.DataLen heißen soll?

von Kolja L. (kolja82)


Lesenswert?

Moin Thorsten

Danke für die Codezeilen.
Ich werds (hoffentlich) gleich noch mal einbauen.

Muss die exakte Länge des Strings angegeben werden?
Da drei der Werte Temperaturen sind und diese eine Stelle kürzer werden,
wenn unter 10°C gemessen wird, kann das natürlich problematisch werden.

Zur Not muss der Sender einfach auf jeden Wert 10 aufaddieren
und im Empfänger werden diese wieder subtrahiert.

Gruß&Dank

Kolja

von Thorsten H. (lordvader91)


Lesenswert?

Nein, MAX_LENGTH ist nur die maximale Länge des Strings. Er kann 
natürlich auch kürzer sein, dann ist aber eben der RAM für die nicht 
genutzten Zeichen futsch. Jedoch darf der String nicht länger als 
MAX_LENGTH sein, sonst kann es passieren, dass dir Daten überschrieben 
werden. Also sofern nicht irgendwie anders sicher gestellt ist, dass die 
Länge der empfangenen Daten MAX_LENGTH nicht überschreitet, kannst du 
zur Sicherheit die noch prüfen:
1
for (i = 0; (i < *radio.DataLen) && (i < MAX_LENGTH-1); i++)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Thorsten H. schrieb:

>
1
> for (i = 0; (i < *radio.DataLen) && (i < MAX_LENGTH-1); i++)
2
>

oder aber anstelle der Eigenbau-Schleife ganz einfach memcpy bzw. strcpy 
benutzen.

Ich würde auch hier
1
      radio.Send(T_GATEWAYID, (uint8_t *)inData, strlen(inData), requestACK);
keinen strlen benutzen. Denn ich kenne ja die Länge des 'Strings'. Die 
muss logischerweise *radio.DataLen sein.
Kein strlen -> keine Notwendigkeit, dass die Eingangswerte \0-terminiert 
sind.

Die Funktion gibt dann einfach nur das weiter, was sie gekriegt hat. Was 
immer das auch war.


Eine ganz andere Frage lautet: Warum muss das Array überhaupt umkopiert 
werden? Würde ein
1
      radio.Send( T_GATEWAYID,
2
                  (uint8_t *)radio.data,
3
                  *radio.DataLen,
4
                  requestACK);
nicht einfacher sein? Es kann jetzt natürlich sein, dass das radio 
Objekt in den dazwischenliegenden Aufrufen den Datenbuffer löscht oder 
aber das der Data Member kein Array von Bytes ist (halte ich aber eher 
für unwahrscheinlich). In diesen Fällen müsste man natürlich umkopieren.



Und ja. Das *radio.Datalen sieht in der Tat merkwürdig aus. So ein 
Konstrukt ist höchst ungewöhnlich. Es muss aber nicht notwendigerweise 
falsch sein, wenn die Klasse des radio Obektes so etwas wie ein 
Double-Buffering macht, um empfangene Daten für die Weiterverarbeitung 
bereit zu stellen, während im Hintergrund der Empfang neuer Daten 
bereits läuft.

: Bearbeitet durch User
von Kolja L. (kolja82)


Lesenswert?

Nabend Heinz & co

Vielen Dank für die Hilfe!
Der Vorschlag aus dem letzen Post ließ den kleinen Repeater alles senden 
was er auch empfangen hat!

Wir waren gerade in dem Gebäude in welchem wir die Messungen durchführen 
werden
und mit einem Repeater können alle Sensoren aus allen Räumen empfangen 
werden
und an den RaspberryPi in den Keller gesendet werden.

Wenn wir die Dokumentation fertig haben,
werde ich hier den entsprechenden Teil verlinken.

Wer vorher schon Fragen hat, gerne!

Gruß Kolja

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.