Implement the stepper motor stuff, start work on UART interaction
This commit is contained in:
parent
a70bb3d733
commit
c080c2aa2a
|
@ -4,6 +4,34 @@
|
||||||
|
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
|
|
||||||
|
enum direction {
|
||||||
|
DIR_CLOCKWISE,
|
||||||
|
DIR_COUNTERCLOCKWISE
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile struct {
|
||||||
|
bool active;
|
||||||
|
bool done;
|
||||||
|
int step_count;
|
||||||
|
enum direction dir;
|
||||||
|
int counter;
|
||||||
|
int increment;
|
||||||
|
int threshold;
|
||||||
|
int phase;
|
||||||
|
} stepper = {
|
||||||
|
true, false, 1000000, DIR_CLOCKWISE, 0, 1, 2, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile struct {
|
||||||
|
bool active;
|
||||||
|
bool done;
|
||||||
|
enum direction dir;
|
||||||
|
int count;
|
||||||
|
int tocount;
|
||||||
|
} brushed = {
|
||||||
|
false, false, DIR_CLOCKWISE, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
rcc_periph_clock_enable(RCC_GPIOA);
|
rcc_periph_clock_enable(RCC_GPIOA);
|
||||||
rcc_periph_clock_enable(RCC_GPIOB);
|
rcc_periph_clock_enable(RCC_GPIOB);
|
||||||
|
@ -46,21 +74,207 @@ int main(void) {
|
||||||
systick_counter_disable();
|
systick_counter_disable();
|
||||||
|
|
||||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||||
systick_set_reload(rcc_ahb_frequency/100000-1);
|
systick_set_reload(rcc_ahb_frequency/1000-1);
|
||||||
systick_clear();
|
systick_clear();
|
||||||
|
|
||||||
systick_interrupt_enable();
|
systick_interrupt_enable();
|
||||||
systick_counter_enable();
|
systick_counter_enable();
|
||||||
|
|
||||||
|
int32_t val = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (stepper.done) {
|
||||||
|
stepper.done = false;
|
||||||
|
usart_send_blocking(USART2, 's');
|
||||||
|
}
|
||||||
|
if (brushed.done) {
|
||||||
|
brushed.done = false;
|
||||||
|
usart_send_blocking(USART2, 'r');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((USART_ISR(USART2) & USART_ISR_RXNE) != 0) {
|
if ((USART_ISR(USART2) & USART_ISR_RXNE) != 0) {
|
||||||
// TODO process byte
|
// TODO process byte
|
||||||
uint8_t rx = usart_recv(USART2);
|
uint8_t rx = usart_recv(USART2);
|
||||||
usart_send_blocking(USART2, rx);
|
|
||||||
|
// if it's a hexadecimal echo back and append it to val
|
||||||
|
if ((rx >= '0') && (rx <= '9')) {
|
||||||
|
usart_send_blocking(USART2, rx); // echo back
|
||||||
|
val <<= 4;
|
||||||
|
val |= (rx - '0');
|
||||||
|
} else if ((rx >= 'a') && (rx <= 'f')) {
|
||||||
|
usart_send_blocking(USART2, rx); // echo back
|
||||||
|
val <<= 4;
|
||||||
|
val |= (rx - 'a' + 10);
|
||||||
|
} else if ((rx >= 'A') && (rx <= 'F')) {
|
||||||
|
usart_send_blocking(USART2, rx); // echo back
|
||||||
|
val <<= 4;
|
||||||
|
val |= (rx - 'A' + 10);
|
||||||
|
} else {
|
||||||
|
switch (rx) {
|
||||||
|
case 's': // get status
|
||||||
|
if (stepper.active) {
|
||||||
|
usart_send_blocking(USART2, '!');
|
||||||
|
} else {
|
||||||
|
usart_send_blocking(USART2, '@');
|
||||||
|
}
|
||||||
|
if (brushed.active) {
|
||||||
|
usart_send_blocking(USART2, '#');
|
||||||
|
} else {
|
||||||
|
usart_send_blocking(USART2, '$');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'w': // start stepper
|
||||||
|
usart_send_blocking(USART2, '!');
|
||||||
|
stepper.active = true;
|
||||||
|
break;
|
||||||
|
case 'W': // stop stepper
|
||||||
|
stepper.active = false;
|
||||||
|
usart_send_blocking(USART2, '@');
|
||||||
|
break;
|
||||||
|
case 'r': // start brushed motor
|
||||||
|
usart_send_blocking(USART2, '#');
|
||||||
|
brushed.count = 0;
|
||||||
|
brushed.active = true;
|
||||||
|
break;
|
||||||
|
case 'R': // stop brushed motor
|
||||||
|
usart_send_blocking(USART2, '$');
|
||||||
|
brushed.count = 0;
|
||||||
|
brushed.active = false;
|
||||||
|
break;
|
||||||
|
case 't': // read stepper counter
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'T': // write stepper counter
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'y': // read stepper increment
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'Y': // write stepper increment
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'u': // read stepper threshold
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'U': // write stepper threshold
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'i': // set stepper direction to clockwise
|
||||||
|
stepper.dir = DIR_CLOCKWISE;
|
||||||
|
usart_send_blocking(USART2, 'i');
|
||||||
|
break;
|
||||||
|
case 'I': // set stepper direction to counterclockwise
|
||||||
|
stepper.dir = DIR_COUNTERCLOCKWISE;
|
||||||
|
usart_send_blocking(USART2, 'I');
|
||||||
|
break;
|
||||||
|
case 'o': // write brushed counter
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'O': // read brushed counter
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 'p': // set brushed direction to clockwise
|
||||||
|
brushed.dir = DIR_CLOCKWISE;
|
||||||
|
usart_send_blocking(USART2, 'p');
|
||||||
|
break;
|
||||||
|
case 'P': // set brushed direction to counterclockwise
|
||||||
|
brushed.dir = DIR_COUNTERCLOCKWISE;
|
||||||
|
usart_send_blocking(USART2, 'P');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysTick_Handler(void);
|
const struct {
|
||||||
void SysTick_Handler(void) {
|
bool active;
|
||||||
|
bool positive;
|
||||||
|
} phase_lut[][2] = {
|
||||||
|
{{true, true}, {false, true}}, // A+
|
||||||
|
//{{true, true}, {true, true}}, // A+, B+
|
||||||
|
{{false, true}, {true, true}}, // B+
|
||||||
|
//{{true, false}, {true, true}}, // A-, B+
|
||||||
|
{{true, false}, {false, true}}, // A-
|
||||||
|
//{{true, false}, {true, false}}, // A-, B-
|
||||||
|
{{false, false}, {true, false}}, // B-
|
||||||
|
//{{true, true}, {true, false}}, // A+, B-
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void sys_tick_handler(void);
|
||||||
|
void sys_tick_handler(void) {
|
||||||
|
if (!stepper.active) {
|
||||||
|
gpio_clear(GPIOA, GPIO5|GPIO6|GPIO7);
|
||||||
|
gpio_clear(GPIOB, GPIO1);
|
||||||
|
} else {
|
||||||
|
stepper.counter += stepper.increment;
|
||||||
|
if (stepper.counter >= stepper.threshold) {
|
||||||
|
--stepper.step_count;
|
||||||
|
stepper.counter -= stepper.threshold;
|
||||||
|
if (stepper.dir == DIR_CLOCKWISE) {
|
||||||
|
++stepper.phase;
|
||||||
|
} else {
|
||||||
|
--stepper.phase;
|
||||||
|
}
|
||||||
|
if (stepper.phase < 0) {
|
||||||
|
stepper.phase = 3;
|
||||||
|
}
|
||||||
|
if (stepper.phase >= 4) {
|
||||||
|
stepper.phase = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stepper.step_count <= 0) {
|
||||||
|
stepper.counter = 0;
|
||||||
|
stepper.active = false;
|
||||||
|
stepper.done = true;
|
||||||
|
// power down stepper motor; TODO maybe lock its position?
|
||||||
|
gpio_clear(GPIOA, GPIO5|GPIO6|GPIO7);
|
||||||
|
gpio_clear(GPIOB, GPIO1);
|
||||||
|
} else {
|
||||||
|
// write to GPIO pins
|
||||||
|
// TODO maybe use a set of OR/AND masks instead? this works but probably
|
||||||
|
// isn't constant time
|
||||||
|
if (phase_lut[stepper.phase][0].active) {
|
||||||
|
if (phase_lut[stepper.phase][0].positive) {
|
||||||
|
gpio_clear(GPIOA, GPIO6);
|
||||||
|
gpio_set(GPIOB, GPIO1);
|
||||||
|
} else {
|
||||||
|
gpio_set(GPIOA, GPIO6);
|
||||||
|
gpio_clear(GPIOB, GPIO1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gpio_clear(GPIOA, GPIO6);
|
||||||
|
gpio_clear(GPIOB, GPIO1);
|
||||||
|
}
|
||||||
|
if (phase_lut[stepper.phase][1].active) {
|
||||||
|
if (phase_lut[stepper.phase][1].positive) {
|
||||||
|
gpio_clear(GPIOA, GPIO7);
|
||||||
|
gpio_set(GPIOA, GPIO5);
|
||||||
|
} else {
|
||||||
|
gpio_set(GPIOA, GPIO7);
|
||||||
|
gpio_clear(GPIOA, GPIO5);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gpio_clear(GPIOA, GPIO7);
|
||||||
|
gpio_clear(GPIOA, GPIO5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brushed.active) {
|
||||||
|
if (brushed.count == 0) {
|
||||||
|
// TODO toggle pins
|
||||||
|
}
|
||||||
|
++brushed.count;
|
||||||
|
if (brushed.count >= brushed.tocount) {
|
||||||
|
// TODO toggle pins
|
||||||
|
brushed.count = 0;
|
||||||
|
brushed.active = false;
|
||||||
|
brushed.done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check limit switches
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue