summaryrefslogtreecommitdiff
path: root/tube-rotator/stepper.c
diff options
context:
space:
mode:
Diffstat (limited to 'tube-rotator/stepper.c')
-rw-r--r--tube-rotator/stepper.c97
1 files changed, 87 insertions, 10 deletions
diff --git a/tube-rotator/stepper.c b/tube-rotator/stepper.c
index ff68072..8b718ae 100644
--- a/tube-rotator/stepper.c
+++ b/tube-rotator/stepper.c
@@ -22,18 +22,13 @@
#include <avr/sfr_defs.h>
#include <avr/interrupt.h>
+#include <util/atomic.h>
+#include <math.h>
#include "stepper.h"
uint8_t step_table [] =
{
- /* full steps */
- /* 6, // 0110 */
- /* 5, // 0101 */
- /* 9, // 1001 */
- /* 10, // 1010 */
-
- /* half steps */
2, // 0010
6, // 0110
4, // 0100
@@ -52,20 +47,30 @@ uint8_t step_table [] =
#define LENGTH_STEP_TABLE (sizeof(step_table)/sizeof(uint8_t))
#define STEPPER_OUTPUT_BITMASK (~(0xF << STEPPER_FIRST_BIT ))
+volatile uint16_t target_speed;
+uint16_t current_speed;
+stepper_state_t current_state;
+
void stepper_init(void)
{
+ target_speed = STEPPER_SPEED_DEFAULT;
STEPPER_PORT &= ~(0xF << STEPPER_FIRST_BIT | 1<<STEPPER_ENABLE_A_BIT | 1<<STEPPER_ENABLE_B_BIT);
STEPPER_DDR |= (0xF << STEPPER_FIRST_BIT) | (1<<STEPPER_ENABLE_A_BIT) | (1<<STEPPER_ENABLE_B_BIT);
+ stepper_stop();
}
void stepper_start(void)
{
+ if(current_state == stepper_running) return;
+
+ current_speed = STEPPER_SPEED_MIN;
STEPPER_PORT |= (1<<STEPPER_ENABLE_A_BIT) | (1<<STEPPER_ENABLE_B_BIT);
- TCCR1A = 0; // prescaler 1:256, WGM = 4 (CTC)
- TCCR1B = 1<<WGM12 | 1<<CS12; //
- OCR1A = 20;
TCNT1 = 0;
+ OCR1A = current_speed;
+ TCCR1A = 0; // prescaler 1:64, WGM = 4 (CTC)
+ TCCR1B = 1<<WGM12 | 1<<CS11 | 1<<CS10; //
TIMSK1 = 1<<OCIE1A;
+ current_state = stepper_running;
}
void stepper_stop(void)
@@ -73,6 +78,7 @@ void stepper_stop(void)
STEPPER_PORT &= ~(0xF << STEPPER_FIRST_BIT | 1<<STEPPER_ENABLE_A_BIT | 1<<STEPPER_ENABLE_B_BIT);
TCCR1B = 0; // no clock source
TIMSK1 = 0; // disable timer interrupt
+ current_state = stepper_stopped;
}
static inline void stepper_handle(void)
@@ -84,9 +90,80 @@ static inline void stepper_handle(void)
STEPPER_PORT = (STEPPER_PORT & STEPPER_OUTPUT_BITMASK ) | stepper_output;
step_idx++;
step_idx %= LENGTH_STEP_TABLE;
+
+ if(step_idx != 0 && step_idx % 8) {
+ if(current_speed > target_speed)
+ OCR1A = (uint16_t)((STEPPER_SPEED_CONVERT_VALUE/(--current_speed)) - 1);
+ else if(current_speed < target_speed)
+ OCR1A = (uint16_t)((STEPPER_SPEED_CONVERT_VALUE/(++current_speed)) - 1);
+ }
}
ISR(TIMER1_COMPA_vect)
{
stepper_handle();
}
+
+stepper_state_t stepper_get_state(void)
+{
+ return current_state;
+}
+
+const char* stepper_state_to_string(stepper_state_t state)
+{
+ switch(state) {
+ case stepper_running: return "running";
+ case stepper_stopped: return "stopped";
+ }
+ return "?";
+}
+
+void stepper_set_speed(uint16_t new_speed)
+{
+ if(new_speed >= STEPPER_SPEED_MIN && new_speed <= STEPPER_SPEED_MAX) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ target_speed = new_speed;
+ }
+ }
+}
+
+void stepper_inc_speed(void)
+{
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ target_speed = (target_speed >= STEPPER_SPEED_MAX) ? STEPPER_SPEED_MAX : target_speed + 1;
+ }
+}
+
+void stepper_dec_speed(void)
+{
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ target_speed = (target_speed <= STEPPER_SPEED_MIN) ? STEPPER_SPEED_MIN : target_speed - 1;
+ }
+}
+
+uint16_t stepper_get_speed(void)
+{
+ return target_speed;
+}
+
+void stepper_set_speed_rpm(uint8_t new_rpm)
+{
+ stepper_set_speed( (uint16_t)lround( ( (double)(64.0 * 800.0 * (double)STEPPER_SPEED_CONVERT_VALUE) / (double)(60.0 * (double)F_CPU) ) * (double)new_rpm) );
+}
+
+uint8_t stepper_get_speed_rpm(void)
+{
+ return (uint8_t)lround( ( (double)(60.0 * (double)F_CPU) / (double)(64.0 * 800.0 * (double)STEPPER_SPEED_CONVERT_VALUE) ) * (double)(target_speed) );
+}
+
+void stepper_inc_speed_rpm(void)
+{
+ uint8_t rpm = stepper_get_speed_rpm();
+ stepper_set_speed_rpm((rpm >= 255) ? 255 : rpm+1);
+}
+
+void stepper_dec_speed_rpm(void)
+{
+ uint8_t rpm = stepper_get_speed_rpm();
+ stepper_set_speed_rpm((rpm <= 1) ? 1 : rpm-1);
+}