Go Down

Topic: 2 Analog Eingänge stören sich, wieso ?? (Read 442 times) previous topic - next topic

linuxer

Oct 21, 2019, 04:36 pm Last Edit: Oct 21, 2019, 04:37 pm by linuxer
Hallo Leute,

ich bin was die Arduino-Geschichte betrifft relativ neu dabei und habe noch nicht so den Überblick.
Um etwas mit der Materie warm zu werden haben ich mir ein Project vorgenommen.

Genauer gesagt habe ich mir einen Staubsauger Roboter gebaut und bin nun daran die ganze Sache nach und nach zu Programmieren.

Ich hatte früher schon so einen gebaut der mit einem Atmega16 lief, ich wollte aber das Design ändern deswegen habe ich die Teile des alten für den neuen verwendet, unter anderem auch die Tastatur.

Betrieben wird der Roboter mit einem Arduino Mega2560, ich weis etwas übertrieben, aber ich hatte den und deswegen habe ich den eingebaut :)

Zum Problem:
Die Tastatur ist an A0 angeschlossen und funktioniert als Spannungsteiler.
Je nachdem welche Taste gedrückt wird, wird ein Widerstand mit R2 parallel geschaltet und der Wert ändert sich.
Soweit so gut und das Funktioniert auch.

Nun muss ich natürlich die Spannung überwachen damit die Batterie nicht komplett Leer gelutscht wird. Deswegen wird an A1 auch über einen Spannungsteiler die 12 V eingespeist ausgewertet und alle 10 Sekunden auf dem Display angezeigt.
Auch das Funktioniert soweit.

Das Problem ist wenn ich die Tastaturabfrage Routine ausklammere, dann funktioniert die Spannungsanzeige ohne Probleme. Alle 10 Sekunden wird die Spannung gemessen und angezeigt. Der gemessene Wert entspricht so ziemlich genau dem Wert den mein Multimeter anzeigt.

Habe ich die Tastatur aktiv dann wird beim ersten mal die Spannung korrekt angezeigt danach wird immer 15.06 Volt angezeigt. Dazwischen erscheint dann zwar mal immer wieder der richtige Wert, aber das ist selten.

Wenn ich mir den Wert des Eingangs der Spannungsüberwachung (A1) anschaue wird immer 1023 (entspricht den 5 Volt) eingelesen es liegen aber definitiv 4,irgendwas Volt an und keine 5 Volt.

Ich habe keine Ahnung was da schief läuft. Vielleicht kann sich jemand ja mal das Script ansehen und findet den Fehler.

Code: [Select]
#include <LiquidCrystal.h>
#include <TimerOne.h>

LiquidCrystal lcd(32, 30, 22, 24, 26, 28);

//Tastatur
int analogpin_1 = A0; //Tastatur
int tastatur_wert = 0;
int taste = 0;

//12 Volt Spannungsüberwachung
int analogpin_2 = A1;
int spannungs_wert = 0;

void setup()
{
 //Timer für Spannungsanzeige
 Timer1.initialize(10000000);      // 10000000µs = 10s
 Timer1.attachInterrupt(spannungsIsr); // soll "timerIsr()" benutzen
 interrupts();                     // Ermöglichen von Interrupts
  
 Serial.begin(9600);
 lcd.begin(16,2);
 lcd.print("Roboter V2.0.");
}


void loop()
{
 tastatur();

}

void tastatur()
{
 tastatur_wert = analogRead(analogpin_1);
 
 if (tastatur_wert<1023)
 {
  if (tastatur_wert > 235 & tastatur_wert < 245)
  {
   taste = 1;
  }

  if (tastatur_wert > 715 & tastatur_wert < 725)
  {
   taste = 2;
  }
 
  if (tastatur_wert > 950 & tastatur_wert < 960)
  {
   taste = 3;
  }

  if (tastatur_wert > 155 & tastatur_wert < 165)
  {
   taste = 4;
  }
 
  if (tastatur_wert > 325 & tastatur_wert < 335)
  {
   taste = 5;
  }
 
  if (tastatur_wert > 910 & tastatur_wert < 920)
  {
   taste = 6;
  }
 
  if (tastatur_wert > 518 & tastatur_wert < 528)
  {
   taste = 7;
  }
 
  if (tastatur_wert > 280 & tastatur_wert < 290)
  {
   taste = 8;
  }
 
  if (tastatur_wert > 860 & tastatur_wert < 870)
  {
   taste = 9;
  }

  Serial.print(taste);
  Serial.println("");  
//  Serial.print(tastatur_wert);  
//  Serial.println("");

  delay(300);  
 }
 taste = 0;
}

void spannungsueberwachung()
{
 float spannung;
 spannungs_wert = analogRead(analogpin_2);               //12 Spannung einlesen
 spannung = (spannungs_wert*(5.0/1023)*3.0125);
 
 lcd.setCursor(0,1);  
 lcd.print("Batt.");
 lcd.setCursor(6,1);  
 lcd.print(spannung);
 lcd.setCursor(12,1);  
 lcd.print("Volt");

 Serial.print(spannungs_wert);
 Serial.print(" - ");
 Serial.println(spannung);
 
 
}

void spannungsIsr()
{
 spannungsueberwachung();
}


Hoffende Grüße  :)
Thomas



Tommy56

Warum willst Du die Spannung unbedingt über einen Interrupt auslesen?
Mit millis() im Loop geht das auch problemlos und Du vermeidest die Fehler im Interrupthandling.

Wenn es denn unbedingt sein muss, mach Dich mal schlau, wie man Variablen für Interrupts deklariert (volatile) und wie man sie im Loop ausliest.
Jede Art von Ausgabe hat in ISR nichts zu suchen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

ElEspanol

Irgendwie habe ich das Gefühl, dass du nicht ganz verstanden hast, was ein Interrupt ist und wozu er verwendet wird.

postmaster-ino

Hi

Zum Problem:
Da Du den Aufbau nur umschreibst und auch nur die Symptome des analogRead, denke ich mir, daß Deine Spannungsteiler sehr hochohmig sind (>>10kΩ) und Du so nicht den S&H-Kondensator (Sample and Hold) innerhalb des analog-Pin in der zur Verfügung  stehenden Zeit geladen/entladen bekommst.
Abhilfe:
- Spannungsteiler niederohmiger machen
- Spannungsfolger (OpAmp Grundschaltung) zwischen Spannungsteiler und A-Pin.
Da der S&H-Kondensator von allen Analog-Pins benutzt wird, muß Das auf beiden Spannungsteilern gemacht werden.

Ggf. reicht Es, wenn Du nur den 12V-Spannungsteiler niederohmiger machst - die Tastatur scheint ja alleine zu funktionieren - hier wäre mein Weg, damit ich nicht die ganzen Widerstände durchtauschen muß, der Spannungsfolger.

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

uwefed

Ich habe auch den Verdacht daß der Spannungsteiler zur Batteriespannungsmessung zu hochohmig ist und darum der interne Sample and Hold Kondensator in der Lade-Zeit nicht auf Endwert geladen / entladen wird und darum vom vorherigen Meßwert beeinflußt wird.

Zu den Lösungsvorschlägen meiners Vorredners möchte ich hinzufügen:
* 0,1µF Kondensator zwischen Analogeingang A1 und Masse. Da sich die Batteriespannung nicht schnell ändert hat der Hochohmige Spannungsteiler Zeit den 0,1µF Kondensator aufzuladen und der S&H holt sich den Ladestrom von diesem.
* Mehrere Messungen der Batteriespannung hintereinander (zB 10) und nur den letzten Meßwert nehmen. So kann sich der S&H Kondensator über mehrere Ladezyklen vollladen.

Enferne die Batteriemessung aus der Interruptroutine.

Grüße Uwe

Tommy56

Oder besser: Entferne die ISR

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

linuxer

Hallo Leute,

ich weis das man die ISR "schnell abhandelt, aber da ich sie sowieso nur alle 10 Sekunden aufrufe sah ich kein Problem darin.
Zum Spannungsteiler der beiden Eingänge kann ich momentan nichts sagen, ich habe die Daten jetzt nicht hier. Ist schon ne weile her das ich das aufgebaut habe. Kann aber schon sein dass das alles hochomig ist.

Ich werde eure Vorschläge mal abarbeiten, mal sehen was daraus wird.

Danke
Thomas


HotSystems

ich weis das man die ISR "schnell abhandelt, aber da ich sie sowieso nur alle 10 Sekunden aufrufe sah ich kein Problem darin.
......
Wozu eine ISR, die du nur alle 10 sek aufrufst.
Ich vermute, du verstehst nicht, wozu eine ISR überhaupt gebraucht wird.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Serenifly

Viele Anfänger denken ISRs wären ein einfacher Weg um Code wiederholt auszuführen. Egal in welchem Zusammenhang. Das ist aber überhaupt nicht in der Fall. In der Realität ist der Umgang mit Interrupts recht kompliziert, da man viele Dinge beachten muss. Die Arduino IDE erweckt da mit ihren Beispielen einen völlig falschen Eindruck

Doc_Arduino

#9
Oct 22, 2019, 05:46 pm Last Edit: Oct 22, 2019, 05:48 pm by Doc_Arduino
Hallo,

grober Schnitzer
Code: [Select]

if (tastatur_wert > 235 & tastatur_wert < 245)
  {


An die Stelle gehört && statt & hin. Letzteres macht eine Bitoperation und nicht den gewünschten Vergleich.
https://www.arduino.cc/reference/en/language/structure/boolean-operators/logicaland/

Und machst du innerhalb der ISR Serial Aufrufe die selbst wiederum Interrupts benötigen. Das kann nicht gut gehen. Mach die zyklischen Aufrufe mit millis Blockierfrei und alles läuft.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

michael_x

Quote
grober Schnitzer, an die Stelle gehört && statt & hin
im Prinzip ja, praktisch hier egal, denn das < bzw. >= hat Vorrang vor beiden and - Verknüpfungen.
true & true liefert dasselbe wie 1 & 1, oder  true && true

2 & 3 ( -> 2) ist allerdings etwas anderes als 2 && 3  ( -> true )

Doc_Arduino

#11
Oct 22, 2019, 06:07 pm Last Edit: Oct 22, 2019, 06:34 pm by Doc_Arduino
Hallo,

korrigieren würde ich es dennoch.

Es sollen ja beide Bedingungen erfüllt sein. Der Wert soll in einem bestimmten Bereich sein. Dieser soll dann nicht verunded sondern verglichen werden. Habs noch nicht getestet, denke jedoch das macht schon einen Unterschied ...

Edit 1:
mir fällt übrigens noch mehr auf im Sketch.

Wofür?
Code: [Select]

if (tastatur_wert<1023)
 {


und die Formel lautet korrekt:
spannungs_wert*(5.0/1024)*3.0125)

Edit 2:
was du noch machen kannst wegen dem Interrupt ist, nur ein bool Flag zusetzen. Das delay muss dabei dennoch raus. Am Ende kannste deswegen gleich alles mit millis erschlagen.

Edit 3:
@ Micha:
habs ausprobiert, funktioniert tatsächlich
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up