Skip to content
Snippets Groups Projects
Commit ecce57b9 authored by David Preiss's avatar David Preiss
Browse files

Update README.md, images/calipers_breadboard.png, images/caliper_port.png,...

Update README.md, images/calipers_breadboard.png, images/caliper_port.png, images/caliper_scope.png, serial_Caliper.ino
parent 6223cb48
No related branches found
No related tags found
No related merge requests found
# Serial Caliper # Serial Caliper
Many of the common cheap digital calipers avaliable on Amazon/Ebay share a relatively easily accessible serial port and protocol at the back of the head, consisting of battery power, ground, and an I2C adjacent serial interface consisting of a CLK and SDA line. Many of the ubiquitous $20 calipers found on amazon and ebay share a relatively accessible serial port and protocol tucked behind the battery compartment. This means that with a level shifter (the calipers run a single coin cell resulting in 1.6V logic level) it's possible to get 10um linear measurement resolution to a microcontroller without having to resort to more expensive linear encoders.
<img src="./images/caliper_port.png" height=400 />
The caveats are that these calipers are only running at only about 2sps, so not useful for real time loop closing, and the protocol is peripheral-less and must be bit-banged which eats up MCU resources.
Here's a [good reference](https://sites.google.com/site/marthalprojects/home/arduino/arduino-reads-digital-caliper) for getting initial results. I made a few changes in code including printing binary packets for debugging, and flipping all of the reads (we are using a level shifter not a transistor). See below for a simple breadboarded circuit to get up and running.
<img src="./images/caliper_breadboard.png" height=600 />
Raw scope readings (reading a 0.01mm) can be seen below, transmitted over seven 4-bit chunks. The readings are fixed point with the two LSB in decimal being devoted to 100 and 10 um significant figures. The 21st bit is devoted to measurement sign, and one of the remaining bits is used for unit conversion, while some are unused.
<img src="./images/caliper_scope.png.png" height=600 />
images/caliper_port.png

1.06 MiB

images/caliper_scope.png

1.37 MiB

images/calipers_breadboard.png

718 KiB

int i;
int sign;
int value;
float result;
int datapin = 15;
int clockpin = 14;
unsigned long tempmicros;
bool bitval[24];
void setup() {
Serial.begin(9600);
pinMode(clockpin, INPUT);
pinMode(datapin, INPUT);
}
void loop () {
while (digitalRead(clockpin) == LOW) {} //wait for the end of the HIGH pulse
tempmicros = micros();
while (digitalRead(clockpin) == HIGH) {} // wait until we go high again (skips first bit)
if ((micros()-tempmicros)>500) {
decode(); //decode the bit sequence
}
}
void decode() {
sign=1;
value=0;
for (i=0; i<23; i++) {
while (digitalRead(clockpin) == LOW) { } //wait until clock returns to HIGH- the first bit is not needed
while (digitalRead(clockpin) == HIGH) {} //wait until clock returns to LOW
if (digitalRead(datapin) == HIGH) { // in original example an NPN transistor was used which flipped the output loic (low = 1, high = 0). If using a proper logic level shifter this would be reveresed
// So if we are reading a bit
if (i<20) { // And if we are within the first 20 bits of data
bitval[i] = 1;
value|= 1<<i; // Shift the bit to its correct order of magnitude (see bit shifting), and add it (using the or operator) with value (which is acting like a sum)
}
if (i==20) { // The 21st bit is the sign bit, which if 1 means we are reading a negative value
sign=-1;
}
}
else {
bitval[i] = 0;
}
}
result=(value*sign)/100.00;
Serial.println(result,2); //print result with 2 decimals
/*
for (i=0; i<23; i++) {
Serial.print(bitval[i]);
}
Serial.println("");
*/
//delay(1000);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment