PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Analog Comparator (Assembler): wo ist der Fehler?



Lektor
18.09.2005, 02:17
Bin so langsam am verzweifeln. Sitze hier nun Stunden bei und kann den fehler nicht finden.


;-------Analog Comparator Test----------------------------
.include "m8def.inc" ;Definitionsdatei einbinden

rjmp reset ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; Timer1 Capture Handler
reti ; Timer1 compare Handler
reti ; Timer1 Overflow Handler
reti ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; UART RX Complete Handler : RXCIE
reti ; UDR Empty Handler
reti ; UART TX Complete Handler
reti ; ADC Conversion Complete Interrupt Handler
reti ; EEPROM Ready Handler
;rjmp comparator ; Analog Comparator Handler

reset:
; sbi ACSR, ACIS1
; sbi ACSR, ACIS0
; sbi ACSR, ACIE
; sei

ldi r16, 0xFF
out DDRC, r16

ldi r16, 0x00
out PORTC, r16 ;LED aus

ldi r17, ACSR
SBRS r17, 5 ;5=ACO Bitabfrage wenn Comparator schaltet
rjmp reset
ledan:
ldi r16, 0xFF ;LED an
out PORTC, r16
ldi r17, ACSR
SBRC r17, 5 ;5=ACO Bitabfrage wenn Comparator schaltet
rjmp ledan
rjmp reset

;comparator:
; ldi r16, 0x00 ;LED an
; out PORTC, r16
;reti



Das ist das Programm. In der Mega8 Doku steht:"When the voltage on the positive pin AIN0 is higher than the voltage on
the negative pin AIN1, the Analog Comparator Output, ACO, is set." Es muß also auch ohne Interrupt gehen. Habe also mal den Interruptteil auskommentiert.
Das Programm läuft in so weit, dass die richtige LED bei einem vollen Potianschlag leuchtet wenn ich das Programm überspielt habe. Drehe ich den Poti zum anderen Anschlag ist die LED immernoch an. Überspiele ich das Programm erneut bei dem gleichen Potianschlag, so geht die LED aus. Und das kann man wieder anders herum wiederholen. Kann es mir irgendwie nicht mehr erklären. Der Comparator scheint also zu funktionieren, aber nur wenn das Programm überspielt wird. Während der Laufzeit funktioniert es nicht.

Woran liegt es?

eric101
18.09.2005, 03:25
das programm ist meiner meinung nach fehlerfrei, hast du mal ausprobiert obs funktioniert wenn du den controller extern resetest? vielleicht ist er ja kaputt. du benutzt ja schon einen spannungsteiler, also den poti und noch 2 widerstände oder?

Lektor
18.09.2005, 10:16
ja genau, sieht ungefähr so aus.


VCC------------1,1k------------Poti 2,5k-------------GND
|
|
AIN0 (0-3,36V)

VCC------------1,1k------------ 1,1k-------------GND
|
|
AIN1 ( 2,45V)


programmiere mit dem avr studio 4 .11 und uppe mit ponyprog.

habe den internen Takt laufen ( glaube 1MHz), müßte doch reichen oder brauch man für den AC mehr?

habe eigentlich mehrere rätzelhafte Probleme. Timer funktionieren nicht sobald ein Prescaler größer 256 drin ist.

so einfach Programme wie.... funktionieren
main:
ldi r16, 0xFF
out DDRC, r16
ldi r16, 0x00
out PORTC, r16
rjmp main

sobald ich aber ne Endlosschleife wie unten programmiere nicht mehr.
ldi r16, 0xFF
out DDRC, r16
ldi r16, 0x00
out PORTC, r16
main:
rjmp main

(in beiden Beispielen habe ich mal den Def-, Interrupttabellen- und Stackpointerbereich weggelassen.)
habe auch schon die IC's ausgetauscht aber habe immer solche Probleme.
War schon am überlegen ob ich nicht testweise auf ein anderes Programm umsteige. WinAVR oder so.

Also wenn ihr der Meinung seid, dass die Beschaltung und das Programm stimmen, dann werde ich es mal mit einem anderen Programm testen denn so langsam wird es echt frustrierend wenn sich solche unerklärlichen Probleme auftun.

JanB
18.09.2005, 11:34
Hallo,

Bin so langsam am verzweifeln. Sitze hier nun Stunden...
Ich vermisse in deinem Codebeispiel zum Analog-Comparator die
Initialisierung des Comparators.
Seh dir doch mal im Handbuch den entsprechenden Abschnitt und
insbesondere die Funktion der Register SFIOR und ACSR an.

Das An-und Abschalten sämtlicher Bits des Port C,
kann zu dem von dir beschriebenen Verhalten führen,
wenn z.B. eines dieser Bits auch per
AINx als Comparator-Eingang geschaltet ist.
Der Comparotor hat zwei Eingänge.
Du hättest dann so eine Art Schmitt-Trigger-Verhalten "gebastelt":

Gruß Jan

Lektor
18.09.2005, 12:11
Weiss nicht ob eine Initialisierung nötig ist, wenn ich nicht die AC Interrupts nutzen möchte. Im Handbuch steht unter ACSR das der Initial Value von Bit 7 ACD=0 was EIN bedeutet. Muß also wohl nicht extra gestartet werden.

SFIOR ist doch zum Einschalten des Analog Comparator Multiplexer und den brauch ich doch auch nicht, oder doch?

Die Bits von Port C sind ja von AINx getrennt. Und die AINx Pins gehören laut Handbuch zu Port D, falls du das meinst.

Also im Simulator passieren auch merkwürdige Dinge und wenn es selbst dort nicht klappt....
Also bei dem Punkt
ldi r17, ACSR
läd er den Wert 0x08 in r17. woher nimmt er den. ACSR hat den Wert 0x00 und nicht 0x08.
Wenn ich den AD Output (ACO) mit dem Bit5 von ACSR simuliere dann hat ACSR 0x20 aber das Programm ldi't immernoch 0x08 ins r17. völlig unverständlich sowas.

Würde mein Windows so ein verhalten zeigen, dann würde ich glatt auf einen Virus tippen, aber beim AVR Studio gehe ich nicht davon aus ;)

JanB
18.09.2005, 12:20
HAllo,
Die Bits von Port C sind ja von AINx getrennt. Und die AINx Pins gehören laut Handbuch zu Port D, falls du das meinst.
Ja, Stimmt. Ich meinte die ADCx-Pins.
Auf den Simulator kann man sich nicht immer verlassen.
Der Mega-8 funktioniert jedenfalls so wie im Datenblatt beschrieben.
Bei mir war es bis jetzt immer so, dass der Fehler
letztendlich vor dem Monitor sass, und nicht im Chip.
Wie hast du denn den posiven Comparator Input beschaltet ?
Wenn du den Comparatot nicht initialisierst, ist die
Bandgap-Referenz ja nicht zugeschaltet .

Gruß Jan

Lektor
18.09.2005, 12:45
Habe oben die "Skizze".
Wie initialisiert man denn den Comparator? Der AC wird doch mit Bit7 von ACSR eingeschaltet (ADC) und das ist er auch.
Den Multiplexer (SFIOR) benötige ich nicht, da ich AIN0 und AIN1 benutze.
Bandgap Referenz wird doch durch AIN1 erzeugt, welcher den Sollwert darstellt und dieser wird mit AIN0 verglichen. Wenn AIN0 größer als AIN1 ist, dann wird Bit 5 (ACO) in ACSR gesetzt, welchen ich abfragen kann. So habe ich es mir zumindest gedacht.

Lektor
19.09.2005, 19:30
kann mir nicht jemand weiterhelfen? Funktionierender Code der AIN1 und 0 benutzt wäre schon hilfreich.
Also es geht darum, dass ich einen NTC Widerstand mit einem einstellbaren Sollwiderstand vergleichen will. Wenn NTC Widerstand niedrieger ist, als der Sollwiderstand, dann soll ein Transistor angesteuert werden, mit dem ich ein Relais schalten möchte.
Dieses Simple muß nicht unbedingt mit einem uC gelöst werden. Habe es nur ausprobiert, weil es mit einen Comparator IC auch nicht gut geklappt hat. (LM 311). Über google und in diesem Forum konnte ich leider auch nichts finden was weiterhilft. Vielleicht hat ja jemand schon so ein Problem gelöst.
Wäre schön könnte mir jemand weiterhelfen.

SprinterSB
20.09.2005, 10:55
Vielleicht bekommst du aus folgendem Code ne Anregung. Ist zwar C (AT90S2313), sollte aber zu verstehen sein. Ich hatte den AC nicht direkt benutzt um eine IRQ auszulösen, sondern zur Zeitmessung via InputCapture von Timer1 (Kapazitätsmessung).
Für deinen Fall einfach den AC-IRQ aktivieren und die gewünschte Flanke einstellen, sollte dann gehen.


#include "use.h"
#include <AVR.h>
#include "ports.h"
#include "capacity.h"
//#include "morse.h"

extern void ioinit();
extern void wait_10ms (const byte);

#include <math.h>
// Multiplikator:
// k = (ny * R * ln 2)^{-1}
// mit ny = 8MHz und R = 10k:

// k = 18pF / Einheit

word measure_time (byte loadTime)
{
// Load capacity via AIN+ push-pull
SET (PORT_AIN_POS); MAKE_OUT (PORT_AIN_POS);
wait_10ms (loadTime);

// disable all interrupts
cli();

// stop timer1
TCCR1B = 0;

// enable AC (ACD = 0)
// AC Input Capture on -> connect to Input Capture of Timer/Counter1
// AC Interrupt on Falling Output Edge
ACSR = _BV(ACIC) | _BV (ACIS1);

// disconnect timer1 from output pin OC, no PWM
TCCR1A = 0;

// reset timer1 to 0
TCNT1 = 0;

// clear Timer1 OVerflow and Input Capture Flag
TIFR |= _BV (TOV1) | _BV (ICF1);

// start timer 1 at full speed
// no clear on compare match
// no noise cancel
// input capture edge = falling
TCCR1B = _BV (CS10);

// here we go!
// start discharging via external resistor
// AIN+ to high Z
MAKE_IN (PORT_AIN_POS); CLR (PORT_AIN_POS);

byte flag;

do
{
flag = TIFR & (_BV (TOV1) | _BV (ICF1));
} while (flag == 0);

if (flag & _BV (TOV1))
return 0xffff;

// if (flag & _BV (ICF1))
return (word) ICR1;

// restore status of machine
// ioinit();

// morse (_O_);
// if (flag & _BV (ICF1))

// morse_dec (capture-4);
// morse (_FRAGE_);
}


-------------------------------------------------------

Als Temperaturdifferenzschaltung hatte ich mal die Schaltung unten gebastelt. Mit µC schien mit da mit Spatzen auf Kanonen geschossen, ausserdem lässt sich eine µC-Schaltung nicht so simpel über Potis nachtrimmen.

Komparator D schaltet, wenn T_innen > T_aussen ist.
Komparator A schaltet, wenn T_aussen > T_const (zB T_const über Frostgrenze).
Komparator B funktioniert als Und-Glied
danach ein Zeitglied und Komparator C als Schmitt-Trigger

Die T-Abhängigen Widerstände sind NTCs.

JanB
20.09.2005, 11:16
Hallo,
Die Bandgap-Referenz liegt nicht an Ain1 sondern an Ain0 !
aber nur wenn ACBG (Bit6) im Register ACSR auf 1 gesetzt ist.
Den Analogwert muss du dann an Ain1 anschliessen.
ACO (Bit5) von ACSR schaltet dann auf 0, wenn die Spannung an Ain1
gößer ist als die Bandgap-Referenz von ca. 1,2V.
Bit 7 in ACSR auf 1 schaltet den Comparator nicht ein, sondern aus.

Gruß Jan

EM84
23.09.2005, 12:15
Hallo!

Bin grad zufaellig auf das Forum gestossen, weil ich auch den Comparator bei einem AtMega8 benutzen moechte. Vielleicht hab ich irgendwas uebersehen, aber in dem Codebeispiel am Anfang ist doch ein Fehler: Muss es nicht

in r17, ACSR

statt

ldi r17, ACSR

heissen?! Mit in funktioniert die Sache bei mir jedenfalls prima.

Gruesse,

Alexander.

Lektor
26.09.2005, 09:04
wenn du das sagst, dann wird es wohl das Problem gewesen sein. Werde ich mal ausprobieren, wenn ich wieder ein bischen mehr Zeit finde.
Danke für den Hinweis. Ich wußte doch das es auch ohne Interrupt geht :)