A couple photos of the breadboard version. Note the three encoders are under the display, this prototype wasn't really meant to be used for anything. Of course the permanent version will have the encoders attached to the XYZ machine and not on a breadboard.
This picture (pardon the rotation) shows the display, you can just see one of the encoders on the breadboard below the display. This picture was taken before I added the math to print out converted inches, it just shows the raw encoder count.
I might also later have at least one button to set the home position, or I may just rely on the Arduino reset button to set 0,0,0. Some sort of home/limit switch setup might be nice too.
The encoders are attached to the ends of the drive screws for the platform. I used a short piece of flexible plastic tubing from the hardware store, because I couldn't find set screw shaft couplers the right size for any reasonable price. The hose gives me a little flex, so it should be OK. It stretches over the encoder shaft and the drive shaft.
Using rotary encoders from sparkfun. They are inexpensive, I hope they hold up to the job over time. They are really for human input knobs. http://www.sparkfun.com/products/9117
Datasheet: http://www.sparkfun.com/datasheets/Components/TW-700198.pdf
Later I swapped with some slightly different encoders from Digikey
http://search.digikey.com/scripts/DkSearch/dksus.dll?WT.z_header=search_go&lang=en&site=us&keywords=987-1199-ND&x=20&y=18
http://www.bitechnologies.com/pdfs/en16.pdf
I changed because these didn't have detents, which tended to snap the encoders to certain values. Also these had threaded shafts and were easier to mount. For $1.18 why not get the best?
Some example rotary encoder code that I started with is here:
http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
The example code worked out of the box, I modified it to read three encoders at the same time.
It makes use of port manipulation to read all the input simultaneously. This page helped http://www.arduino.cc/en/Reference/PortManipulation
However, this guy must have been a programmer for a living, the program was basically 2 lines and very hard to understand. I wrote my version with more comments and a little less pizazz. Hopefully more understandable.
Got the three encoder code working, included it below, it was a bit tricky.
I added the LCD readout, attempting to keep the code delays as small as possible so we don't skip and encoder positions. The LCD is hooked up pretty much like all the Arduino examples, using 4 bit wide parallel mode. I like to use pins 7 6 5 4 3 2 because it keeps all the LCD pins on the same Arduino connector. You might note in the photo there is a adafruit arduino prototype board and some headers that I use to stack the LCD on top of the Arduino and map the pins. I'm not going to repeat the LCD interfacing stuff in this post. The Optrex display i used is cost effective but a bit quirky, it has the tendency to print garbage if you give it commands too fast.
The code is after the break:
/* Rotary encoder readout for XYZ CNC machine */
// Encoders connected as follows
// X encoder PIN A - Analog 0
// X encoder PIN B - Analog 1
// Y encoder PIN A - Analog 2
// Y encoder PIN B - Analog 3
// Z encoder PIN A - Analog 4
// Z encoder PIN B - Analog 5
// Pin C of all encoders is grounded, center pin of http://www.sparkfun.com/products/9117
// thus variable PINC will read this entire register simultaneously
// this avoids missing states of the encoder
//Variables to set the counts/inch
#define TH_PER_IN 20 //lead screw threads per inch
#define CT_PER_REV 48 //encoder counts per revolution
// Thus the accuracy of the measurement 1 inch /(TH_PER_IN*CT_PER_REV)
//Variable to reverse the sign if the machine and encoder don't agree with your sense of things
#define REFLECTX -1
#define REFLECTY -1
#define REFLECTZ 1
//Based on
//http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
//Expanded to 3 encoders and written to be more clear and less over elegant
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
unsigned int olddata;
unsigned int newdata;
char newX;
char newY;
char newZ;
char oldX;
char oldY;
char oldZ;
long int counterX = 0;
long int counterY = 0;
long int counterZ = 0;
// table of meaning of states, input is two bits old value, two bits new value
// the encoder has either moved +1, -1 or stayed in the same place
int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
void setup()
{
/* Setup encoder pins as inputs */
// http://www.arduino.cc/en/Reference/PortManipulation
DDRC = B00000000; //Sets input direction all to analog inputs
PORTC = B11111111; //Sets pull ups on the analog pins to 1
Serial.begin (115200);
Serial.println("Start");
counterX = 0;
counterY = 0;
counterZ = 0;
pinMode(13 ,OUTPUT); //turn on backlight
digitalWrite(13, HIGH); //turn on backlight
lcd.begin(20,4);
delay(500); //Optrex display needs to rest after a begin
lcd.clear();
lcd.setCursor(0,0);
delay(100); //Optrex display needs to rest after setting cursor
lcd.print("XYZ CNC Position");
lcd.setCursor(0,1);
lcd.print("X: ");
lcd.setCursor(0,2);
lcd.print("Y: ");
lcd.setCursor(0,3);
lcd.print("Z: ");
}
void loop()
{
//This loop needs to run fast to avoid missing encoder states
newdata = PINC;
if( newdata != olddata ) {
newX = newdata & 0x03; //mask out just the X bits
oldX = olddata & 0x03; //mask out just the X bits
oldX = oldX << 2; //move over to form address to table
counterX += enc_states[oldX + newX] ; //increment or decrement counter from table
Serial.print(" X:");
Serial.print(counterX, DEC);
lcd.setCursor(3,1);
lcd.print(1000*counterX/(TH_PER_IN*CT_PER_REV*REFLECTX), DEC);
lcd.print(" mils ");
newY = newdata & 0x0C; //mask out just the Y bits
newY = newY >> 2; //shift to LSBs
oldY = olddata & 0x0C; //mask out just the Y bits
counterY += enc_states[oldY + newY] ;
Serial.print(" Y:");
Serial.print(counterY, DEC);
lcd.setCursor(3,2);
lcd.print(1000*counterY/(TH_PER_IN*CT_PER_REV*REFLECTY), DEC);
lcd.print(" mils ");
newZ = newdata & 0x30; //mask out just the Z bits
newZ = newZ >> 4; //shift to LSBs
oldZ = olddata & 0x30; //mask out just the Z bits
oldZ = oldZ >> 2; //shift to form address to table
counterZ += enc_states[oldZ + newZ] ;
Serial.print(" Z:");
Serial.println(counterZ, DEC);
lcd.setCursor(3,3);
lcd.print(1000*counterZ/(TH_PER_IN*CT_PER_REV*REFLECTZ), DEC);
lcd.print(" mils ");
}
olddata = newdata;
}
Hello,
ReplyDeleteI need some help measuring the distance one axis travels on my Lathe but I have no idea how to do it, the screw has some slop so the encoder on the screw won't work.
I've looked at hall effect sensors and I'm really lost on how I achieve accurate measurement mechanically, I have a bar magnet from HomeDepot and the hall effect sensors, how do I read one MM, do i cut grooves in the bar magnet?
I've looked at and tried Ultrasonic but it's inaccurate and it lags a bit too, any suggestions would be greatly appreciated.
Also no LCD needed, the Arduino Serial Monitor is good enough for me, and again it's only one axis I need read back from.
please email me if you like, crob.09 at live dot ca.
Thanks in advance for your help and time.
Multiply and divide are among the slowest things a computer can do and you have 3 multiplys and one divide in your print statement. On top of that all terms are constants. I would suggest the whole thing be replaced with one divide. In your setup, multiply the three terms then divide that by 1000. Then in the print statement just divide the new counter value by that new constant from setup.
ReplyDeleteJe pense que c’est la copie Gucci la moins chère que j’ai jamais achetée.gucci pas cher Je partage ce site avec des amis. Ils sont très contents, leur prix est si bas, gucci ceintures pas cheret ils peuvent acheter de si bonnes chaussures.
ReplyDeleteThank you because you have been willing to share information with us. we will always appreciate all you have done here because I know you are very concerned with our. Fisher paykel cpap machine review
ReplyDeleteExcellent Blog! I would like to thank for the efforts you have made in writing this post. I am hoping the same best work from you in the future as well. I wanted to thank you for this websites! Thanks for sharing. Great websites! Pirani Gauges
ReplyDeleteYou have a sales force for your product, but how well organized are you? The probable answer is 'never enough', because you can't ever have 'too much business'!torque wrench
ReplyDeleteI think this is an informative post and it is very useful and knowledgeable. therefore, I would like to thank you for the efforts you have made in writing this article. https://belltestchamber.com/environmental-chamber/desktop-environmental-climatic-temperature-test-chamber/
ReplyDeleteVery informative article, which you have shared here . After reading your article I got very much information and it is very useful for us. Magnetic coupling
ReplyDeleteNice job
ReplyDeleteSome genuinely nice and utilitarian info on this site, as well I believe the style has got great features. cnc machining
ReplyDeleteGreat job, this is essential information that is shared by you. This information is meaningful and very important for us to increase our knowledge about it. Always keep sharing this type of information. Thanks once again for sharing it. Find Machinerseeker.
ReplyDelete