Atmega16 ADC. Wo ist der Fehler?

OP #3025036
Lesenswert?

Hallo,

ich habe eine Schaltung mit einem Mega16 und KTY81-110 aufgebaut. 
Schaltplan im Anhang.

Derzeit gebe ich die ADC-Werte und die berechnete Temperatur auf einem 
Display aus und die Werte stimmen nicht mit den erwarteten überein.

Bei ca 22°C Raumtemperatur sollte der ADC einen Wert von 276 liefern, 
jetzt komme ich aber nur auf 9°C und einen Wert von 255. Die 255 macht 
mich schon stutzig, wenn ich aber den Sensor abziehe, steigt der 
ADC-Wert wie erwartet auf 1023 an. Stecke ich einen Jumper statt des KTY 
auf, kommt wie erwartet eine 0.

Ein paar relevante Routinen:
1
/***********************************************************************************************/
2
int16_t calculate_temperature(uint16_t adc){
3
  //t=0,64593625*adc-155,4
4
  //#warning "TODO: update equation" done ;)
5
  int32_t adc_temp = 13229 * (uint32_t) adc;
6
  adc_temp = adc_temp / 2048;
7
  adc_temp = adc_temp - 1554;
8
  adc_temp = adc_temp / 10;
9
  return (int16_t) adc_temp;
10
}
11
/***********************************************************************************************/
12
void sprint_temperature(char* str,int16_t temperature){
13
  uint8_t one = 0, ten = 0, houndred = 0;
14
  bool _signed = false;
15
  if(temperature < 0){
16
    temperature *= -1;
17
    str[0] = '-';
18
    _signed = true;
19
    if(temperature > 99) temperature = 99;
20
  }
21
  one = temperature % 10;
22
  ten = (temperature % 100) / 10;
23
  houndred = (temperature % 1000) / 100;
24
  if(houndred == 0){
25
    if(ten == 0){
26
      if(_signed){
27
        str[1] = str[0];
28
      }else{
29
        str[1] = ' ';
30
      }
31
      str[0] = ' ';
32
    }else{
33
      if(_signed){
34
        str[0] = str[0];
35
      }else{
36
        str[0] = ' ';
37
      }
38
      str[1] = ten + '0';
39
    }
40
  }else{
41
    str[0] = houndred + '0';
42
    str[1] = ten + '0';
43
  }    
44
  str[2] = one + '0';
45
}
46
/***********************************************************************************************/
47
void adc_init(void){
48
  uint16_t result;
49
  ADMUX |= (1<<REFS0);                    // VCC with external capacitor at AREF
50
  ADCSRA |= (1<<ADEN) |/* (1<<ADPS2) | (1<<ADPS1) | */(1<<ADPS0); // ADC enabled, prescaler: 1
51
  ADCSRA |= (1<<ADSC);
52
  while(ADCSRA & (1<<ADSC)){;}
53
  result = ADCW; //dummy readout
54
  //ADCSRB = 0x00;
55
}
56
/***********************************************************************************************/
57
uint16_t read_adc(uint8_t portbit){
58
  /*uint16_t result;*/
59
  //ADMUX |= portbit;
60
  //uint16_to_string(str5,ADMUX);
61
  ADCSRA |= (1<<ADSC);
62
  while(ADCSRA & (1<<ADSC)){;}
63
  /*result = ADCW; //dummy readout
64
  result = 0;
65
  for(i=0;i<4;i++){
66
    while(ADCSRA & (1<<ADSC)){;}
67
    result += ADCW;
68
  }
69
  //ADMUX &= ~portbit;*/
70
  return ADCW;
71
}
72
static void avr_init(void)
73
{
74
  
75
  //Enable SPI
76
  spi_init();
77
  adc_init();
78
  
79
  //init communication
80
  //*
81
  USART_Init(0);
82
  
83
  
84
  RELAY_DDR |= (1<<RELAY_DISPLAY) | (1<<RELAY_CAM);
85

86
  DDRC |= (1<<PORTC5);
87

88
  CTRL_DDR |= (1<<REQUEST) | (1<<DISPLAY_READY);
89
  CTRL_PORT |= (1<<REQUEST) | (1<<DISPLAY_READY);
90
  //*/
91
  //Set power mode
92
  set_sleep_mode(SLEEP_MODE_IDLE);   
93
  
94
  //init PAL SYNC port
95
  set_bit(DDRC,7);
96
  //B.4 is sync:1000 ohm + diode to 75 ohm resistor
97
  //MOSI is video:330 ohm + diode to 75 ohm resistor
98
    
99
  // Initialize Sync for PAL
100
  OCR1A = 1024;        //One PAL line 64us
101
  TCCR1B = (1<<WGM12)|(1<<CS10);//full speed; clear-on-match
102
  TCCR1A = 0x00;      //turn off pwm and oc lines
103
  TIMSK = 1<<OCIE1A;    //enable interrupt from Timer1 CompareA
104
  return;
105
}
Im Hauptprogramm werden nur diese Routinen aufgerufen, der Sensor hängt 
am PA0.

Ich habe auch einen zweiten Mega16 probiert, da ist das gleiche Bild. 
Hängt man ein Poti statt des Sensors dran, springt der ADC-Wert von 316 
auf 255 und dann auf 0.

Der Widerstand des 2k7 Pullup stimmt nach Multimetermessung auch und 
kalte Lötstellen konnte ich nicht entdecken.

Ich danke euch für eure Hilfe.
Angehängte Dateien:
Gast #3025070
Lesenswert?

>  ADCSRA |= (1<<ADEN) |/* (1<<ADPS2) | (1<<ADPS1) | */(1<<ADPS0); // ADC 
>enabled, prescaler: 1

Mal den Dreck wegräumen

  ADCSRA |= (1<<ADEN) | (1<<ADPS0); // ADC enabled, prescaler: 1

Läuft deine CPU mit 200kHz?
Ich würde den Prescaler mal höher machen.
Gast #3025242
Lesenswert?

Der ADC braucht eine gewisse Zeit für Sample und Hold.
Ich weiß es beim AVR nicht auswendig, aber bei anderen µCs kann man 
diese Zeiten einstellen, und zwar in ADC-Clock-Takten.
Wenn die Zeiten zu Kurz sind (weil Dein ADC-Takt zu hoch), kann der ADC 
nicht genau arbeiten.

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