# My homemade gear hobber



## Ross Donelly (Jul 13, 2018)

I thought some of you may be interested in this. I modified my milling machine to do gear hobbing. The goal is to turn the gear blank by exactly 1 tooth per revolution of the mill. To achieve this, I use a motor, shaft encoders on the mill motor and the gear blank motor, and an arduino running PID controller software to keep them exactly in sync. I also needed to tilt the mill head by the angle of the hob teeth, which I did with a thick shim.







Here's a picture of the hob cutting a plastic gear (just for a test). This was before I hardened the hob so I wanted to cut something soft.






And here are some gears I've made. Some spur gears and a worm gear (the worm was made on the lathe of course). I also used this to make the gears in my Webster engine.






Cheers,
Ross.


----------



## natalefr (Jul 13, 2018)

Good job !


----------



## Herbiev (Jul 13, 2018)

Great work. Thanks for sharing


----------



## Engineville (Jul 13, 2018)

This is a significant achievement.  If you’re willing, please tell us more of how you made and configured this modified mini-mill.  It appears that you have mounted an optical chopper/counter on the spindle of the mill, but is the spindle drive also a stepping motor?  How do you synchronize the rotation of the mill spindle and the rotation of the a-axis holding the gear blank?


----------



## Ross Donelly (Jul 14, 2018)

Sure. There's a 2-bit opto-interruptor mounted on the mill motor frame and an interruptor disc with 18 notches mounted on the end of the motor shaft. The 2 bits feed the microcontroller, which is set up to count transitions. So the microcontroller knows how many notches have gone by and in which direction. Also knowing the gear ratio of the mill, it knows quite precisely the rotational position of the mill spindle. I have a similar setup on the gear blank motor (a-axis). Now given that we know both positions, we can measure the error in the a-axis position. The goal error is zero. A PID routine is set up to control the motor voltage and keep the motor moving at just the right speed that the error stays at zero (or as close as possible). 

The Arduino has PWM outputs that make motor control easy and accurate, and its inputs can trigger interrupts for counting. It's surprising how well this works. Once stabilized, it's accurate to within about 0.2 degrees. The one minor problem I've had is mill vibration occasionally getting into the opto interruptor, but I could fix that by mounting the LED/phototransistors more solidly.


----------



## Wizard69 (Jul 21, 2018)

Thanks for the post!   This cries out for a video though, a thousand words and all.


----------



## graywd (Jul 22, 2018)

great post but I'm missing something ....  if the hob is spiral, why do you need to tilt the mill ---- or is the hob straight?


----------



## Mechanicboy (Jul 22, 2018)

graywd said:


> great post but I'm missing something ....  if the hob is spiral, why do you need to tilt the mill ---- or is the hob straight?


The hobbing gear cutter has spiral hence it has a angle, when you are creating the gear wheel, then the hob must be tilted to a right angle then the gear tooth is straight. Each hobbing gear cutter has angle marked on then one can set the correct angle on hobbing gear cutter to make straight tooth. If one want the helical gear, then angle + helical angle or angle - helical angle.


----------



## graywd (Jul 22, 2018)

Thank you for the quick response.  I had assumed that the spur blank rotated upward to match the helical rise of the hob so that the cutter always engaged the same spur.  Part of my assumption was that if the head was tilted so that the hob cutter is flat, then the blank would be incremented only when the next spur is to be cut.  I'll need to re-think this.


----------



## kstrauss (Jul 23, 2018)

Did you use a standard Arduino PID module or did you roll your own?


----------



## jsimpson (Jul 23, 2018)

Love it...


----------



## Ross Donelly (Jul 23, 2018)

kstrauss said:


> Did you use a standard Arduino PID module or did you roll your own?


I rolled my own. I'd post the program but I'm on vacation and don't have access to it. There's not much to it, mainly tuning the 3 coefficients.


----------



## kstrauss (Jul 23, 2018)

Ross Donelly said:


> I rolled my own. I'd post the program but I'm on vacation and don't have access to it. There's not much to it, mainly tuning the 3 coefficients.


Absolutely no rush so enjoy your vacation. I just like to see how others do things.


----------



## necchiom (Aug 1, 2018)

Wow! Awesome job.


----------



## Ross Donelly (Sep 23, 2018)

Here's the hobber in operation:


----------



## Engineville (Sep 23, 2018)

I hope that you had a good vacation.  Now that you’re back, thanks for posting a video of your modified mini-mill.  This setup has much potential for CNC of small metal hobby parts without too much expense.  Hence, I’m interested knowing more of you system design.
An overall schematic illustrating how the different hardware components are electrically connected would be informative of how you control your mill.  Did you really do this without the use of MACH4 or G-Code and only programming the Arduino and synchronizing to spindle and A-axis motors?


----------



## Wizard69 (Sep 23, 2018)

Hope vacation went well!!!

As for the video that is icing on the cake.    

As for your code I'm a bit surprised that you found it easy.   In my mind anyways keeping those two spindles in sync and not loosing timing would be a major headache.


----------



## Ross Donelly (Sep 23, 2018)

Yes, this was done without Mach4 or G-code. Below is a look inside the box. There is an Arduino Due clone and a motor driver (VNH5019 from pololu.com). I'm not sure if an Uno would be fast enough for this application.

The orange/brown wires go to the motor position encoder. The green/blue wires go to the mill position encoder. The red wires go to the motor and PC power supply (0V/+5V/+12V). Everything runs off 5V except the motor which is 12V.






Here is a picture of the mill encoder board. There's an IR LED and a 1.2K resistor as light source, and two IR phototransistors (with 10K pull-down resistors) right next to each-other.







Here is a picture of the end of the motor, which is a cheap 12V 100RPM DC worm gear motor (PN01007-100, $64 from makermotor.com). You can see the two IR LEDs (with 1K resistors) press-fit into holes I drilled in the end of the motor case. There are also two hidden phototransistors at the other end of the motor, tucked in through holes I drilled in the side. The armature of the motor has 12 poles, and these act as an interruptor disc (the light shines through the gaps in the armature as it goes past). The beams need to be almost (but not quite) 180 degrees apart.






This is the arduino sketch. It's all controlled from a PC via a USB cable. When it's running, it's constantly dumping info on the state of the PID and how synchronized it is.


```
#define HIGH_SPEED_MODE 0   // set if mill is in high speed gear setting
#if HIGH_SPEED_MODE
#define MREV  (18 * 4 * (30 / 14.0) * (21 / 20.0)) // 162
#else
#define MREV  (18 * 4 * (30 / 14.0) * (29 / 12.0)) // 372.857143
#endif
#define GREV  (12 * 4 * 56.0)
#define NTEETH  23
#define M       2.5          // motor power limit, 2.5 = full power

#define MOTORPWM 13
#define MOTORA 12
#define MOTORB 11
#define GPOS1  10
#define GPOS2  9
#define MPOS1  8
#define MPOS2  7
void setup()
{
  pinMode(MOTORPWM, OUTPUT);
  pinMode(MOTORA, OUTPUT);
  pinMode(MOTORB, OUTPUT);
  pinMode(GPOS1, INPUT);
  pinMode(GPOS2, INPUT);
  pinMode(MPOS1, INPUT);
  pinMode(MPOS2, INPUT);
  digitalWrite(MOTORPWM, LOW);
  digitalWrite(MOTORA, LOW);
  digitalWrite(MOTORB, LOW);
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(GPOS1), handle_gpos_change, CHANGE);
  attachInterrupt(digitalPinToInterrupt(GPOS2), handle_gpos_change, CHANGE);
  attachInterrupt(digitalPinToInterrupt(MPOS1), handle_mpos_change, CHANGE);
  attachInterrupt(digitalPinToInterrupt(MPOS2), handle_mpos_change, CHANGE);
}

void printSigned(double x)
{
  if (x >= 0)
    Serial.print("+");
  Serial.print(x);
}

void get_gpos(int *ppos1, int *ppos2)
{
  *ppos1 = digitalRead(GPOS1);
  *ppos2 = digitalRead(GPOS2);
}

void get_mpos(int *ppos1, int *ppos2)
{
  *ppos1 = digitalRead(MPOS1);
  *ppos2 = digitalRead(MPOS2);
}

int enc(int pos1, int pos2)
{
  if (pos1 == 0 && pos2 == 0)
    return 0;
  if (pos1 == 0 && pos2 == 1)
    return 1;
  if (pos1 == 1 && pos2 == 1)
    return 2;
  if (pos1 == 1 && pos2 == 0)
    return 3;
}

volatile int gposition = 0;
volatile int gpos1 = -1, gpos2 = -1;
void monitor_motor()
{
  int pos1, pos2;
  get_gpos(&pos1, &pos2);
  if (pos1 != gpos1 || pos2 != gpos2)
  {
    int old_enc = enc(gpos1, gpos2);
    int new_enc = enc(pos1, pos2);
    if (old_enc != -1 && new_enc != old_enc)
    {
      if (new_enc == (old_enc + 1) % 4)
      {
        --gposition;
      }
      else if (new_enc == (old_enc + 3) % 4)
      {
        ++gposition;
      }
      else
      {
        Serial.print("skipped motor encoding ");
        Serial.print(old_enc);
        Serial.print(" -> ");
        Serial.print(new_enc);
        Serial.print("\n");
      }
    }
    gpos1 = pos1;
    gpos2 = pos2;
  }
}

volatile int mposition = 0;
volatile int mpos1 = -1, mpos2 = -1;
void monitor_mill()
{
  int pos1, pos2;
  get_mpos(&pos1, &pos2);
  if (pos1 != mpos1 || pos2 != mpos2)
  {
    int old_enc = enc(mpos1, mpos2);
    int new_enc = enc(pos1, pos2);
    if (old_enc != -1 && new_enc != old_enc)
    {
      if (new_enc == (old_enc + 1) % 4)
      {
        ++mposition;
      }
      else if (new_enc == (old_enc + 3) % 4)
      {
        --mposition;
      }
      else
      {
        Serial.print("skipped milling encoding ");
        Serial.print(old_enc);
        Serial.print(" -> ");
        Serial.print(new_enc);
        Serial.print("\n");
      }
    }
    mpos1 = pos1;
    mpos2 = pos2;
  }
}

void handle_gpos_change()
{
  monitor_motor();
}

void handle_mpos_change()
{
  monitor_mill();
}

void set_speed(double speed)
{
  int dir = (speed >= 0);
  double s = speed;
  if (s < 0)
    s = -s;
  int v = (int)(255 * s);
  digitalWrite(MOTORB, dir ? HIGH : LOW);
  digitalWrite(MOTORA, dir ? LOW : HIGH);
  analogWrite(MOTORPWM, v);
}

void run_at_speed(int dir, double speed, int duration)
{
  Serial.print(gposition);
  Serial.print("\n");
  set_speed(dir ? speed : -speed);
  delayMicroseconds(duration);
  digitalWrite(MOTORA, LOW);
  digitalWrite(MOTORB, LOW);
}

void test_motor()
{
  while (1)
  {
    for (int dir = 0; dir < 2; ++dir)
    {
      for (double speed = 0; speed <= 1.0; speed += 0.01)
        run_at_speed(dir, speed, 100000);
      run_at_speed(dir, 1.0, 1000000);
      for (double speed = 1.0; speed >= 0; speed -= 0.01)
        run_at_speed(dir, speed, 100000);
    }
  }
}

void test_mill_pos()
{
  while (1)
  {
    Serial.print(mpos1);
    Serial.print(",");
    Serial.print(mpos2);
    Serial.print(" ");
    Serial.print(mposition);
    Serial.print("\n");
    delay(100);
  }
}

/* PID coeffs */
/* crappy
#define KP  0.001
#define KI  0.0002
#define KD  0.001
*/
/* good */
/*
#define KP  0.05
#define KI  0.0005
#define KD  0
*/
/* less overshoot */
/*
#define KP  0.05
#define KI  0.0005
#define KD  0.001
*/
/* WITH MAX=2.5 */
/* overshoot 43, final error 1 */
/*
#define KP  0.05
#define KI  0.002
#define KD  0
*/
/* overshoot 7, final error <1 */
/*
#define KP  0.05
#define KI  0.002
#define KD  0.001
*/
/* more aggressive, tuned after final assembly */
#define KP  0.05
#define KI  0.02
#define KD  0

void run_pid()
{
  double tlast = 0;
  double sum_error = 0;
  double elast = 0;
  double spindle_pos_last = 0;

  /* PID */
  while (1)
  {
    delayMicroseconds(10000);
    double t = micros() * 1e-6;
    //double target_pos = 1000 + t * 500;
    double spindle_pos = mposition / MREV;
    double target_pos = (GREV * spindle_pos) / NTEETH;
    double error = target_pos - gposition;
    double dt = t - tlast;
    double derror = (error - elast) / dt;
    sum_error += error * dt;
    tlast = t;
    elast = error;
    double v = KP * error + KI * sum_error + KD * derror;
    double rpm = (spindle_pos - spindle_pos_last) * 60 / dt;
    spindle_pos_last = spindle_pos;
    if (v > M)
      v = M;
    if (v < -M)
      v = -M;
    set_speed(-v * 0.4);
    Serial.print("t=");
    Serial.print(t);
    Serial.print(" rpm=");
    Serial.print(rpm);
    Serial.print(" p=");
    Serial.print(gposition);
    Serial.print(" tgt=");
    Serial.print(target_pos);
    Serial.print(" error=");
    printSigned(error);
    Serial.print(" P=");[ATTACH=full]104370[/ATTACH] [ATTACH=full]104371[/ATTACH] [ATTACH=full]104372[/ATTACH]
    printSigned(KP * error);
    Serial.print(" I=");
    printSigned(KI * sum_error);
    Serial.print(" D=");
    printSigned(KD * derror);
    Serial.print(" v=");
    printSigned(v);
    Serial.print("\n");
  }
}

void loop()
{
  //set_speed(1);
  //while (1)
  //  ;
  run_pid();
  //test_mill_pos();
}
```


----------



## Cogsy (Sep 24, 2018)

Thanks for the code, I'll have a study of it later on. One thing that stuck out was all the serial reporting though. Obviously fine for you in this instance but you mention a Uno might not be fast enough. I was mucking around with a Uno a couple of months ago and had serial output continually reporting servo states while I fine tuned a robotic arm range of motion/interferences. Once I had it all set up good enough I disabled the serial output and the speed of execution more than quadrupled. I didn't realise it would have such an effect, at least on a lowly Uno, but if you run into speed issues in the future consider disabling/reducing serial outputs and see if that fixes your issue.


----------



## Jester (Oct 8, 2018)

New to the forum, so be gentle on me...

Are you able to change the ratio for the mill spindle speed to output speed on your a-axis?
Say if your making a different tooth gear for example?


----------



## bazmak (Oct 8, 2018)

Im totally lost,when I was at school I thought an Arduino was a faster than light travelling quark


----------



## Ross Donelly (Oct 8, 2018)

Yes, just set the NTEETH value in the code to how ever many teeth you want. If you want to go to a different pitch, you would need to make a new hob (the cutting tool). The hob I made is for 1/8" tooth pitch.


----------



## rlukens (Oct 8, 2018)

I'm just stupified. Got my ME degree 50 years ago. Wonder what the next 50 will bring.
Nice work though... I guess.


----------



## Corry (Jan 3, 2019)

I'm mostly here to just say thanks. 
I'm a small r&d company who needs what amounts to an individual as a bunch of gears (around 100) but a minuscule quantity to most gear shops.  I'm looking at the cost of just stainless steel spur gears costing about $20/gear.  I can buy a lot of tools for that money...perhaps ones that will make wear parts rather than wear parts themselves!

I have a pretty good CNC shop (5 axis mill, 4 axis lathe) so I thought gear hobbing would be a breeze.  well, the lathe doesn't have "polygonal turning" capabilities, other than that, it would be the ideal place to hob!  So what I'm thinking I'll do is buy a 2Kw servo motor/driver (or make the STMBL open source servo driver), gear it over to a "hobbing spindle", add a servo encoder to the lathe headstock, and the "hobbing spindle" (since I'll be gearing it up since all of the motors I have found are 3000 rpm max or less!) and use PID code to synchronize them. 

PID isn't something I really understand though.  Linear algebra didn't help, and my college requirement was linear algebra OR diffeq   I should've done both!  I know what PID does, but not how to tune it or write it.  Your code will certainly help a lot.

If I could make one request, it would be how you went about tuning?  General process only.  I *think* my non-controlled spindle will have less variance given the extreme amount of inertia it is carrying, as well as the quality of the control system, but who knows.  I'm specifically buying a low inertia spindle motor to hopefully make corrections easy and fast, but again, who knows what the reality will be until I get it all done!

I think I can manage the rest.

Like I said, I mostly wanted to say thanks.  Your post came up on a search for diy hobbing machine as I had started down the line of thinking of making my own machine for this!  (well, evaluating cost/time/chance of success/etc)


----------



## Ross Donelly (Jan 3, 2019)

Corry,

Glad it was helpful. I'm not the first to do this. I got the idea from some videos I found on the web. Just google gear hobber and you should find some. Here's one:

https://thewikihow.com/video_ZhICrb0Tbn4

I tuned the parameters by starting with just P, then adding some I to allow it "catch up" and synchronize, but not too much or you will overshoot. I also tried adding a little D to improve convergence but that can cause oscillation and I ended up not using any. So it's actually a PI controller, not a PID. I never learned the proper mathematical theory behind this but it's not too hard to understand how to tune a PID reasonably well in practice without the math. I found the wikipedia page on PID to be helpful:

https://en.wikipedia.org/wiki/PID_controller


----------



## Corry (Jan 3, 2019)

The idea of using an Arduino to do the work is what got me thinking.  In my mind, I was stuck on the idea of needing a mechanical linkage.  I saw one design where a person used a flex shaft tied to a pulley on the spindle, into some more gears to drive an indexing head.  I was really stuck on the mechanical synchronization.  Even in considering how to make my own hobbing machine, I was thinking mechanical synchronization.  This is far easier, and given they make 5000 ppr in quadrature servo encoders (and I'm guessing the likes of Mitutoyo have even higher precision encoders), its probably able to be more accurate (given all the backlash in the various gear trains needed for a hobbing machine). 

 I've since learned of polygonal turning (which is cool, but not really useful to me), and seen that CNC hobbing machines are doing something similar (though probably with FPGAs, and even fancier algorithms).  Its really funny because professionally, I'm a software engineer.  I should see my favorite hammer (software) and see nails everywhere! 

Either way, I'm pretty excited for this.  I hadn't started updating my designs for the gears, because I really didn't want to spend $2k+ on gears!  If I couldn't find a way to make them, I was going to really try hard to design around them (probably would have done chains with sprockets made on the lathe, but chains are noisy....and my project is a jerk, err, has a lot of jerk....Its going to be hard enough on gears.  Chain stretching would likely have become a major issue as well.

I'm now working on the design changes 

I admit, despite having nice equipment, I'm still a relative newbie with it all.  Despite that, if you ever have need of something made, just ask.  I'll do my best.  Trouble with CNC is that there are billions of ways to get the machine to destroy itself.  Inventor HSM simulation isn't very good either, and vericut is rather expensive.  (Still considering it anyhow), so that why I say, I'll try.  To give you an idea of the capabilities, its a Haas VF-2 with a TR-160 or HRT-160, and a Haas ST-20Y.  Pretty good work volumes for hobby/research/prototyping, but as far as "industry" is concerned, they're small machines


----------



## 99Norton (Jan 4, 2019)

There are some interesting You Tube video by one F. Cleff about his conversion of a Mill/Drill for gear hobbing:


----------



## Racene (Jan 4, 2019)

Try this, contact  info for Syncron gear hobbing , Richard Bartlett,email     [email protected]


----------



## bdrmachine (Jan 5, 2019)

Thanks for posting your gear cutting inspiration!  How about 45 degree bevel gears, Can they be cut this way?


----------



## Mechanicboy (Jan 6, 2019)

bdrmachine said:


> Thanks for posting your gear cutting inspiration!  How about 45 degree bevel gears, Can they be cut this way?



No, not with this hobbing gear cutter,.. see this link --> https://www.index-traub.dk/en/technology-solutions/gearing-technology/bevel-gear-technology/


----------



## zoltan77 (Mar 27, 2022)

kaphatok pontos kapcsolatot?

Kösz!


----------

