It works!
Didn’t have much time to work on it today, but I managed to merge the 2 programs into one and added the switch to select which one to run.
I assembled everything quickly and tested it, and it works. But if it accelerates too fast the motor stalls, I’ll try to increase the motor current or get a 24v psu.
But I messed up the gear ratio, instead of 5:1 I made an 8:1 reduction, I’ll print new gears and see if it will work better. Since stepper motors have higher torque at lower speeds it could work out better.
You can get some cheap acceleration limiting by keeping the previous speed in a global variable. Outside the loop/setup, you would do this:
int prevValue= 0;
const int maxValChange = 50;
In the loop, you would do something like this:
int value = analogRead(POTI);
value = std::min(value, prevValue + maxValChange); //don't speed up too quickly
value = std::max(value, prevValue - maxValChange); // don't slow down too quickly
prevValue = value; // store for next loop
...
If you had a value of 0, and then 155, the value would go 0, then 50, then 100, then 155. You can adjust the maxValChange to make it more responsive, or slower. You can also choose a different value for the max as the min, so it could stop faster.
int d = map(value, 0, 1023, 1000, 10); //map input to delay time
d = max(d, prev_d - MAXACC); //limit acceleration
prev_d = d; //store delay for next loop
digitalWrite(STEP, HIGH);
delayMicroseconds(d);
digitalWrite(STEP, LOW);
Even if I set MAXACC to 1 it doesn’t seem to limit acceleration.
Note that I only care about positive acceleration, meaning d getting lower, when the pedal gets released I want it to stop instantly, so no deceleration limiting.
I’m not sure what this std:: is supposed to do, is it neccessary for it to work?
It does compile, and shouldn’t need any other libraries, min/max/constrain are all included by default.
I think I have to test the code with a simpler example to make sure it works, or figure out why it doesn’t…
Because in the single stitch code I already have an acceleration ramp:
for(int i=0; i<4000; i++) {
if (i < 100) {
d = 1260-i*12;
}
This decreases the delay by 12 for every step (or rather 24, since delayMicroseconds(d) gets called twice). But even with MAXACC set all the way down to 1 it doesn’t change the behavior in the slightest bit… So something has to be wrong with my code, I just haven’t found it yet.
I’ll try to do some tests with the serial plotter, recording d before and after constraining it should point me in the right direction…
Also, to cycle back to the beginning of this thread, I just found the tone() function, which does the opposite of PWM. It allows to set a frequency with which an output pin gets switched, with a fixed 50% duty cycle.
Ok, my sanity is restored. It turns out the code was working, but even a maximum acceleration of 1 was too much. Because my problems were physical; I forgott to decouple the motor of the sewing machine, which was roughly doubling the load on the stepper.
Everything works, the pedal pieces are printing right now, and I can go to bed
If anyone is interested in the finished code, here it is:
#define DIR 5
#define STEP 6
#define SINGLE 7
#define POTI 14
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
const int MAXACC = 1;
int prev_d = 1000;
bool ISPRESSED = false;
int d = 1000;
int value = 0;
void setup() {
pinMode(DIR, OUTPUT);
pinMode(STEP, OUTPUT);
pinMode(SINGLE, INPUT);
digitalWrite(DIR, HIGH);
sbi(ADCSRA, 1);
cbi(ADCSRA, 1);
cbi(ADCSRA, 0); //these 3 lines increase analogRead() speed
}
void loop() {
if (digitalRead(SINGLE)) { //single stitch mode
if ((ISPRESSED == false) && (analogRead(POTI) > 200)) {
ISPRESSED = true;
for(int i=0; i<4000; i++) {
if (i < 400) {
d = 1300-i*3; //accelerate
}
else {
if (i<3900) {
d = 100;
}
else {
d = 1300-((4000-i)*12); //decelerate
}
}
digitalWrite(STEP, HIGH);
delayMicroseconds(d);
digitalWrite(STEP, LOW);
delayMicroseconds(d);
}
}
if (analogRead(POTI) < 50) {
ISPRESSED = false;
}
}
else { //continuous stitch, variable speed mode
value = analogRead(POTI);
d = map(value, 0, 1023, 500, 5); //map input to delay time
d = max(d, prev_d-MAXACC); //limit acceleration
prev_d = d; //store delay for next loop
if (value >= 50){
digitalWrite(STEP, HIGH);
delayMicroseconds(d);
digitalWrite(STEP, LOW);
}
else {
delay(10);
}
}
}
Late to the party here, but if all you want to do is control speed of a stepper, this device, available for about $15 will do it for you- just connect the step/dir/enable to the motor driver, hook up power, and you’re good to go:
This is a very handy device to have around if you work with integrated motors or driver modules for steppers or servomotors.