Hi,
Thanks for the "numbers" which give me some food for thought, although not many definitive answers yet. The "ringing" at about 3 Hz suggests that the feedback loop is potentially unstable at this frequency, probably due mainly to the inertia of the motor, which is not very dependent on the rotational speed. To control this requires the program to process a "large" number of samples during each (ring) cycle, perhaps at least 10. Thus my "ballpark" target would be for each loop around the program to take no more than 30 ms.
At a minimum target shaft speed of 3000 rpm, a single revolution takes 20 ms, which is already a large proportion of the "available" processing time. But we need to consider how long PULSIN takes to execute, for example with a 10% Duty Cycle Pulse, as might occur when a magnet is close to a Hall sensor. PULSIN first "looks" for the leading edge of a pulse (which can be selected as either rising or falling) and then "counts" the time until the trailing (falling or rising) edge is encountered. But if we are "unlucky" a leading edge may have occurred just before the instruction starts looking, so it may need to wait for almost a full revolution of the shaft before the measurement can even start
**. Thus in this example it may be necessary to wait for 1.1 revolutions (22 ms) to measure the Pulse or 1.9 revolutions (38 ms) to measure the Gap between pulses (which is the more normal method to measure a single rotation). In both cases the actual execution time of the instruction can "randomly" vary by the duration of a full revolution, i.e. 20 ms at 3,000 rpm, but the program cannot "know" how long it needed to pause (i.e. only the pulse width is returned, not the length of the "wait" for it to start).
An alternative method could be to use Interrupts with a configurable Timer/Counter, but these need to be Hardware-based and only the X2, not the M2, chips have these. If you were using a 20M2 then it might be worthwhile to upgrade to a 20X2, but from an 08M2 seems a step too far.
Actually, all the M2 chips do have a "Timer1 Gate" Hardware module which might be able to perform this function, but it's not supported by the PICaxe Operating System and actually conflicts with it's operation, so this could involve some very "advanced" programming methods. Therefore, my proposal is to begin by using a second PICaxe 08M2, basically to emulate the operation of the original Tacho Generator. Later, if this works well, then we could consider merging the two programs into a single 08M2, if desired. But an advantage of the second 08M2 is that the Tacho program can effectively synchronise itself to the revolutions of the motor shaft, so we don't need to worry about randomly changing time delays being introduced into the main program.
Here is an (untested) program to emulate the previous Tacho, using a separate 08M2. It connects to a rotation sensor such as a (digital) Hall Magnetic device via Pin C.3 and (for this example) detects the duration of a full revolution by adding the High Pulse time to the Low pulse time
*. It then uses division to calculate the equivalent frequency (or rpm) which is converted to PWM to output on Pin C.2. The PWM needs to be Low-Pass filtered via a resistor (typically 10k) from C.2 to C.1, and a capacitor (typically 1uF) from C.1 to ground This should give an analogue swing between 0 and Vcc (5v), that can be measured (for testing) via the ADC on that pin. This example uses PICaxe's native division operator (
/) which can achieve a resolution/accuracy of about +/-1% by dividing a "large" Word value (e.g. around 60,000) by a large Byte value (e.g. around 250) to give a similar-valued Byte result. If higher accuracy is needed, many a years ago I developed a subroutine to divide a "Double Word" by a single-Word to give a full Word result, which executes in about 6 ms with a 32 MHz clock.
*EDIT: Note that the code cannot measure a
consecutive Pulse and Gap (because the Gap must have already started when the PULSEIN command ends), so this double-reading method adds at least another full revolution to the execution time. But the problem with a single Pulse or Gap measurement is that it may vary with any differences in the Rise and Fall times (or delays), or the widths of the pulses.
Code:
; Tachometer Emulator
#picaxe 08m2
#no_data
setfreq m32
#terminal 38400
symbol pulse = C.3 ; Pulse input
symbol pwmpin = C.2 ; PWM (DAC) Output
symbol tachopin = C.1 ; Filtered Analogue Output
symbol hipulse = w2
symbol lopulse = w3
symbol onerev = w4 ; Period of one revolution of shaft (1.25us units)
symbol duty = w5
do
pulsin pulse,0,lopulse
pulsin pulse,1,hipulse
; lopulse = 14400 : hipulse = 1600 ; sample values for 3000 rpm (uncomment when simulating)
onerev = hipulse + lopulse ; 16000 for 20ms = 3000 rpm
w1 = onerev / 4 * 5
sertxd(cr,lf,#w1,"us=")
onerev = onerev ** 1024 ; scale down for division
duty = 62500 / onerev ; 256 for 25% of full-scale frequency
pwmout pwmpin,255,duty
; readadc10 tachopin,duty ; Test the analogue output (uncomment when hardware running)
w1 = duty * 12 ; convert to rpm
sertxd(#w1,"rpm")
loop
**ADDENDUM: Attaching additional magnet(s) to the shaft is unlikely to be helpful. Remember that the Hall sensors (or equivalent optical devices) are fundamentally analogue components, even if they contain a threshold detector to deliver a digital output signal. Any additional magnet is unlikely to have exactly the same field strength or perfect positioning, so the detected pulses are very unlikely to be identical and/or be spaced exactly symmetrically around the shaft. An optical system might be more practical, because one might stick "stripes" of (say) 1cm or 1 inch wide tape around the shaft/collet, and detect the pulses generated by the width of the bands (not the gaps between them). But optical transmitters and receivers (e.g. LEDs) must still have a finite size, so their resolution/accuracy will always be limited, and ultimately may be compromised when the stripes become (differentially) "dirty".
Cheers, Alan.