You are on page 1of 9

Home Sign Up!

Browse Community Submit


All Art Craft Food Games Green Home Kids Life Music Offbeat Outdoors Pets Photo Ride Science Tech

Reading Digital Callipers with an Arduino / USB


by j44 on June 23, 2010

Table of Contents

Reading Digital Callipers with an Arduino / USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Intro: Reading Digital Callipers with an Arduino / USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Step 1: The Callipers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Step 2: Voltages: Logic and Power . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Step 3: The Data Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Step 4: Arduino Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Related Instructables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
Intro: Reading Digital Callipers with an Arduino / USB
How to use an Arduino to read the signal from a set of digital callipers and send the reading over USB.

Why?
This might be useful for accurate position sensing in home made / hacked computer aided manufacture systems. Adds USB functionality to your callipers.

A great reference on reading digital callipers can be found at:


http://www.shumatech.com/support/chinese_scales.htm

What this instructable adds to the shumatech tutorial is:


How to use an Arduino to read the callipers (using very few extra components).
Details of another protocol found to be in use on some callipers.
Basic Arduino code is provided.

To see more of my work please visit j44industries.

Step 1: The Callipers


The callipers I have been working with were the Electronic Digital Callipers by Precision Gold. I bought the callipers from Maplin (item code N48AA) in the UK for just
under £20.

After some experimenting with a multi meter and a jyetech oscilloscope (a very cheap basic oscilloscope that can be bought in kit form for under £40) I found the pins to
be as shown in the diagram.

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
Step 2: Voltages: Logic and Power
The Arduino uses 5V logic but the callipers output 1.5V logic. This is a bit of a bodge and may not always work, really a proper logic level conversion circuit should be
used but the flowing is a simple hack that worked well with my Arduino:

My Arduino changed between logic high and logic low at about 2.5V (this could vary a bit between boards).

Connecting the positive pin on the callipers to the 3.3V supply means when the clock and data pins are connected to the arduino their voltage seems to vary between
3.3V and 1.8V, which is the Arduino reads as logic high and low respectively.

Powering the callipers with the Arduino:

To avoid needing a battery in the callipers the power circuit pictured can be used (remove the button cell). This method relies on using an LED to regulate the supply
voltage for the callipers.

Resistor
About 200Ohm

Capacitor
I used a 10uF which worked well, but there would be no harm in using a larger capacitance. 2V or more rating.

LED
For the LED try to find one which has as close to a 1.6V drop across it as possible.
I used a red LED with a 1.8V drop across it. Red and IR LEDs tend to have low voltage drops across them.

Step 3: The Data Protocol


The data protocol used on my callipers was as follows:

Clock pulse as shown in the picture.

Reading the data on a falling clock edge gave a sensible output.

Example data output:

1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, (Screen shows 0.00 mm or 0.000 inches)
1,0,0,0, 1,0,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, (Screen shows 10.00mm)
1,0,0,1, 0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,1,0,0, (Screen shows -1.00mm)
1,0,0,0, 1,1,0,0, 1,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, (Screen shows 150.00mm)

Interpretation of data:

?,X,X,X, X,X,X,X, X,X,X,X, X,X,X,X, ?,?,?,?, ?,Y,?,?


? = Not sure
X's for a binary number with least significant bit at the start of the string. The binary number is the distance in mm times 100.
Y = Sign bit if Y = 1 number is negative if Y = 0 number is positive.

Note: make sure the callipers are set to mm the inches mode behaves very similarly except the least significant bit is used to show 1/2000ths of an inch.
http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
Step 4: Arduino Code
This is a very basic Arduino code that should be compatible with several calliper data protocols.
There are commas in between each value to make it easy to use .CSV files to import the data into spreadsheets.

The main requirement of this code is that the data is read on the falling edge of a clock pulse.

Hopefully this code should mean when you connect your Arduino to the computer and use the serial monitor at 115200 Baud you will get sensible looking binary out.

Trouble shooting:
If the length of the binary strings changes a lot you may have the clock and data pins the wrong way around.

Code:

//Simple Digital Calliper Reader


//See http://j44industries.blogspot.com/

// Pin Declarations
int dataIn = 11;
int clockIn = 12;

// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long timeStart = 0;
int out = 0;

void setup() {
// Pin Set Up
pinMode(dataIn, INPUT);
pinMode(clockIn, INPUT);

Serial.begin(115200);
Serial.println("Ready: ");
}

void loop(){

lastClock = clock;
clock = digitalRead(clockIn);

if (lastClock == 1 && clock == 0){


out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
if((micros() - time) > 800){
Serial.println(" ");
}
else if((micros() - time) > 400){
Serial.print(" ");
}

if (out > 1){


Serial.print("1");
}
else{
Serial.print("0");
}
Serial.print(",");

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
time = micros();
}
}

Related Instructables

High Heel Arduino LED How To coin slot


Massage by Matchstick by A Connect a PS/2 detector by
cbabtkis D5quar3 Belly Dancer Accurized Keyboard to the semiotech
Bonanza by Craftsman Drill- iPhone by awgh
aiswaryak Press by Vestus

Comments
12 comments Add Comment

jmg3234 says: Feb 15, 2011. 9:05 PM REPLY


I'm attempting this as my first arduino project- which will be a learning experience. I have wired up my HF digital indicator (which I understand to be the same
interface as the chinese calipers) using the same method shown here to convert the logic level. I have uploaded the script and appears everything is correct,
I'm not sure how to start the data flow. What do i do to view the data on my PC coming from the arduino? I have launched the terminal viewer, but it is blank.
Is a command needed?
TIA, -joe

j44 says: Feb 17, 2011. 1:53 PM REPLY


Hi Joe,

I use the serial monitor part of the arduino software (button next to upload).
It does not need any commands, and even if you have go the wiring wrong you should still get the" ready" message from the code. If you are having
problems with my code try using the Graph example sketch which can be found in the communications section of the examples to test getting data from
the arduino.

J44

jmg3234 says: Feb 18, 2011. 8:52 AM REPLY


J44, thank you for the reply. I found the error, I left the battery in the gauge and used the logic level hack which caused the arduino to not see a
high/low change.

I learned quite a bit playing with your script, and one from another forum. My goal was to have the arduino convert the binary to a decimal value. I
could not figure a way to change your script to capture the 1 and 0 (sent via serial.print.) to a string or array. Is there a command so that you can
append a string with bits as they are read in a loop?

Anyways, I now have a script that mostly works; the binary string is truncated properly and converted. I need work and find a way to set the value to
be divided by 1000- so that is shows inchs with a decimal place rather than thousanths of a inch (it now rounds to 1 if divided by 1000). Also, I need
mod it so that it will display negative readings.

jmg3234 says: Feb 18, 2011. 8:53 AM REPLY


//I modified this script from link below:
//http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235853702/0

volatile int count = 0;


int total = 0;
char data[14];
int dataPin = 4;
int gauge = 0; // display of calipers reading
int factor = 0;
unsigned long sec;

void setup(){
pinMode(dataPin, INPUT); //DATA line goes to Arduino digital pin 4
Serial.begin(9600);
delay(500);
//attachInterrupt(0,getBit,FALLING); //CLOCK line goes to Arduino digital pin 2

void loop(){
int i,time;
for(i=2;i<14;i++){ //initialize array of bits to 0
data[i]=0;

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
}
do{time = pulseIn(2, LOW);} //repeatedly get the length of LOW pulses until one is longer than 130uS
while(time < 130);

attachInterrupt(0,getBit,FALLING); //start watching data line

while(count < 14){} //wait till all bits are filled in

detachInterrupt(0);
count = 0;
for(i=2;i<14;i++){

gauge = 0; //the following is code for converts least significant bit first binary to decminal, units are thousandths of an inch
factor = 1;
for(i=2; i<14; i++){
gauge += data[i]*factor;
factor = factor*2;
}

Serial.print("Time (sec):");
sec = millis();
Serial.print(sec/1000);
Serial.print(" Inches:");
Serial.print(gauge);

delay(1000);
Serial.println();
}

void getBit(){
char sample = 0; //variable used for "triple sampling"
if(digitalRead(dataPin) == HIGH) //here the dataPin is checked three times for a HIGH value.
sample++;
if(digitalRead(dataPin) == HIGH)
sample++;
if(digitalRead(dataPin) == HIGH)
sample++;
if(sample > 1) //if the pin was HIGH at least twice, a 1 is recorded
data[count] = 1;
count++; //increment count so main() knows when the entire string of bits is ready
}

wxws says: Dec 21, 2010. 8:40 AM REPLY


//?????
// gnd data clk vcc1.5
// from china

int dataIn = 3;
int clockIn = 2;

int isin=0; //??inch=1?mm=0


int isfs=0; //???
int index;

unsigned long xData,oData;//????????

int ledPin = 13; // the number of the LED pin


int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
long interval = 500; // interval at which to blink (milliseconds)

long previousGetMillis = 0; //????????


long Timeout = 8; //???? 8ms

void setup(){
digitalWrite(dataIn, 1);
digitalWrite( clockIn, 1);
pinMode(dataIn, INPUT); //DATA line goes to Arduino digital pin 4
pinMode(clockIn, INPUT);
Serial.begin(9600);
delay(500);
attachInterrupt(0,getBit,RISING); //CLOCK line goes to Arduino digital pin 2 ?????
index =0;
xData=0;
oData=999;
}

void loop(){

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
//????
if ((index !=0) && (millis() - previousGetMillis > Timeout) ) {
index=0;
xData=0;
};

//??
if (index >23) {
if (oData !=xData) {
if (isfs==1)
Serial.print('-');

if (isin==1){ //?? inch


xData *=5;
Serial.print(xData/10000);
Serial.print('.');
if ((xData % 10000)<1000){
if ((xData % 10000)<100){
if ((xData % 10000)<10){
Serial.print('0');
};
Serial.print('0');
};
Serial.print('0');
};
Serial.println(xData % 10000);
}else { //?? mm

Serial.print(xData/100);
Serial.print('.');
if ((xData % 100)<10) //?0
Serial.print('0');
Serial.println(xData % 100);
};
}; //if ???
oData =xData;
index=0;
xData=0;
};

if (millis() - previousMillis > interval) {


previousMillis = millis();
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(ledPin, ledState);
}

void getBit(){
previousGetMillis=millis();
if(index < 20){
if(digitalRead(dataIn)==1){
xData|= 1<<index;

};
} else {

if (index==20) //?21????? -
isfs=digitalRead(dataIn);

if (index==23) //?24????? 1=??inch


isin=digitalRead(dataIn);

};

index++;
}

j44 says: Dec 24, 2010. 9:30 AM REPLY


Hmm interesting.

Sadly I do not have my arduinos at hand, but when I do I will try this code out.

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
dp says: Nov 22, 2010. 11:07 PM REPLY
I'm seeing this as the basics of a linear encoder setup for motion control; i.e. x,y,z machines. Possible?

j44 says: Dec 24, 2010. 9:26 AM REPLY


I expect it is possible, it is the kind of use I had in mind when I started the hack.

wxws says: Dec 21, 2010. 8:40 AM REPLY


//?????
// gnd data clk vcc1.5
// from china

int dataIn = 3;
int clockIn = 2;

int isin=0; //??inch=1?mm=0


int isfs=0; //???
int index;

unsigned long xData,oData;//????????

int ledPin = 13; // the number of the LED pin


int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
long interval = 500; // interval at which to blink (milliseconds)

long previousGetMillis = 0; //????????


long Timeout = 8; //???? 8ms

void setup(){
digitalWrite(dataIn, 1);
digitalWrite( clockIn, 1);
pinMode(dataIn, INPUT); //DATA line goes to Arduino digital pin 4
pinMode(clockIn, INPUT);
Serial.begin(9600);
delay(500);
attachInterrupt(0,getBit,RISING); //CLOCK line goes to Arduino digital pin 2 ?????
index =0;
xData=0;
oData=999;
}

void loop(){

//????
if ((index !=0) && (millis() - previousGetMillis > Timeout) ) {
index=0;
xData=0;
};

//??
if (index >23) {
if (oData !=xData) {
if (isfs==1)
Serial.print('-');

if (isin==1){ //?? inch


xData *=5;
Serial.print(xData/10000);
Serial.print('.');
if ((xData % 10000)<1000){
if ((xData % 10000)<100){
if ((xData % 10000)<10){
Serial.print('0');
};
Serial.print('0');
};
Serial.print('0');
};
Serial.println(xData % 10000);
}else { //?? mm

Serial.print(xData/100);
Serial.print('.');
if ((xData % 100)<10) //?0
Serial.print('0');
Serial.println(xData % 100);
};
}; //if ???
http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/
oData =xData;
index=0;
xData=0;
};

if (millis() - previousMillis > interval) {


previousMillis = millis();
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(ledPin, ledState);
}

void getBit(){
previousGetMillis=millis();
if(index < 20){
if(digitalRead(dataIn)==1){
xData|= 1<
};
} else {

if (index==20) //?21????? -
isfs=digitalRead(dataIn);

if (index==23) //?24????? 1=??inch


isin=digitalRead(dataIn);

};

index++;
}

cpotoso says: Jun 30, 2010. 9:59 AM REPLY


Nice work. How do these calipers transduce the linear displacement to numbers? is it a friction wheel or an optical pick-up?

j44 says: Jun 30, 2010. 3:19 PM REPLY


I think the callipers work with capacitance.

Nerdz says: Jun 29, 2010. 4:57 PM REPLY


from your timing diagrams it *looks* like I2C. From your schematic it also Looks like I2C (2 lines, one for clock one for data)..hmmm interesting

http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/

You might also like