Messdatenerfassung

Hallo Leute,

ich arbeite gerade an einem Prüfstand, welcher Messdaten erfassen und ggf. weiter versenden soll. Mit Hilfe des Prüfstands sollen die Losbrechkraft und die Gleitkraft verschiedener Materialien bewertet werden können (z.B. Holz auf Glas...). Als Basis habe ich mich für folgenden Kraftaufnehmer entschieden:

Mit einem passenden Messverstärker soll das Signal des Kraftaufnehmer mit Hilfe des Analogeingangs bei Arduino Uno ausgewertet werden und ggf. über die Serielle Schnittstelle an einen Pi versendet und weiterverarbeitet werden. Hierzu habe ich ein paar Fragen:

  1. Die maximale Spannung die der Messverstärker an den Arduino abgeben dürfte sind 0-5V, oder?

  2. Laut Datenlatt Sampelt der ADC mit maximal 15 kSPS, ich habe schon auf verschiedenen Internetseiten gelesen, dass allerdings eine maximal Samplingrate von 10 kSPS empfohlen wird. Ist das richtig?

3.Wenn ich z.B. eine Messung innerhalb von 5 Minuten durchfahren lasse und mit 10 kSPS sampel, bedeutet das, dass ich 5x60x10000 = 3 Millionen Messdaten verarbeiten und zwischenspeichern muss?
Wäre das umsetzbar? Was begrenzt mich da von Arduinoseite aus?

Vielen Dank für die Hilfe

Ebbi.

  1. Ja
  2. keine Ahnung was ein kSPS ist. Für einen analogRead() auf dem atmega328 sollest du 120 µs rechnen.
    Das geht, mit der atmega328 ADC Hardware, auch schneller. (bei geringerer Auflösung)
  3. Ein atmega328 hat 2 kB RAM. Mit Speichern ist da also nichts. Die serielle Hardware-Schnittstelle zum Raspberry kann 115200 Bd oder auch etwas mehr (250000 Bd). Das wären max. 25000 byte je Sekunde.
    Bei 1 Byte Auflösung (s.o.) passt das, und zeigt dir so etwa die Grenzen des Machbaren.

1 Byte Auflösung hat übrigens den Riesenvorteil, dass es keine Synchronisationsprobleme gibt.

das ist mal wieder eines der Beispiele, wo ich definitiv von Arduino (Bibliotheken) abraten würde. Der größte Vorteil der IDE ist, dass sie einfach zu programmieren ist. Das liegt an den zahlreichen Bibliotheken, in denen einfach zu verwendende Funktion wie analogRead() zur Verfügung gestellt werden. Dieser Komfort hat allerdings einen Preis: und das ist die schlechte Laufzeit-Performance. Wenn es also um zeitkritische Aufgaben geht, ist die Programmierung in nativem C bedeutend besser geeignet.

Ob es mit Standard-Arduino Programmierung geht? Das wird Dir keiner sagen können ... da hilft nur ausprobieren.

Müsste ich die Aufgabe lösen, würde ich vermutlich eher auf Arduino (sowohl soft- als auch hardwaremäßig) verzichten und lieber ein eigenes kleines System bauen, das die Messwerte erst lokal in ein EPROM, SD Karte oder was auch immer ablegt und erst nach Mess-Ende die Daten an den PI weiter reicht. So kann man sich während der Messung ganz auf diese konzentrieren und hat nicht auch noch das Problem, dass Kommunikationsprobleme z. B. zu einem Abbruch führen oder dafür sorgen, dass die gewünschte Sampling-Rate nicht erreicht werden kann.

Zum Vorschlag von Michael: klar kann man die Auflösung auf 8 Bit herunter setzen ... aber dann hast Du halt auch nur max. 256 Abstufungen Deines Messwerts (also rund 0,02 Volt Auflösung bei 0-5 Volt Messbereich). Ob das ausreicht, musst Du selber entscheiden.

dann hast Du halt auch nur max. 256 Abstufungen Deines Messwerts (also rund 0,02 Volt Auflösung bei 0-5 Volt Messbereich). Ob das ausreicht, musst Du selber entscheiden.

Das sind 0,4% Auflösung und reicht für graphische Darstellung, sowie um den Übergang von Haftreibung in Gleitreibung zu erkennen :slight_smile:

Ansonsten gebe ich mgcss natürlich Recht.

Eher ein Problem zum Ausloten wo die Arduino-Grenzen liegen als sich vorrangig um die Messdaten selber zu kümmern.

Erstmal vielen Dank für die Antworten...

Müsste ich die Aufgabe lösen, würde ich vermutlich eher auf Arduino (sowohl soft- als auch hardwaremäßig) verzichten und lieber ein eigenes kleines System bauen, das die Messwerte erst lokal in ein EPROM, SD Karte oder was auch immer ablegt und erst nach Mess-Ende die Daten an den PI weiter reicht. So kann man sich während der Messung ganz auf diese konzentrieren und hat nicht auch noch das Problem, dass Kommunikationsprobleme z. B. zu einem Abbruch führen oder dafür sorgen, dass die gewünschte Sampling-Rate nicht erreicht werden kann.

Vermutlich würde das den Rahmen der Arbeit sprengen, dennoch wäre ich für passende Lektüretipps dankbar.

Wenn ich die Auflösung auf 8-Bit runtersetze würde das doch, auf die Nennkraft von 20N bezogen, bedeuten, dass die kleinste Kraftdifferenz 20 N / 256 = 0,078N wären. Es fällt mir sehr schwer diesen Wert einzuordnen, da ich das zu erfassende Signal nicht kenne. Wäre es bei einem unbekannten Signal schlauer auf eine etwas höhere Auflösung zu gehen?

Alternativ habe ich sowas hier gefunden:

Das Eingangssignal von -10 bis 10 V kommt den meisten Messverstärkern sehr entgegen und ich hätte eine höhere Auflösung, eine höhre Samplingrate und müsste mir keine Sorgen bei der Datenübertragung zwischen Arduino und Pi machen.

klar gibt's auch zig fertige Systeme für sowas. Wie immer in solchen Fällen: erstmal die Anforderungen zusammenstellen und bewerten was ist Must-Have und was Nice-To-Have. Dann System auswählen :slight_smile: Google einfach mal nach "Datenlogger" oder such bei einem Distributor Deiner Wahl (z. B. https://de.farnell.com/c/messtechnik/datenerfassung-datenaufzeichnung/datenlogger)

Moin nochmal,

ich hoffe, dass es ok ist, wenn ich hier nochmal drunter schreibe.

Wenn ich ggf. mit den vollen 10 Bit auflöse, habe ich ja den Nachteil, dass ich zwei Byte über die serielle Schnittstelle verschickt werden müssen, pro Wert. Zu was für Synchronisationsproblemen würde das führen bzw. was muss dabei beachtet werden?

michael_x:
1 Byte Auflösung hat übrigens den Riesenvorteil, dass es keine Synchronisationsprobleme gibt.

Danke nochmal :slight_smile:

Ebbi:
Zu was für Synchronisationsproblemen würde das führen bzw. was muss dabei beachtet werden?

Du weißt nicht welche Bytes zu welchen Werten gehören. z.B. du schickt 2 Bytes und die andere Seite übersieht das erste und fängt dann mit dem zweiten Byte zu lesen an. Kann man z.B. durch eine mehrere Byte lange Startsequenz am Anfang lösen. Oder ein Start Byte und nach X Bytes eine Checksumme. Das Startbyte kann dann im Datenstrom vorkommen aber die Checksumme ist falsch

Zwischeninfo: mit 10kSPS sind 10.000 Samples pro Sekunde gemeint

mgcss:
Wenn es also um zeitkritische Aufgaben geht, ist die Programmierung in nativem C bedeutend besser geeignet.

Wieso jetzt C irgendwelche Performance Vorteile, gegenüber C++, haben soll...?

Naja...
Das will mir nicht unbedingt einleuchten...
(aber, ich kann ja auch nicht alles wissen)

Hallo,

er meint bzw. vermutet das die Arduino Funktionen für den ADC langsamer wären als wenn man das selbst neu schreibt. Also nicht C vs. C++ sondern fertige vs. eigene Funktionen. Wenn der ADC im Free-Running Mode ackern soll muss man jedoch eh selbst Hand anlegen. Kenne keine Arduino Funktion die das konfiguriert.

Achso...

Das muss man aber auch nicht komplett auf die Arduino Software verzichten. Man kann auch den ADC per Hand programmieren und für den Rest weiterhin die Komfort-Funktionen verwenden

Da gibt es auch fertige Anleitungen dafür:

Auf der Seite steht auch welche Sampling Raten möglich sind wenn man nur den ADC-Takt ändert. Dann wird aber immer noch blockierend gemessen. Free Running hat den Vorteil dass man während der Messung andere Dinge tun kann. Dazu kann auch die serielle Übertragung gehören solange diese schneller ist als das Messen. Der ADC kann z.B. die Daten in einen Ring-Puffer eintragen der in loop() abgearbeitet wird

Oder sich selber eine eigene Komfortumgebung schaffen.

#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 ettablieren
 *  
 * 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);
}

CombieAdc.zip (25.5 KB)

Serenifly:
Du weißt nicht welche Bytes zu welchen Werten gehören. z.B. du schickt 2 Bytes und die andere Seite übersieht das erste und fängt dann mit dem zweiten Byte zu lesen an. Kann man z.B. durch eine mehrere Byte lange Startsequenz am Anfang lösen. Oder ein Start Byte und nach X Bytes eine Checksumme. Das Startbyte kann dann im Datenstrom vorkommen aber die Checksumme ist falsch

Gibts dafür irgendwo eine Erklärung? Ich konnte nichts finden...

Danke.

Da musst du mal selbst darüber nachdenken wie du das absichern könntest. Und ein entsprechendes Kommunikationsprotokoll entwickeln.

z.B. du sendest 0xAA als Start-Byte. Dann sendest du sagen wir mal 20 Bytes (kann auch mehr sein) und danach eine Checksumme aus den Datenbytes (CRC oder einfache Addition mit Überlauf). Die andere Seite muss dann nach dem Start-Byte schauen und die Checksumme überprüfen. Wenn die Checksumme korrekt ist ist die Übertragung synchron. Wenn nicht war 0xAA ein Daten-Byte. Dann versucht man sich mit dem nächsten Block zu synchronisieren

Oder die überträgst nur 1-Byte Werte (was eben auch für die A/D-Wandlung praktisch sein kann). Dann passt es immer

Hallo,

ich hab jetzt hier schon eine Weile mitgelesen. So wie ich das verstanden habe dauert ein Messvorgang etwa 5 minuten. Während der Zeit wird die Kraft langsam erhöht und dabei gemessen. Dabei ergeben sich dann ein linear ansteigender Messwerte. Irgendwann setzt sich das Messobjekt in Bewegung und die Haftreibung geht in Gleitreibung über und die Messwerte werden plötzlich kleiner und bleiben dann konstant. Dabei ergeben sich für mich ein paar Fragen.

  1. wie schnell ändert sich die Kraft
  2. wie genau soll gemessen werden daraus ergibt sich mindest die Messrate.

Du hast einen Messdose für 20N ausgesucht ? Damit kann Die Zugkraft während ca. 4 Minuten von 0 auf 20N steigen. das sind 240s bei 0,1s Messzyklus ergeben sich 2400 Messungen mit einer Änderung von 20N/2400=0,008N Das wäre dann die Auflösung der Anordnung.

Im Moment des Übergangs von Haften auf Gleiten, das wir in wenigen ms passieren,ergibt sich eine Ungenauigkeit von einem Messzyklus, Der Übergang selbst kann also nicht gemessen werde. Letztlich liegt er irgendwann zwischen zwei Messwerten. Die Gleitreibung ist aber dann ja konstant.

Ich kann mir nicht Vorstellen das da 1000 Messungen in der Sekunde erforderlich sind. Gefühlsmässig halte ich da 10-20 Messungen/s für ausreichend. Damit müsste ein Messwert in 100ms über die Schnittstelle. Das geht als Text mit LF zeilenweise.

Frage ans Forum ? bin ich da komplett auf dem Holzweg ?

Heinz

Rentner:
Du hast einen Messdose für 20N ausgesucht ? Damit kann Die Zugkraft während ca. 4 Minuten von 0 auf 20N steigen. das sind 240s bei 0,1s Messzyklus ergeben sich 2400 Messungen mit einer Änderung von 20N/2400=0,008N Das wäre dann die Auflösung der Anordnung.

Die Anzahl der Messungen in einem Zeitintervall hat doch nichts mit der Auflösung zu tun, oder Irre ich mich da?
Die Auflösung wird mir doch durch die 10 Bit des A/D-Wandlers vorgegeben, d.h. ich löse maximal mit 20/1024 = 0,02N auf.

Serenifly:
Da musst du mal selbst darüber nachdenken wie du das absichern könntest. Und ein entsprechendes Kommunikationsprotokoll entwickeln.

z.B. du sendest 0xAA als Start-Byte. Dann sendest du sagen wir mal 20 Bytes (kann auch mehr sein) und danach eine Checksumme aus den Datenbytes (CRC oder einfache Addition mit Überlauf). Die andere Seite muss dann nach dem Start-Byte schauen und die Checksumme überprüfen. Wenn die Checksumme korrekt ist ist die Übertragung synchron. Wenn nicht war 0xAA ein Daten-Byte. Dann versucht man sich mit dem nächsten Block zu synchronisieren

Oder die überträgst nur 1-Byte Werte (was eben auch für die A/D-Wandlung praktisch sein kann). Dann passt es immer

Danke für den Denkanstoß. Ich werde mich da mal ran setzen...

Hallo
Auflösung ist in diesem Sinne sicher etwas zweideutig. Ich meine damit die Änderung der Zugkraft zwischen zwei Messwerten während des Anstiegs.

Heinz