AdSense

Montag, 20. Mai 2013

ATmega - Temperaturmessung mit dem DS18S20

(English version) Um die Temperatur in meinem Zimmer zu messen benutze ich einen DS18S20, dies ist ein 3-Pin-Temperatursensor (sieht aus wie ein Transistor), welcher digital von einem ATmega8 ausgelesen wird. Die Genauigkeit liegt laut Herstellerangabe bei ± 0,5 °C. Der Sensor hat folgende Anschlüsse: Vcc (bei mir +5V), Gnd und den Daten-Pin. Genaue Infos zu dem Übertragungsprotokoll gibt es im Datenblatt, hier ist mal der Code, wie ich die Temperatur via ATmega auslese. Zu beachten ist: PORTD0 ist Ausgang, PORTD2 Eingang und beide Pins sind mit dem Daten-Pin des Sensors verbunden:

void on()
{
  PORTD |= (1 << PORTD0);
}

void off()
{
  PORTD &= ~ (1 << PORTD0);
}

void write(int hilow)
{
  if (hilow == 0)
  {
   off();
   _delay_us(80);
   on();
   _delay_us(20);
  }
  else
  {
   off();
   _delay_us(5);
   on();
   _delay_us(95);
  }
}

void read()
{
  off();
  _delay_us(2);
  on();
  _delay_us(98);
}

double read0()
{
  double retVal = 0;
  off();
  _delay_us(2);
  on();
  _delay_us(1);
  if (PIND & (1 << PIND2)) //HIGH
  {
    retVal = 1;
  }
  else
  {
    retVal = 0;
  }
  _delay_us(97);
  return retVal;
}


double measureTemp()
{
  double temp = 0;
  double fac = 0.5;
  double neg = 0;
  double value = 0;

  off();
  _delay_us(500);
  on();
  _delay_us(1000);

  write(0);
  write(0);
  write(1);
  write(1);
  write(0);
  write(0);
  write(1);
  write(1);

  _delay_us(100);
  //Start temperature conversion
  write(0);
  write(0);
  write(1);
  write(0);
  write(0);
  write(0);
  write(1);
  write(0);

  _delay_us(1000);

  off();
  _delay_us(500);
  on();
  _delay_us(1000);

  write(0);
  write(0);
  write(1);
  write(1);
  write(0);
  write(0);
  write(1);
  write(1);

  _delay_us(100);
  //read Temperature
  write(0);
  write(1);
  write(1);
  write(1);
  write(1);
  write(1);
  write(0);
  write(1);

  value = read0();

  temp += fac * value; fac = fac*2; 
  bits[0] = value;

  value = read0();
  temp += fac * value; fac = fac*2;
  bits[1] = value;

  value = read0();
  temp += fac * value; fac = fac*2;
  bits[2] = value;

  value = read0();
  temp += fac * value; fac = fac*2;
  bits[3] = value;

  value = read0();
  temp += fac * value; fac = fac*2;
  bits[4] = value;

  value = read0();
  temp += fac * value; fac = fac*2; 
  bits[5] = value;

  value = read0();
  temp += fac * value; fac = fac*2;
  bits[6] = value;

  value = read0(); 
  temp += fac * value;  bits[7] = value;
  //das letzte Bit beachte ich nicht, wenn man später count_remain mit einbezieht, ist dies nicht mehr nötig.

  neg = read0();
  read();
  read(); 
  read();
  read();
  read(); 
  read();
  read();

  //TH 
  read(); 
  read(); 
  read(); 
  read();
  read(); 
  read();
  read();
  read();

  //TL 
  read(); 
  read();
  read();
  read(); 
  read();
  read(); 
  read(); 
  read();

  //Reserved 
  read(); 
  read(); 
  read(); 
  read(); 
  read(); 
  read(); 
  read(); 
  read();

  //Reserved
  read();
  read(); 
  read(); 
  read(); 
  read(); 
  read(); 
  read(); 
  read();

  //COUNT REMAIN 
  count_remain[0] = read0(); 
  count_remain[1] = read0();
  count_remain[2] = read0();
  count_remain[3] = read0();
  count_remain[4] = read0(); 
  count_remain[5] = read0(); 
  count_remain[6] = read0(); 
  count_remain[7] = read0();

  //COUNT PER °C 
  count_per_c[0] = read0(); 
  count_per_c[1] = read0();
  count_per_c[2] = read0(); 
  count_per_c[3] = read0(); 
  count_per_c[4] = read0(); 
  count_per_c[5] = read0(); 
  count_per_c[6] = read0(); 
  count_per_c[7] = read0(); 

  //CRC 
  read(); 
  read();
  read();
  read();
  read(); 
  read(); 
  read(); 
  read();

  //Man kann die Präzision erhöhen, indem man noch count_remain mit einbezieht.
  //Dies habe ich dann erst an einer späteren Stelle im Programm gelöst. 

  return temp;

}


Keine Kommentare:

Kommentar veröffentlichen