Serielle Datenstring vom Computer im Adruino Mega einlesen und aufteilen

Ich geh mal noch darauf ein.
A3 - A11 sind 9.
Und 25 - 30 sind 6.
:wink:

Hab mir mal Gedanken gemacht. Du hast nen Spannungsteiler? Dann darf ich davon ausgehen, das bei +5V am Analogpin mit 24V gerechnet wird?
Dann könnte man daraus ein map() machen.

Brauchst Du eine Nachkommastelle?
Wie oft brauchst Du den Wert an den Empfängern?
Wie genau muss der Wert zum Zeitpunkt des senden sein?
Wenn Du mittelst zwischen gemessenem und letztem gemessenen Wert, kann es etwas dauern bis das mittel dem (unveränderten) aktuellen Wert entspricht.
Beispiel:
vorher 12V - nachher 20V
(12+20)/2 = 16
(16+20)/2 = 18
(18+20)/2 = 19
(19+20)/2 = 19,5
... usw.
Das kann also ggfls. ne Handvoll Umläufe dauern...
Aber schon nach dem ersten siehst, das es nicht mehr passt.

Ansonsten dürfte das kein grosses Ding werden.
Die Behandlung kann sich an der Funktion sendFeld orientieren und dort sogar eingearbeitet werden.

Bei den Werten für die Ampel muss man sehen, ob man das als bool-array nimmt und dann sendet, wenn sich der Inhalt verändert hat.

Mal sehen, was mir am Wochenende einfällt.

Na denn...

So mein lieber...
Ich hab mal was fürs Senden.
Empfangen sollte dann fast genauso gehen.
Ich hab mir schon nen Kommentar-Tab gebaut :wink:
Na denn. Hier die Kommentare von heute:

Notizen - Pinbelegung - verwendete Sende-Kürzel
2, 4 - NRF-CS/CE
20, 21 - I2C
25 - 29 - DigitalIn für Ampelabfrage
A3 - A10 - AnalogIn Spannungswert Fahrspur (ansprechbar als 57 - 64)
44 - 46 - Taster

Wenn mit Buchstabe begonnen, gilt für alle Empfänger
T {unixtime} - Unixzeit an alle
A {Ampel} - Ampelstatus (5 Pins im Array)
C {Temperatur}- DHT22 Wert
Wenn mit Zahl begonnen, gilt für die Spurnummer
{spurnummer}F - Fahrername
{spurnummer}R - beste Runde
{spurnummer}Z - Rundenzeit
{spurnummer}V - Voltage

Änderungen 10.9.2021
Neu für Ampel und Voltage:
// Bahndaten

  const uint8_t voltagePin[] = {A3, A4, A5, A6, A7, A8, A9, A10};
  const uint8_t ampelPin[] = {25, 26, 27, 28, 29};
  bool ampel[sizeof(ampelPin)] = {false};
  uint8_t voltage[sizeof(voltagePin)+1] = {0};

im Setup:

  // Init AmpelPin
  for (uint8_t i = 0; i < sizeof(ampelPin); i++)
  {pinMode(ampelPin[i], INPUT);}

im loop

  leseVoltage();                           // liest an AnalogPins die Spannung der Spuren

neue Funktion:

  void leseVoltage()
  {
  for (uint8_t i = 0; i < sizeof(spuren); i++)
  {
    voltage[i] = (voltage[i] + map(analogRead(voltagePin[i - 1]), 0, 1023, 0, 240)) / 2;
  }

Änderungen für Voltage
In der Funktion
void sendFeld(const uint8_t spurNummer, const char feldName)
eingefügt:

      case 'V':                              // sendet Voltage
      sprintf(lokalBuf, "%uV %u", spurNummer, voltage[spurNummer]);
      break;

Die Funktion
void sendeBahn(const uint32_t sendTimer) // versendet ein Feld aus den gespeicherten Daten
Neue Variable:

    static uint32_t lastVoltageSend = 0;   // (Zeit-)Merker für den Versand der Voltagedaten

am Ende geändert und NEU eingefügt:

        case fahrer:                         // Fahrername
        if (millis() - lastFahrerSend > 1000)
        {
          sendFeld(spur, 'F');
          lastFahrerSend = millis();
        }
        break;
      case volt:
        if (millis() - lastVoltageSend > 2000)
        {
          sendFeld(spur, 'V');
          lastVoltageSend = millis();
        }
        spur++;
        if (spur >= spuren + 1)
        {
          spur = 0;
        }
        break;
    }
    feld++;
    if (feld > volt)
    {
      feld = runde;
    }
  }
  }

Nicht wundern, die ketzten beiden Klammern aus der Notiz stimmen so.
Und hier der Sender mit Voltage.

Er sendet Voltage als Byte - macht dann irgendwo am Empfänger 240 als oberste Grenze
Ich will, das Du am Empfänger den gesendeten Wert genau so auf dem SerMon darstellst.

Das "Nachkomma" bekommen wir dann hin.
Na dann.

// Benziner_Sender_Stand 10.09.2021
https://forum.arduino.cc/t/serielle-datenstring-vom-computer-im-adruino-mega-einlesen-und-aufteilen/664626/472?u=my_xy_projekt
// basiert auf Benziner_Sender_#174 erste Erweiterung aus #458 (Voltage)

//Uhr
#include <DS1307RTCB.h>                  // auf die TimeLibB angepasste 1307 von Paul Stoffregen
#include <TimeLibB.h>                    // auf deutsch umgeschriebene TimeLib von Paul Stoffregen

// Sender
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>                      // für die nrf-Lib debug-Ausgabe erforderlich
RF24 radio(2, 4);                        // CE, CSN - MISO 50, MOSI 51, SCK 52
const uint8_t address[6] = "00001";      // Sender-Adresse

// Display
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Tasterelemente
const uint8_t tasterLinks = 45;
const uint8_t tasterRechts = 44;
const uint8_t tasterLinksLED = 47;
const uint8_t tasterRechtsLED = 46;
const uint32_t bounceTime = 100;          // hoeher gewaehlt auch wegen LCD-Geschwindigkeit
const uint32_t timeout = 30000;           // Zeit die ohne Tastendruck vergehen muss um einen Abbruch zu erzwingen

// Renndaten
const uint8_t spuren = 4;                 // Anzahl befahrener Spuren
const uint8_t charNum = 26;               // max Anzahl Zeichen (derzeit Fahrername (25+1))
const uint8_t maxPSize = 32;              // maximale Anzahl Zeichen, die mit einem Mal versandt werden können

//                                        // AR - RZ - F werden mehrere Datensätze
uint16_t AR[spuren + 1];                  // Runden in der Spur
uint16_t RZvk[spuren + 1];                // Rundenzeit Vorkomma in der Spur
uint16_t RZnk[spuren + 1];                // Rundenzeit Nachkomma in der Spur
char F[spuren + 1][charNum];              // Fahrername in der Spur

// Bahndaten
const uint8_t voltagePin[] = {A3, A4, A5, A6, A7, A8, A9, A10};
const uint8_t ampelPin[] = {25, 26, 27, 28, 29};
bool ampel[sizeof(ampelPin)] = {false};
uint8_t voltage[sizeof(voltagePin) + 1] = {0};


bool ausgabe = false;                     // Wartet auf Vollständigkeit

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial1.begin(19200);
  // Tasten
  pinMode(tasterLinks, INPUT_PULLUP);
  pinMode(tasterRechts, INPUT_PULLUP);
  // Uhr
  setSyncProvider(RTC.get);               // Festlegen der Zeituebergabe an timeLib
  // setSyncInterval(3000);               // default festgelegt: 5000 ms
  Serial.print("Keine ");
  Serial.println("RTC gefunden");
  // Init AmpelPin
  for (uint8_t i = 0; i < sizeof(ampelPin); i++)
  {pinMode(ampelPin[i], INPUT);}
  // Display
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  // Sender
  printf_begin();                          // muss fuer debugging rein
  pinMode(53, OUTPUT);                     // verhindert den SPI-SlaveMode
  radio.begin();                           // Start der 2,4 GHz Wireless Kommunikation
  radio.enableDynamicPayloads();
  radio.setPALevel(RF24_PA_MIN);           // Leistung des NRF(MAX,HIGH,LOW,MIN)
  radio.setDataRate(RF24_1MBPS);           // Setzen der Übertragungsgeschwindigkeit
  radio.setAutoAck(0);                     // Nicht auf Bestätigungsantwort warten
  radio.openWritingPipe(address);          // Setzen der Sendeadresse
  radio.stopListening();                   // Das angeschlossene Modul als Sender konfiguriert
  startBild();
  while (millis() < 2000)
  {
    sendeZeit(50);                         // Sendet die Zeit an alle Client
  }
  Serial.println(F("Let's go running..."));
}

void loop()
{
  leseBefehl();                            // anstelle eines Menu
  leseBahn();                              // liest fortlaufend vom Renncomputer ein
  leseVoltage();                           // liest an AnalogPins die Spannung der Spuren
  sendeBahn(5);                            // sende alle xx ms ein Datenfeld aus den Bahndaten
  sendeZeit(5000);                         // sende alle xx ms die Uhrzeit
  // serMon();
}

void leseAmpel()
{
  bool ampelTemp[sizeof(spuren)] = {0};      // temporäre Variable
  char sendAmpel[10] = {0};                // Für Übergabe
  for (uint8_t i = sizeof(ampelPin); i > 1 ; i--)
  {
    ampelTemp[i] = digitalRead(ampelPin[i]); // liest den Zustand der Pin ein
  }
  // hier vergleiche ist das gelesene mit dem bekannten
  // nur wenn ungleich, dann senden
  if (memcmp(ampelTemp, ampel, sizeof(ampelTemp)) != 0)
  {
    memcpy(ampel, ampelTemp, sizeof(ampel));
    //sprintf(sendAmpel, "A %i", (uint16_t)ampel);   // Datenpaket zusammenstellen
    //  sendData(&ampel);
    Serial.print(F("Sende Ampel: ")); Serial.println(sendAmpel);
  }
}

void leseVoltage()
{
  for (uint8_t i = 0; i < sizeof(spuren); i++)
  {
    voltage[i] = (voltage[i] + map(analogRead(voltagePin[i - 1]), 0, 1023, 0, 240)) / 2;
  }
}

void sendeBahn(const uint32_t sendTimer)   // versendet ein Feld aus den gespeicherten Daten
// sendTimer: Zeit in ms - in welchen Abständen die Funktion ein(!) Feld sendet
// Ein Umlauf: Anzahl Spuren(5) * Felder je Spur(3) * Zeit(5ms) ca. 75ms
{
  static uint32_t lastMillis = 0;          // Merker für letzte Sendung
  if (millis() - lastMillis > sendTimer)   //
  {
    enum {runde, zeit, fahrer, volt};      // was soll versandt werden
    static uint32_t lastFahrerSend = 0;    // (Zeit-)Merker für den Versand eines Fahrernamen
    static uint32_t lastVoltageSend = 0;   // (Zeit-)Merker für den Versand der Voltagedaten
    static uint8_t feld = runde;           // Merker Welches Feld versandt wird
    static uint8_t spur = 0;               // aus welcher Spur
    lastMillis = millis();
    switch (feld)
    {
      case runde:                          // sende Rundennummer
        sendFeld(spur, 'R');
        break;
      case zeit:                           // Rundenzeit
        sendFeld(spur, 'Z');
        break;
      case fahrer:                         // Fahrername
        if (millis() - lastFahrerSend > 1000)
        {
          sendFeld(spur, 'F');
          lastFahrerSend = millis();
        }
        break;
      case volt:
        if (millis() - lastVoltageSend > 2000)
        {
          sendFeld(spur, 'V');
          lastVoltageSend = millis();
        }
        spur++;
        if (spur >= spuren + 1)
        {
          spur = 0;
        }
        break;
    }
    feld++;
    if (feld > volt)
    {
      feld = runde;
    }
  }
}
void sendFeld(const uint8_t spurNummer, const char feldName)
{
  char lokalBuf[maxPSize] = {0};
  switch (feldName)
  {
    case 'F':                              // sendet Fahrernamen
      sprintf(lokalBuf, "%uF %s", spurNummer, F[spurNummer]);
      break;
    case 'R':                              // sendet Rundennummer / Beste Spurnummer
      sprintf(lokalBuf, "%uR %u", spurNummer, AR[spurNummer]);
      break;
    case 'Z':                              // sendet Rundenzeit
      sprintf(lokalBuf, "%uZ %u %u", spurNummer, RZvk[spurNummer], RZnk[spurNummer]);
      break;
    case 'V':                              // sendet Voltage
      sprintf(lokalBuf, "%uV %u", spurNummer, voltage[spurNummer]);
      break;
  }
  if (strlen(lokalBuf) > 0)                // Nur wenn was im Puffer steht senden!
  {
    sendData(lokalBuf);
  }
}
void sendData(char *sendbuffer)
{
  radio.write(sendbuffer, strlen(sendbuffer));
  Serial.print(F("Daten gesendet: "));
  Serial.println(sendbuffer);
}
void sendeZeit(const uint32_t sendTimer)   // Versendet LokalZeit
{
  static uint32_t lastMillis = 0;          // Merker wann das letzte Mal
  if (millis() - lastMillis >= sendTimer)
  {
    char zeit[14] = {0};                   // Puffer
    lastMillis = millis();
    sprintf(zeit, "T %ld", now());         // Datenpaket zusammenstellen
    sendData(zeit);
    Serial.print(F("Sende Zeit: ")); Serial.println(zeit);
  }
}


void startBild()
{
  // ************ Anfang LCD Start-Anzeige ***********
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Con V-12.0 modx"));
  lcd.setCursor(0, 1);
  lcd.print(F("  4-Spur    "));
  // *************Ende LCD Start-Anzeige *************
}

void serMon()
{
  const uint32_t intervall = 5000;
  serMon(intervall);
}

void serMon(const uint32_t intervall)
{
  static uint32_t lastmillis = 0;
  ausgabe = true;
  if (ausgabe == true && (millis() - lastmillis) > intervall) // Wenn Ausgabe frei
  {
    lastmillis += intervall;
    ausgabe = false;
    for (uint8_t i = 0 ; i <= spuren; i++)
    {
      if (!i)
        Serial.print("BRS");
      else
      {
        Serial.print("AR");
        Serial.print(i);
      }
      Serial.print(": ");
      Serial.print (AR[i]);
      if (!i)
        Serial.print(" BRZ");
      else
      {
        Serial.print(" RZ");
        Serial.print(i);
      }
      Serial.print(": ");
      Serial.print(RZvk[i]); Serial.print(" - "); Serial.print(RZnk[i]);
      if (!i)
        Serial.print(" BRF");
      else
      {
        Serial.print(" F");
        Serial.print(i);
      } Serial.print(": "); Serial.println(F[i]);
    }
    Serial.println();
  }
}
void leseBefehl()
{
  char readChar;                           // Einzelnes Zeichen
  static uint8_t x = 0;                    // Position im Array
  static char buf[charNum] = {0};          // Zwischenspeicher
  while (Serial.available() > 0 )
  {
    readChar = Serial.read();              // Einlesen
    Serial.print(readChar);
    if (!isControl(readChar))              // Zeichen ist kein Steuerzeichen ...
    {
      buf[x] = readChar;                   // ... dann aufnehmen ...
      x++;                                 // ... neue Position setzen
    }
    else                                   // ... ist Steuerzeichen
    {
      if (isLowerCase(buf[0]))             // erstes Zeichen Kleinbuchstabe? ...
      {
        sendData(buf);                     // ... verschicken ...
        memset(buf, 0, sizeof(buf));       // ... Puffer löschen und ...
        x = 0;                             // ... zurücksetzen
      }
    }
  }
}

void leseBahn()                            // Datensatz vom RennPC
{
  const bool serialdebug = false;
  const uint32_t breakTimeRead = 50;       // Abbruchzeit in ms
  char readChar;                           // Einzelnes Zeichen
  static uint8_t x = 0;                    // Position im Array
  static char buf[charNum] = {0};          // Zwischenspeicher
  uint32_t lastmillis = millis();          // Startzeit merken...
  while (Serial1.available() > 0 && millis() - lastmillis < breakTimeRead)
  {
    readChar = Serial1.read();             // Einlesen
    if (serialdebug) Serial.print(readChar);
    if (readChar == ';')                   // Feldende? ...
    {
      buf[x] = '\0';                       // ... CharArray abschliessen ...
      teileBuf(buf);                       // ... Übergeben zum teilen und senden ...
      x = 0;                               // ... Position im Array rücksetzen
    }
    else if (!isControl(readChar))         // Zeichen ist kein Steuerzeichen ...
    {
      buf[x] = readChar;                   // ... dann aufnehmen ...
      x++;                                 // ... neue Position setzen
    }
  }
}

void teileBuf(char *buf)                   // Teilt den (Feld)Puffer
{
  //  Serial.println(buf);
  static bool istGleich = true;            // Merker letzter/aktueller Wert gleich?
  char *c;                                 // Teilstring
  char lokalBuf[charNum] = {0};            // Zwischenspeicher für Vergleich (Zeichenkette) Array
  uint16_t lokalInt = 0;                   // Zwischenspeicher für Vergleich (Zahl) Array
  c = strtok(buf, ":");                    // Übernehme bis Trennzeichen 1
  //                                       // Beste Rundenzeit - Aufteilung kommentiert
  if (!strncmp(c, "BRZ", 3))               // Vergleich auf Feldname ...
  {
    lokalInt = atoi(strtok(NULL, ","));    // ... Erste Zahl - Trenner ist ,
    if (RZvk[0] != lokalInt)               // bisheriger Wert ist anders? ...
    {
      RZvk[0] = lokalInt;                  // ... dann setze den Wert ...
      istGleich = false;                   // ... merke, das neuer Wert gesetzt
    }
    lokalInt = atoi(strtok(NULL, ","));    // ... zweite Zahl ...
    if (RZnk[0] != lokalInt)               // ... wie vor
    {
      RZnk[0] = lokalInt;
      istGleich = false;
    }
    if (!istGleich)                        // Neue Daten bekommen? ...
    {
      sendFeld(0, 'Z');                    // ... sende Daten! ...
      istGleich = true;                    // ... setze Merker zurück
    }
  }
  else if (!strncmp(c, "BRF", 3))
  {
    strcpy(lokalBuf, strtok(NULL, ":"));   // Bester Fahrername
    if (F[0] != lokalBuf)                  // Inhalt geändert? ...
    {
      memcpy(F[0], lokalBuf, sizeof(lokalBuf)); // ... schreibe ins Array ...
      sendFeld(0, 'F');                         // ... sende Daten
    }
  }
  else if (!strncmp(c, "BRS", 3))
  {
    lokalInt = atoi(strtok(NULL, ":"));    // Beste Spur
    if (AR[0] != lokalInt)                 // Inhalt geändert? ...
    {
      AR[0] = lokalInt;                    // ... nehme Daten auf ...
      sendFeld(0, 'R');                    // ... sende Daten: Spur0 Runden
      istGleich = false;                   // ..
    }
  }
  else if (!strncmp(c, "AR", 2))           // Rundennummer
  {
    uint8_t s = c[2] - '0';                // ermittelt die Spur
    lokalInt = atoi(strtok(NULL, ":"));
    if (AR[s] != lokalInt)
    {
      AR[s] = lokalInt;
      sendFeld(s, 'R');
    }
  }
  else if (!strncmp(c, "RZ", 2))           // Rundenzeit
  {
    uint8_t s = c[2] - '0';
    lokalInt = atoi(strtok(NULL, ","));
    if (RZvk[s] != lokalInt)
    {
      RZvk[s] = lokalInt;
      istGleich = false;
    }
    lokalInt = atoi(strtok(NULL, ","));
    if (RZnk[s] != lokalInt)
    {
      RZnk[s] = lokalInt;
      istGleich = false;
    }
    if (!istGleich)
    {
      // ACHTUNG Nicht verrückt machen, der Fahrername für die Spur ist hier noch nicht ermittelt!
      // das sieht etwas komisch in der Ausgabe aus
      //      serMon(0);
      sendFeld(s, 'Z');
      istGleich = true;
    }
  }
  else if (!strncmp(c, "F", 1))            // Fahrer
  {
    uint8_t s = c[1] - '0';
    strcpy(lokalBuf, strtok(NULL, ":"));
    if (F[s] != lokalBuf)
    {
      memcpy(F[s], lokalBuf, sizeof(lokalBuf));
      sendFeld(s, 'F');
    }
  }
}

Trotzdem unglaublich, eine Idee so schnell in die Tat umzusetzen. Ich ziehe den Hut davor mit dem Wissen das Du das erst seit 5 Jahren(wenn ich mich recht erinnere) machst. Wenn ich sehe wie meine Entwicklung in den letzten Jahr war, zweifel ich an mir selbst.

Morgen baue ich das mal auf und dann schau ich mal was Du da schönes programmiert hast.
Freu mich drauf :smiley: :+1:

Ohh Gott wie peinlich....möchte in Boden versinken!!!

Mal, der Witz ist gut....ich glaube das machst Du pausenlos bei meinen Ideen. :wink:
Dankbar, ich Dir bin.

Ja, es werden 8 Spannungsteiler aber die +5 V an den Analogen ist bei 30 V.
Grund ist hierzu ist das die Labornetzteile 30 Volt liefern können, und für den Fall das einer mal an den Netzteilen spielt und auf 30 Volt stellt die Analogen eben nicht mehr wie 5V bekommen.

Nachkommastelle wäre schon schön weil einige fahren mit 14,5 V..... es würden 0,5 V Schritte reichen.Aber ich glaube das hilft nicht wirklich, oder?

Im Grunde würde es reichen wenn er sich am Konverter verändert hat, aber auf Hinsicht NoACK glaub ich nicht empfehlenswert.

Ist abhängig vom senden, um so weniger ich sende um so genauer müsste gesendet werden. Die Zeit spielt dabei nicht die große Rolle.

Ich weiß nicht ob ich jetzt richtig an die Sache ran gehe aber vielleicht inspiziert es ja :wink:
Wie wäre es wenn man nur eine Zahl für die Ampel übermittelt?
z.B.
0=alle 5 Lichter aus
1= 1 Licht an
2= 2 Lichter an usw.

So, wäre die Übermittlung kurz da nur eine Zahl gesendet werden müsste und der Empfänger könnte es wieder umsetzen....hat ja sonst nichts zu tun. :grinning_face_with_smiling_eyes:

Ein großes Danke mal wieder an Dich / Euch

Schade. Ganz doll schade.
Wenn ich max 24V habe, dann kann ich mit einem Byte auskommen.
Der ByteWert 249 entspräche dann 24,9V
Hm..
Na mal schauen.
Ist ja noch nicht Wochenende.

(Unsere beiden Postst waren zeitgleich :wink: ) - na dann...

Ist nur zum Schutz des kleinen..... :wink:
Nicht das er in Rauch aufgeht......

Ich bin grad am überlegen, ob ich das als Kaskade baue.
Der Eingang als uint16_t mappen von 0 - 30.
Das senden von 0-25 und wenn es drüber liegt einfach abschneiden.

Würde das reichen, wenn Du weisst, das mehr als 25V anliegen?
Nehmen wir an, das voltage jetzt uint16_t ist:

voltage[i] = (voltage[i] + map(analogRead(voltagePin[i - 1]), 0, 1023, 0, 300)) / 2;

if (voltage[i] > 250)
  voltage[i] = 251;

Denk mal drüber nach.
Weil 9 Byte (Bahnen) und zusätzlich Kennung passen in ein Paket (maxPayload=32). Es bräuchte keine Umläufe.

Hallo XY Projekt,
irgendwie habe ich das gestern nicht mitbekommen, war heute ganz erstaunt wie fleißig Du gestern warst. Nun kannst Du Dir ja vorstelle das ich damit erst mal wieder zurechtkommen muss. Gehöre dabei nicht gerade zu den schnellsten......

Nur als Info für mein Verständnis, war es Absicht nicht den letzten Stand von Sender zu nehmen?
Wenn ja, wirst Du Deine Gründe dafür haben und werde bestimmt später erfahren warum....oder ich weiß es dann selbst. Aber das glaube ich ehr nicht.

Das ist vollkommen ausreichend.

So, dann werde ich mich jetzt darangeben den Sender zum laufen zu bekommen....na und dann
versuche ich mal die Hausaufgabe zu bewerkstelligen.
Eine Verneigung vor Deinem Können und Deiner Außerordentlichen unermüdlichen Hilfe.

Hallo Agmue,
ich habe heute mal ein Nano mit einem 64er Block WS zusammengesteckt und Deinen Sketch ausprobiert. Gut durch den 64ér Block sind die Led´s nicht an Punkt und Stelle.
Bitte sei mir jetzt nicht böse wenn ich das vorerst zurückstelle, aber die Konvertor / Empfänger haben Vorrang. Und Multitasking in Sachen programmieren hab ich nicht drauf, muss mich da erst mal auf eins konzentrieren.

Euch allen ein gut Nächtle und immer schön Gesund bleiben.

Nö, nur keine Sorgen :slightly_smiling_face:

@my_xy_projekt
Ich hab mal was zum empfangen

// Verarbeitung
uint8_t temp = 21;                    // Temperatur wir noch vom Converter übermittelt
const uint8_t maxSpuren = 8;
uint16_t AR[maxSpuren + 1] = {0};
uint16_t RZvk[maxSpuren + 1] = {0};
uint16_t RZnk[maxSpuren + 1] = {0};
uint16_t Voltage[maxSpuren + 1] = {0}; // Spannung für die Spur
const uint8_t charNum = 26;           // Anzahl Buchstaben -1 für Fahrernamen
char Fahrer[maxSpuren + 1][charNum] = {0};


Die serielle Ausgabe habe ich wie folgt gelöst...

void displayKalender() // Start Anzeige
{
  if (minute() != minutealt)
  {
    minutealt = minute();
    char zeileAnzeige[16] = {0};
    memset(zeileAnzeige, 0, sizeof(zeileAnzeige - 1));
    sprintf(zeileAnzeige, "%s %02u.%02u.  %02u:%02u", dayShortStr(weekday()), day(), month(), hour(), minute());
    for (uint8_t i = 0; i < 7; i++)
        {
          Serial.print(F("Analogwert von Eingang "));
          Serial.print(i);
          Serial.print(F("="));
          Serial.println(Voltage[i])/10;
          
        }
    lcd.setCursor(0, 0);
    lcd.print(ver);
    lcd.setCursor(0, 1);
    lcd.print(zeileAnzeige);
    DEBUG_PRINTLN(zeileAnzeige);
  }
}// Ende Start-Tab

Wollte dann doch mal selbst versuchen die richtigen Werte zu senden....aber klappt noch nicht so...

void leseVoltage()
{
  //Aufbau nach https://mint-unt.de/mediapool/78/781152/data/Voltmeter.pdf  
  
  //for (uint8_t i = 0; i < sizeof(spuren); i++) **Warum hast Du das so gemacht ?**
  for (uint8_t i = 0; i < spuren; i++)
  {
    //voltage[i] = (voltage[i] + map(analogRead(voltagePin[i]), 0, 1023, 0, 240)) / 2;
    MesswertOut = (analogRead(voltagePin[0]))*5;
    MesswertIn = (MesswertOut /1023)/0.09 ;
    voltage[i]= MesswertIn *10 ;Um die Kommastelle mitzubekommen    
    
    //if (voltage[i] > 250)  voltage[i] = 251;
    Serial.print("Voltage ");
    Serial.print(i);
    Serial.print("= ");
    Serial.println(voltage[i]);
    Serial.println(MesswertOut);
    Serial.println(MesswertIn);
  }
}

Nun die Frage aller Fragen.....War ist mein Ansatz halbwegs richtig?

Sender_V33DCA.ino (15.3 KB)
Turm_Empfaenger_V70.5DCA.ino (46.7 KB)

Bitte, was geht nicht.
Was erwartest Du, was kommt ?

Ich muss wissen, wo ich was suchen muss.

Nun ich habe am A3 über den Spannungsteiler wie in ( https://mint-unt.de/mediapool/78/781152/data/Voltmeter.pdf beschrieben) eine 9V Block angeschlossen.

Da es nicht möglicht ist Floatzahlen in ein Array zu schreiben habe ich das Problem das ich für jede Spur zwei Float Variablen benötige. Ich wüsste nicht wie ich das Spuren abhängig hinbekommen soll. Möchte nicht unnötig Speicher verbraten :wink:

Wer behauptet das?

float fArr[6];

Gruß Tommy

Ne.
Der ist falsch, dafür war ja mein Ansatz.
Ich nehme das byte.
Bei Dir müsste aus dem Mapping dann 90 rauskommen.
Was bekommst Du als Wert, wenn Du mit dem - (achtung der Spannungsteiler muss auf die 30V gesetzt sein!!!) für einen Wert am analogPin ausgegeben?

Kleiner Einwurf:

memset scheint mir überflüssig zu sein, wenn man snprintf verwendet:

    char zeileAnzeige[16];
    snprintf(zeileAnzeige, sizeof(zeileAnzeige), "%s %02u.%02u.  %02u:%02u", dayShortStr(weekday()), day(), month(), hour(), minute());

Nur Kosmetik, aber warum eine Zeile zu viel schreiben :slightly_smiling_face:

@Tommy56 Bitte nicht!
Das braucht niemand. Es werden 9 Werte abgefragt, die auch noch mittels ner NRF übertragen werden müssen.
Ich fang jetzt nicht an, das wieder aufzudröseln, wenn nich das nicht brauch.
Ein NK. Nicht mehr und nicht weniger.

Versuch mal und gib mal, was da rauskommt: (mit der 9V Battery)

const byte pin = A3;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
}

void loop()
{
  uint16_t tik=analogRead(pin);
  Serial.print(tik);
  Serial.print("\t");
  Serial.println(map(analogRead(pin), 0, 1023, 0, 300));
  delay(1000);
}

Aufbau:

*--+
   |
   -
  |R1|
   -
   |
   +----PIN
   |
   -
  |R2|
   -
   |
---+----GND

R1 100K
R2 10K

Leider habe ich gerade kein Netzteil hier, genauen Wert gibt es dann leider erst Morgen.Habe wenn's hilft auf die schnelle mit 3 stück 9V Block getestet.
Getestet mit Widerständen R1=100KOhm; R2=10KOhm und Deinen ersten Vorgaben0,1023,0,240
Bei 9V Wert 40
bei 18 V Wert 82
bei 27 V Wert 124

Serial.println(map(analogRead(pin), 0, 1023, 0, 300));

Bei 9V Wert 50
bei 18 V Wert 103
bei 27 V Wert 153

Das war wohl nee glatte Falschmeldung von mir....Tommy,Danke Du hast mich eines besseren Belehrt.

Ne.
Im Code ist das auskommentiert und selbst errechnet.

void leseVoltage()
{
  //Aufbau nach https://mint-unt.de/mediapool/78/781152/data/Voltmeter.pdf  
  
  //for (uint8_t i = 0; i < sizeof(spuren); i++) 
  for (uint8_t i = 0; i < spuren; i++)
  {
    //voltage[i] = (voltage[i] + map(analogRead(voltagePin[i]), 0, 1023, 0, 240)) / 2;
    MesswertOut = (analogRead(voltagePin[0]))*5;
    MesswertIn = (MesswertOut /1023)/0.09 ;
    voltage[i]= MesswertIn *10 ;    
    
    //if (voltage[i] > 250)  voltage[i] = 251;
    Serial.print("Voltage ");
    Serial.print(i);
    Serial.print("= ");
    Serial.println(voltage[i]);
    Serial.println(MesswertOut);
    Serial.println(MesswertIn);
  }
}

Das, was Du da ausgibst sieht aus als wenn der Wert halbiert wäre.
Bei 27V -> 124
124 x 2 = 248 -> passt, wenn Obergrenze 30V ist.
Bei 18V -> 82
82 x 2 = 164 -> passt etwas mehr als die Hälfte

Insgesamt aber ungenau.
Ich würde genauer wollen.
Zumal ich schoin sehe, das Du hier dańeben liegst:

Die 0 ist ja eigenlich der PIN - Du fütterst jetzt alle Werte mit dem ersten Pin.