Skip to content

Instantly share code, notes, and snippets.

@kesor
Created September 19, 2024 14:05
Show Gist options
  • Save kesor/51a99d44b0602acb63e221bcb378cf97 to your computer and use it in GitHub Desktop.
Save kesor/51a99d44b0602acb63e221bcb378cf97 to your computer and use it in GitHub Desktop.
Arduino code for Chinesium Calipers or Dial Indicator digital output
int bit_array[25]; // For storing the data bit. bit_array[0] = data bit 1 (LSB), bit_array[23] = data bit 24 (MSB).
unsigned long time_now; // For storing the time when the clock signal is changed from HIGH to LOW (falling edge trigger of data output).
int CLOCK_PIN = 2;
int DATA_PIN = 3;
void setup() {
Serial.begin(115200);
pinMode(CLOCK_PIN, INPUT);
pinMode(DATA_PIN, INPUT);
digitalWrite(CLOCK_PIN, LOW); // Disable internal pull-up resistor
digitalWrite(DATA_PIN, LOW); // Disable internal pull-up resistor
}
void loop() {
while (digitalRead(CLOCK_PIN) == LOW) {} // If clock is LOW wait until it turns to HIGH
time_now = micros();
while (digitalRead(CLOCK_PIN) == HIGH) {} // Wait for the end of the HIGH pulse
if ((micros() - time_now) > 500) { // If the HIGH pulse was longer than 500 micros we are at the start of a new bit sequence
decode(); //decode the bit sequence
}
}
float last_value = -0.1;
int last_sign = 0;
int last_unit = 1;
void decode() {
int sign = 1;
int unit = 0;
int i = 0;
float value = 0.0;
float result = 0.0;
bit_array[i] = digitalRead(DATA_PIN); // Store the 1st bit (start bit) which is always 1.
while (digitalRead(CLOCK_PIN) == HIGH) {};
for (i = 1; i <= 24; i++) {
while (digitalRead(CLOCK_PIN) == LOW) { } // Wait until clock returns to HIGH
bit_array[i] = digitalRead(DATA_PIN);
while (digitalRead(CLOCK_PIN) == HIGH) {} // Wait until clock returns to LOW
}
for (i = 1; i <= 20; i++) { // Turning the value in the bit array from binary to decimal.
value = value + (pow(2, i-1) * bit_array[i]);
}
if (bit_array[21] == 1) sign = -1; // Bit 21 is the sign bit. 0 -> +, 1 => -
unit = bit_array[24];
if (last_value == value && last_sign == sign && last_unit == unit)
return;
if (unit) { // Bit 24 tells the measureing unit (1 -> in, 0 -> mm)
result = (value*sign) / 2000.00;
Serial.print(result,4); // Print result with 3 decimals
Serial.println(" in");
} else {
result = (value*sign) / 100.00;
Serial.print(result,2); // Print result with 2 decimals
Serial.println(" mm");
}
last_value = result;
last_sign = sign;
last_unit = unit;
delay(100);
}
#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 = 150; // clock edges are every ~175us
void tick() {
unsigned long currentUS = micros();
if (currentUS - lastClock < DEBOUNCE_US)
return; // debounce
// if (currentUS - lastClock < 1000)
// Serial.println(currentUS - lastClock);
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++;
lastClock = currentUS;
}
// falling edge for bits 0-23
if (lastClockState == HIGH & state == LOW && bitCount < BITS) {
dataBits[bitCount] = digitalRead(PIN_DATA);
bitCount++;
lastClock = currentUS;
}
lastClockState = state;
}
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 debugBits() {
for (int i = 0; i < BITS; i++) {
Serial.print(dataBits[i]);
if ((i+1) % 4 == 0)
Serial.print(" ");
}
Serial.println();
}
void decode() {
static int signLast, unitLast, valueLast;
int sign = 1;
int unit = 0;
int value = 0;
debugBits();
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;
if (unit) { // Measure in inches
Serial.print(sign * value / 2000.0, 4);
Serial.println(" in");
} else { // Measure in 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