<-- zurück
Im Web gibt es viele Anleitung für den Auslesen eine
digitalen Messschiebers. Man muss nur nach den Begriffen oder dem englischen 'digital Caliper' suchen.
Es wird auch von verschieden Varianten berichtet.
|
Meine Messschieber habe ich für etwa 10,- das Stück in einem Online-Shop erstanden.
Ich habe darauf geachtet, dass ein digitaler Anschluss in der Abbildung des Händlers sichtbar
war oder die Anschlussmöglichkeit explizit in der Artikelbeschreibung angegeben war. Einerseits.
Andererseits ist mir kein Angebot aufgefallen, dass keinen Anschluss hatte. Eine Produkt- oder
Firmenbezeichnung habe ich nicht gefunden. Deshalb hier eine Abbildung der Verpackung. |
Erklärungen zu den konkreten Protokollen gab es in keinem Fall. Angaben wie "RS232"
kann man getrost mit "irgendwie seriell" gleichsetzen. Also blieb nichts anderes üblich
als in die Analyse einzusteigen.
Ein wichtiger Punkt ist die niedrige Spannung von
1,5 V. Die reicht üblicherweise nicht aus, um Eingänge von Mikroprozessoren, die mit 5
V betrieben werden, sicher anzusteuern. Auch bei 3,3 V Betriebsspannung wird es knapp. Ein einfacher
Transistor schafft Abhilfe. Näheres dazu weiter unten. Hier sei nur erwähnt, dass durch
den Transistorverstärker das Signal invertiert wird. Dies muss bei der nachfolgenden Beschreibung
berücksichtigt werden.
(Die folgenden Beschreibungen beziehen sich auf die verstärkten
Signale, sind also invertiert zu den Basis-Daten. Die unterschiedliche Dauer der Clock-Pulse sind
im wesentlichen Artefakte der Aufzeichnung.)
Anhand der Analyzer-Ausgabe kann man erkennen, dass auch bei den gekauften Messschiebern ein
synchrones Protokoll verwendet wird. D.h. eine Leitung enthält ein Clock-Signal, die andere
die Daten. Die Daten werden in 6 Paketen zu je 4 Bit übertragen. Insgesamt also 24 Bit.
Die Übertragung geschieht fortlaufend. Nach einiger Zeit ohne Änderung der Messwerte
geht der Messschieber in einen Standby-Modus. Die Anzeige erlischt und die Datenübertragung
wird eingestellt. Wenn der Schieber erneut bewegt wird, wird sofort wieder in den Anzeige-Modus zurückgeschaltet.
Es erfolgt kein Zurücksetzen des Messwerts. (Der Standby-Modus kann auch mit der "On/Off"-Taste
erzwungen oder abgebrochen werden.)
Zwischen den Datenpaketen liegt eine längere Pause.
In meinem Fall beträgt die Pause zwischen zwei Datenpaketen minimal 2,5 mSec. Sie kann auch
länger sein, z.B. dann, wenn der Messschieber in den Standby-Modus übergeht und keine Übertragung
stattfindet. Während der Pausenzeit liegt das Signal auf Low-Level. Wegen der Inversion liegt
damit das Original-Signal in den Pausenzeiten auf +1,5V. Wenn der Messschieber im Batterie-Betrieb
läuft, muss dies beachtet werden. Ansonsten wird ggf. die Batterie über Gebühr belastet.
Wenn man sich den Signalverlauf genauer anschaut, erkennt man, dass die Daten sich niemals ändern,
solange das Clock-Signal auf Low liegt. Wenn Clock auf High liegt, werden die neuen Signale
auf der Datenleitung eingestellt. Damit ist die fallende Flanke der richtige Zeitpunkt, die Datenleitung
abzugreifen.
Clock bleibt für ca. 100µSec auf Low, bei jedem 4. Mal für etwa
400µSec. Die Zeit, die Clock auf High verweilt, liegt zwischen 160 und 200 µSec. Insgesamt
werden so 24 Bit übertragen. Die gesamte Übertragung eines Messwerts dauert etwa 9 mSec.
Mit Pause also ca. 12 mSec. Somit werden etwas mehr als 15 Messwerte pro Sekunde versandt.
Die ersten 20 Bit sind der angezeigte Messwert in
binärer Form, mit dem
LSB zuerst. Obwohl die Viererpäckchen
bei der Datenübertragung eine
BCD-Codierung
vermuten lassen, ist dies
nicht der Fall. Das 21.Bit enthält
das Vorzeichen 0=- 1=+ (bei invertiertem Eingang) und das 24.Bit die Einheit: 1=mm 0=inch (bei invertiertem
Eingang).
Hiermit bietet sich folgender Auslese-Algorithmus an:
- Timer starten.
- Interrupt initialisieren, der auf die entsprechende Flanke reagiert (z.B. ICP).
- In der Interrupt-Routine:
- Warten bis seit dem letzten Interrupt mindestens 2,5 mSec vergangen sind.
- Variablen für ein Datenpaket initialisieren.
- 24 Bit einlesen und zurecht schieben.
- Vorzeichen und Maßeinheit verrechnen.
- Weiter bei 1.
Der Algorithmus ist eigentlich sehr einfach. Wenn man den Compiler "überreden" kann, für
die Zwischenwerte ansonsten nicht benutzte Register zu nehmen, ist es nicht notwendig, den kompletten
Registersatz bei Interrupt-Eintritt zu sichern und beim Ende zurück zu speichern. Dann belastet
der Interrupt den Prozessor kaum.
Ein Versuchsaufbau, der dies macht und die Daten per "regulärer"
RS232 an einen PC schickt, wird nachfolgend präsentiert.
Schaltplan |
Versuchsaufbau |
|
|
Die Transistoren T1 und T2 verstärken
das Signal des Messschiebers. Ein separater Kollektorwiderstand ist nicht notwendig, wenn der
Pullup-Widerstand des entsprechenden µC-Pins eingeschaltet wird. Die Basiswiderstände
sollten auf 1MΩ erhöht werden, wenn der Messschieber mit Batterien betrieben wird
(Im Standby-Modus liegen Clock und Data auf High-Pegel(!). Es fließt also der Basis-Strom.). Zu
beachten ist, dass die die Transistoren das Signal invertieren.
T3 bildet eine Spannungsquelle
für etwa 1,5 V. Da bereits eine geregelte Spannung für die µC-Versorgung vorhanden
ist, reicht ein Transistor in Kollektorschaltung mit festem Spannungsteiler an der Basis (R3/R5).
R4 dient der Strombegrenzung bei Kurzschluss. Es würden dann max. 50 mA fließen.
R6 stellt eine kleine Last für den Fall dar, dass kein Messschieber angeschlossen ist.
Auf diesen Widerstand kann ggf. auch verzichtet werden. Mit dieser Schaltung lässt sich
auch mehr als ein Messschieber betreiben. Ein einzelner Messschieber zieht etwa 0,2 mA.
C1 ist im Messschieber selbst, anstelle der Batterie, eingelötet. Es gibt eine saubere
Lösung von David Cook, der
einen SMD-Kondensator in ein kleines Gehäuse in Batteriegröße untergebracht
hat. Das war mir aber zu aufwändig. Da ich, wie das Foto zeigt, die Anschlussdrähte
aus Ermangelung eines passenden Stecker direkt angelötet hatte, habe ich auch den Kondensator
direkt an die Batterie-Klemmen angelötet. Im Test klappte auch alles ohne diesen Kondensator.
Aber wenn später in der Nähe die Antriebsmotoren laufen ... Zu prüfen wäre,
ob die 100 nF ausreichen. Wahrscheinlich ist es besser, noch einen weiteren Kondensator von
10-100 µF parallel zu schalten.
Die anderen Anschlüsse (ISP, RS232, etc.)
sind in diesem Schaltplan nicht enthalten. |
So sah aus. 4 Adern eines Flachbandkabels wurden an den Datenschluss
des Messschieber angelötet. Die andere Seite erhielt einen Stecker fürs Steckbrett.
Zwei Transitoren dienen der Signalverstärkung. Weiterhin ist der ISP-Adapter (links auf
dem Steckbrett) und der Pegelwandler für die RS232 zu sehen (zumindest ein wenig unter
der PIN-Karten für den Chip). Um wenig Ärger mit der seriellen Übertragung zu
bekommen, habe ich den Chip mit einem Quarz betrieben.
Die Spannungsversorgung für
den Messschieber ist noch nicht enthalten. Hier läuft er noch auf Batterie. Auch liegt
der Anschluss noch nicht an den endgültigen Prozessor-Pins. |
Das wichtigste Programmteil, die ISR, ist unten angeführt. Durch sie wrde die Variablen
CaliperValue und CaliperUnit regelmäßig gefüllt.
typedef unsigned int icp_sample_t;
icp_sample_t icpStartTime;
icp_sample_t icpPeriod;
uint32_t Input; //Zwischenpuffer zum durchschieben der Bits
uint8_t InpCnt; //Anzahl eingelesener Bits
ISR(TIMER1_CAPT_vect)
{ uint8_t t;
uint8_t tmp = CaliperPIN; // Datenleitung sichern
icp_sample_t icr = ICP_ICR; // Timerstand sichern
// hier kann der Interrupt unterbrochen werden
sei();
icp_sample_t icpPeriod = icr - icpStartTime; // Pulslänge berechnen
icpStartTime = icr; // Neue Startzeit merken
if (tmp & CaliperDataMask) // Invertierung aufheben, CaliperDataMask maskiert den Data-PIN
{ t = 0;
}
else
{ t = 1;
}
if (icpPeriod < 0x1600) // kurze oder lange Pause? 0x1600 entpricht bei 16MHz etwa 2,5 mSec
{ Input = (Input >> 1) | ((uint32_t) t << 23); // alten Wert rechtsschieben, neues Bit einfügen (auf Position 24)
InpCnt++; // Bitzähler hochzählen
if (InpCnt == 24) // Alle Bits? Dann Ergebnis übertragen
{ cli(); // während der Datenübergabe keine Unterbrechung zulassen
CaliperValue = Input & 0xFFFFF; // Messwert ist in den untersten 20 Bit enthalten
if (Input & 0x100000)
{ CaliperValue = -CaliperValue;
}
if (Input & 0x800000)
{ CaliperUnit = 2; // inch
}
else
{ CaliperUnit = 1; // mm
}
sei(); // Datenübergabe vollständig
}
}
else // Neues Datenpaket
{ Input = (uint32_t) t << 23; // Zwischenspeicher initialisieren: 1. neue Bit auf Position 24
InpCnt = 1; // Bitzähler auf 1
}
return;
}
Hier das gesamte
Testprogramm als AVR-Studio-Projekt.
Anmerkung 1: Eine Alternative zu PD6 zur KClock-Erkennung wäre der Analog-Komparator. Dies hätte
den Vorteil, dass ein Verstärkungstransistor weniger benötigt würde. Nachteilig ist
jedoch, dass Data nach wie vor verstärkt werden muss, der Komparator benötigt einen
zweiten Pins für die Referenzspannung, für deren Einstellung werden zwei Widerstände
gebraucht.
Anmerkung 2: Zum Schluß bleibt nur noch zu überlegen, ob man die Taster
ebenfalls beschaltet, also über den Controller die Anzeige an- und abschalten und die Anzeige
auf 0.00 zurückgesetzt werden kann.
<-- zurück