Last active
April 18, 2024 01:09
-
-
Save kesor/3577811486a4032baed0549bbc61c4df to your computer and use it in GitHub Desktop.
Digital Caliper / Digital Dial Indicator Arduino reader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Arduino Sketch for Digital Calipers and Dial Indicators Reading | |
* | |
* This sketch is designed to interface with digital calipers or dial indicators, reading measurements | |
* via a simple two-pin setup. It effectively handles data on both rising and falling edges of a clock signal, | |
* managing debouncing and differentiating between measurement units (inches or millimeters). | |
* | |
* Features: | |
* - Uses interrupts to capture data from clock signal changes. | |
* - Debouncing logic for accurate edge detection. | |
* - Detects measurement units and sign of the measurement. | |
* - Automatic reset after idle periods. | |
* - Debug output of bit patterns for verification. | |
* | |
* Pin Configuration: | |
* - PIN_CLOCK (Digital Pin 3): Clock signal input. | |
* - PIN_DATA (Digital Pin 2): Data signal input. | |
* | |
* Setup: | |
* Connect the clock and data outputs of your measuring tool to the respective Arduino pins. | |
* Upload this code to the Arduino and open the serial monitor at 115200 baud to see the measurements. | |
* | |
* Author: Evgeny Zislis | |
* License: MIT License | |
* | |
* Keywords: Arduino, Digital Caliper, Dial Indicator, Interrupts, Edge Detection, Debouncing | |
*/ | |
#include <Arduino.h> | |
#include <avr/interrupt.h> | |
#define BITS 24 | |
const int PIN_CLOCK = 3; | |
const int PIN_DATA = 2; | |
// keep track of the clock edge and timing | |
volatile unsigned long lastClock = 0; | |
volatile bool lastClockState = LOW; | |
// remember data values on each clock change | |
volatile byte dataBits[BITS]; | |
volatile int bitCount = 0; | |
const unsigned long IDLE_TIME = 100000; // idle between reads is about 125kus, 8 times per second. | |
const unsigned long DEBOUNCE_US = 20; // clock falling edges are every ~175us | |
void tick() { | |
unsigned long currentUS = micros(); | |
if (currentUS - lastClock < DEBOUNCE_US) | |
return; // debounce | |
if (currentUS - lastClock > IDLE_TIME) | |
bitCount = 0; // reset | |
bool state = digitalRead(PIN_CLOCK); | |
// rising edge for bit 24 :( | |
if (lastClockState == LOW & state == HIGH && bitCount == BITS) { | |
dataBits[bitCount - 1] = digitalRead(PIN_DATA); | |
bitCount++; | |
} | |
// falling edge for bits 0-23 | |
if (lastClockState == HIGH & state == LOW && bitCount < BITS) { | |
dataBits[bitCount] = digitalRead(PIN_DATA); | |
bitCount++; | |
} | |
lastClockState = state; | |
lastClock = currentUS; | |
} | |
void setup() { | |
Serial.begin(115200); | |
pinMode(PIN_CLOCK, INPUT); // don't pullup the clock! | |
pinMode(PIN_DATA, INPUT_PULLUP); | |
attachInterrupt(digitalPinToInterrupt(PIN_CLOCK), tick, CHANGE); | |
} | |
void loop() { | |
if (bitCount > BITS) | |
decode(); | |
} | |
void decode() { | |
static int signLast, unitLast, valueLast; | |
int sign = 1; | |
int unit = 0; | |
int value = 0; | |
if (dataBits[0] != 1) | |
return; // start bit error | |
for (int i = 0; i <= 20; i++) | |
if (dataBits[i + 1]) // ignore start bit | |
value += (1 << i); | |
sign = (dataBits[21] == 1) ? -1 : 1; | |
unit = dataBits[BITS - 1]; | |
if (signLast == sign && unitLast == unit && valueLast == value) | |
return; // don't repeat the same output more than once | |
signLast = sign; | |
unitLast = unit; | |
valueLast = value; | |
// --- DEBUG the bits --- | |
// for (int i = 0; i < BITS; i++) { | |
// Serial.print(dataBits[i]); | |
// if ((i+1) % 4 == 0) | |
// Serial.print(" "); | |
// } | |
// Serial.print(" : "); | |
if (unit) { // inches | |
Serial.print(sign * value / 2000.0, 4); | |
Serial.println(" in"); | |
} else { // millimeters | |
Serial.print(sign * value / 100.0, 2); | |
Serial.println(" mm"); | |
} | |
Serial.flush(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment