Skip to content

Instantly share code, notes, and snippets.

@mstaflex
Created February 10, 2016 15:05
Show Gist options
  • Save mstaflex/97fe348dd2b5c36eea48 to your computer and use it in GitHub Desktop.
Save mstaflex/97fe348dd2b5c36eea48 to your computer and use it in GitHub Desktop.
C program that lets a connected stepper motor swing back and forth through a run-time defined angle with a run-time defined speed
#define N_EN PORTB.f2
#define TRIS_N_EN TRISB.f2
#define MS1 PORTB.f1
#define TRIS_MS1 TRISB.f1
#define MS2 PORTB.f0
#define TRIS_MS2 TRISB.f0
#define MS3 PORTA.f5
#define TRIS_MS3 TRISA.f5
#define N_RST PORTA.f4
#define TRIS_N_RST TRISA.f4
#define N_SLP PORTA.f3
#define TRIS_N_SLP TRISA.f3
#define STEP PORTA.f2
#define TRIS_STEP TRISA.f2
#define DIR PORTA.f1
#define TRIS_DIR TRISA.f1
#define SWITCH PORTA.f0
#define TRIS_SWITCH TRISA.f0
#define STEP_DIVISOR 16
#define MAX_SPEED 400
#define MIN_SPEED 50
#define DELAY_STEP 300
unsigned short wait = 0;
unsigned short direction = 0;
unsigned int delayCounter = 0;
unsigned int delayValue = 0; // microsteps not included in this value
unsigned int delayCounterMax = 0;
unsigned int stepCounter = 0;
unsigned int stepStart = 0;
unsigned int stepCounterMax = 0;
unsigned short subStepCounter = 0;
unsigned int speed = 80; // in steps pro second
short writeDelayValue = 0;
unsigned int clock = 0;
short stepIncrement = 1;
unsigned short switchLatch = 0;
short buttonClickCounter = 0;
unsigned int buttonClickDelay = 0;
void setMS(short microSteps) {
if ((microSteps == 2) || (microSteps == 8) || (microSteps == 16))
MS1 = 1;
else
MS1 = 0;
if ((microSteps == 4) || (microSteps == 8) || (microSteps == 16))
MS2 = 1;
else
MS2 = 0;
if (microSteps == 16)
MS3 = 1;
else
MS3 = 0;
}
unsigned int calculateDelay(unsigned int velocity) {
unsigned long calc = (1000000L / (unsigned long) velocity);
return (unsigned int) calc;
}
void stepping(unsigned int delayTime) {
unsigned int t = 0;
STEP = 1;
Delay_us(2);
STEP = 0;
for (t=0; t<delayTime; t++)
Delay_ms(1);
}
void main() {
ADCON1 = 0x0f; // disable all analog inputs
TRIS_SWITCH = 1;
TRIS_N_EN = 0;
TRIS_MS1 = 0;
TRIS_MS2 = 0;
TRIS_MS3 = 0;
TRIS_N_RST = 0;
TRIS_N_SLP = 0;
TRIS_STEP = 0;
TRIS_DIR = 0;
N_EN = 0;
setMS(1);
N_RST = 1;
N_SLP = 1;
STEP = 0;
DIR = 1;
T0CON.PSA = 0;
// PreScaler of 000 -> 1/2 => 1us
T0CON.T0PS2 = 0;
T0CON.T0PS1 = 0;
T0CON.T0PS0 = 0;
T0CON.T0CS = 0;
T0CON.T08BIT = 0;
T0CON.TMR0ON = 0; // enabled later
T1CON.RD16 = 1;
T1CON.TMR1ON = 1;
RCON.IPEN = 1; // Int priorities enabled
PIE1.TMR1IE = 1;
IPR1.TMR1IP = 0; // TMR1 gets low priority
INTCON.TMR0IE = 1;
INTCON.GIE = 0; // enaled after setup phase
INTCON.GIEL = 1;
stepCounterMax = EEPROM_Read(0) + (EEPROM_Read(1) << 8);
delayValue = EEPROM_Read(2) + (EEPROM_Read(3) << 8);
stepStart = EEPROM_Read(4) + (EEPROM_Read(5) << 8);
delayCounter = delayValue / STEP_DIVISOR;
// Rotation angle setup
if (!SWITCH) {
stepCounter = 0;
setMS(1);
while (!SWITCH);
while (SWITCH) {
stepCounter++;
stepping(50);
}
stepStart = stepCounter;
EEPROM_Write(4, stepStart);
EEPROM_Write(5, stepStart >> 8);
stepCounter = 0;
while (!SWITCH);
while (SWITCH) {
stepCounter++;
stepping(50);
}
while (!SWITCH);
stepCounterMax = stepCounter;
stepCounter = 0;
EEPROM_Write(0, stepCounterMax);
EEPROM_Write(1, stepCounterMax >> 8);
}
// end rotation angle setup
// going to zero position
N_RST = 0;
Delay_ms(1000);
N_RST = 1;
while (stepCounter++ < stepStart)
stepping(40);
stepCounter = 0;
// end going to zero position
setMS(STEP_DIVISOR);
INTCON.GIE = 1;
T0CON.TMR0ON = 1;
while (1) {
while (!switchLatch && (buttonClickCounter==0)) {
if (SWITCH) break;
speed += stepIncrement;
if (speed > MAX_SPEED)
speed = MIN_SPEED;
delay_ms(15);
delayValue = calculateDelay(speed);
delayCounter = delayValue / STEP_DIVISOR;
writeDelayValue = 1;
}
if (writeDelayValue) {
writeDelayValue = 0;
EEPROM_Write(2, delayValue);
EEPROM_Write(3, delayValue >> 8);
}
}
}
void interrupt_low() {
TMR1H = 0xF8;
TMR1L = 0x2f;
clock++;
PIR1.TMR1IF = 0;
}
void interrupt() {
unsigned int rms = 0xffff - delayCounter;
TMR0H = rms >> 8;
TMR0L = rms;
STEP = 1;
Delay_us(1);
STEP = 0;
subStepCounter++;
if (subStepCounter >= STEP_DIVISOR) {
subStepCounter = 0;
stepCounter++;
}
if (stepCounter > stepCounterMax) {
DIR = (DIR + 1) & 1;
stepCounter = 0;
}
INTCON.TMR0IF = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment