For the CNC milling machine, I'm using a Kress FM 530 spindle. This is the most basic model from Kress and consists of just a 530W universal motor and an on-off switch. The more expensive models use a knob and a triac to allow varying the speed. Mine just spins up to 28000 RPM upon turning it on.
It would be very easy to add such a triac based speed control circuit, but I would like to be able to control the spindle from Mach3 or EMC2. Additionally, it would be nice if a feedback mechanism ensures that the spindle speed is maintained during milling.
I found that all this is offered by Super-PID, but as it did not seem that hard, I decided to build a speed controller from scratch.
So... what is needed?
Detecting the zero-passing of the AC sine can be done in various ways. The easiest is to directly connect the mains to a 1M resistor to the input pin of a uC and have the chip's internal EMC protection diodes limit the voltage.Very simple and explained in this AVR application note.
Of course, if cost is not paramount and you want some safety, you'll want to isolate the mains completely from the microcontroller part. Then, some more noise immunity would not hurt either. So looking for an alternative, I found this and this. Both circuits are very similar and use an optocoupler to isolate the detection pulses. You can read the full circuit descripton by following the links.
The circuit generates a short pulse around the zero crossing, which can be easily used as GPIO interrupt input for the STM8S I'm using here.
Measuring the speed of the spindle is done using an IR sensor. The hard part is finding a suitable location inside the router where the IR receiver can look at the spinning axle. In the Kress, there is a small black plastic "wheel" at the top end of the axle, just before the bearing. It has small indentations, so it is possible that it is was intended for measuring the speed, if it were painted.
The sensor/diode combination used is a Vishay TCRT5000. I tried a TCRT1000 as wel, but its range was insufficient to obtain a reliable pulse signal. In the picture below, you can see the sensor mounted on a piece of protoboard and the white dot (corrector fluid) on the plastic wheel, just above the motor's armature.
To keep things simple, I'm using a single pulse per revolution. For a range between 2000 to 30.000 rpm, this translates to pulses with a frequency of 33 Hz to 500 Hz.
The application of triacs as a dimmer or motor controller is widespread; they can be found in appliances such as vacuum cleaners and light dimmers. If no specific control is necessary, a potmeter can be used to control the triac's phase angle, but we want to have a feedback loop through the microcontroller.
For the triac, I chose a BTA08-600, which can handler 8A at 600Vrms. Should be plenty.
It is possible to drive the triacs gate directly from a microcontroller if the triac is logic-level compatible. This means that the gate is more sensitive and can trigger faster (with a smaller current). But if this is not the case, there exist triac drivers that include both the driver circuit and an optocoupler to isolate the circuit parts, such as the MOC3022. Below is an application example from the datasheets, which fits perfectly for what we have in mind.
The STM8S is an 8 bit microcontroller from ST. Its major point is that it includes lots of onboard peripherals such as timers of various complexity. The timers can be configured extensively so that almost no support code is necessary during their operation.
In this case, we want to count the amount of time between pulses from the IR sensor to derive the router speed (an alternative is counting pulses in a certain interval but this is less accurate at low speeds). It involves using TIMER1 in Slave-reset mode, so that it resets on an interrupt on its input channel. The current counter value is then stored in its capture-compare register. I have already covered the code here.
To cover the possible range of speeds with adequate accuracy, the timer is run at 2Mhz. At 30.000rpm this relates to 4000 pulses and at 2000 rpm 60.000 pulses:
The measured intervals are stored in an array with moving index, and then averaged when the RPM value is calculated. To limit computation time with the division involved, everything is kept as an integer.
At the TIMER2 update interrupt, the timer is stopped and an ignition pulse is created. Some nop()'s were inserted to ensure the pulse is long enough.
So, this is where the TM1638 comes in. These ICs are available via Chinese webshops and typically combine 8 leds, 8 buttons and 8 segment blocks on a single PCB, for prices around €7-8. Libraries exists for the Arduino, so I adapted it to work on the STM8S.
Periodically, we need to read the setpoint value from the speed control knob, execute the PID code, update the display and read the settings buttons. We use TIMER4 to set flag-variables that signal the main loop to execute certain tasks:
When setPointFlag is set in the code above, the A/D converter reads the voltage from a potentiometer knob:
This value (10 bit) is averaged and rescaled to a range between 0 and 32768 (max rpm).
During testing, we saw that the a sudden change in setpoint caused the spindle to accelerate so hard that it jumped of the table, leading to major mayhem to the cables connected :) So it was changed to "buffer" the setpoint and ramp the real speed towards the setpoint. But only for rising values of the setpoint.
The important part of course is the PI feedback loop.
Because of the very low inertia of the armature, speed can vary very fast, so only a small proportional action can be used. The values of Kp and Ki were determined experimentally by applying a step to the speed setpoint and monitoring the measured RPM. This is the theoretical ideal way to do it... In other words, you'll have to fiddle with the values manually because it is not possible to measure the RPM without delay or apply a good setpoint step (motor reacts too violently).