JYE-Tech Cap Meter mit Arduino UNO auslesen

Hallo
ich bin komplett neu hier auf dem Forum und ebenfalls komplett neu in der Arbeit mit einem Arduino UNO. Meine BA-Betreuung hat mir den gestern quasi an den Kopf geworfen und gesagt: Hier mach das mal....
Nun Gut, jetzt sitze ich hier und versuche mich irgendwie damit auseinander zu setzten. Aber erstmal zu meinem Problem. Ich messe eine Kapazität mit dem Cap-Meter Kit. Das Messgerät funktioniert auch sehr gut. Laut der Anleitung gibt es am TXD Pin einen ASCii output in der Form SSSSS TTTTT.tt CCCCU. Also insgesamt 3 Bereiche. SSSSS ist eine 5digit Sequenznummer, TTTTT.tt ist ein 8digit Zeitstempel in Sekunden und CCCCU ist die 5digit gemessene Kapazität mit U als Buchstabe für die gemessene Größenordnung, z.B. p für pico-Farad. Die Output baud rate ist 38400. die einzelnen Felder sind durch eine Leerstelle (space) getrennt. Daten Format ist 8 data bits, 1 stop bit und no parity.

Zur Verbindung von Messgerät mit UNO:
Ich dachte mir ich muss den TXD Pin vom Messgerät mit dem RX->0 Pin am UNO verbinden. Das Messgerät wird extern mit Strom versorgt, der UNO über USB.

Zur programmierung dachte ich mir folgendes:
zuerst muss ich dem Arduino sagen wo er die Daten herbekommt. ich vermute es geht mit dem digitalRead(0) Befehl. die Ausgabe davon sollte über Serial.println() funktionieren. Damit ich nur alle 5Sekunden einen Messwert aufnehme brauche ich delay()?

void setup() {
  
  Serial.begin(38400); //vorgegebene Baud-rate
}

void loop() {
  
  int cap = digitalRead(0); //einlesen am RX->0 Pin 
  Serial.println(cap);
  delay(5000);
}

Beim kompilieren wird mir kein Fehler ausgegeben, aber die Ausgabe über den Monitor ist immer der Wert 1.

Ich hab es auch schonmal mit analogRead(A0) probiert, dann ist die Ausgabe immer 0.

Ich muss am Ende für die Ausgabe auf dem Monitor am besten auch die Werte direkt lesbar anzeigen, also nicht als ASCii code ausgeben, ist das möglich?
Ich hoffe ihr könnt mir weiterhelfen und entschuldige mich schonmal für mein Unwissen :sweat_smile:

Was ist eine "BA-Betreuung"?

Die hat einen Fehler gemacht, da der UNO nur eine serielle Schnittstelle (Hardware) hat, die gleichzeitig mit USB verbunden ist und damit für den seriellen Monitor belegt. Alternativ könnte man das Meßgerät auch an eine per Software generierte serielle Schnittstelle hängen, da funktionieren aber keine 38400 Baud. Wenn sich die Baudrate nicht auf 9600 reduzieren läßt, sehe ich Dich in einer Sackgasse.

Laß Dir einen Arduino Mega2560 an den Kopf werfen, der hat drei freie serielle Schnittstellen.

Damit willkommen im Forum!

BA ist Bachelorarbeit, und ich kann die Messdaten die mein Messgerät ausgibt nicht auf den UNO übertragen und am PC ausgeben? habe ich das jetzt richtig verstanden? Ich dachte genau dafür wäre der da...

agmue:
....Alternativ könnte man das Meßgerät auch an eine per Software generierte serielle Schnittstelle hängen, da funktionieren aber keine 38400 Baud. Wenn sich die Baudrate nicht auf 9600 reduzieren läßt, sehe ich Dich in einer Sackgasse....

Das stimmt nicht ganz.
Auch SoftwareSerial funktioniert mit hoheren Baudraten.

Ich arbeite hier problemlos über eine längere Leitung (als R232) mit 57600. Es gibt jedoch keine Fehlerprüfung.
SoftwarSerial

Allerdings sollte man bei höheren Baudraten besser "AltSoftwareSerial" einsetzen.

Bachelorarbeit also, danke.

HotSystems:
Auch SoftwareSerial funktioniert mit hoheren Baudraten.

Das lese ich gerne und will es Dir einfach mal so glauben :slight_smile:

Was mir noch eingefallen ist: Bei RS232 auf die verwendeten Spannungen achten.

agmue:
Was mir noch eingefallen ist: Bei RS232 auf die verwendeten Spannungen achten.

Ja, da habe ich kleine Konverterplatinen für genommen. Konverter
Das funktioniert prima. :wink:

so wirklich hilft mir das alles leider nicht weiter, ich habe kein anderes Gerät zur Verfügung und laut meiner Betreuerin funktioniert das mit dem UNO auch. Später sollen die Messwerte im .csv Format auf einer SD-Karte gespeichert werden...
Jetzt will ich mir halt die Messwerte auf dem PC speichern. Meine Frage wäre jetzt warum ich mein Messgerät nicht an den UNO anschließen kann?
Irgendwie ergibt das alles für mich keinen Sinn o.O

funksteckdose:
Meine Frage wäre jetzt warum ich mein Messgerät nicht an den UNO anschließen kann?

Die entsprechende Antwort habe ich inzwischen zurückgezogen.

Also PC an USB und Meßgerät an andere Pins und mit SoftwarSerial ansteuern. HotSystems schreibt, das geht auch mit 38400 Baud, dann wollen wir ihm das glauben.

Grüße Deine Betreuerin, es gäbe bessere Arduinos wie den Mega2560 mit drei freien Schnittstellen für diese Aufgabe. Der Arduino soll ja wohl nur Rechenknecht sein und nicht im Mittelpunkt Deiner Arbeit stehen, vermute ich.

funksteckdose:
Irgendwie ergibt das alles für mich keinen Sinn o.O

Wieso macht das keinen Sinn ?
Poste doch mal einen Link, bitte Hyperlink, von deinem Messgerät.

Ich kenne das nicht und bin nicht sicher, ob es nicht auch eine RS232 braucht.

Wichtige Frage:
Was hat dein “Cap-Meter Kit” für eine (serielle) Schnittstelle? Was gibt es dort für Pegel?
Ist es TTL, dann sind das z.B. 5 Volt und 0 Volt oder ist es
RS232, da hast du Pegel von z.B. +12 Volt und -12 Volt.
Im ersten Fall kannst du das direkt an den Arduino anschließen, im zweiten Fall brauchst du Hardware (das hat HotSystems ja schon erwähnt), sonst kann es sein, dass du den Arduino killst.

So wie es aussieht, willst du das Arduino-Board eigentlich “nur” als Serial-zu-USB-Wandler gebrauchen.
Dass heißt die seriellen Daten sollen nur “durchgereicht” werden, völlig ohne Bearbeitung.
Das geht ganz (wenn du mal TTL-Pegel hast) mit einem UNO ganz leicht…

Aber versuche bitte zuerst die “wichtige Frage” zu beantworten. :slight_smile:

Also hier mal zuerst ein Link zum Cap-Meter http://www.watterott.com/en/Capacitance-Meter-Kit. und die Anleitung dazuhttp://www.jyetech.com/Products/CapMeter/Capacitance%20Meter%20Manual.pdf

Theoretisch würde ich die Daten gerne umgewandelt dargestellt speichern bzw anzeigen lassen. Also nicht im ASCii-Format sondern direkt lesbar :cold_sweat: :cold_sweat:

Ok, lt. Datenblatt kannst du das Ding direkt an den Arduino anschließen und mit der SoftwareSerial auch auslesen.
Das solltest du erst mal hinbekommen, dann kannst du dichum die weitere Datenbearbeitung kümmern.

ich komme irgendwie nicht weiter, ich habe das Messgerät jetzt am Arduino UNO angeschlossen und bekomme auch Daten zurück.

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
int S = 0; 
float T = 0; 
char C = 0; 

void setup() {
  Serial.begin(38400);
  inputString.reserve(200);                                                                   // reserve 200 bytes for the inputString:
  }

void loop() {
  // print the string when a newline arrives:
  
  if (stringComplete /*&& !Serial.available()*/) {
    Serial.print("inputString:  ");Serial.println(inputString);
    inputString = "";                                                                         // clear the string:
    stringComplete = false;
    }
  }

void serialEvent() {
  while (Serial.available()) {
      char inChar = (char)Serial.read();                                                        // get the new byte:
      inputString += inChar;                                                                    // add it to the inputString:
      if (inChar == '\n') {                                                                     // if the incoming character is a newline, set a flag so the main loop can do something about it:
        stringComplete = true;
      }
    }
  }

aber die Rückgabe ist zum Großteil nicht leserlich und öfter wird auch mal keine neue Zeile angefangen...

Die Rückgabe sieht folgendermaßen aus:
inputString: 09373 šÂÊÂr‚¢šªr0p

inputString: 09374 03898.45 &“)‚)09375 šÂÊÂrºš¢.7p

inputString: 09376 šÂÊÊr’š¢.5p

Die erste Zahl ist die Sequenznummer, diese wird zu 95% richtig dargestellt, danach sollte eig ein 8stelliger Zeitstempel kommen und danach die Kapazität. das p am ende steht für die Größenordnung pico. Könnt ihr mir sagen warum die Ausgabe so aussieht? Baud-rate ist im Monitor richtig eingestellt.

p.s. Habe die Ausgabe mit 2 unterschiedlichen UNOS, einem Nano und 2 unterschiedlichen Messgeräten versucht...

An welche Pins des Arduino hast Du das Meßgerät angeschlossen? Wenn es 0 und 1 sind, dann ist das falsch, weil schon von USB belegt. Du mußt SoftwareSerial an anderen Pins verwenden!

DANKE DANKE und nochmals DANKE
habs soweit hinbekommen und kann das Messgerät nun vernünftig auslesen. Jetzt muss ich nur noch gucken wie ich das ganze auf eine SD-Karte schreiben kann, aber dafür gibt es bestimmt genug vorhandene Threads xD

hier für interessierte mal mein Code, falls es Verbesserungsvorschläge gibt nehme ich die natürlich gerne an…

#include <SoftwareSerial.h>        // entsprechende Bibliothek einbinden 
                                  
SoftwareSerial softSerial(10, 11); // Pin Digital 10 ist RX, Pin Digital 11 ist TX
                                   // Die Funktion softSerial() kann nun wie Serial() genutzt werden

char c_inChar;   // Jedes empfangene Zeichen kurz in dieser Variable speichern
String s_input;  // Alle Zeichen werden nacheinander in diesem String gespeichert

void setup()
{
  //initialisieren der seriellen Schnittstelle (USB) des UNO, hier findet die Kommunikation mit dem PC statt
  Serial.begin(9600);
  Serial.println("Messgeraet 1"); 

  //initialisieren der seriellen Schnittstelle der SoftwareSerial Bibliothek
  softSerial.begin(38400);
}

void loop() 
{
 
  while(softSerial.available() > 0){        //Schleife wird solange wiederholt wie Daten empfangen werden
    c_inChar = softSerial.read();           //Speichere das empfangene Zeichen in c_inChar
    s_input.concat(c_inChar);               //gibt alle Zeichen an den string 
    if (c_inChar == '\r') {                 //sobald das letzte Zeichen ein Zeilenende makiert
      Serial.print("input-String: ");       //schreibe input-String:
      Serial.print(s_input);                //und in dieselbe Zeile dann den gesamten String
      Serial.print('\n');                   //für eine neue Zeile
      s_input="";                           //Lösche den Inhalt des Strings zum neubeschreiben
    }
  }
}

funksteckdose:
Jetzt muss ich nur noch gucken wie ich das ganze auf eine SD-Karte schreiben kann, aber dafür gibt es bestimmt genug vorhandene Threads xD

Lade Dir die Bibliothek SdFat runter, die kann längere Dateinamen beispielsweise mit Datum, da gibt es auch ein csv-Beispiel. Das sieht etwas erschreckend aus, ist aber bei näherer Betrachtung nicht so schlimm, finde ich.

funksteckdose:
hier für interessierte mal mein Code, falls es Verbesserungsvorschläge gibt nehme ich die natürlich gerne an…

  • In diesem Forum wird “String” als fehlerbehaftet und daher nicht empfehlenswert eingestuft. Nutze lieber ein Feld char s_input; Dann kannst Du die in der C-Bibliothek enthaltenen, aber nicht in der Arduino-IDE beschriebenen, Funktionalitäten für Zeichenketten nutzen. (Funktionen zur Speichermanipulation)
  • Konzeptionell mußt Du möglichst blockadefrei programmieren, da Du keine Zeichen verlieren möchtest. Ich habe mal probiert, daß schon ein kleines delay() den Datenempfang durcheinander bringt. Da loop schon eine Schleife ist, würde ich while zu if ändern und damit die while-Schleife öffnen. Dann kannst Du später neue Zeichen empfangen, während Du die alten auf die SD-Karte schreibst, quasi parallel. Wie häufig werden Datenpakete gesendet, wie groß ist die Pause dazwischen?

also ich würde gerne eine bestimmte Anzahl an Messwerten aufnehmen, z.B. 100 Messwerte, danach will ich eine 10minütige Pause machen und danach die nächsten 100 Messwerte aufnehmen. Diese Messwerte will ich dann in einer Datei auf einer microSD speichern.
Momentan weiß ich noch nicht wie ich die microSD beschreiben kann. Aus dem rawwrite Beispiel werde ich irgendwie nicht schlau -,-
Bei meinem Versuch soll nachher kein Laptop dabei stehen. ich habe also nur den Arduino UNO an dem das Messgerät und der microSD-Adapter angeschlossen sein soll.
Leider kann ich meinen Code momentan nicht überprüfen, da die Messgeräte beide im Einsatz in der Uni stehen, aber ich habe zumindest mal versucht mir den Timer zu programmieren. Hoffe das es so funktioniert…

#include <SoftwareSerial.h>        // entsprechende Bibliothek einbinden 
                                  
SoftwareSerial softSerial(10, 11); // Pin Digital 10 ist RX, Pin Digital 11 ist TX
                                   // Die Funktion softSerial() kann nun wie Serial() genutzt werden

char inChar;              // Jedes empfangene Zeichen kurz in dieser Variable speichern
String input;             // Alle Zeichen werden nacheinander in diesem String gespeichert
int cnt = 0;              //zählt anzahl einträge 
unsigned long timeOld;    // speichert zeitpunkt an dem 100 erreicht wurde
int bol = 0;              // zustand der state machine

void setup()
{
  //initialisieren der seriellen Schnittstelle (USB) des UNO, hier findet die Kommunikation mit dem PC statt
  Serial.begin(9600);
  Serial.println("Messgeraet 1"); 

  //initialisieren der seriellen Schnittstelle der SoftwareSerial Bibliothek
  softSerial.begin(38400);
}

void loop() 
{
 if(cnt <100 && bol == 0) {
  while(softSerial.available() > 0){        //Schleife wird solange wiederholt wie Daten empfangen werden
    inChar = softSerial.read();           //Speichere das empfangene Zeichen in inChar
    input.concat(inChar);               //gibt alle Zeichen an den string 
    if (inChar == '\r') {                 //sobald das letzte Zeichen ein Zeilenende makiert
      Serial.print("input-String: ");       //schreibe input-String:
      Serial.print(input);                //und in dieselbe Zeile dann den gesamten String
      Serial.print('\n');                   //für eine neue Zeile
      input="";                           //Lösche den Inhalt des Strings zum neubeschreiben
       }
    }
    cnt = cnt+1;
  }
  else if (bol == 0){
    timeOld = millis(); //zeitpunkt in ms 
    bol = 1; //nicht mehr sammeln
  }
  if(bol == 1 && ((millis() - timeOld) >= 600000)) {  //600000ms = 10min
  cnt = 0; bol = 0;
  } 
}

ich finde mich irgendwie immer noch nicht so zurecht was programmieren angeht, hätte in der Vorlesung dazu mal besser aufpassen sollen.
Wäre aber auch angenehmer gewesen wenn meine Betreuerin nicht gerade 2 Wochen vor der Abgabe damit ankommt 0,o

funksteckdose:
Momentan weiß ich noch nicht wie ich die microSD beschreiben kann. Aus dem rawwrite Beispiel werde ich irgendwie nicht schlau -,-

In readCSV.ino steht alles, was Du brauchst.

Ich komme immer noch nicht damit zurecht, habe jetzt erstmal mit dem Timer Probleme bei der Ausgabe. Es werden zwar immer 10 Messreihen ausgegeben und die erste Ausgabe ist auch immer korrekt, danach startet die 2. Ausgabe aber nicht in einer neuen Zeile. Auch gibt er mir quasi 3 alte Messwerte mit aus und nur 7 neue, anhand der Sequenznummer ist jedes Mal zu erkennen das er 3 Messwerte aus dem jeweils vorhergehenden Messblock bezieht. Ich hoffe es ist klar wie ich das meine, die Ausgabe sieht folgendermaßen aus:

Messgeraet 1

input-String: 03597 03734.75 98.4n

input-String: 03598 03735.39 98.4n

input-String: 03599 03736.02 98.4n

input-String: 03600 03736.66 98.5n

input-String: 03601 03737.30 98.4n

input-String: 03602 03737.94 98.5n

input-String: 03603 03738.58 98.4n

input-String: 03604 03739.22 98.5n

input-String: 03605 03739.85 98.4n

input-String: 03606 03740.49 98.5n

input-String: 03607 03741.13 98.4n

input-String: 03608 03741.77 98.5n

input-String: 03609 03742.41 98.403700 03800.50 98.5n

input-String: 03701 03801.14 98.4n

input-String: 03702 03801.78 98.5n

input-String: 03703 03802.42 98.5n

input-String: 03704 03803.06 98.4n

input-String: 03705 03803.69 98.5n

input-String: 03706 03804.33 98.5n

liegt das daran das ich das ganze noch mit dem String input und nicht mit char s_input laufen lasse?
Ich hab versucht das zu ändern aber dann wird bei dem
input.concat(inChar); //gibt alle Zeichen an den string
eine Fehlermeldung ausgegeben:

Arduino: 1.8.1 (Windows 10), Board: “Arduino/Genuino Uno”

auslesen_Zeitverz_gert\auslesen_Zeitverz_gert.ino: In function ‘void loop()’:

auslesen_Zeitverz_gert:28: error: request for member ‘concat’ in ‘s_input’, which is of non-class type ‘char’

s_input.concat(inChar); //gibt alle Zeichen an den string

^

…auslesen_Zeitverz_gert\auslesen_Zeitverz_gert.ino:33:14: warning: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]

s_input=""; //Lösche den Inhalt des Strings zum neubeschreiben

^

exit status 1
request for member ‘concat’ in ‘s_input’, which is of non-class type ‘char’

vllt könnt ihr mir ja direkt mit meinem code helfen, was genau ich ändern soll/muss

#include <SoftwareSerial.h>        // entsprechende Bibliothek einbinden 
                                  
SoftwareSerial softSerial(8, 9); // Pin Digital 8 ist RX, Pin Digital 9 ist TX
                                   // Die Funktion softSerial() kann nun wie Serial() genutzt werden

char inChar;              // Jedes empfangene Zeichen kurz in dieser Variable speichern
char s_input[];             // Alle Zeichen werden nacheinander in diesem String gespeichert
int cnt = 0;              //zählt anzahl einträge 
unsigned long timeOld;    // speichert zeitpunkt an dem 100 erreicht wurde
int bol = 0;              // zustand der state machine

void setup()
{
  //initialisieren der seriellen Schnittstelle (USB) des UNO, hier findet die Kommunikation mit dem PC statt
  Serial.begin(9600);
  Serial.println("Messgeraet 1");
  Serial.print('\n'); 

  //initialisieren der seriellen Schnittstelle der SoftwareSerial Bibliothek
  softSerial.begin(38400);
}

void loop() 
{
 if(cnt <200 && bol == 0) {                 //solange noch keine 100 Messwerte erreicht sind läuft die Schleife
  if(softSerial.available()){        //Schleife wird solange wiederholt wie Daten empfangen werden
    inChar = softSerial.read();           //Speichere das empfangene Zeichen in inChar
    s_input.concat(inChar);               //gibt alle Zeichen an den string 
    if (inChar == '\r') {                 //sobald das letzte Zeichen ein Zeilenende makiert
      Serial.print("input-String: ");       //schreibe input-String:
      Serial.print(s_input);                //und in dieselbe Zeile dann den gesamten String
      Serial.print('\n');                   //für eine neue Zeile
      s_input="";                           //Lösche den Inhalt des Strings zum neubeschreiben
       }
    cnt = cnt+1;
    }
  }
  else if (bol == 0){
    timeOld = millis(); //zeitpunkt in ms 
    bol = 1; //nicht mehr sammeln
  }
  if(bol == 1 && ((millis() - timeOld) >= 60000)) {  //60000ms = 1min
  cnt = 0; bol = 0;
  } 
}

Die String-Methoden funktionieren nicht mit Zeichenketten, da ist mehr Handarbeit gefragt. Also

s_input[j]=inChar;
j++;

Für das Zwischenspeichern der Meßwerte wäre ein zweidimensionales Feld sinnvoll. Das darf nur den Speicher des UNO nicht sprengen.

Serial.print braucht recht lange, also erst zwischenspeichern und dann das Feld in der Pause ausgeben, so wie dann später bei der SD-Karte.