Created
September 19, 2024 14:05
-
-
Save kesor/51a99d44b0602acb63e221bcb378cf97 to your computer and use it in GitHub Desktop.
Arduino code for Chinesium Calipers or Dial Indicator digital output
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
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); | |
} |
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
#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