This code uses pulses to control a motor to very slow speeds. This code is for a 12f683 pic microcontroller.
//Motor Controller
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
#include <stdint.h> /* For uint8_t definition */
#include <stdlib.h>
//#fuses NOMCLR,NOPROTECT,NOWDT,INTRC
#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
void init()
{
//Configure GPIO Port
//ANSEL = 0b00000001; //Configure GPIO pins as digital GP0 set to analog
ANSEL = 0b01111000; //Configure GPIO pins as digital, GP4 Analog
TRISIO = 0b11011000; //Set GP1,GP2,GP4,GP5 as outputs
WPU = 0x00; //Disable weak pullups
//Configuer AD Convertor
ADCON0 = 0b10001101; //AD Set up
ADRESH = 0x00; //Init the AD Register
//Configure Comparator
CMCON0 = 0xFF; // Comparator is turned off
CMCON1 = 0x00; // Comparator is turned off
//Interrupt configuration
INTCON = 0x00; //Disable all interrupts
OPTION_REGbits.nGPPU = 0;
WPU = 1<<1; //Enable weak pullups on GP1
//Configuer AD Convertor
//ADCON0 = 0x00; //AD disabled
//ADRESH = 0x00; //Init the AD Register
//Configuer AD Convertor
}
int read_v()
// Read voltage from input 0
{
int val;
ADCON0bits.GO=1;
while(ADCON0bits.nDONE);
val = (ADRESH<<2)+(ADRESL>>6);
return val;
}
void vdelay(int n)
{
int i;
for (i=0;i<n;i++)
{
__delay_us(100);
}
}
void pwgen(int pw)
// Send pulse width
{
int i, n=4; // Standard time interval of 400 microseconds
if (pw>56) // Switch over to max speed
{
pw = 255;
n=1;
}
if (pw<16) // May not have enough drive for the motor
{ // at low speeds, so switch to longer pulses
n = 10;// 100 microseconds
}
for (i=0;i<255;i++)
{
if (i<pw) // Turn motor on for a fraction of the time
{
GPIO = 0b00000010; // Motor is connected to output 2
vdelay(n);
}
if (i>pw)
{
GPIO = 0b00000000;
vdelay(n);
}
}
}
void main()
{
uint8_t db_cnt;
int v;
init();
GPIO = 0b00000000;
while(1)
{
v = read_v();
pwgen(v<<2); // Voltage seems to read between 0 and 15
}
}