Because the ET227 transistor acts as a current limiter, the motor current waveform has flat tops at the level set by the DAC voltage. However, the current depends strongly on the temperature of all those transistor junctions, with some commutation noise mixed in for good measure, so the firmware must measure the actual current to know what’s going on out there.
Here’s one way to pull that off:

The upper waveform shows the motor current sporting flat tops at 650 mA.
The lower waveform marks the current measurement routine, with samples taken just before the falling edge of the first nine pulses. The (manually tweaked) delay between the samples forces them to span one complete cycle of the waveform, but they’re not synchronized to the power line. Remember that the motor runs from a full wave rectifier, so each “cycle” in that waveform is half of a normal power line cycle.
Given an array containing those nine samples, the routine must return the maximum value of the waveform, ignoring the little glitch at the start of the flat top and taking into consideration that the waveform won’t have a flat top (or much of a glitch) when the current “limit” exceeds the maximum motor current.
After a bit of fumbling around with the scope and software, the routine goes like this:
- Collect samples during one current cycle
- Sort in descending order
- Ignore highest sample
- Return average of next two highest samples
Given that the array has only nine samples, I used a quick-and-dirty bubble sort. The runt pulse at the end of the series in the bottom waveform brackets the sort routine, so it’s not a real time killer.
Seeing as how this is one of the very few occasions I’ve had to sort anything, I wheeled out the classic XOR method of exchanging the entries. Go ahead, time XOR against swapping through a temporary variable; it surely doesn’t make any difference at all on an 8-bit microcontroller.
The sampling code, with all the tracing stuff commented out:
//------------------ // Sample current along AC waveform to find maximum value // this is blocking, so don't call it every time around the main loop! #define NUM_I_SAMPLES 9 unsigned int SampleCurrent(byte PinNum) { unsigned int Samples[NUM_I_SAMPLES]; unsigned int AvgSample; byte i,j; // digitalWrite(PIN_SYNC,HIGH); for (i=0; i < NUM_I_SAMPLES; i++) { // collect samples // digitalWrite(PIN_SYNC,HIGH); Samples[i] = ReadAI(PinNum); // digitalWrite(PIN_SYNC,LOW); delayMicroseconds(640); } // digitalWrite(PIN_SYNC,LOW); // digitalWrite(PIN_SYNC,HIGH); // mark start of sorting for (i=0; i < (NUM_I_SAMPLES - 1); i++) for (j=0 ; j < (NUM_I_SAMPLES - 1 - i); j++) if (Samples[j] < Samples[j+1]) { Samples[j] ^= Samples[j+1]; // swap entries! Samples[j+1] ^= Samples[j]; Samples[j] ^= Samples[j+1]; } // digitalWrite(PIN_SYNC,LOW); // mark end of sorting // printf("Samples: "); // for (i=0; i < NUM_I_SAMPLES; i++) // printf("%5d,",Samples[i]); AvgSample = (Samples[1] + Samples[2])/2; // discard highest sample // printf(" [%5d]\r\n",AvgSample); return AvgSample; }
If you are looking for the peak, could you time it off of a zero crossing? That is, detect a line voltage crossing, wait 1/4 cycle, then grab a sample. Or maybe take several samples and average them to cut the noise. That should tell you what current is flowing at the peak of the AC sine wave.
I’ve used the trick of feeding raw AC into a PIC’s digital input using a huge current-limiting resistor and some clamp diodes, when wanting a quick and dirty zero crossing detector. Kind of a kludge, but Microchip AN521, “Interfacing to AC Power Lines” gives it the thumbs up so who am I to complain :-)
I’ve been resolutely not building a zero-crossing detector, even though there’s one unused screw terminal in the back for the hot bridge lead. The gotcha is the power dissipation required to wrestle 120 VAC down to 2 V & 10 mA in the isolator: 12 kΩ / 1.2 W, more or less. I have power to burn, but that’s a big resistor; usually, there’s a step-down transformer available!
Then I realized that I’d be taking a few samples anyway, so not bothering with the synchronization might not matter. The sampling routine blocks for 9 ms, which hasn’t been a problem yet; if I really need a timer & interrupt handler ticking along in the background, a zero-crossing pulse starts looking downright attractive.
More firmware twiddling ahead…
[Shudders]
How about a fast photodiode staring into a neon lamp wired across line as a zero-crossing detector? :)
I hate neon lamps, because they actually go bad on the shelf, but that’s likely the least-worst alternative out there. I’m sure something involving epoxy would work well enough.
Thanks for the idea…
Do they? Other than the 85Kr ones decaying?
All the myriad neon bulbs in ancient power strips, instruments, and whatnot around here flicker cheerfully at me, even if they haven’t been used in a long, long time. Maybe it’s those ancient resistors crapping out, but …
FWIW, I knew the flicker started when the helium leaked away through the glass, like it does in old helium-neon lasers, but the ever-dependable Wikipedia sez the bulbs contain 0.5% argon. Yet another example of something I know that’s just not so. [sigh]