Ergebnis von A/D-Umsetzung falsch

In dieses Forum gehören all deine Fragen rund um die Elektrotechnik und im Speziellen zum Bereich der Mikrocontrollertechnik.

Ergebnis von A/D-Umsetzung falsch

#1

Ungelesener Beitrag sebbl » 3. Apr 2019, 07:12

Hallo,

Ich habe versucht, wie im Artikel beschrieben, eine AD-Auswertung zu machen. Im Debugger funktioniert auch alles ohne Probleme. Wenn ich den PIC (12F675) aber in die Schaltung einsetze, dann wird mir der AD-Wert “verschoben”. Ich versuche auszuwerten ob sich eine Spannung zwischen zwei Grenzen bewegt. Wenn ja soll ein Ausgang geschaltet werden.

Wenn ich jetzt auf 0V, abfrage dann wird der Ausgang geschaltet wenn die Spannung am Eingang jedoch bei 3,1V liegt. Die Versorgungspannung beträgt 5V aus einem USB-Lader und am Eingang ist ein Spannungsteiler.

Gibt es dazu eine Idee? Könnte ich in der Software den Nullpunkt verschieben? Anders vergleichen (auf Minuswerte)?

Vielen Dank schonmal und beste Grüße
Sebbl


Link zum Artikel hinzugefügt auf den sich Sebbl bezieht und Titel geändert (aussagekräftiger) - Nico

Re: Ergebnis von A/D-Umsetzung falsch

#2

Ungelesener Beitrag Nico » 3. Apr 2019, 07:24

Hallo Sebbl,

kannst du bitte dein Programm hochladen (als Datei anhängen). Ggf auch den Schaltplan zeigen. Dann wird es für uns deutlich einfacher das Problem zu finden.

Viele Grüße
Nico

Re: Ergebnis von A/D-Umsetzung falsch

#3

Ungelesener Beitrag sebbl » 3. Apr 2019, 07:55

Hi,
hier der Schaltplan und das Programm
Dateianhänge
main.c
(2.31 KiB) 37-mal heruntergeladen
IMG_20190403_074004.jpg

Re: Ergebnis von A/D-Umsetzung falsch

#4

Ungelesener Beitrag Peter1 » 3. Apr 2019, 08:10

Lebt dein USB Port noch?
Du hast da so gut wie ein kurzschluss
Gemacht.

Re: Ergebnis von A/D-Umsetzung falsch

#5

Ungelesener Beitrag Nico » 3. Apr 2019, 08:14

Ohne das Programm jetzt genauer angesehen zu haben schon mal zwei Anmerkungen:
  1. Der Spannungsteiler ist viel zu niederohmig (siehe auch Kommentar von Peter1)
  2. GPIO7 muss (nachdem der Spannungsteiler hochohmiger ist) zwischen die beiden Widerstände
Gruße Nico

Re: Ergebnis von A/D-Umsetzung falsch

#6

Ungelesener Beitrag Peter1 » 3. Apr 2019, 08:31

Du meinst Pin 7.
Gpio 7 gibt es da nicht.
Die Widerstände können 10k Ohm
Oder höher sein.

Re: Ergebnis von A/D-Umsetzung falsch

#7

Ungelesener Beitrag Nico » 3. Apr 2019, 08:36

Peter1 hat geschrieben:
3. Apr 2019, 08:31
Du meinst Pin 7.
Gpio 7 gibt es da nicht.
Richtig :-)

Re: Ergebnis von A/D-Umsetzung falsch

#8

Ungelesener Beitrag pic18 » 3. Apr 2019, 11:57

wie wird denn hier der Interrupt ausgelöst?! Außerdem sollte man im Interrupt keine Zeitschleifen machen!

Re: Ergebnis von A/D-Umsetzung falsch

#9

Ungelesener Beitrag sebbl » 4. Apr 2019, 06:58

Guten Morgen,
ja, der USB-Port lebt noch ;) Genau um eine solche Belastung geht es, sollen USB-Lader sortiert werden. Die eine Sorte bricht bei dieser Belastung deutlich ein und bei der anderen bleibt die Spannung konstant. Daher muss der Spannungsteiler so niederohmig sein.

Dass Pin 7 am oberen Anschluss und nicht in der Mitte ist, ist quasi mein Workaround um das Problem. Auf diese Weise mess ich beim "kleineren" Lader eine Spannung von 3,6V und diese kann ich ja auswerten. Ich wüsste aber gerne wie es "richtig" geht.

gruß sebbl

Re: Ergebnis von A/D-Umsetzung falsch

#10

Ungelesener Beitrag Peter » 4. Apr 2019, 14:37

Wenn du garantieren kannst das die Spannung
nicht höher als die Spannung für den µC wird,
dann kann man es so machen.

Re: Ergebnis von A/D-Umsetzung falsch

#11

Ungelesener Beitrag Nico » 17. Apr 2019, 09:41

Hallo Sebbl,

also gut, du hast den AD-Umsetzer mit ADCON0 = 0b10000000; auf VDD (5V) für die Referenz gesetzt. Der Umsetzer arbeitet mit 10 Bit, demnach ist dein ULSB = 4,88mV. In deinem Programm fragst du verschiedene Bereiche ab:

Code: Alles auswählen

while (Modus == 1) // 2,1A-Modus
{ 
	if ((Wert3 > 50) && (Wert3 < 200))
	{
		Ausgang = 0;
	}
	else 
	{  
		Ausgang = 1;
	}
}    
while (Modus == 0) // 2,4A-Modus (Punkt)
{ 
	if ((Wert3 > 200) && (Wert3 < 300))
	{ 
		Ausgang = 0;
	}
	else
	{  
		Ausgang = 1;
	}
} 
Hieraus würde ich lesen, dass Ausgang aka GPIO5 gelöscht wird, wenn die Spannung an AN0 im Bereich von ca. 0,25 bis 0,976V liegt (etwas gerundet) und Modus aka GPIO2 ein high sieht. Wenn jedoch ein low an Modus anliegt, ändert sich der Spannungsbereich in dem Ausgang gelöscht wird auf 0,976V bis 1,47V (erneut gerundet).

Anmerkung(en) an dieser Stelle:
  • #defines werden üblicherweise immer in Großbuchstaben geschrieben.
  • Variablen werden üblicherweise mit einem Kleinbuchstaben begonnen.
Demnach würde ich empfehlen deine zwei #defines entsprechend zu ändern (englische Begriffe habe ich mir jetzt mal verkniffen ;-) ):

Code: Alles auswählen

#define MODUS		GPIO2
#define AUSGANG		GPIO5
Des Weiteren die Änderung deiner (globalen) Variablen:

Code: Alles auswählen

int wert;
Richtig, nur noch eine statt drei (nicht notwendig, siehe später). Ein weiterer Hinweis: Globale Variablen sollten wenn möglich immer vermieden werden. Aber das soll uns an dieser Stelle jetzt erstmal nicht weiter kümmern.
pic18 hat geschrieben:
3. Apr 2019, 11:57
[..] Außerdem sollte man im Interrupt keine Zeitschleifen machen!
Da hat er recht. Mach es lieber so: Wenn ein Interrupt auftritt, setzt ein Flag für dieses aufgetretene Ereignis (einfach ein Bit / Variable setzen). In der Hauptschleife kannst du dieses Flag überprüfen und entsprechend reagieren.
pic18 hat geschrieben:
3. Apr 2019, 11:57
wie wird denn hier der Interrupt ausgelöst?
Da er in initPIC() das Bit T0IE in INTCON setzt, vermute ich, dass der Timer0 einen kontinuierlichen Interrupt auslösen soll. Konfiguriert hat er diesen über OPTION_REG = 0b00000111;. Somit sollte der Timer mit 4Mhz / (4*256) ~ 3,9kHz laufen (sofern ich nichts übersehen habe). Bei 8 bit ergibt das also einen Interrupt alle ~66ms.



Ich habe mir mal erlaubt deine main.c etwas umzuschreiben (siehe Anhang). Man könnte sicherlich noch mehr verbessern aber lassen wir es erstmal dabei. Ich wollte auch nicht zu viel verändern. Also was habe ich gemacht?

Im Grunde nicht sehr viel .. Ich habe die Anmerkungen (siehe oben) umgesetzt, etwas überflüssige Variablen entfernt und allem voran die Interrupt Service Routine aufgeräumt: In der Routine wird nun nur noch ein Flag gesetzt (flag_tmr0). Dieses Flag wird in der Hauptschleife geprüft und entsprechend die Messung gestartet (ausgelagert in die Funktion readAN0() um es etwas übersichtlicher zu gestalten).

Frage: Mit welchem Compiler arbeitest du? Ich musste die ISR umbenennen, da mein Compiler (XC8) es in diesem Format haben möchte. Das ganze Programm habe ich mit dem Simulator durchgespielt (Funktion wie erwartet).

PS: Die Widerstände sollten die hohe Last vertragen können. Normale 0815 Drahtwiderstände haben oftmals nur 125..250 mW als Belastungsgrenze. Bei den im Quellcode genannten 2,4A sind das dann aber schon >5W! Das möchte ich dann nicht mehr mit nackten Fingern anfassen. Wie wäre es die Last nur kurzzeitig zu schalten (Einschaltdauer je nach Belastungsverhalten/Erprobung der Lader)?
Dateianhänge
main.c
(1.85 KiB) 30-mal heruntergeladen


Zuletzt als neu markiert von Anonymous am 17. Apr 2019, 09:41.

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast