C program to Control the Speed of a Motor
Here is an outline of a C program to control the speed of a motor.
Note that it is better to use the DBug12 printf function rather than the C
printf function. The reason for this is that, to use the C printf, we would
need to define a putchar() function to tell C how to send a byte to the
screen. It is easier to just use the DBug13 printf, and convert the floating
point number to an integer before printing.
#include "hc12.h"
#include "DBug12.h"
#define TRUE 1
#define FALSE 0
volatile unsigned int period;
volatile int calc_dc_flag;
main()
{
float speed; /* Actual speed, measured using TIC1 */
float desired; /* Desired speed from pot */
float m; /* Slope to calculate desired speed */
float b; /* Intercept to calculate desired speed */
float fdc; /* Fractional duty cycle (0.1 to 1.0) */
float k; /* Control proportionality constant */
int i; /* Temp variable */
/* Setup stuff
* Enable A/D converter, start continuous conversions
* Enable Timer Subsystem, enable TIC1 interrupt,
* Enable RTI interrupt
* Enable PWM Channel 0, set PWPER0 to 249
*/
enable();
PWDTY0 = 124; /* Start with 50 % duty cycle */
/* Wait for 10 seconds (160 RTI periods) for motor to come to speed */
i = 0;
while (i < 160)
{
if (calc_dc_flag)
{
i = i + 1;
calc_dc_flag = FALSE;
}
}
while(TRUE)
{
if (calc_dc_flag)
{
speed = 1.5e6/((float) period);
desired = m * ((float) ADR0H) + b;
fdc = fdc + k * (desired - speed);
if (fdc < 0.1) fdc = 0.1;
if (fdc > 1.0) fdc = 1.0;
PWDTY0 = fdc * (float) (PWPER0 - 1);
calc_dc_flag = FALSE;
DBug12FNP->printf("Desired Speed = %f\n\r",(unsigned int) desired);
DBug12FNP->printf("Actual Speed = %f\n\r",(unsigned int) speed);
}
}
}
@interrupt void rti_isr(void)
{
calc_dc_flag = TRUE;
RTIFLG = 0x80;
}
@interrupt void tic1_isr(void)
{
// Find difference between TC1 now and TC1 last time
period = ...;
TFLG1 = xxxx;
}