Arduino Zeit zwischen Aufgaben messen

Ich messe mit einem Arduino Uno die Aufladespannung eines Kondensators. Wenn die Spannung von 0,01V überschritten ist, soll der Arduino mit der millis() Funkton anfangen zu zählen. Wenn dann 3,16V erreicht ist soll die Zeit die der Kondensator brauchte um bis 3,16V zu laden in Millisekunden auf einem Display angezeigt werden.

Könnt ihr mir helfen wie ich die Zeit ausmessen kann?
Ich bin für jede Hilfe dankbar.

Hast du vor das mit dem ADC zu messen? Das wird etwas kritisch bei 10mV mit 4,88mV Auflösung. Ein Komparator wäre da genauer. Den kann man an einem normalen digitalen Eingang abfragen, oder auch per Interrupt.

@ Serenifly
Danke für deine Antwort.
ich denke der ADC sollte zum Messen ausreichen.

ich denke der ADC sollte zum Messen ausreichen.

Wenn ganze millis, ca. +-5mV als Auflösung und Vcc als Vref für nom. 5V reichen, dann ja.

analogRead(), millis() und eine passende LCD library für dein Display, fertig.
Das Problem wird eher sein, wann und wie eine neue Messung gestartet wird...

Warum nicht einfach den Code für einen kapazitiven Sensor nehmen, und digital abfragen? Da kann man zwar die Schaltschwelle nicht einstellen, aber 3,16V erscheinen mir ja auch ziemlich willkürlich.

Mein größtes Problem ist gerade, dass der Timer zwar bei 0,1V anfängt zu zählen; dann bei 3,16V aber weiterläuft und nicht anhält um mir den Wert anzuzeigen. Ich möchte sehen wie lange der Kondensator braucht bis 3,16V zu laden.

Danke für eure Hilfe.

@DrDiettrich
3,16V ist 1 Tau des Kondensators wenn man ihn mit 5V auflädt.

wie sieht dein Sketch aus?

Hier ist der Code. Sorry ich bin noch Anfänger.

/*
Pinbelegung:
Arduino 1 auf 14 Display
3 auf 13
4 auf 12
5 auf 11
11 auf 6
12 auf 4
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,5,4,3,2);

int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // Wiederstand R1 (100K)
float R2 = 10000.0; // Wiederstand R2 (10K)
int value = 0;
void setup()
{
pinMode(analogInput, INPUT);
lcd.begin(16, 4);
}
void loop()
{

delay(100); //Hier wird die 2,5 sek. lange pause gemacht.

// read the value at analog input

value = analogRead(4);
vout = (value * 5.0) / 1024.0 + 0.00; // see text
vin = vout ;//((R1+R2)/R2)*8.75/8.54;
//if (vin<0.09) {vin=0.0;} //statement to quash undesired reading !

lcd.setCursor(0,1);
if (vin>3.16) {lcd.print("1 Tau");}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}

lcd.setCursor(9,1);
if (vin>4.965) {lcd.print("5 Tau");}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}

lcd.setCursor(0,2);
if (vin>0.1) {lcd.print(millis());}
if (vin>3.16) {} // an dieser stelle komme ich nicht weiter. ich weis nicht wie ich den Zähler anhalten soll und die Zeit, die der Kondensator brauchte um bis hier zu laden anzuzeigen.

lcd.setCursor(0,0);
lcd.print("Kondensatorkurve");

lcd.setCursor(0, 3);
lcd.print("C1");
if (vin>0.5) {lcd.write(255);} //Hier wird der Abstand der Balken eingestellt.
if (vin<0.5) {lcd.write(25);}
if (vin>1.0) {lcd.write(255);}
if (vin<1.0) {lcd.write(25);}
if (vin>1.5) {lcd.write(255);}
if (vin<1.5) {lcd.write(25);}
if (vin>2.0) {lcd.write(255);}
if (vin<2.0) {lcd.write(25);}
if (vin>2.5) {lcd.write(255);}
if (vin<2.5) {lcd.write(25);}
if (vin>3.0) {lcd.write(255);}
if (vin<3.0) {lcd.write(25);}
if (vin>3.5) {lcd.write(255);}
if (vin<3.5) {lcd.write(25);}
if (vin>4.0) {lcd.write(255);}
if (vin<4.0) {lcd.write(25);}
if (vin>4.5) {lcd.write(255);}
if (vin<4.5) {lcd.write(25);}
if (vin>5.0) {lcd.write(255);}
if (vin<5.0) {lcd.write(25);}

lcd.setCursor(11, 3);
lcd.print(vin); lcd.print("V");

}

Dieses könnte dir als Ansatz dienen, eine brauchbare Kondensatormessung aufzubauen:
https://www.mikrocontroller.net/articles/AVR_Transistortester
Denn dieser Ansatz funktioniert sehr gut.

Was ich vorhabe ist eigendlich das :

  1. Startzeit merken
  2. Kondensator aufladen und ständig analog read machen.
  3. Wenn ich 3,16V erreicht habe dann möchte ich die Endzeit - Startzeit rechnen.

Könntet ihr mir sagen wie ich das im Code machen sollte?

Was ich vorhabe ist eigendlich das :

Du beschreibst einen Weg, nicht das Ziel. Oder?

Möchtest du die Kapazität ermitteln?

Ich möchte die Spannung messen die der Kondensator gerade hat.

Wenn 3,16V erreicht sind will ich einfach den Zähler (millis) stoppen. Ich weis aber nicht wie ich das anstellen soll. Ich müsste einfach nur den Zähler pausieren.

Möchtest du die Kapazität ermitteln?

Eher die Zeitkonstante eines RC-Glieds bestimmen ...

Nehmen wir mal an, die schwierigen Aufgaben hättest du geschafft: Den Kondensator entladen und einen Start-Trigger erkannt und du weisst wie du was auf das Display ausgibst...

#define MINIMUM 3  // StartKriterum > 0.002*Vcc (ca. 0.01V )
#define MAXIMUM 614 // Ende bei >  0.6*Vcc         ( ca. 3.00V )


void setup() { Serial.begin(9600); } // statt LCD-Anzeige
void loop() {
  static bool running;
  static unsigned long startzeit;  
  static bool starttrigger = true; // mit Reset geht's los, danach ist unklar 

  int wert = analogRead(A0);

  if (running == false && wert == 0  && starttrigger) {
    running = true;
    starttrigger = false;
  }
  
  if (running && startzeit == 0 && wert >= MINIMUM)   
       startzeit = millis();

  if (running && wert >= MAXIMUM) {
     running = false;
     unsigned long dauer = millis() - startzeit;
     Serial.print(dauer); Serial.println (" msec");
     Serial.println("Entladen und Reset fuer neue Messung");
  }

}

Danke für die Antwort.

Als ich Teile des Programms in meinen Code implementiert habe kommen allerdins diese Fehlermeldungen:

sketch_aug26a.ino: In function 'void loop()':
sketch_aug26a:68: error: 'running' was not declared in this scope
sketch_aug26a:68: error: 'wert' was not declared in this scope
sketch_aug26a:68: error: 'starttrigger' was not declared in this scope
sketch_aug26a:73: error: 'running' was not declared in this scope
sketch_aug26a:73: error: 'startzeit' was not declared in this scope
sketch_aug26a:73: error: 'wert' was not declared in this scope
sketch_aug26a:76: error: 'running' was not declared in this scope
sketch_aug26a:76: error: 'wert' was not declared in this scope
sketch_aug26a:78: error: 'startzeit' was not declared in this scope
'running' was not declared in this scope

Der Code sieht jetzt so aus:

/*
Pinbelegung:
Arduino 1 auf 14 Display
3 auf 13
4 auf 12
5 auf 11
11 auf 6
12 auf 4
*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);

int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // Wiederstand R1 (100K)
float R2 = 10000.0; // Wiederstand R2 (10K)
int value = 0;
#define MINIMUM 3 // StartKriterum > 0.002Vcc (ca. 0.01V )
#define MAXIMUM 614 // Ende bei > 0.6
Vcc ( ca. 3.00V )
void setup()
{
pinMode(analogInput, INPUT);
lcd.begin(16, 4);
}
void loop()
{

delay(100); //Hier wird die 2,5 sek. lange pause gemacht.

// read the value at analog input

value = analogRead(4);
vout = (value * 5.0) / 1024.0 + 0.00; // see text
vin = vout ;//((R1+R2)/R2)*8.75/8.54;
//if (vin<0.09) {vin=0.0;} //statement to quash undesired reading !

lcd.setCursor(0,1);
if (vin>3.16) {lcd.print("1 Tau");}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}
if (vin<3.16) {lcd.write(25);}

lcd.setCursor(9,1);
if (vin>4.965) {lcd.print("5 Tau");}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}
if (vin<4.965) {lcd.write(25);}

/* lcd.setCursor(0,2);
if (vin>0.1) {lcd.print(millis());}
if (vin>3.16) {} */ // an dieser stelle komme ich nicht weiter. ich weis nicht wie ich den Zähler anhalten soll und die Zeit, die der Kondensator brauchte um bis hier zu laden anzuzeigen.

if (running == false && wert == 0 && starttrigger) {
running = true;
starttrigger = false;
}

if (running && startzeit == 0 && wert >= MINIMUM)
startzeit = millis();

if (running && wert >= MAXIMUM) {
running = false;
unsigned long dauer = millis() - startzeit;
Serial.print(dauer); Serial.println (" msec");
Serial.println("Entladen und Reset fuer neue Messung");
}

lcd.setCursor(0,0);
lcd.print("Kondensatorkurve");

lcd.setCursor(0, 3);
lcd.print("C1");
if (vin>0.5) {lcd.write(255);} //Hier wird der Abstand der Balken eingestellt.
if (vin<0.5) {lcd.write(25);}
if (vin>1.0) {lcd.write(255);}
if (vin<1.0) {lcd.write(25);}
if (vin>1.5) {lcd.write(255);}
if (vin<1.5) {lcd.write(25);}
if (vin>2.0) {lcd.write(255);}
if (vin<2.0) {lcd.write(25);}
if (vin>2.5) {lcd.write(255);}
if (vin<2.5) {lcd.write(25);}
if (vin>3.0) {lcd.write(255);}
if (vin<3.0) {lcd.write(25);}
if (vin>3.5) {lcd.write(255);}
if (vin<3.5) {lcd.write(25);}
if (vin>4.0) {lcd.write(255);}
if (vin<4.0) {lcd.write(25);}
if (vin>4.5) {lcd.write(255);}
if (vin<4.5) {lcd.write(25);}
if (vin>5.0) {lcd.write(255);}
if (vin<5.0) {lcd.write(25);}

lcd.setCursor(11, 3);
lcd.print(vin); lcd.print("V");

}

Dann schau mal das Beispiel allein an, und erkenne dass millis() nie angehalten wird,
Die Differenz millis() - startzeit kann natürlich, wenn die Zeit es erlaubt, auch während der Messung ermittelt und angezeigt werden.

Und wenn du unbedingt willst, kannst du loop() auch nur alle 100 ms laufen lassen (Schade, aber ist ja dein sketch) Lieber würde ich noch einen zweiten Zeitmerker nehmen, der dir mit der gleichen Methode
if (millis() - letzteAnzeige > 100)  { ... } sagt, wann das Display wieder aktualisiert werden soll.

Nachtrag: Glaub nicht, dass nur weil du mit float rechnest, 3.16 auch 3.16V wären. Krieg lieber raus, welcher Wert (0 .. 1023) deiner 4.965 entspricht.

Um einen LCD Balken zu zeichnen, braucht man keine float-Berechnung.

Vielen Dank für deine Mühe. Morgen will ich mich etwas mit deinen Tipps auseinandersetzen.

du hast Teile von dem Sketch von michael_x übernommen, aber die Variablendeklaration vergessen.
Ändere in deinem Sketch wert in value und setze am Anfang von loop

static bool running;
            static unsigned long startzeit;  
            static bool starttrigger = true; // mit Reset geht's los, danach ist unklar

ein, dann müsste es fehlerfrei kompelieren.

Wenn du einen Sketch ins Forum kopieren willst, benutze bitte </> oben links über den Smilies.

beim betrachten deines Sketches sind mir noch ein paar Dinge aufgefallen:

int analogInput = 0;
pinMode(analogInput, INPUT);
value = analogRead(4);

Du defenierst analogInput als A0, liest dann aber A4 ein.

vout = (value * 5.0) / 1024.0 + 0.00; // see text
vin = vout ;//((R1+R2)/R2)*8.75/8.54;

Bei einem 10Bit ADC gehen die Werte von 0 bis 1023, also müsstest du durch 1023 teilen.
Wofür steht das + 0.00?
Du setzt vin=Vout ohne Bedingung, also könntest du gleich vin = (value * 5.0) / 1023.0; nehmen

float R1 = 100000.0; // Wiederstand R1 (100K)
float R2 = 10000.0; // Wiederstand R2 (10K)

Du definierst R1 + R2, benutzt sie aber in deinem Sketch nicht.

lcd.begin(16, 4);

Du initialisierst dein Display mit 16 Zeichen und 4 Zeilen, rufst aber 20 x lcd.write auf.

@ ardubu; michael_x

Vielen dank für eure Hilfe. Jetzt funktioniert das Programm endlich! :smiley:

Danke auch an alle anderen die geholfen haben.