Serielle Datenstring vom Computer im Adruino Mega einlesen und aufteilen

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.

Diese Zeile habe ich wieder aktiviert....am ende dividiert durch 2

Das war der Grund warum ich anfing mit den Floatzahlen zu rechnen.....
Daher der Grund ein Float Array, wo ich dachte es würde nicht gehen.
MesswertOut ist eine Floatzahl, wenn ich nun ein Array MesswertOut erzeuge, dann könnte ich doch....
MesswertOut[i] = (analogRead(voltagePin[i]))*5;.....und dann wäre es wieder richtig.

Oder :thinking:

ODER!

Ha,
und ich hab auch raus, was Dir das Genick bricht:
Aus dem PDF:

TATA!
Der rechnet als Obergrenze mit 55V.
Damit ist auch klar, wo die Abweichung bei 18V herkommt.
unbelastet:

// Uin=30V

      Uin*R2
Upin=--------
      (R1+R2)

UPin=(30*10000)/(100000+10000)
UPin=300000/110000
UPin=2,727272727

AAAlso.
Dann rechnen wir mal Spannungsteiler:

R1 56K
R2 10K
Uin=30V

unbelastet:
      Uin*R2
Upin=--------
      (R1+R2)

UPin=(30*10000)/(56000+10000)
UPin=300000/66000
UPin=4,545454545

r1 51k
UPin=(30*10000)/(51000+10000)
UPin=300000/61000
UPin=4,918032787

Das dürfte Deine Größe sein.

Mach noch ne Z-Diode quer, wenn mal jemand 48V drauf haut und danach einen Längswiderstand und alles wird gut.

Morgen werde ich ein Netzteil mitbringen und dann teste ich das ganze mal, es ist schon wieder zu spät für mich....oder anders der Wecker soll es schaffen mich pünktlich aus dem Bett zu bekommen. :grinning_face_with_smiling_eyes:

@agmue
ist gemerkt....keine Zeile zuviel :wink:

Euch Allen ein großes Danke, ein gut Nächtle.....und schlaft schön den...
Morgen kommt der Chaot schon wieder :wink: :joy:

Bye

Hallo Xy Projekt,

ich weiß genau wo das Problem liegt...also zumindest hier bei mir.
Es liegt genau zwischen Bildschirm und der Rückenlehne vom Stuhl. :joy:

So, ich hab es noch mal versucht mit Labornetzteil und Float Array (Dank Tommy) Das Ergebnis ist gar nicht so schlecht ( finde ich)
Die Werte liegen nun fast immer im Bereich der eingestellten Spannung, Schwankungen +/- 0,3V aber das wird das Netzteil sein. Bei 9V Block bleiben die Werte konstant.

Bekomme nun folgende Werte heraus....
bei 5V / 49 +/-3

bei 14,5 V / 145 +/-3

bei 20 V / 200 +/-3

Wenn ich am Empfänger durch 10 dividiere habe ich Vorkomma / Nachkomma entweder ich lasse es dann als Floatzahl (dann durch 10.0 dividieren) oder mache daraus 2 int bzw. byte.

Und schon taucht ein neues Problem auf..... :woozy_face:
Der Wert z.B. 203 würde ja 20,3 V bedeuten. Wie bekomme ich das auf 20,5 gerundet oder andersrum wie bekomme ich den Wert 198 auf 20,0 gerundet?

Scheint ein Problem zu werden weil es ja nicht immer die gleiche Spannung ist.... :thinking:

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++)
  {
    MesswertOut[i] = (analogRead(voltagePin[i])) * (5.0 / 1024.0);
    voltage[i] = (MesswertOut[i] * ((R1 + R2) / R2)) * 10 ;
    if (voltage[i] > 245)  voltage[i] = 250;

    Serial.print("Voltage ");
    Serial.print(i);
    Serial.print("= ");
    Serial.println(voltage[i]);

  }
}

Ach da hab ich noch einen...
Werte über 245 werden nicht als 250 angezeigt, lasse ich die Zeile weg wird der Wert bis 300
wieder richtig angezeigt....Aber der Wert darf 250 nicht überschreiten.

Ich glaub ich tausche den Typen auf dem Stuhl aus... :thinking: :grinning:

Du machst es Dir VIEEL zu umständlich.
Las das selbst rechnen weg!

Was macht der sketch aus #487?
Der Wert 300 ist das Maximum, was ich ERWARTE.
Wenn Du einen Spannungsteiler 10/100 baust, ist das Maximum 550.
Wenn Du einen anderen R nimmst -> siehe meine Rechnerei in #492 - also 51K statt 100 - dann hast Du als Obergrenze 30V. Vorsicht, nicht drüber gehen beim testen ohne Schutzbeschaltung, wie von mir angesprochen.

Höre auf mit dem float.
Das ist überflüsig und nicht mal annähernd zielführend.
Las das byte als eine Zahl und NUR die Anzeige aufteilen.

Warum willst du runden? Du bekommst auf eine NK genau das Ergebnis geliefert.
runden geht so:
https://www.cplusplus.com/reference/cmath/round/
Willst Du nicht :wink:

Gut. Wenn Du unbedingt auf halbe Stelle runden willst, dann trenn die NK ab und schau, was Du hast. Ist NK <3 NK=0
NK>2 && NK <8 dann NK=5
Wenn NK >7 dann NK=0 und VK+1

Ist ne MinimalFunktion.

Mir erschliesst sich nur noch nicht das warum. :face_with_monocle:

Alles andere als Werte die man gebrauchen könnte....
Die Werte springen wahllos von 4 bis 250 auf und ab.
Nehme ich den den Teiler /2 am Ende der Zeile auf bleiben die Werte konstant auf 50
Gemessen an 9 V Block die mit Multimeter 9,56V anzeigt.

Na das schaffe ich erst morgen wieder.... :sleepy:

Okay, dann höre ich auf damit, war ein versuch von mir vernünftige Zahlen aus den Analogen zu bekommen.

Weil dann die Anzeigen nicht auch auf und ab springen sollten.

Nein :woozy_face: :thinking:

Damit bekomme ich wahrscheinlich ruhe in die Displays

Also werde ich morgen mal im E-Shop meines Vertrauens vor und noch ein paar Widerstände holen. Könntest Du mir bitte noch eine kleine Skizze machen wie Du das meintest mit der Schutzschaltung.... :kissing_closed_eyes:

So, und nu ab ins Bett....Euch ein gut Nächtle.

Diese Spannungsteiler sind zu hochohmig damit der AD/Wandler immer sicher funktioniert. Schalte einen 0,1µF Kondensator zwischen Analogeingang und Masse.

Diese Rechnung geht falsch. Ohne andere Maßnahmen wird mit INT gerechnet und da ist 300-tausend und 66-tausend zu groß für ein INT. Da hilft UL dazuschreiben

Grüße Uwe

Das wird ja nicht im Code gerechnet.
Das ist eine Nebenrechnung mit einem Taschenrechner, die darstellt, was beim Spannungsteiler 56K(51k)/100K mit einer Eingangsspannung von 30V am Pin als Spannung ankommt.

Jo. das wäre jetzt auch meine Massnahme gewesen, bzw. die Widerstandswerte 4teln. Das dürfte noch reichen.
UIN=30V - R1=13k - R2=2.5K
UPin=(30*2500)/(13000+2500)
UPin=75000/15500
UPin=4,838709677

Kann man machen, man kann aber auch eine Hysterese festlegen, ab wann der Displayinhalt neu geschrieben wird.
Einfach abfragen, ob das aktuelle byte mehr als xxx Abweichung zum letzten byte hat.

Ansonsten, nur um mal das mit der Aufteilung zu zeigen:

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (uint16_t i = 0; i < 300; i++)
    serialRound(i);
}

void serialRound(uint16_t rund)
{
  const byte obergrenze = 250;
  if (rund > obergrenze) rund = obergrenze;

  Serial.print(rund);
  Serial.print("\t");
  if (rund >99)
  Serial.print(rund%1000/100);
  Serial.print("\t");
  if (rund >9)
  Serial.print(rund%100/10);
  Serial.print("\t");
  if (rund >0)
  Serial.print(rund%10);
  Serial.println();
}

void loop()
{
}

Seriellen Monitor an - einfach durchlaufen lassen.
(Nein es wird noch nicht gerundet - nur die Aufteilung....)
Na dann.
Ich mach mir Gedanken - aber nicht zu morgen Abend.

Hallo Uwe,
vielen Dank für deine Unterstützung, ich weiß Eure Hilfe bei meinem Projekt sehr zu schätzen.

Hallo Xy Projekt,
das klingt nicht schlecht, ich verstehe es zwar nicht warum diese Schwankungen am Mega sichtbar sind und am Display des Labornetzteil nicht. Vielleicht bringt der von Uwe vorgeschlagene Kondensator schon ein wenig Ruhe rein.

Bin schon am überlegen ob es Sinn macht in 0,5 V Schritten anzuzeigen zu lassen wenn die Anzeigen so zappeln. Da steig ich dann lieber auf 1 Volt Schritte um.

Mein freundlicher E-Shop hat leider sein Geschäft dauerhaft geschlossen..... auch ein Corona-Opfer der willkürlichen Corona-Regeln . :worried:

Schade, was bleibt ist die Reichen eben noch reicher zu machen.....macht auch Sinn für die Umwelt, Hunderte von Kilometer fahren für en Tütchen Widerstände......Aber da sagt Greta nichts.....

Sorry, aber regt mich einfach auf das unsere Innenstädte immer mehr aus 1 Euro Geschäfte und Imbissbuden bestehen.

Was ich eigentlich sagen wollte das ich die Widerstände bestellt habe, und wenn die kommen ich erst dann weitertesten kann....
von daher "aber nicht zu morgen Abend" gar nicht so tragisch :wink:

Kann auch mal ne Pause gebrauchen, der wenige Schlaf und und das 18 Stundendenken macht mich fertig :joy:

Hab das getestet mit der Aufteilung 1+ :+1:
Was ich noch fragen wollte, die eventuelle Umrechnung der Analogwerte machen wir im Empfänger oder ?

Heute geh ich früh ins Bett, bin fix und alle.... :yawning_face:
Euch noch ein schönen Abend,ein gut Nächtle und immer schön Gesund bleiben.

Nunja.....
Wenn ein numerisches Literal nicht in int passt, erhält es automatisch den Datentype long

Beweis:

  Serial.println(sizeof(42);
  Serial.println(sizeof(47114711);

Natürlich würde ein UL in solchen Fällen vermutlich mehr Klarheit verschaffen.

Das liegt am Eingangsverhalten.
Der Spannungsteiler ist so hochohmig, das alles was das rundrum an EMV exisitiert mitgemessen wird.
Wer Mist misst, misst Mist :slight_smile:

So.
Aber um dem mal so ein wenig die Angst zu nehmen, hab ich was gebaut.
Die Funktion leseVoltage() wird um einen kleinen Ringpuffer mit 10 Werten ergänzt.
Damit laufen immer 10 Werte (Nach einem kompletten Umlauf sind das auch immer gemessene Werte) in die Auswertung.
Das funktioniert ganz gut.

Auf was Du achten musst:
Alle Pins müssen ein definiertes Potenzial haben!
Unbenutzte analoge Pins lege auf GND! Alle unbenutzten analogPins!

Sobald irgendwo etwas "in der Luft hängt" bekommst Du nur wirres / verfälschtes Zeug.

Die Funktion ist mit sehr vielen SerMons belegt.
Ich habe am Anfang tikTime mit 250ms gesetzt. Alle 250ms wird die Funktion durchlaufen - das kannst auch größer machen.
Letztendlich musst das irgendwann sowieso anhalten, weil die Unmenge der Ausgaben Dich einfach erschlägt.

Dafür einfach im SerMon den Haken bei 'Autoscroll' rausnehmen - dann händisch durchblättern - und später wieder da AutoSrcoll rein :wink:

Dann suche mal, ob Du 2 R findest: Wenn Du 10K und 1K hast, dann bekommst Du einen schnöden 55V Spannungsteiler:
[edit] siehe #507
UIN=55V - R1=10k - R2=1K
UIN=55V; R1=10k; R2=1K
[/edit]
UPin=(55*1000)/(10000+1000)
UPin=55000/11000
UPin=5
Das ist im Code noch nicht berücksichtigt.

So. na dann...

void leseVoltage()
{
  // max. Wert der Eingangsspannung die der Spannungsteiler aufnimmt
  // um am AnalogPin ca. 5V abzubilden 100/10K->55.0V 13/2,5K->30.0V
  // Die Spannungsteiler geben keine 5V an der Obergrenze zurück!
  // mit map wird später die Obergrenze auf 10xx festgelegt
  const uint16_t maxVoltageDividier = 300; // 2VK 1NK -stelle
  //
  const uint8_t maxUmlauf = 10;  // Anzahl der Werte, die in den Puffer gehen
  static uint8_t umlauf = 0;     // Startwert Umlauf
  static uint8_t localVoltage[spuren + 1][maxUmlauf] = {0}; // Lokaler Ringspeicher
  bool tik = false;  // nur wenn tik == true, wird die Funktion insgesamt ausgeführt
  const uint16_t tikTime = 250;   // Zeit bis tik in ms
  if (millis() % tikTime == 0) tik = true; //Festlegen von tik
  // tik = true; // ERSATZWEISE ohne Pause
  if (tik)
  {
    for (uint8_t i = 0; i < spuren; i++)
    {
      // Hier wird ein Wert zurück gegeben der als OberGrenze maxVoltageDividier hat!
      // Wenn der nicht stimmt, stimmt das Ergebnis nicht!!!
      uint16_t mapVoltage = map(analogRead(voltagePin[i]), 0, 1023, 0, maxVoltageDividier);
      // Obergrenze 25V - Wenn darüber, mache 25.5 (255) draus
      if (mapVoltage > 250) mapVoltage = 255;
      //Übernehme den Wert in den localen Ringspeicher
      localVoltage[i][umlauf] = mapVoltage;
      // Erste Ausgabe
      // Serial.print(F("Index: ")); Serial.print(i); Serial.print(F(" Inhalt: ")); Serial.println(localVoltage[i][umlauf]);
    }
    // Erklärt sich von selbst
    umlauf++; if (umlauf >= maxUmlauf) umlauf = 0;
    //
    // Ab hier berechnen
    if (umlauf == 0)
    {
      uint16_t zwischenSpeicher = 0;                    // Zwischenspeicher muss zur Aufnahme von 10 * byte fähig sein
      for (uint8_t i = 1; i <= spuren; i++)             // zählt Spuren durch - ACHTUNG! Beginnt mit Spur 1!
      {
        zwischenSpeicher = 0;                           // Setzen 
        for (uint8_t b = 0; b < maxUmlauf; b++)         // Auslesen aller Werte anhand des Index
        {
          Serial.print(F("localVoltageIndex "));
          Serial.print(b);
          Serial.print(": ");
          Serial.println(localVoltage[i - 1][b]);
          zwischenSpeicher += localVoltage[i - 1][b];   // und aufaddieren
        }
        voltage[i] = (zwischenSpeicher / maxUmlauf);    // VoltageWert der Bahn abspeichern
        Serial.print(F("VoltagePin: "));                // Und ab hier ausgeben
        Serial.print(i);
        Serial.print(" ");
        Serial.print(zwischenSpeicher);
        Serial.print(" ");
        Serial.print(voltage[i]);
        Serial.print(" ");
        if (voltage[i] > 99)
          Serial.print(voltage[i] % 1000 / 100);
        else
          Serial.print(" ");
        if (voltage[i] > 9)
          Serial.print(voltage[i] % 100 / 10);
        else
          Serial.print(" ");
        Serial.print(".");
        Serial.print(voltage[i] % 10);
        Serial.println();
        Serial.print("= ");
        Serial.println(voltage[i]);
      }
    }
  }
}

Wenn Du Dein NT noch bei Dir hast und Zeit und Lust, bau das mal und schau mal, was der lcd macht.
Danmn die tik-Zeile mit den millis() auskommentieren und darunter die tik-Zeile rein, damit Du ständig die Ausgaben ohne Pause bekommst.
Das Ergebnis auf dem LCD würde ich gerne wissen.

1 Like

:joy: Ich kenne es so... Wer viel misst, misst Mist. Trifft irgendwie beides zu.
Ja, da war der Lieferant doch nicht so schnell wie er versprochen hat....kommt 2 Tage später.
Kochen doch nur alle mit Wasser....

Aber kannst Du mir bitte EMW noch übersetzen, weiß nicht was es bedeudet. :thinking:

NT bleibt hier.... :smiley: Zeit für das neue Hobby...leider viel zu wenig. Lust.....aber so Richtig richtig.
Muss Morgen mal gucken ob ich die Widerstände in meiner Krabbelkiste finde, ansonsten müssen wir noch 2 Tage warten :roll_eyes:

Reicht es nicht wenn ich die über einen 0,1µF gegen GND schalte. Ich frage deswegen wenn ich die Spuren über das Menü erweitere z.B. von 4 auf 6 müsste ich dann die Verdrahtung ändern.

Und wieder mal 1000 Dank an Dich, wird....nein es ist ein wirklich g.... Projekt geworden.
D A N K E, es hängt bald ein Porträt von Dir über meinem Bett :wink:

Ein gut Nächtle, an alle