In my last article, Digital Calipers Data Port, we looked at how the calipers encode and transmit data. In this article, we will examine how to interface the calipers to an Arudino.
Because the CLK and DAT lines operate at the battery voltage (1.5 V), a pair of transistors need to be used to bring the voltages up to TTL/CMOS levels (typically no more than 0.8 V for logical 0 and no less than 2.0 V for logical 1). Without the transistors, the microcontroller would not be able to “see” the HIGH values. Due of the nature of the circuit used to buffer the voltage levels, the CLK and DAT lines will be inverted.
The transistors can be any NPN type (I used 2N5088) and the resistors can be anywhere between 1k and 10k (I used 10k). CLK_IN and DAT_IN connect to the caliper’s data port and CLK_OUT and DAT_OUT connect to the microcontroller. VCC connects to the microcontroller’s supply voltage (not the caliper’s).
Here is some Arudino code that continuously prints the measurement as it is shown on the calipers’ LCD:
#define PIN_CLK 3 #define PIN_DAT 4 #define INTERRUPT_CLK 1 #define enable_clk_interrupt() \ attachInterrupt(INTERRUPT_CLK, interrupt_clk, FALLING) #define disable_clk_interrupt() \ detachInterrupt(INTERRUPT_CLK) unsigned long time; byte count; // keep track of how many bits we have read union { struct { unsigned int value; // integer value byte __empty:4; // 0000 byte sign:1; // 0 = +, 1 = - byte __unknown:2; // 00 byte unit:1; // 0 = mm, 1 = in }; unsigned long _ulong; } data; void interrupt_clk() { long val = digitalRead(PIN_DAT); // Bits come LSB first from the calipers so we // have to do things from the opposite side. data._ulong >>= 1; data._ulong |= val << 23; count--; } void setup() { pinMode(PIN_CLK, INPUT); pinMode(PIN_DAT, INPUT); Serial.begin(115200); } void loop() { count = 25; // 24 bits to read +1 data._ulong = 0; time = millis(); while (digitalRead(PIN_CLK) == LOW); // Transmissions are 250 ms apart. // Make sure there was at least a 200 ms delay. if (millis() - time < 200) { return; } time = millis(); enable_clk_interrupt(); while (count) { // Transmissions take 20 ms. // If we aren't done in 25 ms, bail. if (millis() - time > 25) { break; } } disable_clk_interrupt(); // Data comes out inverted because of the buffer circuit data._ulong = ~data._ulong; // 1 = -, 0 = + Serial.write(data.sign ? '-' : ' '); // 1 = in, divide by 2000, 4 decimal places. // 0 = mm, divide by 100, 2 decimal places. Serial.print(data.unit ? data.value / 2000.0 : \ data.value / 100.0, data.unit ? 4 : 2); Serial.write(' '); Serial.println(data.unit ? "in" : "mm"); }
