music with stepper motors
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.
 
 
 

142 lines
3.0 KiB

#ifndef _STEPPER_H
#define _STEPPER_H
#include <Arduino.h>
#include <Tone.h>
class FrequencyLUT {
public:
FrequencyLUT();
uint16_t* frequencies;
uint16_t& operator[](int);
};
FrequencyLUT::FrequencyLUT() {
int pitch = 24;
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();
protected:
int8_t currentNote;
int dir_pin;
int step_pin;
int enable_pin;
uint8_t multiplicator = 4;
};
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;
private:
unsigned long currentStepMicros;
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() {
digitalWrite(enable_pin, HIGH);
}
void Stepper::playNote(int8_t midi_note) {
currentNote = midi_note;
uint16_t f = frequencies[midi_note];
f *= multiplicator;
while (f > 12000) 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 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::loop() {
if (currentStepMicros == 0) return;
if (micros() - prevStepMicros >= currentStepMicros) {
prevStepMicros += currentStepMicros;
digitalWrite(step_pin, HIGH);
digitalWrite(step_pin, LOW);
}
}
#endif /* _STEPPER_H */