You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.0 KiB
177 lines
4.0 KiB
#ifndef _STEPPER_H
|
|
#define _STEPPER_H
|
|
|
|
#include <Arduino.h>
|
|
#include <Tone.h>
|
|
//#include <TimerOne.h>
|
|
|
|
class FrequencyLUT {
|
|
public:
|
|
FrequencyLUT();
|
|
uint16_t* frequencies;
|
|
uint16_t& operator[](int);
|
|
};
|
|
|
|
FrequencyLUT::FrequencyLUT() {
|
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
|
int pitch = 24;
|
|
#elif defined(__AVR_ATmega328P__)
|
|
int pitch = 0;
|
|
#endif
|
|
frequencies = malloc(128*sizeof(uint16_t));
|
|
for (int d=0; d<128; d++) {
|
|
frequencies[d] = pow(2.0, (d-69.0+pitch)/12.0) * 440.0;
|
|
}
|
|
}
|
|
|
|
uint16_t& FrequencyLUT::operator[](int index) {
|
|
return frequencies[index];
|
|
}
|
|
|
|
FrequencyLUT frequencies;
|
|
|
|
class Stepper {
|
|
public:
|
|
virtual void begin(int dir_pin, int step_pin, int enable_pin);
|
|
virtual void playTone(uint16_t freq) = 0;
|
|
virtual void playNote(int8_t midi_note);
|
|
virtual void bend(int value);
|
|
virtual void loop();
|
|
virtual void stopTone() = 0;
|
|
void enable();
|
|
void disable();
|
|
void setMaxFrequency(uint16_t max_freq);
|
|
protected:
|
|
int8_t currentNote;
|
|
int dir_pin;
|
|
int step_pin;
|
|
int enable_pin;
|
|
uint8_t multiplicator = 4;
|
|
uint16_t maxFrequency;
|
|
};
|
|
|
|
class TimerStepper : public Stepper {
|
|
public:
|
|
void begin(int dir_pin, int step_pin, int enable_pin) override;
|
|
void playTone(uint16_t freq) override;
|
|
void stopTone() override;
|
|
void loop() {};
|
|
private:
|
|
Tone tone;
|
|
};
|
|
|
|
class LoopStepper : public Stepper {
|
|
public:
|
|
void begin(int dir_pin, int step_pin, int enable_pin) override;
|
|
void playTone(uint16_t freq) override;
|
|
void stopTone() override;
|
|
void loop() override;
|
|
void setMaxPosition(int pos);
|
|
private:
|
|
unsigned long currentStepMicros = 0;
|
|
unsigned long currentPosition;
|
|
unsigned long maxPosition;
|
|
bool direction;
|
|
unsigned long prevStepMicros;
|
|
};
|
|
|
|
void Stepper::begin(int dir_pin, int step_pin, int enable_pin) {
|
|
this->dir_pin = dir_pin;
|
|
this->step_pin = step_pin;
|
|
this->enable_pin = enable_pin;
|
|
|
|
pinMode(dir_pin, OUTPUT);
|
|
pinMode(step_pin, OUTPUT);
|
|
pinMode(enable_pin, OUTPUT);
|
|
|
|
digitalWrite(enable_pin, HIGH);
|
|
}
|
|
|
|
void Stepper::enable() {
|
|
digitalWrite(enable_pin, LOW);
|
|
}
|
|
|
|
void Stepper::disable() {
|
|
stopTone();
|
|
digitalWrite(enable_pin, HIGH);
|
|
}
|
|
|
|
void Stepper::playNote(int8_t midi_note) {
|
|
currentNote = midi_note;
|
|
uint16_t f = frequencies[midi_note];
|
|
f *= multiplicator;
|
|
while (f > maxFrequency) f/=2;
|
|
playTone(f);
|
|
}
|
|
|
|
void Stepper::bend(int value) {
|
|
uint16_t f = frequencies[currentNote];
|
|
uint16_t f_b = f * pow(2, (double)value/(4096.0*12));
|
|
playTone(f_b);
|
|
}
|
|
|
|
void Stepper::setMaxFrequency(uint16_t max_freq) {
|
|
maxFrequency = max_freq;
|
|
}
|
|
|
|
void TimerStepper::begin(int dir_pin, int step_pin, int enable_pin) {
|
|
Stepper::begin(dir_pin, step_pin, enable_pin);
|
|
tone.begin(step_pin);
|
|
}
|
|
|
|
void TimerStepper::playTone(uint16_t freq) {
|
|
enable();
|
|
tone.play(freq);
|
|
}
|
|
|
|
void TimerStepper::stopTone() {
|
|
currentNote = 0;
|
|
tone.stop();
|
|
}
|
|
|
|
void LoopStepper::begin(int dir_pin, int step_pin, int enable_pin) {
|
|
Stepper::begin(dir_pin, step_pin, enable_pin);
|
|
multiplicator = 1;
|
|
}
|
|
|
|
void LoopStepper::playTone(uint16_t freq) {
|
|
enable();
|
|
prevStepMicros = micros();
|
|
currentStepMicros = 1000000UL / freq;
|
|
}
|
|
|
|
void LoopStepper::stopTone() {
|
|
currentStepMicros = 0;
|
|
}
|
|
|
|
void LoopStepper::setMaxPosition(int pos) {
|
|
maxPosition = 2*pos;
|
|
currentPosition = 2*pos;
|
|
currentStepMicros = 4545UL;
|
|
direction = 1;
|
|
prevStepMicros = micros();
|
|
while (currentPosition > 0) loop();
|
|
while (currentPosition != 2) loop();
|
|
currentPosition = 0; maxPosition -=4;
|
|
direction = 0;
|
|
currentStepMicros = 0;
|
|
}
|
|
|
|
void LoopStepper::loop() {
|
|
if (currentStepMicros == 0) return;
|
|
|
|
if (micros() - prevStepMicros >= currentStepMicros) {
|
|
prevStepMicros += currentStepMicros;
|
|
digitalWrite(step_pin, !digitalRead(step_pin));
|
|
// digitalWrite(step_pin, HIGH);
|
|
// digitalWrite(step_pin, LOW);
|
|
if (direction == 0) currentPosition++;
|
|
else currentPosition--;
|
|
if (currentPosition >= maxPosition) direction = 1;
|
|
if (currentPosition <= 0) direction = 0;
|
|
digitalWrite(dir_pin, direction);
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* _STEPPER_H */
|
|
|