Problem mit Spannungsmessung 24V

Hallo alle zusammen,
ich hab ein Problem mit der Messung von 24DC.
die Spannung kommt über zwei Akkus mit jeweils 12V.

Mein Problem ist jetzt, das mir der Spannung-Wert Falsch angezeigt wird, anstatt zu fallen steigt er beim Entleeren der Akkus.

values = analogRead(analogInput);
vin =   values * (4.5 / 1023.0) * (100 + 6.8) / 6.8 ;

Woran könnte das Liegen?

Danke schon mal im voraus..

Hallo,
Versuche es einmal damit:

values = analogRead(analogInput);
vin = values * ( 4.5 / 1023.0 ) / ( 100 + 6.8 ) * 6.8 ;

Lg, Robi

Edit: Die Klammern werden bei mir als Smile angezeigt.. daher Abstand eingefügt..

Roky:
Hallo,
Versuche es einmal damit:

values = analogRead(analogInput);
vin = values * (4.5 / 1023.0) / (100 + 6.8) * 6.8 ;

Lg, robi

Setze dein Sketch-Fragment bitte in Code-Tags, dann wird der auch lesbar.

Sorry, schreibe gerade am iPad, da werden mir die diversen Codes nicht zur Auswahl angeboten und auswendig weiß ich den bestimmten leider nicht.. nächste mal aber, „Ehrenwort“

Hallo Roky,
leider werden mir jetzt Ganz falsche Werte angezeigt.

0.10V bei Values von 364.

Hier mal der Komplette Code ...

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


int analogInput = 2;
float vin = 0;
float values = 0;

// An die Pins 2 und 3 ist der Encoder angeschlossen
#define encoderA 2
#define encoderB 3

// Globale Variablen zur Auswertung in der
// Interrupt-Service-Routine (ISR)
volatile int8_t altAB = 0;
volatile long encoderWert = 0;

// 1/1 Auflösung
int8_t schrittTab[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};

// 1/2 Auflösung ergibt bei Lego-Motoren 1 tick pro Grad (standard wie bei Lego)
//int8_t schrittTab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};

// 1/4 Auflösung
//int8_t schrittTab[16] = {0,0,0,0,0,0,0,-1,0,0,0,0,0,1,0,0};

ISR(TIMER1_COMPA_vect) {
  altAB <<= 2;
  altAB &= B00001100;
  altAB |= (digitalRead(encoderA) << 1) | digitalRead(encoderB);
  encoderWert += schrittTab[altAB];
}

void setup()
{
  pinMode(encoderA, INPUT_PULLUP); // mit pullUp pinMode(encoderA, INPUT_PULLUP);
  pinMode(encoderB, INPUT_PULLUP); // mit pullUp pinMode(encoderB, INPUT_PULLUP);
  pinMode(2, INPUT);
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  lcd.begin(16, 2); 
  lcd.setCursor(1, 0);
  lcd.print("xxx");
  lcd.setCursor(1, 1);
  lcd.print("Encoder Test");

  noInterrupts(); // Jetzt keine Interrupts
  TIMSK1 |= (1 << OCIE1A); // Timer 1 Output Compare A Match Interrupt Enable
  TCCR1A = 0; // "Normaler" Modus
  TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
  OCR1A = 14;
  interrupts(); // Interrupts wieder erlauben

  delay(1500);

  Serial.begin(115200);
}

void loop()
{
  lcd.begin(16, 2);

  for (int x = 0; x < 2; x++)
  {
    lcd.print("  Bitte Warten "); // print a simple message
    delay(1000);
    lcd.clear();
    delay(1000);
  }
  while (true)
  {

    // Werte am analogen Pin lesen
    values = analogRead(analogInput);  //Messwerte am analogen Pin als "values" definieren
    vin =   values * ( 4.5 / 1023.0 ) / ( 100 + 6.8 ) * 6.8; // Messwerte in Volt umrechnen = Spannung am Ausgang des

    Serial.println(values);

    if (vin < 0)
  {
    lcd.print("   Akku Laden "); // print a simple message
      delay(1000);
      lcd.clear();
      delay(1000);
    }
    else
    {
      lcd.setCursor(1, 0);
      lcd.print("       "); // print a simple message
      lcd.setCursor(6, 0);
      lcd.print(vin    ); // print a simple message
      lcd.setCursor(10, 0);
      lcd.print("V Batt"); // print a simple message

      lcd.setCursor(1, 1);
      lcd.print("ecWert:"); // print a simple message
      lcd.setCursor(8, 1);
      lcd.print(encoderWert); // print a simple message

      if (encoderWert < 10) lcd.print(' ');
      if (encoderWert < 100) lcd.print(' ');
      if (encoderWert < 1000) lcd.print(' ');
      if (encoderWert < 10000) lcd.print(' ');
      if (encoderWert < 100000) lcd.print(' ');
      if (encoderWert < 1000000) lcd.print(' ');
    }
  }
}

Aufgabestellung:
Hallsensor einlesen und auf LCD ausgeben.
Versorgung-Spannung auf dem LCD Anzeigen.
Bei Unterschreitung von Spannung XX Meldung auf dem LCD Ausgeben.

zu #1: ich weiß nicht, wie Roky darauf kommt, aber diese Antwort scheint grundlegend falsch.
Die Formel scheint korrekt, wenn die Widerstände wirklich diese Werte haben. Nur scheint der Spannungsteiler stark überdimensioniert: der ADC hat einen Messbereich von 0-1023. Bei ungefähr 350 sollten dann 24V anliegen, also misst Du nur im Bereich 0-350.
Dass der Wert beim Entleeren des Akkus steigt kann gar nicht sein, der berechnete Wert ist proportional zum Messwert. Es kann also nur sein, dass etwas mit der Hardware nicht stimmt... ein Schaltplan wären hier hilfreich.

Anmerkung zu Deinem Code: delay ist böse! Schau Dir mal das Beispiel blinkWithoutDelay an :wink:

12V Bleiakkus haben oft Überspannungen von bis zu 3V, also sollte man sich besser auf max. 30V einrichten.
Wenn man auch auf 3.3V Boards messen will, muss der Spannungteiler das auf max. 3.3V herunter schrauben - ein Spannungsteiler aus 1k und 10k ist da sicher am schnellsten konstruiert.

dann gilt per Dreisatz:

Va/1k= VBatt/11k // Va ist die Spannung am 1k -> ADC, damit 1/11 der Batteriespannung VBatt.
<=>
(1) VBatt=11*Va

Va ergibt einen Wert von ADC=0-1023 für 0-5V bzw. 0-3.3V
per Dreisatz
ADC/1023=Va/5 // ADC ist der gemessene int Wert per analogRead
<=>
Va=5*ADC/1023

eingesetzt in (1)
<=>
(2) VBatt=5*(11*ADC/1023)

bei 3.3V Boards entsprechend
(3) VBatt=3.3*(11*ADC/1023)

so würde ich es zumindest machen.

PS:
delay ist nicht böse, solange man keine Timing Probleme hat.

Hallo Danke für die Antworten,
ich habe jetzt die Formel umgestellt,
jetzt bekomme ich auch die Richtigen Werte Angezeigt.

 vin =   (values *  4.5) / 1023.0  * ( 100 + 6.8 ) / 6.8;

Nein das delay ist momentan kein Problem.

danke für die Hilfe...

ich habe jetzt die Formel umgestellt,
jetzt bekomme ich auch die Richtigen Werte Angezeigt.

-->Eine richtige Umstellung seh ich gerade nicht, oder bin ich blind? :astonished:
Ich würde zudem noch einen laufenden Mittelwert nutzen, um die Spannung zu bestimmen, sonst könnten Störungen zur Verwirrung führen.

Hi,
alle drei Versionen...

vin =   (values *  4.5) / 1023.0  * ( 100 + 6.8 ) / 6.8; // Jetzige Version

vin =   values * ( 4.5 / 1023.0 ) / ( 100 + 6.8 ) * 6.8; // Code von Roky

vin =   values * (4.5 / 1023.0) * (100 + 6.8) / 6.8 ;    //  Original

Eben...Ich kann hier keinen Unterschied erkennen, weder mathematisch noch informatisch. Habe mal um ganz sicher zu gehen Deine Formeln getestet... die Ausgaben sind haargenau gleich.

Code zum Testen:

float values = 0;
float vin = 0;

void setup() {
  Serial.begin(9600);
  for(int i=0; i<300; i++){
    values=i;
    vin =   (values *  4.5) / 1023.0  * ( 100 + 6.8 ) / 6.8; // Jetzige Version
    Serial.print(vin);
    Serial.print("V    ");
    vin =   values * (4.5 / 1023.0) * (100 + 6.8) / 6.8 ;    //  Original
    Serial.print(vin);
    Serial.println("V");
  }
  
}

void loop() {

}

Das sollten sie auch, da Multiplikation und Division gleiche Priorität haben.
Das erste Klammerpaar ist also unnötig, es sei denn man will damit einen logischen Zusammenhang der beiden Werte optisch als Gedächtnisstütze untermauern, was ich hier aber nicht sehe.

Gruß Tommy

Hi,
auch ich habe noch einen Test gemacht,
und auch ich musste Feststellen das Original und der jetzigen Version die selben Werte liefern, bei Roky bekomme ich zwar die selben values Werte aber keine Anzeige.

int analogInput_3 = 3; // Original
int analogInput_4 = 4; // Roky
int analogInput_5 = 5; // Aktuell

float vin_3     = 0;
float values_3  = 0;
float vin_4     = 0;
float values_4  = 0;
float vin_5     = 0;
float values_5  = 0;

void setup() {
  pinMode(analogInput_3, INPUT);
  pinMode(analogInput_4, INPUT);
  pinMode(analogInput_5, INPUT);

  Serial.begin(9600);
}

void loop() {
  messung();
  serial();
}

void messung () {
  //Original
  values_3 = analogRead(analogInput_3);
  vin_3 =   values_3 * (4.5 / 1023.0) * (100 + 6.8) / 6.8;
  //Roky
  values_4 = analogRead(analogInput_4);
  vin_4 =   values_4 * ( 4.5 / 1023.0 ) / ( 100 + 6.8 ) * 6.8;
  //Aktuell
  values_5 = analogRead(analogInput_5);
  vin_5 =   (values_5 *  4.5) / 1023.0  * ( 100 + 6.8 ) / 6.8;
}

void serial() {
  Serial.print("V_org :");
  Serial.print(vin_3);
  Serial.print(" - ");
  Serial.print("val_Org :");
  Serial.print(values_3);
  Serial.print(" -- ");

  Serial.print("V_rok :");
  Serial.print(vin_4);
  Serial.print(" - ");
  Serial.print("val_rok :");
  Serial.print(values_4);
  Serial.print(" -- ");

  Serial.print("V_akt :");
  Serial.print(vin_5);
  Serial.print(" - ");
  Serial.print("val_akt :");
  Serial.println(values_5);
}

werde ich morgen nochmal darum kümmern

Also Roky's Formel kannst Du rausnehmen:
Er hat nur auf Verdacht das Reziproke vom zweiten Teil der Formel gebildet:

( 100 + 6.8 ) / 6.8

-->Im Zähler steht eine sehr große Zahl, im Nenner eine kleine Zahl. Multiplikator ist also recht groß. Das Reziproke hingegen bildet einen Faktor, der gegen 0 geht. Daher ist die Anzeige unsinnig.

Das sollten sie auch, da Multiplikation und Division gleiche Priorität haben.
Das erste Klammerpaar ist also unnötig, es sei denn man will damit einen logischen Zusammenhang der beiden Werte optisch als Gedächtnisstütze untermauern, was ich hier aber nicht sehe.

-->Mein Anfangsverdacht bestand darin, dass der Controller irgendwo in der Formel in int umwandelt, und dabei Daten verloren gehen könnten. Ist aber auch nicht gegeben, values ist ja ebenso als float deklariert.

Hi Tommy,
ja das ist mir schon klar, deswegen war ich ja auch so verwundert warum es nicht ging.

Ich denke das es an den Akkus gelegen hat, denn die Verkabelung und Spannungsteiler haben sich nicht geändert, sondern nur die Spannungsquelle.

Anderer Verdacht, was hängt denn noch an der Versorgung? Vielleicht sogar ein Motor?

ja es war ein bürsten Motor angeschlossen.

Spannungsteiler_II.JPG