Der in diesem Artikel verwendete Temperatursensor ist der MCP9808 von Adafruit. Als Anzeige der Temperatur dient ein LCD Display, welches eine parallele Datenübertragung nutzt (bereits hier eingeführt).


Temperatursensor MCP9808

Abb.: Adafruit Temperatursensor; Quelle: BBS2 Wolfsburg


Der Temperatursensor verfügt über die für I²C notwendigen SCA und SDA Pins, sowie Vdd zur Spannungsversorgung und Gnd. Zusätzlich beinhaltet er einen Alert Pin, welcher konfigurierbar ist. Er kann z.B. beim Überschreiten oder Unterschreiten einer definierten Temperatur auf Low oder High gesetzt werden und so busunabhängig "Warnungen" ausgeben. Die Pins A0 bis A2 dienen der Manipulation der Slave Adresse. Standardmäßig verwendet der MCP9808 die Adresse 0x18. Will man diese verändern, so zieht man die Pins A0 bis A2 auf High. Eine entsprechende Konfigurationstabelle sieht wie folgt aus:

Adressen

Abb.:MCP9808 Adressen; Quelle: BBS2 Wolfsburg


In dem folgenden Beispiel werden die Pins A0 bis A2 nicht zusätzlich beschaltet. Daraus ergibt sich die Standard-Adresse des Sensors 0x18. Der Aufbau sieht folgendermaßen aus:


Aufbau Hardware

Abb.: Aufbau der Schaltung Temperaturanzeige; Quelle: BBS2 Wolfsburg


Es werden beim I²C Bus explizit keine Pull-Up-Widerstände verwendet, da diese bereits auf der MCP9808 Platine integriert sind.

Das nachfolgende Programm verwendet Bibliotheken, die zwingendermaßen eingebunden werden müssen. Wie dies möglich ist, erfahren Sie hier.

Die Bibliothek (lcd-routines.c und lcd-routines.h) für das LCD Display finden Sie hier. Die für I²C (twinmaster.c und i2cmaster.h) auf folgendem Link. Es handelt sich bei letzteren um eine von Peter Fleury entwickelte I²C Bibliothek. Wie man die LCD Bibliothek konfiguriert, sodass sie nutzbar ist, erfahren Sie im Moodle Artikel "Hello world mittels LCD". Die Bibliotheken i2cmaster.h und twimaster.c erfordern keine Änderungen.

Ziel dieses Projektes ist es, die Temperatur auszulesen und auf dem LCD Display auszugeben. Um die Temperatur des Temperatursensors zu erfassen, sind einige Schritte notwendig. Der MCP9808 verwendet ein Pointer System. Dieser Register Pointer (auch als Zeiger bezeichenbar) muss als erstes in einem Schreibezugriff auf das Temperaturregister (0x05 -> siehe Datenblatt) gelegt werden (siehe Block-Diagramm). Nachfolgend muss die I²C Verbindung gestoppt und als Lesezugriff neu gestartet werden. Im Lesezugriff kann nun die Temperatur ausgelesen werden. Die Temperatur wird als 16 Bit großer Messwert ausgegeben (beschrieben werden nur 11 Bit). Daher verwendet man ein 8 Bit Integer für die 8 höchstwertigsten Messbits (abgeschlossen mit ACK), der im Quellcode mit der Variable hbyte bezeichnet ist. Zusätzlich wird ein 8 Bit Integer für die restlichen 8 Messbits angelegt (lbyte; abgeschlossen mit NAK). Nachfolgend wird die I²C Übertragung erneut gestoppt und als Integer dem Funktionsaufruf zurückgeliefert. Innerhalb der while-Schleife erfolgt die Umwandlung der gemessenen dualen Temperatur in eine dezimale Temperatur sowie ein Wandlung von Integer zu Char, um sie auf dem Display darstellen zu können.


Block-Diagramm:

Block Diagramm

Abb.: Block Diagramm; Quelle: Datenblatt MCP9808 [http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf]


Signaldarstellung von Schritt 1 "Pointer per Schreibezugriff umlegen":

Singlaverlauf

Abb.: Pointer per Schreibzugriff umlegen; Quelle: Datenblatt MCP9808 [http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf]



Signaldarstellung von Schritt 2 "Temperatur auslesen":

Signalpegel

Abb.: Temperatur auslesen; Quelle: Datenblatt MCP9808 [http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf]



Quelle: Datenblatt MCP9808 (Letzter Aufruf: 04.02.2022)

Anhand der Signaldarstellung lassen sich die beiden erforderlichen Schritte gut erkennen. Im ersten wird der Pointer gesetzt und im zweiten die Temperatur ausgelesen. Die MSB Data landen im hbyte Integer und die LSB Data im lbyte Integer. MSB wird mittels ACK und LSB mittels NAK abgeschlossen.


Der Quellcode:

#define F_CPU 16000000UL
#include <avr/io.h>
#include <string.h>
#include <stdlib.h>
#include <util/delay.h>
#include "i2cmaster.h"
#include "lcd-routines.h"
#include "math.h"

int mcp9808(int I2C_Adresse)
{
	int hbyte, lbyte;	//Deklaration zweier Integervariablen
				//hbyte für die 8 höherwertigen Messbits
				//lbyte für die 8 niederwertigen Messbits
						
	i2c_start((I2C_Adresse << 1) & 0xFE);	//Schreibender Zugriff auf den Temperatursensor (Slaveadresse mit LSB = 0)
	i2c_write(0x05);			//Auslessen der Temperatur
	i2c_stop();				//Stoppen der I²C Übertragung
	
	i2c_start((I2C_Adresse << 1) & 0x01);	//Lesender Zugriff auf den Temperatursensor (Slaveadresse um einen nach links + LSB = 1)
	hbyte = i2c_readAck();			//Auslesen der höherwertigen Temperaturbits
	lbyte = i2c_readNak();			//Auslesen der niederwertigen Temperaturbits
	i2c_stop();				//Stoppen der I²C Übertragung
	
	return (hybte << 8) + lbyte;		//Rückgabe eines 16 Bit Integers (dem Messwert)
}

int main(void)
{
    i2c_init();	//Initialisierung des I²C Busses
    lcd_init();	//Initialisierung des LCD Displays
	
    while (1) 
    {
		lcd_clear();					//Inhalte auf dem LCD Display löschen
		
		char chartemp[1];				//2 Zeichen Char Array für die Temperatur (wichtig, da LCD Display kein Integer ausgeben kann)
		char chartempnack = NULL;				//Char zum Speichern der Nachkommestelle der Temperatur
		int messwert = 0;
		
		messwert = mcp9808(0x18);			//Messaufruf des Temperatursensor (liefert 16 Bit Messwert)
		
		float temp = messwert & 0x0FFF;			//Bitmanipulation, nur 11 relevante Bits
		temp /= 16.0;
		int tempnack = ((int) round(temp * 10)) % 10;	//Erzeugen der Nachkommastelle
		
		if(messwert & 0x1000)
		{
			temp -= 256;
		}
		
		itoa(temp, chartemp, 10);			//Wandelt gemessene Integer Temperatur (temp) in char um und speichert diese im Char-Array charteamp
		lcd_string(chartemp);				//Ausgabe der in Char umgewandelten Temperatur (Vorkommestelle)
		lcd_string(".");				//Punkt für die Trennung der Nachkommastelle
		itoa(tempnack, chartempnack, 10);		//Wandelt gemessene Integer Temperatur der Nachkommastelle in char um und speichert diese im Char-Array charteampnack
		lcd_string(chartempnack);			//Ausgabe der in Char umgewandelten Temperatur der Nachkommastelle
		lcd_string("°C");				//Ausgabe der Einheit °C
		_delay_ms(1000);
    }
}


Auf dem LCD Display erscheint die Temperatur mit einer gerundeten Nachkommastelle. Sie wird jede Sekunde aktualisiert. Prüfen kann man die Funktion des Sensors durch Erwärmung des ICs mittels Finger.



Zuletzt geändert: Donnerstag, 17. Februar 2022, 10:39