Thanks to Athul's input that bit 21 in the code is actually bit 22 in the photos and description of this post. For more detail, please refer to Athul's input in the comment section at the end of this post.
--------------------------------------------------------------------------------------------------------------------------
I came across an interesting gadget called filament width sensor (http://www.thingiverse.com/thing:454584). This gadget uses light sensor to measure the shadow of the filament passing through it. However, I am afraid that such kind of configuration may not be able to measure filaments that are transparent.
As there already are plenty info. on the internet that show how to turn digital caliper into the DRO for lathe / milling machine. I believe the same tech. could be used to build a filament width sensor that could handle transparent filament so I decided to go ahead to build one.
Preparing the digital caliper
The digital caliper that I use is a cheap Chinese one which is very common on the internet. It could be easily obtained from eBay, Amazon, Alibaba, Taobao, etc.
Remove the sticker on the back to reveal the 4 screws.
Remove the 4 screws and you will see a PCB similar to the one below.
Because a finished data cable for this kind of digital caliper costs more than the caliper itself, I decided to solder 4 wires to the 4 pins directly. It's not a difficult job to solder the wires, but care must be taken to make sure there is no short circuit.
The photo below shows that the blue data wire is a bit too long (red circle). The extra wire needs to be removed.
The read out sent out from the data port consists of 24-bit and it's sent within 9ms.
In the pic below, Channel 1 (Yellow) is Clock Output. Channel 2 (Blue) is Data Output.
CLOCK signal is normally high and is taken down on every bit. Thus, you need to read DATA on high-to-low transition. DATA line is taken high or low to signal corresponding bit.
The read out is sent continuously about every 110ms. Hence, the digital caliper is sending out about 8 read outs every second (1000ms / (110ms + 9ms)) = 8.47.
Understanding the data format
The data format is shown below.
Bits form integer that corresponds to number of 100th of mm in case of metric system. And 2000th of inch in case of measurements in inches. That is, if display reads 3.67mm, you get integer 367. The same reading in inches is 0.1445 and this gives us 289 (0.1445 * 2000). So, in case if caliper is switched to inches, for the same reading, it will send now 289 instead of 367.
Here is how 367 is shown on the scope.
Which translates into 367.
According to the table above, in theory, the digital caliper has the capacity to measure up to 5242.87mm (1+2+4+8+16+32+64+128+256+512+1,024+2,048+4,096+8,192+16,384+32,768+65,536+131,072+262,144 = 524,287).
Below is the wave form for 99.99mm.
The table below shown how 1111100001110010 is translated into 9999.
Preparing the circuit
I want to use Arduino Uno to read and display the readout from the digital caliper. However, as the digital caliper is running on 1.5V and Arduino Uno is on 5V, there needs to be a way to handle the difference in signal level. Below are some possible solutions to this issue.
1. Power the digital caliper using the 3.3V output from Arduino Uno.
For detail, check out this post:
http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/?ALLSTEPS
2. Use transistor such as 2N2222 or BC548 to raise the logic level of the Clock and Data outputs from the digital caliper.
For detail, check out the below posts:
http://robocombo.blogspot.tw/2010/12/using-tis-launchpad-to-interface.html
https://sites.google.com/site/marthalprojects/home/arduino/arduino-reads-digital-caliper
3. Use a logic level shifter such as this one from Pololu or this one from Sparkfun.
As I have some logic level shifters with me, I will be using them for this post. Below is how to wire up the digital caliper and Arduino Uno to the logic level shifter.
Checking the circuit
Below is the Arduino Uno end readout on the scope. It's clear that the signals have been shifted from 1.5V to 5V.
The code
There are 2 approaches to capture the clock and data signals from the digital caliper. If the Arduino Uno is dedicated to perform DRO task, a non-interrupt approach may be ideal. If the Arduino Uno also needs to handle other tasks, an interrupt approach would be more suitable.
Below is the code based on the non-interrupt approach.
------------------------------------------------------------------------------------------------------------------------
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(9600);
pinMode(CLOCK_PIN, INPUT);
pinMode(DATA_PIN, INPUT);
}
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
}
}
void decode() {
int sign = 1;
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 = 0; i <= 24; i++) { // Show the content of the bit array. This is for verification only.
Serial.print(bit_array[i]);
Serial.print(" ");
}
Serial.println();
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 => -
if (bit_array[24] == 1) { // Bit 24 tells the measureing unit (1 -> in, 0 -> mm)
result = (value*sign) / 2000.00;
Serial.print(result,3); // 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");
}
delay(1000);
}
------------------------------------------------------------------------------------------------------------------------
Serial Monitor Screen Shot.
Here, the change between the measuring unit ("in" and "mm") can be clearly seen in the decimal value as well as in the right-most bit of the output bit array.
Here is a short video on the working of this device https://youtu.be/dborXvt7DA8.
References:
- Interfacing TI Launchpad to Digital Caliper
http://robocombo.blogspot.tw/2010/12/using-tis-launchpad-to-interface.html
- Arduino reads digital caliper
https://sites.google.com/site/marthalprojects/home/arduino/arduino-reads-digital-caliper
- Reading Digital Callipers with an Arduino / USB
http://www.instructables.com/id/Reading-Digital-Callipers-with-an-Arduino-USB/?ALLSTEPS
- https://www.arduino.cc/en/Reference/AttachInterrupt
It feels awesome to read such informative and unique articles on your websites.cnc mills
ReplyDeleteThank you for your comment. I am glad that you enjoy it.. :-)
DeleteI am using the same caliper with Arduino to input data to android app 'TouchDRO'. works great if caliper is in inch display mode. If caliper is powered by Arduino, and power is removed and re-connected, caliper starts defaulted to MM display. Do you know of any way to force caliper to start in inch display mode?
ReplyDeleteA possible way would be to detect the output of the digital caliper, if it's in mm mode, you could use Arduino to trigger the mode switch to change it to inch mode..
ReplyDelete