Bridgeport Mill Tachometer

Susquatch

Ultra Member
Administrator
Moderator
Premium Member
Here's one for you guys (@CalgaryPT will appreciate this as well) LOL.

CO calls me and tells me the Regiment is refreshing their IMP supply (He knows I like to use them for my mountain sheep hunting trips). I beetled down to HQ and sure as heck there were stacks and stacks of unexpired IMPs beside the dumpster. Got the van half loaded when the Regimental QM stepped out the back door for a smoke. Oh.... Oh.... That was the end of that... drove away with nothing LOL...

It is sooooo sad that has to happen. You would have put them to much better use than filling a big hole in the ground.
 

YYCHM

(Craig)
Premium Member
For what it's worth, here are my mods to @whydontu s RPM code...... I wanted to reduce the LCD flicker and have RPM go to zero when I turn off the mill.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
//LiquidCrystal_I2C lcd(0x3F, 16, 2);
const int dataIN = 2; //IR sensor INPUT

unsigned long prevmillis; // To store time
unsigned long duration; // To store time difference
unsigned long lcdrefresh; // To store time for lcd to refresh
unsigned long SCCount = 0; // State change count
unsigned long SCCheck = 0; // State change timeout check

int rpm; // RPM value

boolean currentstate; // Current state of IR input scan
boolean prevstate; // State of IR sensor in previous scan

void setup()
{
pinMode(dataIN,INPUT);

lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Spindle RPM");
lcd.setCursor(0,1);

prevmillis = 0;
prevstate = LOW;
}

void loop()
{

// RPM Measurement
currentstate = digitalRead(dataIN); // Read IR sensor state
if( prevstate != currentstate) // If there is change in input
{
SCCount++;

if( currentstate == HIGH ) // If input only changes from LOW to HIGH
{
duration = ( micros() - prevmillis ); // Time difference between revolution in microsecond
rpm = (60000000/duration); // rpm = (1/ time millis)*1000*1000*60;
prevmillis = micros(); // store time for next revolution calculation
} // if state HIGH
} // if state change


prevstate = currentstate; // store this scan (prev scan) data for next scan

// State Change check
if( ( millis()-SCCheck ) >= 1000 * 5 )
{
if (SCCount > 0) SCCount = 0;
else rpm = 0;

SCCheck = millis();
}

// LCD Display
if( ( millis()-lcdrefresh ) >= 1000 )
{
lcd.setCursor(0,1);
lcd.print(rpm);
lcdrefresh = millis();
}

}//loop
 
Last edited:

Susquatch

Ultra Member
Administrator
Moderator
Premium Member
For what it's worth, here are my mods to @whydontu s RPM code...... I wanted to reduce the LCD flicker and have RPM go to zero when I turn off the mill.

Very very cool @YYCHM ! Well done! I'm jealous.

I shall use your code as the starting point for mine - which is still a few months away due to other priorities (especially my bride's).

Still looking for some code to test the Arduino with though.

I meant to ask you how your soldering turned out. Obviously it worked, but were you happy with it? Mine wasn't what I expected or remembered. My left eye abandoned me to the distance wolves.
 

YYCHM

(Craig)
Premium Member
I meant to ask you how your soldering turned out. Obviously it worked, but were you happy with it? Mine wasn't what I expected or remembered. My left eye abandoned me to the distance wolves.

Didn't solder the headers on, got these instead LOL.....



The unsoldered versions have been sent to @whydontu for assembly.
 
Last edited:

Susquatch

Ultra Member
Administrator
Moderator
Premium Member

I see! Well, that's one way to skin a cat!

Glad you didn't send them to me. I didn't realize how bad my eyes were when I made the offer.

For the peanuts it costs to solder them up with headers, it amazes me that they don't sell them already done at Canadian solder.

I'll have to check at Simcoe to see if they sell a USB-C version.
 

whydontu

I Tried, It Broke
Premium Member
Solder the I2C adapter direct to the LCD panel, or solder in a header socket to the LCD so you can remove the adapter if needed?

Should I replace the 4-pin angle header on the I2C adapter with a straight one? I found having the I2C pins come of at an angle was a pain getting the display to fit in tight spaces.

Let me know...
 

YYCHM

(Craig)
Premium Member
Solder the I2C adapter direct to the LCD panel, or solder in a header socket to the LCD so you can remove the adapter if needed?

Should I replace the 4-pin angle header on the I2C adapter with a straight one? I found having the I2C pins come of at an angle was a pain getting the display to fit in tight spaces.

Let me know...

Angled? You lost me? I didn't have any issues mounting this arrangement. But what ever you suggest is fine by me.

b4249c_8945d182740545599fe409ea2c3845fc~mv2.jpg
 

whydontu

I Tried, It Broke
Premium Member
Angled? You lost me? I didn't have any issues mounting this arrangement. But what ever you suggest is fine by me.

b4249c_8945d182740545599fe409ea2c3845fc~mv2.jpg
I always find the four pins on the right mean the mating wires have to stick out quite a ways from the edge of the LCD. If you look at the photo of my tach, the case is very small and the connector fouls the inside of the case.
 

JohnW

(John)
I haven' been around this forum for a while (not for any good reason), but as it turns out Brent H was over at my place picking up various Opel parts for his new project (I am involved with Opels as well) on the Monday after he picked up his new project and had the meetup. I was actually in Winnipeg at the time of the meetup, but did the 900km/h return on Sunday night. I have driven that WAY too often, and all I had to bring back was several homemade apple pies from my Mom. We got to talking about machining and he mentioned the CHM site and this thread in particular after I showed him something I had built a couple of years ago. He suggested that people might be interested in what I had done.

I built an Arduino based tach type project that is similar to what is discussed in this thread for my lathe. Here is what I built . . .

SF Display and Controls.jpg
This is the control box / display that sits on top of my VFD that is just above the headstock on the lathe. It can be switched to use Imperial or Metric modes. The second switch selects what is displayed: the X-feed (distance/rev), Y-feed (distance/rev) or Lead Screw (TPI or metric pitch). The knob sets a work diameter that is used to calculate the surface cutting speed (FPM or MPM).

In the first row, it displays the current spindle RPM, followed by whatever the diameter knob is set to ('in' or 'mm'), and the calculated surface speed ('F' or 'M').

The second row shows 'X', 'Y' or 'T' to indicate X/Y feed or threading mode, followed by the feed rate ('in/R' or 'mm/R') or the thread pitch ('TPI' or 'mm/T').

The three connectors on the upper right lead to the encoders I installed on the spindle shaft, feed shaft, and lead screw. Here is what I installed on the LHS of the headstock (under the cover that is normally there):

SF Spindle Encoder.jpg
The encoder provides 360 pulses / rev and is driven by a GT2 timing belt. The plastic spindle pulley was salvaged from an old ink jet printer and epoxied to an aluminum sleeve I made. It is held on with two set screws which you can't see here since it is blurred because it is spinning. The pulley ratio is 99:60, so the encoder actually provides 594 pulses per revolution of the spindle.

On the RIHS of the lathe I installed two encoders. One on the feed shaft, and one on the lead screw:
SF Encoder Cover.jpg

Not really exciting with the aluminum protection cover on it, but from the back side you can see this:

SF Shaft Encoders.jpg

These are two 400 pulse per rev encoders. I have been thinking about installing this sort of thing for a while, so when I rebuilt the lathe a couple of more years ago, I put the end of the two shafts in my old smaller lathe, faced them nice and flat and drilled a centered, threaded hole in the ends that the adapter pieces you can see here are threaded into.

The Arduino code monitors the state of the switches to see what it should display, then uses pin change interrupts to count both the rising and falling edge of each pulse from each encoder. That provides 1188 interrupts per spindle revolution and 800 interrupts per revolution of the lead screw and feed shafts. It then calculates the RPM from the number of pulses per second on the spindle, and calculates the ratio of the spindle pulses to the pulses from one of the shafts to calculate the feed or threading rate. The code uses the pitch of the lead screw (1/4") and the internal ratios in the carriage to calculate the feed or threading rates to display.

It updates the display 4 times a second using the averages it calculates over several revolutions of the spindle.

If you are interested in any more of the internals I'd be happy to share.
 
Last edited:

whydontu

I Tried, It Broke
Premium Member
Very nice! Way more sophisticated than mine, I might have to get ambitious.
I use my tach in a mill, and I tweaked my setup to display the cutter size and calculate the cutter FPM. I’d love to see your code to see if I can steal (borrow) some ideas.

I use an ancient glorious Monarch 62 lathe at work, and the coolest thing about it is the hydraulic system that adjusts spindle RPM by rotating one dial to desired FPM and another dial to workpiece diameter. So looking at your design, and thinking about the Monarch, think how cool it would be to have a VFD control combined with a linear scale that reads workpiece diameters and adjusts motor speed to maintain fixed FPM. I have visions of an Arduino to 4-20mA converter. A winter project!
 

Susquatch

Ultra Member
Administrator
Moderator
Premium Member
@Brent H was right. I'm glad you took the time to share. That looks awesome!

How did you make the lettering on the face of the display unit?

Is the selector a discrete switch setting or a continuous potentiometer?

I'd love to see your code too.

You have also answered my questions earlier about resolution. Did you manage the interrupts directly at the processor level or using the IDE?
 

JohnW

(John)
It is built a lot like yours using an Arduino Nano (with 16MHz ATMega328 CPU @ 16 MHz), a standard 16x2 LCD display with an I2C to parallel converter for the LCD.
SF Inside.jpg
The heat-shrinked device in the foreground is a constant current source for the LCD backlight. The LCD is a bit of an older device I've had around for a while that is unique in that it has larger than usual fonts (good for old eyes like mine), but uses the standard LCD parallel interface.. The disadvantage is that the LED backlighting uses old design LED's that are quite inefficient so it needed a special supply.

A design mistake is that I should have mounted the Nano with the USB port at the edge of the box with a hole. As it is, to re-program it, I have to open it up and use a 90 degree USB adapter to connect it to my laptop. On the other hand, I've only had to do that once since I found a bug after installing it, and will likely never update the code since it seems to work well.

The board is just perf board with point to point wiring on the back. A DC-DC converter takes 24VDC (that I had available in the lathe control circuitry) and brings it down to 5V that the Arduino and encoders are happy with.

The encoders are cheap units from Aliexpress: (something like: https://www.aliexpress.com/item/1005002241818396.html - I don't remember exactly which ones I ordered), so nothing fancy.

It would be cool to interface an Arduino to my DRO Y-axis and use it to drive the VFD to achieve a semi-constant speed across a face like you are suggesting.

This has gotten me thinking that I need to build a simpler version of this for the mill giving RPM and feed rate for a cutter diameter.

I am willing to share my code (it also provides much of the project's detailed documentation), but I do not want to post it on a public forum. Send me a PM with an e-mail address and I will send it to you.

The front panel is created by back engraving a thin sheet of clear acrylic with a laser cutter. The acrylic has a layer of sliver and then black paint on it (I didn't coat it, I bought it like that). The lettering is then painted with a couple of colors of acrylic paint (stolen form my wife's art supplies) so the text shows up as colored text on the front, but does not have to be applied carefully. The clear window was engraved in the same way and then polished with a Dremel since the engraver leaves a matt finish in the acrylic.

SF_Painting Panel.jpg

The diameter control is a pot that is read with an AnalogRead(), and fed into a log function to make it non-linear so it can reasonably be used from 0.1 - 12".

It was all written using the Arduino IDE, but there is no official Arduino support for the ATMega328 pin-change interrupts (maybe there is a library, but I didn't really look for one and performance is really important there so I wanted to do it myself), so that is done by directly manipulating the CPU registers and writing the (very simple) interrupt functions.
 

Susquatch

Ultra Member
Administrator
Moderator
Premium Member
It is built a lot like yours using an Arduino Nano (with 16MHz ATMega328 CPU @ 16 MHz), a standard 16x2 LCD display with an I2C to parallel converter for the LCD.
View attachment 18809
The heat-shrinked device in the foreground is a constant current source for the LCD backlight. The LCD is a bit of an older device I've had around for a while that is unique in that it has larger than usual fonts (good for old eyes like mine), but uses the standard LCD parallel interface.. The disadvantage is that the LED backlighting uses old design LED's that are quite inefficient so it needed a special supply.

A design mistake is that I should have mounted the Nano with the USB port at the edge of the box with a hole. As it is, to re-program it, I have to open it up and use a 90 degree USB adapter to connect it to my laptop. On the other hand, I've only had to do that once since I found a bug after installing it, and will likely never update the code since it seems to work well.

The board is just perf board with point to point wiring on the back. A DC-DC converter takes 24VDC (that I had available in the lathe control circuitry) and brings it down to 5V that the Arduino and encoders are happy with.

The encoders are cheap units from Aliexpress: (something like: https://www.aliexpress.com/item/1005002241818396.html - I don't remember exactly which ones I ordered), so nothing fancy.

It would be cool to interface an Arduino to my DRO Y-axis and use it to drive the VFD to achieve a semi-constant speed across a face like you are suggesting.

This has gotten me thinking that I need to build a simpler version of this for the mill giving RPM and feed rate for a cutter diameter.

I am willing to share my code (it also provides much of the project's detailed documentation), but I do not want to post it on a public forum. Send me a PM with an e-mail address and I will send it to you.

The front panel is created by back engraving a thin sheet of clear acrylic with a laser cutter. The acrylic has a layer of sliver and then black paint on it (I didn't coat it, I bought it like that). The lettering is then painted with a couple of colors of acrylic paint (stolen form my wife's art supplies) so the text shows up as colored text on the front, but does not have to be applied carefully. The clear window was engraved in the same way and then polished with a Dremel since the engraver leaves a matt finish in the acrylic.

View attachment 18810

The diameter control is a pot that is read with an AnalogRead(), and fed into a log function to make it non-linear so it can reasonably be used from 0.1 - 12".

It was all written using the Arduino IDE, but there is no official Arduino support for the ATMega328 pin-change interrupts (maybe there is a library, but I didn't really look for one and performance is really important there so I wanted to do it myself), so that is done by directly manipulating the CPU registers and writing the (very simple) interrupt functions.

Your use of the interrupts and on chip timers is EXACTLY what I have been after. My instincts told me it could be done that way, but you are the first one I've seen who has actually done it. I'm pretty sure there are others, but I never saw them.

My wife has paint that I can swipe. But sadly, I have no laser engraving capabilities here. It's something I have always wanted to do though. So mine will not look nearly so nice.

Yes, I noticed the log scale and thought it was a great way to handle big ranges.

I am new to the Arduino but not to programming or microcontrollers.

All in all what you have done is very impressive. Thanks so much for sharing!

I appreciate your privacy needs. I'll send you a PM for the code!
 

whydontu

I Tried, It Broke
Premium Member
This is thevengraving toy I use for my front panels. takes forever to engrave aluminum faceplates, but does the job. I‘ll need to try JohnW’s method.

 

Attachments

  • 1DE9E56C-2A25-47FE-AA24-109E0054D1E0.png
    1DE9E56C-2A25-47FE-AA24-109E0054D1E0.png
    1.5 MB · Views: 4

JohnW

(John)
I don't directly use the CPU timers. The pin-change interrupts simply increment a count when the pin change occurs (the ATMEGA368 has exactly three independent pin-change sources, so it worked out).

I just count the number of pin changes over 250ms (1/4 second). I use the Arduino micros() function to get the 250ms elapsed time to the nearest 4 microseconds. That function reads one of the CPU timers (timer0, I think) that is set to run at 4us/tick - I assume they've used a 64x pre-scaler on the hardware timer.
 

Brent H

Ultra Member
Haha! Glad to have you back @JohnW ! Now you can share a few other cool projects like machining pistons etc - LOL. It was super amazing to see your shop set up and the neat things you are working on!! I will send you an email about a few Opel projects for advice
 

Susquatch

Ultra Member
Administrator
Moderator
Premium Member
I don't directly use the CPU timers. The pin-change interrupts simply increment a count when the pin change occurs (the ATMEGA368 has exactly three independent pin-change sources, so it worked out).

I just count the number of pin changes over 250ms (1/4 second). I use the Arduino micros() function to get the 250ms elapsed time to the nearest 4 microseconds. That function reads one of the CPU timers (timer0, I think) that is set to run at 4us/tick - I assume they've used a 64x pre-scaler on the hardware timer.

That sounds to me like the IDE actually does access the timers pretty directly. I'll know a bit better after I read your code. If the IDE can access the timers, then that's all I would need. From 1000 ft up, it certainly appears that even it it doesn't, the resolution is plenty fine enough for this job.

I guess I just have to get off my butt and move the Arduino learning curve up the priority list. Right now looking after my mother's dementia is consuming most of my priority time. I did get one unit soldered up ready for programming. But I have not read much about how to use the IDE yet. I'm not expecting that to be a big challenge despite all my white hair, but I guess you never know. Hopefully later this winter it will all happen. If not, then next winter, or the winter after that....... LOL!

I have been able to squeeze a little time into using my new mill and I'm making a 3-way tram fixture for it as we speak. It's driving my bride crazy. "Every time I turn around you are sneaking off to your Fg shop and playing with your toys..... You are never gunna get your mom looked after this way" She is right of course. Good thing she has no idea what all I am up to! (sorry for the short complaint guys.....)
 

YYCHM

(Craig)
Premium Member
As in solid wire, or stranded wires but not multi-conductor?

Solid wire, multiple colors with the Dupont ends, like the Amazon image only solid wire.

Or put it this way. What gauge solid core wire is good for bread board projects? Is that called wrapping wire?
 
Last edited:
Top