Digispark-Luxmeter
Die Arduino-Philosophie, Nichttechnikern Mikrocontroller nahebringen zu
wollen, bringt eine gewisse Abstraktion mit sich - als Nutzer der
Core-Funktionen und der Libraries weiss man oft nicht so recht, welche
internen Hardwarekomponenten sie benutzen, und manchmal kollidieren
zusammen eingesetzte Libraries, weil sie die selbe interne Hardware des
Mikrocontrollers einbinden wollen (z.B. Timer oder
Hardware-Interrupts).
Bei den Digisparks mit ihren begrenzten Ressourcen ist das
noch kritischer, außerdem existiert kaum Dokumentation zu den
Digispark-Libraries, so daß nur ein Blick in den Quellcode der Library
oder schlichtes Probieren weiterführt.
Um einfach mal auszuprobieren, wie sich die USB-Libraries mit
der I2C-Library "vertragen", habe ich den Adapter für das
TSL45315-Breakout-Board der
seriellen Luxmeter-Variante etwas umgestrickt und an den
Digispar "geflanscht"
(jedoch mit einer kleinen Abweichung: die Energieversorgung des
Breakout-Boards erfolgt nicht direkt, sondern über PB1; er muss also zu
Beginn des Programms per Software als Ausgang und auf "High" geschaltet
werden).
In der neuen Konfiguration entfällt also der externe
Seriell-USB-Wandler, er wird durch den Mikrocontroller emuliert. Als
Übertragungsprotokoll stehen der CDC-Modus und der DigiUSB-Modus zur
Verfügung.
Die I2C-Library nutzt das Universal Seriel Interface (USI), für SDA und SCL müssen daher die Ports PB0 und PB2 genutzt werden.
Abbildung 1: Schaltplan
Abbildung 2: Streifenraster-Platinen-Layout
DigiCDC erfordert auf der Gegenseite (PC) ein herkömmliches
Terminal-Programm und präsentiert sich als normale COM-Schnittstelle
comx (unter Linux /dev/ttyACMx), überträgt aber sehr langsam. DigiUSB
ist deutlich flotter, erfordert aber ein spezielles Terminalprogramm
"digiusb.exe", das in der Windows-Eingabeaufforderung (bzw. unter Linux
in Xterm bzw. Konsole) läuft.
Digiusb.exe und der Quelltext sind in diesem Paket
enthalten (rechts unten "Download ZIP" anclicken). Will man digiusb
selbst übersetzen, muss man in Zeile 206 von digiusb.cpp den Befehl
"usleep (100000);" löschen, der wohl ein Überbleibsel von irgendwelchen
Tests ist und digiusb sehr langsam macht (das bereits übersetzte
digiusb.exe ist jedoch ok).
Im angehängten zip-File sind vier Mikrocontroller-Sketches
enthalten; je zwei für den Basis-Messbereich bis 65535 Lux und je zwei
für den Bereich bis ca. 262000 Lux.
Vergleicht man den folgenden Beispielsketch mit der oben
verlinkten Bascom-Version, zeigt sich, daß man recht ähnlich wie unter
Bascom "drauflosprogrammieren" kann. Die Systax ist etwas anders,
Gross-/Kleinschreibung sind relevant, das Semikolon am Zeilenende ist
ungewohnt, aber letztlich sind das recht geringe Hürden, die man mit
der (englischsprachigen) Arduino-Hilfe (Menüpunkt Hilfe - Referenz)
recht schnell überwindet. Vorhandene Bascom-Programme für andere
I2C-Chips lassen sich also recht einfach "recyceln" und mit
USB-Funktionalität ausstatten.
//
// Helligkeitssensor TSL 45315 auf Watterott-Breakout Board
// 1 Lux bis 65535 Lux in 1er-Schritten
// Beschaltung:
// SDA an PB0
// SCL an PB2
// Energieversorgung des Boards an PB1
#include <TinyWireM.h> // I2C Master lib for ATTinys which use USI
#include <DigiUSB.h>
#define TSL_ADDR 0x29 // 7 bit I2C address for TSL sensor
uint16_t Lob = 0;
uint16_t Hib = 0;
uint16_t Lux = 0;
void setup() {
pinMode(1, OUTPUT); // Betriebsspannung TSL
digitalWrite (1, HIGH);
TinyWireM.begin(); // initialize I2C
DigiUSB.begin();
Init_TSL();
DigiUSB.delay (2000);
}
void loop() {
Get_Lux();
DigiUSB.delay (500);
}
void Init_TSL() {
TinyWireM.beginTransmission(TSL_ADDR);
TinyWireM.send(0x80); // Control Register
TinyWireM.send(0x03); // Power on
TinyWireM.endTransmission();
TinyWireM.beginTransmission (TSL_ADDR);
TinyWireM.send (0x81); // command register
TinyWireM.send (0x00); // Multiplikator 1
TinyWireM.endTransmission();
}
void Get_Lux() {
TinyWireM.beginTransmission(TSL_ADDR);
TinyWireM.send(0x84); // data low byte register
TinyWireM.endTransmission();
TinyWireM.requestFrom(TSL_ADDR, 0x02); // request 2 bytes from slave
Lob = TinyWireM.receive(); // low byte
Hib = TinyWireM.receive(); // high byte
// hier kein TinyWireM.endTransmission();
Lux = Lob + (256 * Hib);
DigiUSB.print ("Helligkeit: ");
DigiUSB.print (Lux, DEC);
DigiUSB.println (" Lux");
}
Eigenartigerweise verlief ein Test der Digispark-Keyboard-Library
negativ. Baut man in den den obenstehenden Code statt der
DigiUSB-Library die Keyboard-Library ein, läuft das entstandene
Programm zwar brav los, zeigt aber Unfug an (einen konstanten grossen
Wert).
Download: 0215-digispark-luxmeter.zip