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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.