INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
[Vorstellung] Serieller Sender ohne 2. MC
13.04.2019, 20:44 (Dieser Beitrag wurde zuletzt bearbeitet: 13.04.2019 21:04 von Tommy56.)
Beitrag #1
[Vorstellung] Serieller Sender ohne 2. MC
Hallo zusammen,

ich bin bei einigen Problemen mit seriellen Schnittstellen im weitesten Sinne immer mal wieder darüber gestolpert, dass man zum Testen immer einen 2. MC als Sender braucht, wenn man Empfangsroutinen bauen/testen will.

Das hat mich dazu bewogen, eine Klasse zu bauen, die von Stream erbt und damit kompatibel zu Serial/1...3, Softwareserial usw. ist, aber nur als Empfänger.

Damit kann man in seinem Sketch den zu erwartenden Bytestrom selbst bereitstellen, um die Empfangsroutine zu testen. Die Klasse ist bewußt auch für binäre Daten ausgelegt.

Ich hoffe, sie hilft Euch bei der Erarbeitung von Empfangsroutinen.

Code:
/********************************************************************************​********
Copyright by Thomas Kühnert. All rights reserved.

This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details. https://www.gnu.org/licenses/lgpl-3.0.en.html
********************************************************************************​*********/

/***** Klasse zur Simulation eines Empfängers ******/
// erbt von Stream, um an Funktionen übergeben zu werden,
// die Serial u.a. verwenden
class EmuSerRead : public Stream {

public:

// len = Bytes, die alloziiert werden
// abschneiden = zu lange Eingaben werden verkürzt (true) oder abgelehnt (false)
// bewusst wird der Speicher einmal im Construktor allotiiert
  EmuSerRead(byte len = 25, bool abschneiden = false) {
    _str = (byte *)malloc(len);
    if (_str != nullptr) _alloc = len;
    else _alloc = 0;
    _abschneiden = abschneiden;
  }

  ~EmuSerRead() {
    if (_str != nullptr) free(_str);
    _str = nullptr;
    _alloc = 0;
  }
  
  boolean getAbschneiden() {return _abschneiden;}
  void setAbschneiden(bool abschneiden) {_abschneiden = abschneiden;}

  // wieviele Bytes sind da  
  virtual int available() {
    return _len - _qi;
  }

  // lese 1 Byte und entnehme es
  virtual int read() {
    if (!available()) return -1;
    else return _str[_qi++];
  }

  // lese 1 Byte ohne es zu entnehmen
  virtual int peek() {
    if (!available()) return -1;
    else  return _str[_qi];
  }

  // die sind eher für Debugzwecke
  char * getStr() {return _str;}
  byte getLen() {return _len;}
  byte getAlloc() {return _alloc;}

  // kein schreiben
  virtual size_t write(uint8_t) {return 0;}

  // Return 0=ok, 1 = zu lang (abgeschnitten/nicht übernommen), -1 = nicht initialisiert
  char setStr(char *p, byte len) {
  bool zuGross = false;
    if (_str == nullptr) return -1;  // sollte nicht vorkommen
    if (len > _alloc) {
      zuGross = true;
      if (!_abschneiden) return 1;
      _len = _alloc;
    }  
    else _len = len;
    memcpy(_str,p, _len);
    _qi=0;
    return (zuGross) ? 1 : 0;
  }

private:
  byte *_str = nullptr;  // Bytearray
  byte _alloc = 0;       // Wieviel Bytes sind alloziiert
  byte _qi =0;           // Index zum byteweisen auslesen
  byte _len = 0;         // reale Länge
  bool _abschneiden = false;  // sollen zu lange Eingaben bei setStr abgeschnitten werden
};


Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
13.04.2019, 21:37
Beitrag #2
RE: [Vorstellung] Serieller Sender ohne 2. MC
Hallo Tommy,
Echt grandios, was du für uns alle hier immer wieder lieferst.

Ich liege gerade mit Margen Darm Grippe flach,
aber werde es die Tage mal ausprobieren.

Mit Klassen hab ich noch nichts gemacht,
Wie wird das verwendet?
Einfach Serial öffnen und was senden?
Und dann den Empfang in EmuSerRead abholen?

Gruß, Markus

Immer in Stress
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
13.04.2019, 22:03
Beitrag #3
RE: [Vorstellung] Serieller Sender ohne 2. MC
Nö, eher so was:
Code:
/***** Klasse zur Simulation eines Empfängers ******/
// erbt von Stream, um an Funktionen übergeben zu werden,
// die Serial u.a. verwenden
class EmuSerRead : public Stream {

public:

// len = Bytes, die alloziiert werden
// abschneiden = zu lange Eingaben werden verkürzt (true) oder abgelehnt (false)
// bewusst wird der Speicher nur einmal im Construktor allotiiert
  EmuSerRead(byte len = 25, bool abschneiden = false) {
    _str = (byte *)malloc(len);
    if (_str != nullptr) _alloc = len;
    else _alloc = 0;
    _abschneiden = abschneiden;
  }

  ~EmuSerRead() {
    if (_str != nullptr) free(_str);
    _str = nullptr;
    _alloc = 0;
  }
  
  boolean getAbschneiden() {return _abschneiden;}
  void setAbschneiden(bool abschneiden) {_abschneiden = abschneiden;}

  // wieviele Bytes sind da  
  virtual int available() {
    return _len - _qi;
  }

  // lese 1 Byte und entnehme es
  virtual int read() {
    if (!available()) return -1;
    else return _str[_qi++];
  }

  // lese 1 Byte ohne es zu entnehmen
  virtual int peek() {
    if (!available()) return -1;
    else  return _str[_qi];
  }

  // die sind eher für Debugzwecke
  char * getStr() {return _str;}
  byte getLen() {return _len;}
  byte getAlloc() {return _alloc;}

  // kein schreiben
  virtual size_t write(uint8_t) {return 0;}

  // Return 0=ok, 1 = zu lang (abgeschnitten/nicht übernommen), -1 = nicht initialisiert
  char setStr(char *p, byte len) {
  bool zuGross = false;
    if (_str == nullptr) return -1;  // sollte nicht vorkommen
    if (len > _alloc) {
      zuGross = true;
      if (!_abschneiden) return 1;
      _len = _alloc;
    }  
    else _len = len;
    memcpy(_str,p, _len);
    _qi=0;
    return (zuGross) ? 1 : 0;
  }

private:
  byte *_str = nullptr;  // Bytearray
  byte _alloc = 0;       // Wieviel Bytes sind alloziiert
  byte _qi =0;           // Index zum byteweisen auslesen
  byte _len = 0;         // reale Länge
  bool _abschneiden = false;  // sollen zu lange Eingaben bei setStr abgeschnitten werden
};

/******************** Ausgabefunktion **************************/
void printChArrHex(char *p) {
byte i = 0;
byte c;
  while (c = p[i++]) {
    Serial.print(" 0x");Serial.print(c,HEX);
  }
  Serial.println("0x0");
}

void printByteArrHex(byte *p, byte len) {
byte c;
  for(byte i=0; i< len; i++) {
    c = p[i];
    Serial.print(" 0x");Serial.print(c,HEX);
  }
  Serial.println();
}


/***************************************************************************/

char puffer[21];

enum Status {RUHE, IM_LESEN, FERTIG};

EmuSerRead ser(10,false);

void senden(byte id, int h, int t) {
  puffer[0]=0x1; // Startbyte
  puffer[1]=id;
  sprintf (puffer+2, "%d,%d\n", h, t);
  // Serial.println(puffer);
  // printChArrHex(puffer);
  char res = ser.setStr(puffer, strlen(puffer));
  Serial.print("Res: ");Serial.println(res,HEX);
  memset(puffer,0,sizeof(puffer));
  // printByteArrHex(ser.getStr(),ser.getLen());
  
  
}

byte readInput(Stream &s) {
static byte idx = 0;
static Status status = RUHE;
byte c;
  if (status == FERTIG && idx > 0) { // aufräumen
    status = RUHE;
    idx = 0;
    memset(puffer,0,sizeof(puffer));
  }

  if (s.available()) {
    c = s.read();
    if (status == RUHE) {  
      if (c == 0x1) status = IM_LESEN; // Startbyte gefunden
    }
    else if (status == IM_LESEN) {
      if (c == '\n') {
        puffer[idx] = '\0'; // Ende gefunden
        status = FERTIG;
        return puffer[0];  // id
      }  
      else puffer[idx++] = c;
    }
    
  }
  return 0;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start");
  senden(0x90,12345,31890);
  // Serial.println(ser.available());
}


void loop() {
byte b;
int h,t;
static bool neu = true;
  if (b = readInput(ser)) {
    Serial.print("ID: ");Serial.println(b,HEX);
    sscanf(puffer+1,"%d,%d",&h,&t);
    Serial.print("Hum:  ");Serial.println(h);
    Serial.print("Temp: ");Serial.println(t);
    if (neu) {
      senden(0x91,1111,4444);
      neu = false;
    }
  }
}

Man kann es natürlich auch in eine
EmuSerRead.h auslagern und per #include einfügen.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  virtual wire empfänger-sender peterfried 30 793 17.04.2019 07:21
Letzter Beitrag: Tommy56
  2 PWM-Signale ohne Überschneidung mephistopheles 8 473 27.03.2019 09:45
Letzter Beitrag: mephistopheles
  [Vorstellung] Erweiterte Printroutinen Tommy56 1 331 19.02.2019 18:33
Letzter Beitrag: Blende8
  GShield v5B / Arduino Due / Verwendung ohne G-Code bytecook 0 333 26.08.2018 11:33
Letzter Beitrag: bytecook
  Doppelte Abfrage der Bedingung mit Wartezeit ohne Delay soluman 3 983 05.07.2018 20:53
Letzter Beitrag: GuaAck
  Serieller Monitor BluPxl 13 2.046 28.05.2018 16:21
Letzter Beitrag: BluPxl
  Leds dimmen ohne delay jennerlein 9 1.609 20.04.2018 02:04
Letzter Beitrag: Corvus
  Struct mit Defaultdaten ohne initalisieren nutzen? da_user 14 1.630 22.03.2018 19:11
Letzter Beitrag: da_user
  Serieller Eingang sendet alles per SMS weiter Timmae3000 2 667 08.03.2018 09:30
Letzter Beitrag: hotsystems
  Serieller string zwischenspeichern und wieder ausgeben. Matt 15 2.552 03.03.2018 20:23
Letzter Beitrag: Tommy56

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste