Forum: Mikrocontroller und Digitale Elektronik AVR 2313 Komparator


von Jens Riecken (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Als kompletter Neuling auf dem Sektor µC scheitere ich bereits bei
meinem ersten Projekt, und bitte hiermit um Hilfe :-)

Ich moechte via 2 NTCs (100k) mit einem 90S2313 Temperaturen
vergleichen.

Dazu habe ich eine kleine Testplatine mit Inline-Programmer gebaut, und
versucht das mit dem angehaengten Programm zu realisieren.

Wenn ich nun die NTCs an AIN0 und AIN1 haenge, passiert zwar
irgendwas, aber nichts nachvollziehbares.

Es kommt immer irgendwie eine Suppe aus 0'en und 1'en raus.

Vielleicht hat ja jemand eine hilfreiche Idee fuer mich.

Gruss
Jens

von johnny.m (Gast)


Lesenswert?

Erste Auffälligkeit beim Drüberschauen:

DDRB &= (!(1<<PINB3));

Das geht definitiv schief. Da musst Du den Bitkomplement-Operator ~
nehmen. Der Negierungs-Operator ! ist ein logischer Operator und gibt
an der Stelle immer 0 für alle Pins, weil (1<<irgendwas) immer logisch
wahr, also 1 ist.

von johnny.m (Gast)


Lesenswert?

Im übrigen verwendest Du in einer Interrupt-Subroutine globale
Variablen, die nicht 'volatile' deklariert sind. Das kann auch zu
undefiniertem Verhalten führen. Also z.B.:

volatile unsigned int uart_counter = 0;

von johnny.m (Gast)


Lesenswert?

In dem Interrupt-Handler deklarierst Du eine lokale Variable 'buffer',
die zwar abgefragt, aber nirgends mit einem Wert versehen wird. I.a.
werden nicht definierte Variablen automatisch mit '0' initialisiert,
d.h. Deine Abfragen machen keinen wirklichen Sinn...

BTW: Abgesehen von der Tatsache, dass der 90S2313 ein mittlerweile
ziemlich altes Schätzchen ist (Nimm lieber gleich nen Tiny2313, der ist
pinkompatibel, kann wesentlich mehr und wenn Du ihn zersemmelst kriegst
DU auch noch nen neuen und musst nicht auf was ganz neues umsteigen),
solltest Du Dir auch die aktuelle Version von WINAVR besorgen. SIGNAL
ist nämlich auch nicht mehr aktuell. Da Du anscheinend gerade anfängst,
Dich mit der Materie zu befassen, lerne am besten nicht erst was
Veraltetes sondern gleich das Aktuelle, dann brauchste nicht schon so
bald wieder was Neues zu lernen... Nur als Tipp

von johnny.m (Gast)


Lesenswert?

...Ach ja, dadurch, dass Du nirgends das UDR-Register liest, empfängst
Du natürlich auch kein Zeichen und das RXC-Flag wird nie rückgesetzt...

von johnny.m (Gast)


Lesenswert?

Ich vermute mal, da fehlt irgendwo ein 'buffer = UDR;', gell??

von Jens R. (iwo)


Lesenswert?

Erst mal vielen Dank fuer die schnelle Antwort!

> Erste Auffälligkeit beim Drüberschauen:
> DDRB &= (!(1<<PINB3));

Ich hab das nun mal nach
  DDRB &= ~(1<<PINB3));

geaendert, und natuerlich die globale variable mit 'volatile'
versehn.

Das mit dem Interrupt-Handler darfst Du noch nicht so eng sehn - bisher
gibts noch keine Routinen, um das dann abzuarbeiten - nur mal ein
Geruest wies aussehn koennt :)

Vielen Dank fuer den Tip mit dem veralteten 90s2313. Ich hab hier noch
2 Stk ATMega8 und ATMega32 - der 2313'er steckte halt zufaellig schon
im Sockel, und man muss ja nicht gleich die 'dicken Brummer'
verheizen :)

Nachdem das Teil schon 'brennheiss' wurde, ists ja nicht ganz so
abwegig...

Das SIGNAL() Zeugs hab ich aus irgendwelchen Beispielen aus dem Netz
zusammengekratzt, wundert mich also garnicht sonderlich, dass es
nichtmehr aktuell ist. Mal nachsehn, ob bei WinAVR gute Doku dabei
ist.

Dankeschoen - ich versuchs nun mal mit den eingearbeiteten
Korrekturen.

Gruss
Jens

von Jens R. (iwo)


Lesenswert?

Nachtrag:

Witziger Weise funktioniert alles pippifein wenn ichs im Simulator von
AVR Studio laufen lasse...

von Jens R. (iwo)


Lesenswert?

Achja, ein hab ich vergessen... nach haareraufendem Studium des
Datenblattes hab ich die NTCs folgender Massen verkabelt:

  AIN0 -- NTC 100k@25° -- +5V
  AIN1 -- NTC 100k@25° -- GND

Wirkt ein bisschen abartig auf mich, aber so hab ichs interpretiert.

Gruss
Jens

von Thorsten F. (thorsten)


Lesenswert?

Versuchst du die Spannung über den NTCs mit dem Komparator zu
digitalisieren?

Wenn ja, wird das so wie du es aufgebaut hast nicht funktionieren.
Der Kompatator kann wie der Name schon sagt die beiden Spannungen an
den Eingängen miteinander vergleichen und damit nen internen Pin
steuern. ->OP-Amp

Suchst du evtl. nen AD-Wandler? Damit kannst du dann die Spannung über
den NTCs digitalisieren ohne große Beschaltung.

Falls du beim 2313 bleiben willst kannst du das ganze lösen, indem du
einen Kondensator über den NTC lädts und dann die Schaltschwelle
registrierst.

Gruß

von Jens R. (iwo)


Lesenswert?

Aeh, oeh... will ich das?

Ich denke nicht, kann aber durchaus einen Denkfehler in dem ganzen
haben.

Prinzipiell moecht ich eigentlich nur wissen, welche 'Seite' die
waermere ist, also einfache Ausgabe von 0 oder 1 reicht mir voellig.

Gruss
Jens

von Jens R. (iwo)


Lesenswert?

Eh ichs vergess...

Ich hab die Aenderungen eingearbeitet, und obwohl im Sim wenn ich ACO
anhake DDRB3 leuchtet, und auf uart passend 0 oder 1 ausgegeben wird,
seh ich im Terminal-Fenster nur 1en oder durcheinander.

Gruss
Jens

von johnny.m (Gast)


Lesenswert?

> kann aber durchaus einen Denkfehler in dem ganzen
> haben

So siehts wohl aus...
Du musst die NTCs als Teil eines Spannungsteilers betreiben. Sonst
misst Du überhaupt nix Sinnvolles. Da Du die Werte ja nur direkt
vergleichen willst, bist Du nicht auf Linearität angewiesen, so dass Du
mit einem normalen Teiler klarkommen müsstest. Also:

+5V ---> NTC --+-- WIDERSTAND ---> GND
               |
              AINx

oder je nach Gegebenheiten auch den NTC und den Widerstand vertauschen.
Das ganze mit beiden NTCs gleich, dann sollten auch sinnvolle Werte
rauskommen. Bei der Schaltung wie angegeben hast Du eine direkte
Proportionalität zwischen Temperatur und Spannung, das heißt, die
Spannung an dem AINx-Pin ist umso höher, je höher die Temperatur am NTC
ist.

von Henning S. (xtsi)


Lesenswert?

Ganz blöde Idee (hab mit NTCs nie was gemacht), aber wäre das nicht auch
was?

+5V ---> NTC1 --+-- NTC2 ---> GND
                |
               AIN

Wenn Spannung am AIn über 2,5 V dann bei NTC1 wärmer, sonst bei NTC2.
Wäre natürlich nicht mit Komparator, aber nur ein Eingang am AVR würde
genutzt werden...

Nur ne Idee...

Gruss,

XtSI

von Jens R. (iwo)


Angehängte Dateien:

Lesenswert?

Vielen Dank fuer die zahlreichen Antworten!

Leider klappt das nochimmer irgendwie garnicht - nicht mal, wenn ich
ganz plump einfach AINx an GND/VCC haenge.

Ich hab mich nun mal hingesetzt, und versucht ein korrektes Schema zu
zeichnen - evtl. hab ich ja auch in der Schaltung einen murks drinnen.

Aeh und ja, ich weiss, dass ich fuer so ein Schema eingesperrt gehoere
;-)

Gruss
Jens

von Karl heinz B. (kbucheg)


Lesenswert?

Immer noch nicht.

In Langform:

   +5V

   von dort auf einen Anschluss vom Widerstand

   vom anderen Anschluss vom Widerstand zu
      1) dem einen Anschluss am NTC
      2) zum AIN Eingang am µC

   vom anderen Anschluss vom NTC nach Masse


Ein stinknormaler Spannungsteiler halt

   5V   +------+
               |
              ---
              | |  R
              | |
              ---
               |
               |
               +---------------> AIN
               |
               |
              ---
              | |  NTC
              | |
              ---
               |
   0V   -------+


Ob du den NTC jetzt oben oder unten im Spannungsteiler nimmst
ist erst mal egal.

Und ja. Mit dem 2. NTC machst du's ganz genau so

von Jens R. (iwo)


Lesenswert?

Ok, aber jetzt mal ungeachtet des Fehlers in den Spannungsteilern -
meinem Verstaendnis nach, sollte wenn ich AIN0 auf VCC oder AIN1 auf
GND lege die Ausgabe von 0 auf 1 bzw. auf PINB3 5v messbar sein, oder?

Gruss
Jens

von Karl heinz B. (kbucheg)


Lesenswert?

Das sollte es allerdings.
AIN0 auf Vcc UND AIN1 auf GND sollte einen schoenen
stabilen Zustand geben.

von Karl heinz B. (kbucheg)


Lesenswert?

Aber das:

     if (tmp > 0)
    DDRB |= (1<<PINB3); // PINB3
       else
    DDRB &= (!(1<<PINB3));

    }

schreibst du mal besser als

    if( tmp > 0 )
      PORTB |= ( 1 << PINB3 );
    else
      PORTB &= ~( 1 << PINB3 );

Den Pin 3 laufend von Eingang auf Ausgang zu schalten
wird wohl nicht so toll sein.

von Jens R. (iwo)


Lesenswert?

Ok, nun wirds abartig...


Wenn ich nun AIN0 auf +5V lege, dann wechselt die Anzeige auf 1

Wenn ich AIN1 auf GND lege, dann passiert garnichts - ausser dass ein
undefinierter Zustand entsteht sobald ich das Kabel beruehre.

Wenn ich AIN1 auf +5V lege, dann wechselt die Ausgabe auf 0

An PINB3 messe ich 0.000V wenn 0 ausgegeben wird, und 0.002V wenn 1
ausgegeben wird.

'ne Idee, was das bedeutet?

Gruss
Jens

von Karl heinz B. (kbucheg)


Lesenswert?

Zeig nochmal das aktuelle Programm.
Wenn eine 1 ausgegeben wird und der Port richtig eingestellt
ist, dann stehen da aber sowas von Vcc.

von Jens R. (iwo)


Lesenswert?

Hier der aktuelle Code:

      1 #include <avr/io.h>
      2
      3 // RS232 Empfang
      4 #define UART_F_CPU 4000000; // CPU Frequenz
      5 #define UART_PREBYTE '#'  // Kennzeichen fuer start von
Daten
      6 #define UART_RPLBYTE '$'  // Kennzeichnung fuer start von
reply
      7 #define UART_MYADDR  'a'  // Eigene Adresse
      8 #define UART_BAUDRATE 9600; // Baudrate fuer seriell
      9 #define UART_UBR 25
     10 #define UART_EOD     '\n' // End Of Data
     11
     12 volatile unsigned int uart_counter = 0;
     13 unsigned char tmp_last_state = 0;
     14
     15
     16 void uart_send(unsigned char c)
     17 {
     18   UDR = c;
     19   loop_until_bit_is_set(USR, UDRE);
     20 }
     21
     22
     23 void uart_send_string(char *buf)
     24 {
     25   int i, j;
     26
     27   j = strlen(buf);
     28
     29   for (i = 0; i < j; i++)
     30           uart_send(buf[i]);
     31 }
     32
     33
     34
     35 int main(void)
     36 {
     37   unsigned char tmp;
     38
     39   DDRB =  0x00; // PORT B Eingang
     40   DDRB |= (1<<PINB3); // PINB3 als AUSGANG
     41
     42   ACSR = 0x00; // Komparator initialisieren
     43
     44
     45   // UART
     46   UCR = (1<<RXCIE) | (1<<RXEN); // Receive interrupt und
empfaenger akti        vieren
     47   UBRR = UART_UBR; // Baudrate setzen
     48
     49   UCR |= (1<<TXEN); // Transmitter aktivieren
     50
     51
     52   for (;;)
     53     {
     54           // ACO ist gesetzt wenn 2. Komp. Wert groesser
     55           tmp = (ACSR & (1 << ACO));
     56
     57           if (tmp > 0)
     58             uart_send('1');
     59       else
     60             uart_send('0');
     61
     62           if (tmp > 0)
     63             {
     64                   DDRB |= (1<<PINB3); // PINB3
     65                 }
     66       else
     67             {
     68                   DDRB &= ~(1<<PINB3);
     69                 }
     70
     71         }
     72
     73 }
     74

von Karl heinz B. (kbucheg)


Lesenswert?

>          if (tmp > 0)
>     63             {
>     64                   DDRB |= (1<<PINB3); // PINB3
>     65                 }
>     66       else
>     67             {
>     68                   DDRB &= ~(1<<PINB3);
>     69                 }
>     70

Dachte ichs mir doch.
Du schaltest immer noch den Port von Ein auf Ausgabe um.

Du willst den PORT-Pin selbst auf 0 oder 1 setzen:

  if (tmp > 0)
    PORTB |= ( 1 << PINB3 );
  else
    PORTB &= ~( 1 << PINB3 );

von Jens R. (iwo)


Lesenswert?

Alter, ich bin sowas von daemlich...

Jetzt liegt sowas von Vcc an :-)

D.h ich kann am Montag dann das Problem mit den NTCs angehen :)



Danke Dir vielmals fuer die qualifizierte Hilfe!

Gruss & schoenes WE

Jens

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.