AVR 2313 Komparator

Gast #347807
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
Angehängte Dateien:
Gast #347808
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.
Gast #347809
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;
Gast #347810
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
#347813
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
#347815
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
#347816
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ß
Gast #347819
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.
#347820
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
#347821
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
Angehängte Dateien:
#347822
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
#347826
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
#347828
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
#347829
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 );

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren