HiDTemp
von Michael Odenwald
Dieser Artikel nimmt am Artikelwettbewerb 2012/2013 teil.
Ein Mini Temperatur Messmodul mit USB Anschluss zur Kommunikation via Windows eigener HID Treiber.
Einleitung
Die USB Schnittstelle gehört sicherlich zu den anspruchsvolleren Schnittstellen an einem aktuellen PC-System.
Die Entwicklung von Prototypen Schaltungen und auch die Anwendungssoftware ist dabei im Laufe der Jahre durch die Unterstützung seitens der Hersteller von Mikrocontrollern und der OpenSource Community immer leichter geworden.
Einzig und allein die System Treiber für die Ansteuerung der USB Geräte bei einem Windows System, stellen nach wie vor eine deutliche Hürde da, die es bei der Entwicklung zu überwinden gilt.
Möchte man nicht den Weg einer RS-232/USB Kommunikation gehen, bietet sich eine Klasse von Geräten an, die bei Hobby Projekten bisher nicht sehr oft betrachtet wurde nämlich die der HID Geräte [1].
In der Regel denken Benutzer bei Thema HID Geräten sofort an eine PC-Maus oder eine Tastatur. Der USB Standard sieht in seiner Definition aber auch „Sonstige“ Geräte vor [2].
Ziel
Ziel dieses Projektes ist die Konstruktion eines kleinen und relativ genauen Temperatur Moduls, dass als USB HID Gerät sehr leicht an typische PC Systeme angeschlossen werden kann.
Als weiterer Punkt soll das USB HID Gerät explizit mit Windows 7 x64 Systeme zu betreiben sein und die Anwendungssoftware soll mit c# erstellt werden.
Schaltung
Die Schaltung besteht, wie aus dem Schaltplan ersichtlich ist, nur aus wenigen Bauteilen deren wichtigste Komponente der Mikrocontroller vom Typ Atmel Tiny85-20 ist. Als Temperatursensor wird ein Dallas DS18B20 verwendet.
Die Realisierung der USB Schnittstelle geschieht hier mit der vielfach bewährten Software V-USB aus [3] die für die relativ langsame und nur wenige Bytes umfassende Informationen ausgezeichnet harmoniert.
Der Schaltplan zeigt den Anschluss der USB Verbindung samt der Schutzwiderstände (R1 und R3). Die beiden 3,6V Zehnerdioden begrenzen die Spannung auf den USB Datenleitungen auf die durch die Norm festgelegten Pegel. Für die USB Enumeration sorgt (R2) der dem USB Host ein USB Low Speed Device mit max. 1,5 MBit/s Datenübertragung Geschwindigkeit signalisiert [4].
Der Dalles DS18B20 Temperatur Sensor wird im Parasität Power Modus [5] betrieben um die Eigenerwärmung möglichst gering zu halten.
Der Atmel Prozessor vom Typ Tiny85-20 läuft mit 16,5 MHz und 5V Versorgungsspannung die direkt aus der USB Anbindung bezogen werden.
Die Taktfrequenz von 16,5 MHz wird dabei mit Hilfe der internen PLL erzeugt. Dies spart ein externes Quarz und vereinfacht den Aufbau, gleichzeitig ist der Mikrocontroller aber schnell genug um die USB Kommunikation einwandfrei zu gewährleisten.
Die beiden Kondensatoren C1 und C2 sorgen für eine Glättung und Filterung der 5V USB Spannung.
Die LED1 signalisiert, wenn sie aktiv ist, einen gerade stattfindenden Messzyklus der bei einem DS18B20 typ. 750ms dauert [5].
Die Abfrage des Temperatursensors und die Übermittlung der Daten an den PC geschieht immer unabhängig voneinander. Der DS18B20 ist dabei langsamer, als die maximale Wartezeit des USB Protokolls. Auf diese Weise werden USB Timeout Meldungen vermieden.
Anstelle des Dallas DS18B20 kann auch ein Dallas DS18S20 oder ein Dallas DS1820 verwendet werden. Die Sensor Software ermittelt automatisch den richtigen Typ und liest die maximale gültigen Stellen des Sensors aus.
Schaltplan für das HiDTemp Gerät
Firmware
Die Firmware benutzt für die Abfrage des Temperatur Sensors die Library Funktionen aus [6].
Der USB Stack wird mit der V-USB Software realisiert und hat einen speziell für dieses Gerät definierten HID Descriptor [7].
Der Descriptor definiert für die USB Hostsoftware, welche USB Endpoints es gibt und wie mit ihnen kommuniziert werden kann.
Der USB HID Descriptor des HiDTemp Gerätes sieht dabei wie folgt aus:
/* --------------------------------------------------------------------- */
/* --------------------------- USB interface --------------------------- */
/* --------------------------------------------------------------------- */
PROGMEM char usbHidReportDescriptor[51] = /* USB report descriptor */
{
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x01, // REPORT_COUNT (1)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Ary,Abs,Buf)
0x85, 0x02, // REPORT_ID (2)
0x95, 0x01, // REPORT_COUNT (1)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x03, // REPORT_ID (3)
0x95, 0x0a, // REPORT_COUNT (10)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x04, // REPORT_ID (4)
0x95, 0x04, // REPORT_COUNT (4)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
};
Man erkennt vier ReportIDs (1-4) mit unterschiedlich langen Informationsblöcken (1-10 Byte), die jeweils als Feature Report realisiert sind.
Ein Feature Report ist zum schreiben und lesen von Daten konzipiert, da er Einstellungen (Features) abfragen oder einstellen soll.
Mit den ReportIDs "1" und "2" können zwei Ausgänge des Mikrocontrollern ein und ausgeschaltet werden. Diese Funktionen spielen derzeit aber keine weitere Rolle und ist für zukünftige Erweiterungen vorgesehen. (z.B. Schaltausgänge bei über oder unterschreiten einer bestimmten Temperatur)
Mit der ReportID "3" kann ein HiDTemp Geräte Ident String ausgelesen werden, zusätzlich zu den Standard USB Informationen.
Die ReportID "4" übermitteln den während des letzten Messzyklus ermittelten und zwischengespeicherten Wert des Temperatur Sensors.
Zusammenfassung:
ReportID | Aktion | Bemerkung |
---|---|---|
1 | I/O Pin setzen/abfragen Input/Output 1 Byte Format: x | (zukünftige Erweiterung) |
2 | I/O Pin setzen/abfragen Input/Output 1 Byte Format: x | (zukünftige Erweiterung) |
3 | Version abfragen Output 10 Byte Format: 'yyyy-mm-tt' | |
4 | Temperatur abfragen Output 4 Byte Format: xxxx |
Ein kompletter Messzyklus wird mit Hilfe einer State Maschine alle 10s durchlaufen. Die State Maschine läuft dabei unabhängig von der USB Aktivität und speichert den letzten ermittelten Temperatur Wert in einer internen Variable.
Bei einer USB Anfrage mit der ReportID "4" kann die USB Software nun die letzten gültigen Daten abfragen, ohne den Messvorgang selber einleiten zu müssen oder auf das Ergebnis danach warten zu müssen.
Die Informationen des letzten Messzyklus werden umgehen an den USB Host übertragen. Es spielt dabei auch keine Rolle ob die Abfrage vom USB Host direkt wiederholt wird oder nicht, der nächste Messzyklus wird immer asynchron alle 10s durchgeführt.
Dieses Vorgehen gibt dem Temperatur Sensor Zeit sich zu erholen, um nicht durch zu häufige Abfragen sich selbst zu erwärmen und so das Messergebnis zu verfälschen.
Die USB Kommunikation dagegen ist zeitlich völlig frei darin wann sie eine Abfrage startet, da sie synchron immer eine Antwort bekommt.
Aufbau
Der Aufbau der Schaltung ist unkritisch und auf einem Steckbrett oder wie hier auf einer kleinen Lochraster Platine schnell erledigt.
Da es sich um einen einmaligen Prototyp handelt, ist kein Platinen Layout entworfen worden.
Treiber
Ein Windows System installiert die eigenen HID System Treiber automatisch beim ersten Kontakt mit der fertig aufgebauten und mit der Firmware programmierten Schaltung.
Dabei ist es egal, ob es sich um ein Windows x32 oder Windows x64 System handelt.
Der Microsoft HID System Treiber ist immer vorhanden und auch immer signiert. Er wird deshalb auch automatisch ohne jede Nachfrage installiert.
HiDTemp als vollwertiges USB HID Device gekoppelt an den Windows eigenen Treiber
Anwendung
Die Anwendungssoftware ist in c# geschrieben und lässt sich problemlos auch mit der kostenlosen Visual Studio 2010 Express Version [8] übersetzen, da keinerlei spezial Komponenten benötigt werden.
Windows HiDTemp Anwendungsprogramm
Der Kern der Software ist dabei die usbGenericHIDDevice Library aus [9] die die Windows HID API Funktionen in einer leicht nutzbaren Weise kapseln und zur eigenen Verwendung bereitstellen.
Abgeleitet von der Basisklasse usbGenericHidCommunication wird eine eigene USB Device Klasse erstellt, die das reale Gerät widerspiegelt und fertig implementiert alle seine möglichen Eigenschaften in Service Methoden abbildet.
Die zentrale Klasse 'usbDevice' für das HiDTemp Gerät sieht so aus
//-----------------------------------------------------------------------------
//
// usbDevice.cs
//
// The implementation of the real USB HiD Device with his functions.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using usbGenericHidCommunications;
using System.Diagnostics;
namespace hidApp_2
{
/// <summary>
/// It also serves as a demonstration of how to use the class
/// library to perform different types of read and write
/// operations.
/// </summary>
class usbDevice : usbGenericHidCommunication
{
private int tval;
private string ByteArrayToString(byte[] arr)
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
return enc.GetString(arr);
}
/// <summary>
/// Class constructor - place any initialisation here
/// </summary>
/// <param name="vid"></param>
/// <param name="pid"></param>
public usbDevice(int vid, int pid)
: base(vid, pid)
{
}
/// <summary>
/// USB HiD User Function GetTemeratur
/// </summary>
public int GetTemperatur()
{
// Declare a input buffer
Byte[] inputBuffer = new Byte[5]; // we expect 5 byte; 1 x ReportID and 4 Byte temperatur
inputBuffer[0] = 4; // ReportID 4 abfragen
// Perform the read command
bool success;
success = getFeatureReport(inputBuffer);
if (success == false)
{
Debug.WriteLine("Error during getFeatureReport");
return tval; // Error during USB HiD_GetFeature Request so return the old value
}
tval = inputBuffer[1] << 24;
tval |= inputBuffer[2] << 16;
tval |= inputBuffer[3] << 8;
tval |= inputBuffer[4];
return tval; // Return the new value
}
}
}
HiDTemp wird mit den beiden Werten VID = 0x16c0 für die Vendor ID und PID = 0x05df für die Produkt ID abgefragt.
Diese beiden Werte ergeben sich aus der Dokumentation in [3] und sollten nur geändert werden wenn man sich absolut sicher ist, dass kein anderer Hardware Hersteller und seine USB Geräte davon beeinträchtigt wird.
Die eigentliche Abfrage der Sensor Temperatur geschieht mit der Methode GetTemperatur()
Die Temperatur für den DS18B20 Sensors kann im Bereich von -55°C bis +125°C liegen. Der Temperatur Wert wird dabei als Vorzeichen behaftete ganze Zahl im Bereich von -550000 bis 1250000 abgebildet.
Ein Temperaturwert wird in 4 Byte gespeichert und übertragen. Auf dem Zielsystem muss dieser Wert dann nur noch durch 10000 geteilt werden, um die aktuelle Temperatur zu erhalten.
An dieser Stelle der Hinweis das Auflösung und Genauigkeit nichts miteinander zu tun haben. Der Sensor hat gemäß Datenblatt eine Grundgenauigkeit von +/- 0,5°C. Die Auflösung für einen DS18B20 ist dabei 12Bit also 0.0625°C oder 1/16°C.
Fazit
Die Schaltung und die Software für das HiDTemp Gerät arbeitet auf meinem Windows 7 x64 Systemen schon länger stabil und ohne Probleme.
Das System eignet sich prima zum experimentieren und bietet dem Leser Platz eigenen Erfahrungen mit der kleinen Schaltung zu sammeln.
Die Schaltung ist so einfach gestaltet, dass sie sehr sicher und problemlos nachgebaut werden kann und dazu auch noch sehr preiswert ist.
Dieses Projekt wäre ohne dem Gedanken der OpenSource Community sicher nicht so schnell, ausgereift und produktiv umsetzbar gewesen. Aus diesem Grund stelle ich meine eigenen Sources auch unter die GNU General Public License (GPL).
Referenzen
- [1] Def. Human Interface Device
- [2] HID Information
- [3] V-USB
- [4] Universal Serial Bus
- [5] DS18B20 Programmable Resolution 1-Wire Digital Thermometer
- [6] DS18X20 with AVR
- [7] USB-Deskriptoren
- [8] Visual Studio 2010 Express
- [9] Open Source Framework for USB Generic HID devices