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
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.
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;
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
...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...
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
Nachtrag: Witziger Weise funktioniert alles pippifein wenn ichs im Simulator von AVR Studio laufen lasse...
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
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ß
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
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
> 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.
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
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
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
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
Das sollte es allerdings. AIN0 auf Vcc UND AIN1 auf GND sollte einen schoenen stabilen Zustand geben.
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.
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
Zeig nochmal das aktuelle Programm. Wenn eine 1 ausgegeben wird und der Port richtig eingestellt ist, dann stehen da aber sowas von Vcc.
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
> 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 );
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.