Hello Kris,
I will make some assumptions about what you might want to achieve, and look at an approach for doing so.
Firstly, stepper motors are capable of both position control and speed control without the need for feedback. Since you are using the L297 device, I will assume that you have interest only in speed control of the motor.
Since you wish to use the ADC to control the motor speed, I will assume 10-bit mode, with an output value of 0- 1023, which will linearly control the speed of the motor. If each control step were to represent an increment of 0.1 rpm, this would give a maximum speed of 409.5 rpm.
It would seem that the L297 requires four clock pulses for each full step of the motor, and with 48 steps per revolution of the motor, this would require 192 clock pulses per revolution. At the maximum speed, the clock rate would be 1310 Hz I do not know whether this is too fast for the stepper you are using - it will depend on the inertia of the load, in addition to the inertia of the motor rotor - but this might be a reasonable experimental starting point.
In order to achieve linear control of the clock frequency, I am proposing a method where the 10-bit ADC reading is periodically added to a 16-bit accumulating counter, and the MSB of the counter determines the output clock state at a selected GPIO pin. To achieve the required output clock rate, the accumulating register should be updated every 47.7 microseconds. This would be controlled within a TPM module channel ISR (software output compare mode).
With this method, we now come to a time critical process. The number of CPU cycles available for the completion of ISR code will be determined by the bus clock. For a 8 MHz clock, the number of bus cycles between updates is 381. The ISR must be completed in substantially less than this number of cycles. I am not sure whether this is feasible, but if so is likely to require the use of tight assembly code. A bus clock of 16 MHz would give 762 cycles between updates, and is a little more comfortable.
The following sequence of events would need to occur within the channel ISR code:
- Clear TPM channel flag.
- Add 381 (or 762) to current channel register value, for next compare.
- Read previous ADC reading, and add to accumulating register.
- Start new ADC reading.
- Test MSB of register, and set/clear port pin.
Maybe something like the following C code would work.
#define INCR_VAL 762 // 16 MHz bus assumed#define ADC_CHAN 1 // ADC channel 1#define STEP_CLK PTAD_PTAD0 // GPIO pininterrupt void ISR_TPM1C0( void){ static word accum = 0; TPM1C0SC_CHOF = 0; // Clear flag TPM1C0V += INCR_VAL; // Next compare value accum += ADCR; // Update accumulation count ADCSC1 = ADC_CHAN; // Start next conversion if (accum & 0x8000) // Test MSB STEP_CLK = 1; else STEP_CLK = 0;}
You will also need to initialise the TPM module and the ADC module.
I guess that there are other possible approaches that would have less critical timing, but would require more complex calculations to convert the ADC reading to an equivalent period value for a TPM channel. In this case the step clock would appear at the TPM channel pin.
Regards,
Mac