Posts mit dem Label Messung werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Messung werden angezeigt. Alle Posts anzeigen

Sonntag, 23. Januar 2022

Arduino als Messgerät mit Logging (Teil 2)

Im ersten Teil habe ich erläutert, welche Schritte nötig sind, um den Arduino als Messgerät einzusetzen. Nun gehe ich einen Schritt weiter. Statt einem, können jetzt vier Messungen erfasst und auf der WPF Anwendung angezeigt werden.

Die Anwendung ist eigentlich zum Probieren von verschiedenen Mechanismen gedacht. Praktisch ein Training, um für meinen Beruf immer fit zu bleiben.

 

Benötigte Materialien:

  • Arduino
  • mindestens 2 x 10k Ohm Widerstände für Spannungsteiler
  • Verschiedene Spannungsquellen für Messungen

 

Was geht?

Der Arduino kann mehr als nur eine Spannungsquelle messen. Mit der WPF Anwendung können vier Spannungsquellen gleichzeitig gemessen werden. Natürlich geht mehr, doch die weiteren sollen für die Schnittstelle I²C offen bleiben.

  

WPF Anwendung

Bei meinem letzten Blog Eintrag habe ich am Ende bereits geschrieben, dass ich auch schon die zukünftige WPF Anwendung im GitHub Repository mit hochgeladen habe. Zu dieser Zeit war jedoch die Messung nur an einem Messpunkt möglich.

Mit der Möglichkeit mehrere Spannungen zu messen, ändert sich der Programmcode für den Arduino. Ich habe das soweit ausgebaut, dass nun vier Messungen gleichzeitig möglich sind.

 

Arduino Code Änderung

Damit die vier Messungen auch übertragen werden, muss die Übertragung erweitert werden. Wie beim ersten, müssen die drei weiteren INPUT Eingangswerte ebenfalls aufbereitet und dann in das zu versendete Array geschrieben werden.

 #define PIN_Input_1 A0  
 #define PIN_Input_2 A1  
 #define PIN_Input_3 A2  
 #define PIN_Input_4 A3  
 void setup() {  
  Serial.begin(115200);  
  Serial.println("Volatage Measuerment Logger Started");  
  pinMode(PIN_Input_1, INPUT);  
  pinMode(PIN_Input_2, INPUT);  
  pinMode(PIN_Input_3, INPUT);  
  pinMode(PIN_Input_4, INPUT);  
 }  
 void loop() {  
  int16_t rawMeasurement1 = analogRead(PIN_Input_1);  
  int16_t rawMeasurement2 = analogRead(PIN_Input_2);  
  int16_t rawMeasurement3 = analogRead(PIN_Input_3);  
  int16_t rawMeasurement4 = analogRead(PIN_Input_4);  
  byte ba[9];  
  ba[0] = (byte)((rawMeasurement1 >> 8) & 0xff);  
  ba[1] = (byte)(rawMeasurement1 & 0xff);  
  ba[2] = (byte)((rawMeasurement2 >> 8) & 0xff);  
  ba[3] = (byte)(rawMeasurement2 & 0xff);  
  ba[4] = (byte)((rawMeasurement3 >> 8) & 0xff);  
  ba[5] = (byte)(rawMeasurement3 & 0xff); 
  ba[6] = (byte)((rawMeasurement4 >> 8) & 0xff);  
  ba[7] = (byte)(rawMeasurement4 & 0xff);   
  int8_t countedBits = CountBits(rawMeasurement1);  
  countedBits += CountBits(rawMeasurement2);  
  countedBits += CountBits(rawMeasurement3);  
  countedBits += CountBits(rawMeasurement4);  
  ba[8] = (byte)countedBits;  
  Serial.write(ba, 9);  
  delay(20);  
 }  
 int8_t CountBits(int16_t rawMeasurement) {  
  int8_t result = 0;  
  for(int i = 0; i < 16; i++) {  
   result += (int8_t)bitRead(rawMeasurement, i);  
  }  
  return result;  
 }  

Versuchsaufbau

Für den Test werden verschiedene Spannungsquellen eingesetzt:
Eine Schaltung mit einem Lichtsensor,
eine Solarplatte,
Batterie mit Step-Down und
eine weitere Schaltung mit einer Z-Diode. 

Diese vier werden wiederum selbst am Spannungsteiler angeschlossen.


 

Verbindung herstellen

Die Spannungsquellen können vor dem Einschalten/Anschließen des Arduinos angeschlossen werden. Ist der Arduino verbunden, kann die Verbindung zur Anwendung gestartet werden. Hier entsprechend den COM Port auswählen und den Button Connect klicken. Im Diagrammbar sollten nun vier Linien entsprechend der Spannung angezeigt werden.


Problem mit der Diagrammlinie

Aktuell besteht mit dem Diagramm das Problem, dass durch nicht genutzte Events die Diagrammlinie nicht aktualisiert wird, wenn sich z.B. der Mauszeiger über dem Steuerelement bewegt.


Loggen starten

Nicht immer schafft man es auf die Anzeige zu schauen und eventuell verpasst man die zu beobachtende Spannung. Deshalb habe ich den Logger mit eingebaut, um hier entgegen zu wirken.

Im Test konnten zehn minütige Aufzeichnungen vorgenommen werden, trotz des CSV Datenformates. Auch, wenn die Datei nur wenige Kilobyte groß ist, ist die Art der Speicherung in performant.

Um die Aufzeichnung anzusehen, muss auf den Tab „Log Data“ gewechselt werden. Dort wird dann der Log-Name ausgewählt, der zuvor zum Speichern verwendet wurde. Die Einträge sind hier nicht nur durchscrollbar, sondern man kann auch auf die nächst Spannungsveränderung springen/wechseln.


 

Unfertig!

Sofern ich wieder Zeit habe, entwickle ich das Programm weiter.
Das richtet sich auch etwas nach meinem eigenen Bedarf.

 
Ihr könnt mir auch in die Kommentare schreiben, welche Funktion man einbringen könnte.


Als nächstes kommt eine Erweiterung der Divisor Einstellung, welche aktuell noch für alle vier verwendet wird.
Die Anzeige im Diagramm mit über 10V ist noch ausbaufähig, da eine höhere Spannung angezeigt werden könnte. 

Neben dem Programm wäre eine vollständige Schutzschaltung schön. Das Thema bin ich bereits angegangen und ich musste feststellen, dass der Bereich größere Kreise zieht als ich gedacht habe.


Nun könnte ich alle meine Vorhaben hier unter hinschreiben, aber dann wäre das nur für heute aktuell. Deshalb packe ich meine offenen Punkte in den Issues.

Offene Aufgaben Liste - Issues


GitHub - VoltageMeasurementLogger

In der Solution befindet sich das Projekt SimpleVoltageMeasurement, das die Grundlage der Spannungsmessung am Arduino und C# Konsolenanwendung abbildet. Das Projekt VoltageMesurementLogger ist die Anwendung, die im Blogeintrag beschrieben wurde.

 

Dienstag, 7. Dezember 2021

Arduino als einfaches Messgerät


Eigentlich hatte ich einen anderen Text bereits fertig, aber der passte nicht mehr zu dem folgenden Inhalt.
Diesmal geht’s darum einen Arduino als Messgerät einzusetzen und den PC als Anzeigegerät. Natürlich mit dem Ziel eine größere Anwendung zu schreiben, mit welcher man die Messungen aufzeichnen kann.

 

Benötigt

  • Arduino
  • Breadboard
  • 2x 10kOhm Widerstände
  • 3x Jumper Kabel
  • Eine Anwendung, mit der man die Messungen loggen kann

 

Anforderung

Mit einem Arduino soll eine Spannung an einem Step-Down Modul gemessen werden, welches ich in meinem Crawler verwende. Da die Spannung auch höher als 5V sein kann, muss ein Spannungsteiler eingesetzt werden, der die zu erwartenden Spannung abdeckt. Um aktiv das Spannungsgeschehen zu beobachten, soll das Messergebnis auf dem PC wieder gegeben werden.

 

Arduino als Messgerät

Für ein einfaches Messgerät werden grundsätzlich zwei Widerstände benötigt. Zwar kann man auch direkt messen, aber das schränkt den Messbereich stark ein. In meinem Fall könnte die Spannung bei 7,4V hoch gehen und vielleicht auch drüber. Zudem soll mit den Widerständen auch der Strom begrenzt werden, dass zudem den Arduino vom Durchbrennen schützen soll.

 

Bevor eine Messung stattfindet, wird ein kleines Arduino Programm benötigt, mit dem wir auf dem Serial Monitor einen Wert ausgeben können.

 

 #define PIN_Input A0  
 void setup() {  
  Serial.begin(115200);  
  pinMode(PIN_Input, INPUT);  
 }  
 void loop() {  
  int16_t rawMeasurement = analogRead(PIN_Input);  
  byte ba[3];  
  ba[0] = (byte)((rawMeasurement >> 8) & 0xff);  
  ba[1] = (byte)(rawMeasurement & 0xff);  
  ba[2] = (byte)CountBits(rawMeasurement);  
  Serial.write(ba, 3);  
  delay(20);  
 }  
 int8_t CountBits(int16_t rawMeasurement) {  
  int8_t result = 0;  
  for(int i = 0; i < 16; i++) {  
   result += (int8_t)bitRead(rawMeasurement, i);  
  }  
  return result;  
 } 

 

Simple Consolen Anwendung

Der simple Aufbau ist zunächst ein Vorläufer zu meiner eigentlichen kleinen Anwendung. Die Auswahl des seriellen Port hätte man auch weg lassen können, aber auf den Komfort wollte ich dann doch nicht verzichten.

 

class Program  
 {  
   private static int _rawValue;  
   private static int _divisorValue = 511;  
   private static float _voltage;  
   static void Main(string[] args)  
   {  
     Console.WriteLine("Connect Serial with");  
     string[] ports = SerialPort.GetPortNames();  
     if(!ports.Any()) {  
       Console.WriteLine("No Arduino connected!");  
       return;  
     }  
     for (int index = 0; index < ports.Length; index++) {  
       Console.WriteLine($"Index:{index}, Port: {ports[index]}");  
     }  
     string selectindex = Console.ReadLine();  
     if (!int.TryParse(selectindex, out int indexResult)) {  
       Console.WriteLine("You can only typ the index number!");  
       return;  
     }  
     if(indexResult >= ports.Length) {  
       Console.WriteLine("You can only typ the index number!");  
       return;  
     }  
     var sp = new SerialPort(ports[indexResult], 115200);  
     sp.DataReceived += Sp_DataReceived;  
     sp.Open();  
     while (true) {  
       Console.Clear();  
       Console.WriteLine($"{_rawValue} / {_divisorValue} * 5.0 = {_voltage:N2} V");  
       Thread.Sleep(1000);  
     }  
   }  
   private static void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)  
   {  
     var sp = (SerialPort)sender;  
     byte[] buffer = new byte[3];  
     if (sp.Read(buffer, 0, 3) != 0) {  
       int result = (buffer[0] << 8) | buffer[1];  
       var b = new BitArray(new int[] { result });  
       bool[] bits = new bool[b.Count];  
       b.CopyTo(bits, 0);  
       if (bits.Sum(s => s ? 1 : 0) != buffer[2])  
       {  
         return;  
       }  
       _rawValue = result;  
       _voltage = result / (float)_divisorValue * 5.0f;  
     }  
   }  
 } 

 

Divisor festlegen

Man bekommt zunächst einen Rohwert, der zunächst nichts aussagt. Würde man direkt die 5V Pin vom Arduino abgreifen und am Eingangspin A0 anschließen, bekäme man einen Wert von 1024. Dieser Wert muss durch 1024 geteilt und dann mit 5,0 Volt multipliziert werden.

 

Spannung = Rohmesswert / Divisor * 5,0

5,0V = 1024 / 1024 * 5,0V

 

Durch den Spannungsteiler verschiebt sich der eigentliche Rohwert, der die 5 Volt darstellt. Statt durch 1024 zu teilen, fällt dieser Wert in meinem Beispiel auf 511.


2,5V = 511 / 1024 * 5,0V



Das bedeutet, der Divisor muss in meinem Fall auf den aktuellen Rohwert angepasst werden, denn die 5V sind jetzt bei einem Rohwert von 511.

 

5,0V = 511 / 511 * 5,0V

 

Zum testen kann nun vom 3,3V Pin die Spannung zum Messen verwendet werden. Hier sollte nun ein Rohwert bei ca. 345 ankommen. Folgendes Ergebnis ergab sich bei meinem Test:

 

3,39V = 346 / 511 * 5,0V


 

Kleiner Anfang

Natürlich sind die Ergebnisse nicht sehr genau, aber für eine einfache Lösung reicht die grobe Messung aus und ist besser als gar kein Messgerät.

Der Spannungsteiler, mit den zwei 10k Ohm Widerständen, kann eine Spannung von maximal 10V angelegt werden.

 

Warnung

Natürlich sollte man immer berücksichtigen, dass die Leistungsgrenzen nicht überschritten werden. Die zu verwendenden Widerständen sollten möglich hochohmig sein, so dass am Arduino Pin kein hoher Strom eingeht.

 

Zielmessung

Kommen wir zum Testaufbau, mit dem wir eine Messung an einem anderem Stromkreis vornehmen können. Wichtig ist, dass der Ground von der anderen Spannungsquelle mit am GND des Arduinos angeschlossen wird.


 

Was kommt als nächstes?

Eine Sache habe ich hier zunächst ausgelassen, und zwar das Aufzeichnen der Messungen. Eigentlich kann ein Mehrwert mit der Funktion gewonnen werden. Andernfalls hätte man auch ein kleines Display für den Arduino einsetzen können und auf das Spannungsergebnis ausgeben würde.

 

In der Solution befinden sich die Consolen Anwendung SimpleVoltageMeasurement und bereits mein neues Projekt VoltageMeasurementLogger, dass das Aufzeichnen der Daten ermöglicht.

GitHub - VoltageMeasurementLogger

Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...