bmtil
29.09.2011, 07:13
Guten Morgen.
Ich hab an meinem µC AtMega16 einen LM35 angebracht. Alles drum und dran, UART, ADC funtkionieren, kleines LabView Prog dazu geschrieben, alles super. Nun habe ich an der Stelle des alten LM35 einen neuen angebracht, allerdings in mit 4 Meter Kabel (der soll in 4 meter Entfernung in einer Klimakammer haengen) und nun spuckt mir die Software komische Werte raus. Die Innentemperatur "schwankt" plötzlich zwischen 17 und 35 °C, dabei bin ich doch noch recht jung. Und früh am Morgen draußen mess ich Werte bis zu 32 °C!
Denke ich mir also dass der Sensor ne Macke hat und vermesse den. Der funktioniert. Der Multimeter zwischen Signalausgang und GND zeigt mir auch vernuenftige Werte an, also irgendwas immer um die 220mV wenn es um die Raumtemperatur geht.
Es muss also an der Software liegen, wobei das natuerlich auch recht unmoeglich ist, da mit dem alten LM35 es ja super funktioniert hat.
daher bin ich gerade etwas ratlos.
Hier der Code nochmal:
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include "uart_komplett.h"
#include "timer1.h"
//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; //halt die noetige variable festlegt
volatile uint8_t overflowzahl = 0; //zaehlt die overflows
//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<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler bei 128, ergibt eine WandelFrequenz von 57,6kHz
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 = ADCL; // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register)
result |= (ADCH<<8); //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)
{
uint16_t result;
ADMUX = ((ADMUX & 0b11000000) | (channel & 0b00111111)); //kanal waehlen
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) )
{
}
result = ADCL; // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register)
result |= (ADCH<<8);
return result;
} //geb mir das ergebnis, ADCW is das selbe wie result = ADCL
void 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=0;
uint16_t adc_wert;
char buffer[20];
usart_init();
timer1_init();
adc_init();
sei(); //interrupts aktivieren, zum overflows zaehlen, damit die adc werte alle 2 sekunden kommen
adc_wert = adc_read(0);
while(1)
{
if (overflowzahl >= 1)
{
adc_wert = adc_read(0);
itoa(adc_wert, buffer, 10);
uart_puts("");
uart_puts(buffer); //puts fuer den string
USART_Transmit(0x0A);
overflowzahl=0;
}
}
}
Grueße und vielen Dank schonmal.
Ich hab an meinem µC AtMega16 einen LM35 angebracht. Alles drum und dran, UART, ADC funtkionieren, kleines LabView Prog dazu geschrieben, alles super. Nun habe ich an der Stelle des alten LM35 einen neuen angebracht, allerdings in mit 4 Meter Kabel (der soll in 4 meter Entfernung in einer Klimakammer haengen) und nun spuckt mir die Software komische Werte raus. Die Innentemperatur "schwankt" plötzlich zwischen 17 und 35 °C, dabei bin ich doch noch recht jung. Und früh am Morgen draußen mess ich Werte bis zu 32 °C!
Denke ich mir also dass der Sensor ne Macke hat und vermesse den. Der funktioniert. Der Multimeter zwischen Signalausgang und GND zeigt mir auch vernuenftige Werte an, also irgendwas immer um die 220mV wenn es um die Raumtemperatur geht.
Es muss also an der Software liegen, wobei das natuerlich auch recht unmoeglich ist, da mit dem alten LM35 es ja super funktioniert hat.
daher bin ich gerade etwas ratlos.
Hier der Code nochmal:
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include "uart_komplett.h"
#include "timer1.h"
//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; //halt die noetige variable festlegt
volatile uint8_t overflowzahl = 0; //zaehlt die overflows
//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<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler bei 128, ergibt eine WandelFrequenz von 57,6kHz
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 = ADCL; // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register)
result |= (ADCH<<8); //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)
{
uint16_t result;
ADMUX = ((ADMUX & 0b11000000) | (channel & 0b00111111)); //kanal waehlen
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) )
{
}
result = ADCL; // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register)
result |= (ADCH<<8);
return result;
} //geb mir das ergebnis, ADCW is das selbe wie result = ADCL
void 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=0;
uint16_t adc_wert;
char buffer[20];
usart_init();
timer1_init();
adc_init();
sei(); //interrupts aktivieren, zum overflows zaehlen, damit die adc werte alle 2 sekunden kommen
adc_wert = adc_read(0);
while(1)
{
if (overflowzahl >= 1)
{
adc_wert = adc_read(0);
itoa(adc_wert, buffer, 10);
uart_puts("");
uart_puts(buffer); //puts fuer den string
USART_Transmit(0x0A);
overflowzahl=0;
}
}
}
Grueße und vielen Dank schonmal.