-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Problem der ADC Wandlung bei AtMega16

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23

    Problem der ADC Wandlung bei AtMega16

    Anzeige

    Hallo,
    ich bin recht neu in der Welt der µC'er und braeuchte etwas Starthilfe.
    Bin gerade dabei einen "intelligenten" Thermometer zu basteln, indem ich die Temperatur ueber einen LM35 auslese, die Werte an den ADC des AtMega16 uebergebe, und dieser mir dann die Werte ueber die UART an den Rechner sendet (an Hterm).
    Folgendes Problem gibt es dabei: ich kann nur eine 1023 rauslesen auf dem Hterm.
    Die Hardware ist voellig richtig, wenn ich mit dem Multimeter an den GND und Output des LM35 geh, mess ich vernuenftige 230mV, die sich auch erhoehen wenn ich den Sensor erwaerme.
    Der UART teil der Hardware ist auch richtig, hab davor um die UART zu testen ein Programm geschrieben mit dem ich ueber die UART die LED auf der Platine ein und ausschalten konnte und das Programm mir den "Status" der LED auf Hterm rausgegeben hat.
    Das Problem muss also an dem ADC liegene, respective an meinem Code.
    Ich hab mal meinen Code als .txt angehangen und hoffe auf zahlreiche Tipps.
    Schonmal vielen Dank und Grüße.
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    in deiner Schleife rufst du zwar adc_read auf, aber du weist das Ergenis deiner Variablen adc_wert nicht zu, der Wert wird nur VOR der Schleife einmal belegt und bleibt dann unberührt! Da du außerdem beim ersten adc_read die interrupts noch abgeschaltet hast, wird vermutlich auch kein Messergebnis entstehen, was die 0 erklären würde!

    wofür zum Geier brauchst du das "overflowzahl" ? Der dürfte dir theoretisch niemals antworten! Da du die Bedingung if (overflowzahl==1) nie erfüllen kannst!!!

    Außerdem kannst du dir das lesen des ADC-Wertes in deiner Init sparen!!! Der wert wird nur DANN nicht aktualisiert, wenn du das High- ohne das Lowbyte liest! Also erst ADCH dann ADCL und nicht andersrum! Wenn du garnichts liest intressiert das nicht, nur durch das lesen des Highbytes wird das Lowbyte gesperrt und das Lowbyte durch lesen desselbigen wieder freigegeben!

    Das ADCSRA |=(1<<ADEN); im adc_read ist auch überflüssig, wenn der ADC einmal an ist, geht er nicht wieder aus bis du das Flag explizit löschst.
    und dein Kanalwählen ist so auch nciht richtig: ADMUX = (ADMUX & 0b11000000) | (channel & 0b00111111);
    denn Bit 7 und 6 bestimmen deine Analog-Referenz und dürfen nicht durch die Kanalwahl verändert werden!!!! Deswegen erst die Bits 0 bis 5 löschen und dann die channel Variable maskieren und abschließend ver-oder-n
    Geändert von Ceos (26.09.2011 um 10:39 Uhr)
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23
    @Ceos:
    Vielen Dank fuer die Antwort.
    Also hab jetzt folgendes gemacht:
    erstmal die Zuweisung "adc_wert = adc_read(0);" in die Mainloop gepackt. Dann in der main(void) die Interrupts als allererstes aktiviert. Das Maskieren des ADMUX hab ich jetzt aus deinem Post uebernohmen.
    "overflowzahl" stammt eigentlich aus meinem Timer (ich benutz den ADs ohne Interrupts), der µC soll nur beim auftreten eines Overflows mir auf den Hterm den AD-Wert senden (bei meinem Quarz ist ca. alle 2 Sekunden, also gut lesbar).
    Mit den ganzen Veränderungen funktioniert es trotzdem nicht, ich bekomm jetzt wieder nur noch Nullen, und der Wert veraendert sich natuerlich immer noch nicht wenn ich den Sensor erwaerme.
    Wie wuerdest du das Auslesen realisieren?
    Grueße.

    Nachtrag: der Sensor ist natuerlich am PA0 des AtMegas angeschlossen.

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    das sei() erst nach den inits aber noch vor dem read_ADC so früh darfst du den natürlich auch nicht raushauen ^^

    hast du denn mal z.B. mit einem Voltmeter überprüft ob da überhaupt eine Spannung messbar ist ?!

    EDIT: Ei Ei Ei ... das erste read darf außerdem NICHT vor dem init stehen!!!!! erst die inits, dann sei() dann das erste read

    PS: ich schau nochmal eben ins DAtenblatt ob alles richtig konfiguriert iss

    okay Folgendes:
    mit REFS0 REFS1 nimmst du die interne 2.56V Referenz richtig?
    mit ADPS1 ADPS0 ist dein Teiler 8 nicht 128 wie im Kommentar richtig?

    Wie hast du den Sensor angeschlossen?! Was erwartest du für eine Spannung?! Wie ist der AREF-Pin beschaltet !?

    PPS: Hast du überprüft ob er den Wert mehr als nur einmal ausgibt?!
    Geändert von Ceos (26.09.2011 um 11:13 Uhr)
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23
    Sicherlich, mit dem Voltmeter mness ich eine Spannung, diese veraendert sich auch wenn ich mit den Fingern den Sensor erwaerme. Die Hardware ist zu 100% richtig.
    Meine Zuweisung adc_wert=adc-read(0); steht jetzt in der if-Bedienung der main-loop drin, damit halt beim jedem Overflow der Wert neu ausgelesen wird.

    Interne 2,56V Spannung nehme ich.
    Wegen dem Teiler: hab vergessen in den Kommentaren zu aendern, ist aber auf 8.

    Sensorbeschaltung:
    Ist ein LM35, Vout (mittlerer Pin) geht an PA0, GND sicherlich an GND und Vin sicherlich an Vcc.
    ich erwarte eine Spannung zwischen 200 und 250mV (dieselbe mess ich zwischen Vin und Vout des LM35).
    AREF PIN ist ueber einen Abblockkondensator (100nF) mit GND verbunden.

    Nachtrag: die Null kommt kontinuirlich alle 2 Sekunden (wie auch erwuenscht, nur eben ist der Wert falsch und nicht veraenderbar -.-)
    Geändert von bmtil (26.09.2011 um 11:15 Uhr)

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    ich erwarte eine Spannung zwischen 200 und 250mV (dieselbe mess ich zwischen Vin und Vout des LM35).

    Schreibfehler ?!

    Denn sonst wären das ja 4.8V am PA0 und das wäre ein wenig über der Referenz ^^ ... bisher ergibt sich mir der Fehler nicht, vll. bin ich auch gerade etwas zu blind dafür -.- die Kaffee-Maschine ist Kaputt

    Poste den code einfach nochmal fix (PS versuchs mit den[ C O D E] dein code [ / C O D E] -Tags, macht es einfacher als Dateien hochzuladen, lass nur die Leerzeichen zwischen den Buchstaben weg)
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23
    Ja, ich meinte sicherlich zwischen Vout des Sensors und der Ground.
    Zwischen Vout des Sensors und Vin des Sensors kommen auch die richtigen 4.8V

    hier nochmal der code in "sauber":

    Code:
    #include <avr/io.h>
    #include <stdlib.h> 
    #include <string.h> 
    #include <avr/interrupt.h>
    #include "uart_komplett.h"                        //meine UART
    #include "timer1.h"                                 //meine timer funktion, sorgt dafür dass die UART ausgabe nur alle 2 sekunden erfolgt (overflows halt)
    
    //Dinge definieren
    #define LED_DDR	DDRC               //definieren der LED DDR
    #define LED_PORT	PORTC             //defintion des genauen ports für die DDR
    #define LED_PORTPIN1   PC1                 //definition der roten LED
    #define LED_PORTPIN0   PC0                 //definition des gruenen LED
    
    //Variablen definieren
     
     uint16_t adc_wert = 0;              //Wert des ADC
     volatile uint8_t overflowzahl = 0; //zaehlt die overflows, wichtig für den timer und die UART ausgabe (zwei sekunden takt halt)
      
    //Funktionen definieren
     void adc_init()
     {
     	uint16_t result;                                                       //ergebnis variable festlegen, uint16 wegen 10 bit ergebnis
     	
     	ADMUX = (1<<REFS1)|(1<<REFS0);                            //die interne Referenzspannung nehmen
     	ADCSRA = (1<<ADPS1)|(1<<ADPS0);                          // Frequenzvorteiler bei 8
     	ADCSRA |= (1<<ADEN);                                            //ADEN "enabled" ADC     
     	ADCSRA |=(1<<ADSC);                                            //analog zu digital wandlung aktivieren      
     	                                                  
     													                  
     	while (ADCSRA & (1<<ADSC))                                  // eine "sinnlos" Wandlung durchfuehren um den eventuellen Mist
     	{                                                                       // aus dem Wandler rauszuschmeissen 
     		                                           
     	}
        result = ADCW;                                                         // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register)
                                                                                     //dabei wird immer von ADCL nach ADCH gelesen/                                                                    
                                                                                     //muss einmal gelesen werden, sonst wird das ergebnis der naechsten wandlung nicht gelesen 
     }
    
    //Einzelne ADC Messung und "Lesung" des Wertes
    
     uint16_t adc_read (uint8_t channel)
     {
     	ADMUX = (ADMUX & 0b11000000) | (channel & 0b00111111);    //kanal waehlen
     	 												  
     	ADCSRA |= (1<<ADSC);                                                     // eine Wandlung "single conversion"
         while (ADCSRA & (1<<ADSC) ) 
     	{
     	}                                                                                   // s.o.
         return ADCW;
     }	                                   //geb mir das ergebnis, ADCW is das selbe wie result = ADCL, zusaetzlich zu result += (ADCH<<8)
    
     int main(void)
     {
       
     	 LED_DDR  |= (1<<LED_PORTPIN1)|(1<<LED_PORTPIN0);               //PC1 und PC0 Pins als ausgang festlegen und einschalten  
    
         
    	   
                  LED_PORT = 0x01;                                                     //rote LED an
               
                  DDRA = 0x00;                                                            //explizit den PortA als Eingang deklarieren
       	  uint16_t adc_wert;
    	  char buffer[20];	 
    	     
    	    
                               usart_init();  
                              timer1_init(); 
                              adc_init(0);	
             
                               sei();                                                          //interrupts aktivieren
    		 
                              adc_wert = adc_read(0);                                //zuweisung der Wert - Variable der "Auslese-Funktion"
      
         while(1)
         {        
    		  	    
                              adc_wert = adc_read(0);                                //zuweisung der Wert - Variable der "Auslese-Funktion"
      
    			   if (overflowzahl==1)	                              //UART Uasgabe nur wenn ein Overflow stattfinden
    			   {
    				 
    			   sprintf  ( buffer, "ADC: %d\r\n", (int)adc_wert );                     //string rausgeben, hier leider nur "ADC: 0 "endzeichen""
                   
                                        uart_puts( buffer );			                                //puts fuer den string  
    				
                                        overflowzahl=0;		                    //die zählung der overflows wieder auf 0 setzen, in der ISR fuer den Timer steht drin: "overflowzahl++;", damit die
                                                                                                      // if-Bedienung dieser main-loop erfuellt wird
                                                   
      			 
     		            
        		   } 
    					    
         }
     }
    Geändert von bmtil (26.09.2011 um 11:54 Uhr)

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    okay, das sieht aufegräumter aus, aber ich finde dein besagtes

    adc_wert = adc_read(0);

    nicht innerhalb der while(1)-schleife wieder, was allerdings wichtiger ist, du hast wahrescheinlich ebenfalls einen tippfehler begangen udn das erste adc_read(0) VOR dem sei sollte richtig ein adc_init() sein ?
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23
    Ja genau, hab jetzt nochmal oben (und sicherlich in meinem AVR Studio) die adc_wert=adc_read(0); auch in die while(1) gepackt. Und das adc_read(0) vor dem seio ist sicherlich ein adc_init.
    nun kommt kontinuirlich eine 767, diese verändert sich immer noch nicht und hat auch nichts mit dem Ergebniss zu tun. Nach der Rechnung ADWert= Vout*1024/Vref sollten naemlich ca. 90 rauskommen.

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    26.09.2011
    Beiträge
    23
    So, Problem geloest.
    hab den AtMega getauscht, und es ging mit einem neuen AtMega16. Hab tatsaechlich einen defekten erwischt.
    PS, sorry fuer den Doppelpost, dachte nur das waer interresant.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. AD-Wandlung Freilaufend mit ATMega16 - seltsame ergebnisse
    Von DuRo im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 02.06.2007, 22:58
  2. ADC Wandlung mit Atmega16
    Von C1122345 im Forum Assembler-Programmierung
    Antworten: 1
    Letzter Beitrag: 18.04.2007, 19:52
  3. Problem bei RGB zu HSV-Wandlung
    Von troede im Forum Software, Algorithmen und KI
    Antworten: 12
    Letzter Beitrag: 24.09.2006, 11:47
  4. ADC-Wandlung mit ATMEGA16. Weiterarbeiten mit 10Bit und ASM
    Von moonwalker99 im Forum AVR Hardwarethemen
    Antworten: 10
    Letzter Beitrag: 23.03.2006, 12:03
  5. Problem D/A Wandlung mit MEGA16
    Von farmerjo im Forum AVR Hardwarethemen
    Antworten: 3
    Letzter Beitrag: 18.12.2005, 23:16

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •