Häufung der Messdatenerhebung mittels millis()?

Hallo Arduino Community,
ich bin neu im Forum und habe vor kurzem angefangen mit dem Arduino zu experimentieren.
In meinem aktuellen Projekt möchte ich zwei Spannungen messen (kleiner 5V) und ein Mosfet schalten. Mein vermutlich nicht normgerechter Schaltplan ist auf dem Foto zu sehen. Die Spannung welche ich messen möchte ist stark und schnell schwankend.


Mein Code tut fast alles was ich möchte. Dazu gehört:

  1. Schalten des Mosfet (hier eingestellt mit 1000ms)
  2. Messen der Spannungen 1 und 2 (hier eingestellt mit 1ms)
  3. Mathematische weiterverwendung der Spannung 1 (hier CSB genannt und erst mal nur eine Verdoppelung die richtige Umformung an der Stelle muss noch eingetragen werden)
  4. Ausgabe der Spannungen 1 und 2 auf ein LCD Display
  5. Ausgabe des "CSB-Wertes" auf dem LCD Display
  6. Umschalten der Anzeige zweischen Spannung und CSB auf dem Display mittels Taster
  7. Loggen der gemessenen Daten auf einer SD-Karte.
    Der Code dazu sieht wie folgt aus:
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int mosfetPin = 9;
unsigned long mosfetMillis = 0;
const long mosfetInterval = 1000;  // Intervall für MOSFET-Steuerung in Millisekunden

const int analogPin1 = A0;
const int analogPin2 = A1;
unsigned long analogMillis = 0;
const long analogInterval = 1;  // Intervall für Spannungsmessung in Millisekunden

const int buttonPin = 2;  //Button zum Wechseln der Displayausgabe

int displayMode = 1;

File dataFile;

void setup() {
  pinMode(mosfetPin, OUTPUT);
  pinMode(analogPin1, INPUT);
  pinMode(analogPin2, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

  // Initialisiere die SD-Karte
  if (SD.begin(10)) {
    Serial.println("SD-Karte initialisiert.");
  } else {
    Serial.println("Fehler beim Initialisieren der SD-Karte!");
  }

  // Überprüfe, ob die .csv-Datei vorhanden ist, andernfalls erstelle sie
  if (!SD.exists("daten.csv")) {
    dataFile = SD.open("daten.csv", FILE_WRITE);
    if (dataFile) {
      // Schreibe Spaltenüberschriften in die erste Zeile
      dataFile.println("Spannung 1,Spannung 2");

      // Schließe die Datei
      dataFile.close();
      Serial.println("Datei daten.csv erstellt.");
    } else {
      Serial.println("Fehler beim Erstellen der Datei.");
    }
  }
}

void loop() {
  unsigned long currentMillis = millis();

  // MOSFET-Steuerung im mosfetInterval-Takt
  if (currentMillis - mosfetMillis >= mosfetInterval) {
    mosfetMillis = currentMillis;
    digitalWrite(mosfetPin, !digitalRead(mosfetPin));
  }

  // Taster abfragen, um zwischen den Spannungen umzuschalten
  if (digitalRead(buttonPin) == LOW) {
    if (displayMode == 1) {
      displayMode = 2;
    } else {
      displayMode = 1;
    }
    delay(500);
  }

  // Spannungsmessungen im analogInterval-Takt
  if (currentMillis - analogMillis >= analogInterval) {
    analogMillis = currentMillis;

    int rawValue1 = analogRead(analogPin1);
    int rawValue2 = analogRead(analogPin2);

    float voltage1 = (rawValue1 * 5.0 / 1023.0) * 1000.0;  // Spannung 1 in mV (drei Nachkommastellen)
    float voltage2 = (rawValue2 * 5.0 / 1023.0) * 1000.0;  // Spannung 2 in mV (drei Nachkommastellen)

    // Öffne die CSV-Datei im Schreibmodus (wird erstellt oder überschrieben)
    dataFile = SD.open("daten.csv", FILE_WRITE);

    if (dataFile) {
      // Schreibe Daten in die CSV-Datei
      dataFile.print(voltage1, 2);  // Anzeige auf 2 Dezimalstellen
      dataFile.print(",");
      dataFile.println(voltage2, 2);  // Anzeige auf 2 Dezimalstellen

      // Schließe die Datei
      dataFile.close();

      Serial.println("Daten in CSV-Datei geschrieben.");
    } else {
      Serial.println("Fehler beim Öffnen der Datei.");
    }

    // Aktualisiere das Display
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Spannung 1: ");
    lcd.print(voltage1, 3);

    lcd.setCursor(0, 1);
    lcd.print("Spannung 2: ");
    lcd.print(voltage2, 3);
  }
}

Meine Problem mit dem Code ist, dass die erhobenen und dokumentierten Messungen deutlich weniger sind als erwartet. Meine Erwartung ist, dass bei einem Schaltintervall von 1000ms des Mosfets und einem Intervall der Spannungsmessung von 1ms theoretisch 1000Spannungesmessungen inerhalb einer Mosfet-Umschaltung gemacht werden müssten. Dies ist aber nicht der fall der Dokumentation auf der SD-Zufolge werden nur ~14 Messungen in 1000ms gemacht.
Ich benötige nicht die vollen 1000 Messungen aber 50-200 Messungen währen für mein Projekt gut.
Könnt ihr mir helfen und erklären wieso nur so wenig Messungen gemacht werden? Hängt es vielleicht mit Aktualisierungsraten des LCD´s, oder Schreibgeschwindigkeiten der SD-Karte zusammen?
Ich hoffe das ihr mit meinen Angaben und Dokumentation etwas anfangen könnt und es nicht all zu laienhaft wirkt :sweat_smile:
Über eine Lösung meines Problems würde ich mich auf jeden Fall sehr freuen :slight_smile:
Mit besten Grüßen in die Community
Connnnee

glaube ich dir.
Serialle Schnittstelle mit 9600 bremst

SD.open bremst
SD schreiben bremst
SD.close bremst
lcd bremst,
I2C Kommunikation bremst
die LiquidCrystal_I2C ist noch mal langsamer
lcd.clear() bremst sowieso noch mal ein ganzes eck (+2ms)

--> 115200 baud
--> nur bei Fehler auf die Serielle schreiben
--> SD file offen lassen und nur öffnen falls nicht offen
--> lcd nur ein, zweimal pro Sekunde updaten, auf clear verzichten, öfter als 1, 2mal in der Sekunde kannst du das ohnehin nicht lesen.

Ich halte das alles für nicht so dramatisch....
Bei einem 16Mhz Arduino sollten sicherlich so an die 6000 Messungen/s dran sitzen. Also 3000 für jeden der beiden Kanäle. Bei verringerter Genauigkeit auch deutlich mehr.

Damit die Show dann nicht blockiert, denn SPI und I2C brauchen ganz schön Zeit, wird das analog Gedönse im Interrupt Betrieb arbeiten müssen. millis() wird da kaum helfen. Evtl. einen Timer dafür nutzen, falls ein gröberes/genaueres/einstellbares Zeitraster gewünscht ist.

EDIT:
Gerade getestet .... im Free Running Mode ... ein UNO
Fast 10000 Messungen/s ohne Kanalumschaltung.
Mit Kanalumschaltung, in der ISR, halbiert sich das, weil bei der Methode jeder 2te Wert verworfen werden müsste.
Es bleiben also fast 2500 Messungen Pro Sekunde Pro Kanal

#include <CombieAdc.h>

#include <util/atomic.h>

#ifndef ADC_MODELL_WITH_THERMO 
  #error Dieser AVR hat keinen eingebauten Temperatursensor
#endif

/**
 * 
 * Den eingebauten Temperatursensor im Interruptbetrieb lesen
 * 
 * Beachte:
 * Die CallBack Funktion läuft im Interrupt Kontext.
 * Also müssen alle genutzten Variablen als volatile(??) 
 * deklariert werden, und aus dem Hauptprogramm muss darauf
 * Atomar zugegriffen werden
 * 
 * Setup:
 * ADC Einstellungen 
 * Interrupt etablieren
 *  
 * In loop: 
 * Messwert lesen
 * Ausgabe
 * 
 * Tipp:
 * http://www.atmel.com/Images/Atmel-8108-Calibration-of-the-AVR%27s-Internal-Temperature-Reference_ApplicationNote_AVR122.pdf
 * 
*/

using Combie::Adc;
Adc adc;


volatile unsigned long irqCount;
volatile int tempWert;



void adcCallBack(int value)
{
  irqCount++;
  tempWert = value;
}




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

   adc  .enable()
        .setReference(Adc::REF_11)
        .setClockDivisor(Adc::DIV_128)
        .setSource(Adc::MUX_THERMO)
        .setCallBack(adcCallBack)
        .enableAutoTrigger()
        .setTrigger(Adc::TRIG_FREERUNNING)
        .enableIrq()
        .startConversion();
}

void loop() 
{
  unsigned long count;
  int wert;
  
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
    count = irqCount;
    wert  = tempWert;
    irqCount = 0;
  }
 
  Serial.print("Gelesener Temperatur Wert ");
  Serial.println(wert);
  Serial.print("Anzahl Interrupts pro Sekunde ");
  Serial.println(count);
  Serial.println("---");
  delay(1000);
}

Ausgabe: (Ausschnitt)

---
Gelesener Temperatur Wert 356
Anzahl Interrupts pro Sekunde 9686
---
Gelesener Temperatur Wert 356
Anzahl Interrupts pro Sekunde 9686
---

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int mosfetPin = 9;
unsigned long mosfetMillis = 0;
const long mosfetInterval = 1000;  // Intervall für MOSFET-Steuerung in Millisekunden

const int analogPin1 = A0;
const int analogPin2 = A1;
unsigned long analogMillis = 0;
const long analogInterval = 1;  // Intervall für Spannungsmessung in Millisekunden

const int buttonPin = 2;  //Button zum Wechseln der Displayausgabe

int displayMode = 1;

File dataFile;

void setup() {
  pinMode(mosfetPin, OUTPUT);
  pinMode(analogPin1, INPUT);
  pinMode(analogPin2, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(115200);
  lcd.init();
  lcd.backlight();

  // Initialisiere die SD-Karte
  if (SD.begin(10)) {
    Serial.println("SD-Karte initialisiert.");
  } else {
    Serial.println("Fehler beim Initialisieren der SD-Karte!");
  }

  // Überprüfe, ob die .csv-Datei vorhanden ist, andernfalls erstelle sie
  if (!SD.exists("daten.csv")) {
    dataFile = SD.open("daten.csv", FILE_WRITE);
    if (dataFile) {
      // Schreibe Spaltenüberschriften in die erste Zeile
      dataFile.println("Spannung 1,Spannung 2");
      dataFile.close();
      Serial.println("Datei daten.csv erstellt.");
    } else {
      Serial.println("Fehler beim Erstellen der Datei.");
    }
  }
  lcd.setCursor(0, 0);
  lcd.print("mV 1: ");
  lcd.setCursor(0, 1);
  lcd.print("mV 2: ");
}

void loop() {
  // MOSFET-Steuerung im mosfetInterval-Takt
  if (millis() - mosfetMillis >= mosfetInterval) {
    mosfetMillis += mosfetInterval;
    digitalWrite(mosfetPin, !digitalRead(mosfetPin));
  }

  // Spannungsmessungen im analogInterval-Takt
  if (millis() - analogMillis >= analogInterval) {
    analogMillis += analogInterval;

    int rawValue1 = analogRead(analogPin1);
    delayMicroseconds(10);
    int rawValue2 = analogRead(analogPin2);

    float voltage1 = rawValue1 * 5.0 / 1.023;  // Spannung 1 in mV (drei Nachkommastellen)
    float voltage2 = rawValue2 * 5.0 / 1.023;  // Spannung 2 in mV (drei Nachkommastellen)

    // Öffne die CSV-Datei im Schreibmodus (wird erstellt oder überschrieben)
    dataFile = SD.open("daten.csv", FILE_WRITE);

    if (dataFile) {
      // Schreibe Daten in die CSV-Datei
      dataFile.printf("%0.2f,%0.2f\n", voltage1, voltage2); // Anzeige auf 2 Dezimalstellen
      dataFile.close();
    } else {
      Serial.println("Fehler");
    }

    // Aktualisiere das Display
    lcd.setCursor(6, 0);
    lcd.print(voltage1, 3);
    lcd.print("  ");

    lcd.setCursor(6, 1);
    lcd.print(voltage2, 3);
    lcd.print("  ");
  }

  // Taster abfragen, um zwischen den Spannungen umzuschalten
  //  if (digitalRead(buttonPin) == LOW) {
  //    if (displayMode == 1) {
  //      displayMode = 2;
  //    } else {
  //      displayMode = 1;
  //    }
  //    delay(500);
  //  }

}

Allein dein display.clear()verballert bei jedem Umlauf 2ms.

/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear(){
	command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
	delayMicroseconds(2000);  // this command takes a long time!
  if (_oled) setCursor(0,0);
}

Gibt es einen bestimmten Grund, warum Du im File mit 2 und auf dem Display mit 3 Nachkommastellen arbeitest?

Serial.println("Daten in CSV-Datei geschrieben.");

... dauert 33 ms bei 9600, wenn der Ausgabe-Puffer erstmal vollgelaufen ist.
(das delay im display.clear findet allerdings gleichzeitig statt)
Diese Ausgabe weglassen sollte die Geschwindigkeit um den Faktor 10 steigern. Alles andere wird aufwendiger.

Legst du Wert auf gleiche Zeitabstände zwischen den Messungen? Das kann

if (currentMillis - analogMillis >= analogInterval) {
  analogMillis = currentMillis;

bei analogInterval = 1; nur ganz bedingt leisten, da die SD-Karte ziemlich unterschiedliche Zeiten brauchen kann.

Evtl. den millis-Zähler mitloggen.

Ich würde eher auf 4-5 mS tippen.

Grüße Uwe

der Italiener wieder :wink:

mS ... Millisiemens (der Leitwert)
ms ... Millisekunden

2 Likes

Dann müsste das command nochmal 2ms verbrauchen. Und das macht es nicht, auch wenn I2C nicht grad das schnellste ist :wink:

Ich biete mal einen Code an.
Der ist so. Absichtlich.
Ich gehe davon aus, das ich an der Stelle, wo es notwedig ist ausreichend kommentiert habe.

Es kompiliert.
Ob es funktioniert, weiss ich nicht.
Das Wichtigste:
Auf der SD-Karte soll neben den Voltages auch die currentmillis gespeichert werden, damit man daraus evtl. die Laufzeiten ermitteln kann.
Auf dem SerMon kommt mit jedem Pegelwechsel auf dem MosfetPin eine Ausgabe. Da ist die Laufzeit zwischen den Pegelwechseln und die Anzahl der Messungen drin.
Den taster hab ich umgebaut um das delay da raus zu bekommen.

Der Display wird alle 50ms aktuallisiert. Und geschrieben wird nur, wenn sich der Wert geändert hat.

Na dann..

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int mosfetPin = 9;
unsigned long mosfetMillis = 0;
const long mosfetInterval = 1000;  // Intervall für MOSFET-Steuerung in Millisekunden

constexpr byte anzahl {2};
constexpr byte analogPin[anzahl] {A0, A1};
unsigned long analogMillis = 0;
const unsigned long analogInterval = 1;  // Intervall für Spannungsmessung in Millisekunden

uint16_t rawValue[anzahl];
float voltage[anzahl];

const int buttonPin = 2;  //Button zum Wechseln der Displayausgabe
byte displayMode;
constexpr byte maxDisplayMode {1};
constexpr byte sdSelect {10};
char filename[] = {"Daten.csv"};
File dataFile;

unsigned long currentMillis;

uint32_t measureSize;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(mosfetPin, OUTPUT);
  for (byte b = 0; b < anzahl; b++)
  {
    pinMode(analogPin[b], INPUT);
  }
  pinMode(buttonPin, INPUT_PULLUP);
  lcd.init();
  lcd.backlight();
  // Initialisiere die SD-Karte
  if (SD.begin(sdSelect))
  {
    Serial.println(F("SD-Karte initialisiert."));
  }
  else
  {
    Serial.println(F("Fehler beim Initialisieren der SD-Karte!"));
  }
  // Überprüfe, ob die .csv-Datei vorhanden ist, andernfalls erstelle sie
  if (!SD.exists(filename))
  {
    dataFile = SD.open(filename, FILE_WRITE);
    if (dataFile)
    {
      // Schreibe Spaltenüberschriften in die erste Zeile
      dataFile.println(F("time,Spannung 1,Spannung 2"));
      // Schließe die Datei
      dataFile.close();
      Serial.print(F("Datei "));
      Serial.print(filename);
      Serial.println(F(" erstellt."));
    }
    else
    {
      Serial.println(F("Fehler beim Erstellen der Datei."));
    }
  }
}
//
void checkDataFile()
{
  if (digitalRead(mosfetPin))
    // zwischengespeicherte Daten werden geschrieben
  { dataFile.flush(); }
  else
  {
    // Datei wird geschlossen und neu geöffnet
    dataFile.close();
    dataFile = SD.open(filename, FILE_WRITE);
    if (!dataFile)
    {
      Serial.println(F("Fehler beim ReOpen"));
    }
  }
}
//
void switchMosfet()
{
  // MOSFET-Steuerung im mosfetInterval-Takt
  if (currentMillis - mosfetMillis >= mosfetInterval)
  {
    // gibt die Anzahl der Messungen des letzten Intervall und die aktuelle Laufzeit aus
    Serial.print(currentMillis - mosfetMillis);
    Serial.print('\t');
    Serial.println(measureSize);
    // Zaehler löschen für neuen Messzyklus
    measureSize = 0;
    mosfetMillis = currentMillis;
    digitalWrite(mosfetPin, !digitalRead(mosfetPin));
    // Kleine Spielerei
    checkDataFile();
  }
}
//
void switchDisplayMode()
{
  static bool lastSwitch = false;
  static uint32_t pressTime = 0;
  constexpr uint32_t debounceTime {40};
  // Taster abfragen, um zwischen den Spannungen umzuschalten
  if (currentMillis - pressTime > debounceTime )
  {
    if (digitalRead(buttonPin) == LOW)
    {
      if (lastSwitch == false )
      {
        lastSwitch = true;
        displayMode++;
        if (displayMode > maxDisplayMode)
        { displayMode = 0; }
        Serial.print(F("DisplayMode: "));
        Serial.println(displayMode);
      }
    }
    else
    { lastSwitch = false; }
  }
}
//
void readAnalog()
{
  // Spannungsmessungen im analogInterval-Takt
  if (currentMillis - analogMillis >= analogInterval)
  {
    analogMillis = currentMillis;
    for (byte b = 0; b < anzahl; b++)
    {
      rawValue[b] = analogRead(analogPin[b]);
      voltage[b] = (rawValue[b] * 5.0 / 1023.0) * 1000.0;  // Spannung in mV (drei Nachkommastellen)
    }
    measureSize++;
  }
}
//
void writeData()
{
  if (!dataFile)
  { return; }
  // Schreibe Daten in die CSV-Datei
  dataFile.print(currentMillis);
  for (byte b = 0; b < anzahl; b++)
  {
    dataFile.print(',');
    dataFile.print(voltage[b], 2);  // Ausgabe auf 2 Dezimalstellen
  }
}
//
void displayData()
{
  constexpr uint32_t displayIntervall {50};
  static uint32_t lastDisplayTime = 0;
  static uint16_t lastRaw[anzahl] = {0};
  static byte lastDisplayMode = 255;
  if (currentMillis - lastDisplayTime < displayIntervall)
  { return; }
  lastDisplayTime = currentMillis;
  if (lastDisplayMode != displayMode)
  {
    lcd.clear();
    switch (displayMode)
    {
      case 0:
        for (byte b = 0; b < anzahl; b++)
        {
          lcd.setCursor(0, b);
          lcd.print(F("Spannung "));
          lcd.print(b + 1);
          lcd.print(':');
        }
        break;
      case 1:
        lcd.setCursor(0, 0);
        lcd.print(F("V1:"));
        lcd.setCursor(0, 1);
        lcd.print(F("V2:"));
        break;
    }
    lastDisplayMode = displayMode;
  }
  for (byte b = 0; b < anzahl; b++)
  {
    if (lastRaw[b] != rawValue[b])
    {
      switch (displayMode)
      {
        case 0:
          lcd.setCursor(12, b);
          lcd.print(voltage[b], 3);
          break;
        case 1:
          lcd.setCursor(5, b);
          lcd.print(voltage[b], 3);
          break;
      }
      lastRaw[b] = rawValue[b];
    }
  }
}

//
void loop()
{
  currentMillis = millis();
  switchMosfet();
  readAnalog();
  writeData();
  switchDisplayMode();
  displayData();
}

Da hier heute nix mehr passiert, noch schnell ein edit:
Ich komme mit Deiner Rechnerei mit den mV noch nicht ganz zurecht, weil ich nicht weiß, was da rauskommen soll..
Aber bedenke: float hat eine Genauigkeit von 7 Digit.
Es zaehlen alle mit. Auch die vor dem Komma.
Dir könnte also Deine *1000.0 evtl. auf die Füsse fallen, wenn Du gleichzeitig genügend Stellen nach dem Komma abbilden willst...
Das ist im Übrigen auch der Grund, warum ich grundsätzlich nicht die errechneten, sondern die gemessenen Werte benutze.
Und eigentlich auch genau so auf die SD schreibe.

1 Like

Vielen Dank für die ganzen Kommentare die sind wirklich sehr hilfreich.
Wie die meisten hier geschrieben haben lag es vor allem an der Aktualisierungsrate des LCD und dem häufigen öffnen der Datei. Auch eine Umstellung auf 115200 baut hat etwas gebracht.
@my_xy_projekt dein Code funktioniert sehr gut vielen Dank dafür. Wie eingangs kurz erwähnt bin ich relativ neu im Arduino-Game und lerne aktuell jeden Tag etwas neues. Dein Code hat mir auf jeden Fall etliche neue Ideen gegeben und Wege aufgezeigt von denen ich nicht wusste das es sie gibt :stuck_out_tongue:. Mit deinem Code komme ich auf 350-500 Messwerte pro Zyklus was absurd hoch ist da muss ich schon wieder anfangen zu drosseln :sweat_smile:. Da ich nicht jeden Tag so viel Zeit habe werde ich noch wohl ein paar Tage brauchen um meine Schlüsse daraus zu ziehen und einen eigenen Code zu schreiben welchen ich auch zu 100% verstehe. Ich werde diesen Anfang nächster Woche mal hier Posten und Rückmeldung geben ob alles klappt

Das war Absicht.
Ich hätt ja mal gerne gewusst, was so für 3-4 Zyklen auf dem Seriellen Monitor rauskommt....

Dann liegst Du aber auch noch immer bei etwa 2-3ms je Zyklus. wenn Dir das zuviel ist, dann kannst Du in der Definition vorgeben wie lang Dein Zyklus ist (derzeit eine Sekunde) und dann angeben wie viele Messungen Du meinst zu brauchen.
Davon errechnet sich dann Zykluszeit fürs analogRead().

In meiner Spielerei checkDataFile()habe ich einen elsezweig drin.
Wenn Du den ganzen Kram weglässt und nur das .flush() bei jedem Zykluswechsel machst, wird das dann noch schneller, brauchst aber eine Behandlung, im Falle irgendwas mit dem datafFile ist.

Hallo,

Nur einmal ein Gedanke dazu wenn es in mV sein soll.
Man könnte auch nur

rawValue[b] = analogRead(analogPin[b]);
voltage[b] = 5000UL * rawValue[b] / 1023;  // Spannung in mV

rechnen oder technisch korrekter

rawValue[b] = analogRead(analogPin[b]);
voltage[b] = 5000UL * rawValue[b] / 1024;  // Spannung in mV

Wenn man mehr Kommastellen in Ganzzahl erhalten möchte, dann kann man 50000UL * x oder 500000UL * x rechnen, muss aber in uint32_t speichern. Und dann diesen Rohwert immer erst bei Verwendung in Fließkomma umrechnen, was beim TO dann sicherlich Excel o.ä. macht. Man gewinnt Genauigkeit ohne relevante Einbuße der Rechenleistung.

Ich würde meinen, das es genauso oder schneller läuft. Das float ist IMHO aufwendiger als uint32_t
Ich hatte ja schon geschrieben, das es noch mehr Möglichkeiten gibt, da Geschwindigkeit rauszuholen. Das wird jetzt aber nur noch Kleinstückwerk...
Da macht es dann die Summe.

Und zu schnell ist es ja jetzt schon :slight_smile:

Hallo,

ich will das jetzt nicht ausufern lassen. Noch paar Gedanken. Man kann die gewonnene Durchlaufgeschwindigkeit nutzen um die Wiederholgenauigkeit zu erhöhen. Damit das Meßintervall immer besser eingehalten wird, dass Timing aller x ms. Bei hunderten Messungen summiert sich das. Falls der TO die gewonnenen Werte die er speichert sowieso erst in Excel auswertet, dann würde ich nur die Digits von analogRead speichern und damit gar nicht vorher auf dem µC umrechnen und damit noch weniger Zeit liegen gelassen. Und wenn er es aller 1s auf dem Display anzeigt dann auch erst hierfür 1x aller der 1s umrechnen statt immer. Kommt immer darauf an ... wissen wir ja. :wink: Das kann man bestimmt noch weiter auf Speed trimmen. Bspw. den IC vom Display anschauen, im Datenblatt lesen und mit Glück kann er 400kHz statt 100kHz. Das display.clear kann man sicherlich auch weglassen wenn man gezielt überschreibt. Da geht immer was ... wissen wir ja. :wink:

:joy: Ja... Alles schon #10 vorgesehen. Danke für die Bestätigung. Na denne... Gute Nacht.

Hallo,

okay :+1:

Frage: Warum wird in der ersten Formel mit 1023 und in der zweiten Fomel mit 1024 gerechnet?

Das ist eine Frage, die ein gehöriges „Konfliktpotential“ in sich trägt…..

https://forum.arduino.cc/t/strom-mittels-rogowski-spule-messen/

Ab Beitrag #24 nimmt die Diskussion fahrt auf….

1 Bit Auflösung
0 = 0V, 1 = 5V
2 Bit Auflösung
5V / 4 = 1,25V
5V / 3 = 1,66V -->
00 = 0V, 01 = 1,66V, 10 = 3,33V, 11 = 5V

Damit ergibt sich, das bei 10 Bit nicht durch 1024 sondern durch 1023 geteilt werden muss.