OK, here is the actual code of the program that I'm running.
I use PlatformIO with CLion IDE. It handles compiling and uploading just fine. It's a far more luxurious interface than the stock Arduino IDE.
The program uses three DRV8825 drivers, but with two of them, I simply mirror the logic pins to the pico, and then I reverse the coils on the second driver. The motors face each other and when stepper1 is stepped, those motors spin identically but they both spin in the same direction (because they are facing each other).
The third DRV8825 turns a piece of allthread that I have a 3D printed object mounted on.
The project is used to make vape coils. While the two facing motors spin a wire (or a group of wires) in the same direction, I can have a spool of wire on the allthread that is feeding wire to the spinning wire and that allthread moves at a speed that is dictated by the wires gauge size to that it properly wraps the wire around the spinning wire.
This is why you might be puzzled about how I did certain calculations. I found it easier to keep everything in float units for all the calculations to prevent the need to convert anything until the number is actually needed.
With a serial terminal, I can set the wire gauge of the "feeding" wire, which has a direct impact on the speed of stepper2. I can also change the microstepping which I only included for testing to find optimal spinning for the motors.
BlockNot is a library that I wrote. I just re-wrote it so that it can do microsecond timing and I just published that update about 20 minutes ago so I'm not sure when it will hit the Arduino repository, but in your IDE, if you look it up and see that it is 2.0.0, then that's the version that will work with this code.
Otherwise, you can download it and add it manually.
#include "pico/multicore.h"
#include <BlockNot.h>
short MICROSTEPS = 32;
const int M0_1 = 0; //GP0
const int M1_1 = 1; //GP1
const int M2_1 = 2; //GP2
const int SLEEP_1 = 3; //GP3
const int STEP_1 = 14; //GP14
const int DIRE_1 = 15; //GP15
const int M0_2 = 6; //GP6
const int M1_2 = 7; //GP7
const int M2_2 = 8; //GP8
const int SLEEP_2 = 9; //GP9
const int STEP_2 = 10; //GP10
const int DIRE_2 = 11; //GP11
const int PEDAL = 27;//GP27
const int POS = 26;//GP26
const int BUTTON1 = 19;//GP19
const int BUTTON2 = 21;//GP21
const int BUTTON3 = 22;//GP22
volatile float rpm = 0;
volatile bool run = false;
volatile float pot;
volatile float staggard = 1;
int selectedGauge = 33;
BlockNot dataTimer(1000);
BlockNot stepper1Delay(250, MICROSECONDS);
BlockNot stepper2Delay(250, MICROSECONDS);
unsigned long microStart1 = micros();
unsigned long microStart2 = micros();
#define READ_PEDAL analogRead(PEDAL)
#define REVERSE digitalRead(BUTTON1) == LOW
#define BUTTON2_PRESSED digitalRead(BUTTON2) == LOW
#define BUTTON3_PRESSED digitalRead(BUTTON3) == LOW
float reMap(float, float, float, float, float);
void showData();
uint delayCalc(float);
void setStepper1Delay();
void setStepper2Delay();
void microsteps();
void checkSerial();
void setSpeed();
void sleepStepper();
void wakeStepper();
void stepStepper1();
void stepStepper2();
void setPins();
const float gauge[] = {8.25146,7.34814,6.54371,5.82734,5.18940,4.62129,4.11538,3.66485,3.26364,2.90636,2.58819,2.30485,
2.05253,1.82783,1.62773,1.44953,1.29085,1.14953,1.02369,0.91162,0.81182,0.72295,0.64380,
0.57332,0.51056,0.45467,0.40489,0.36057,0.32109,0.28594,0.25464,0.22676,0.20194,0.17983,
0.16014,0.14261,0.12700,0.11310,0.10072,0.08969,0.07987,0.07113,0.06334,0.05641,0.05023,
0.04473};
float reMap(float sourceNumber, float fromRangeStart, float fromRangeEnd, float toRangeStart, float toRangeEnd) {
float deltaA = fromRangeEnd - fromRangeStart;
float deltaB = toRangeEnd - toRangeStart;
float scale = deltaB / deltaA;
float negA = -1 * fromRangeStart;
float offset = (negA * scale) + toRangeStart;
float finalNumber = (sourceNumber * scale) + offset;
return finalNumber;
}
void showData() {
String message =
"D1: " + String(stepper1Delay.getDuration()) + "\n" +
"D2: " + String(stepper2Delay.getDuration()) + "\n" +
"Pot: " + String(pot) + "\n" +
"Rev: " + (REVERSE ? "True" : "False") + "\n" +
"RPM: " + String(rpm) + "\n" +
"Staggard: " + ((staggard == 2) ? "YES" : "NO");
Serial.println(message);
}
uint delayCalc(float RPM) {
float numerator = RPM * 360 * (float) MICROSTEPS;
float denominator = 60 * 1.8;
float stepsPerSecond = numerator / denominator;
float steppingMicrosecondsPerSecond = stepsPerSecond * 2.0F;
float delta = 1000000 - steppingMicrosecondsPerSecond;
return (uint) ((delta / stepsPerSecond)/2);
}
void setStepper1Delay() {
stepper1Delay.setDuration((rpm == 0) ? 0 : delayCalc(rpm));
}
void setStepper2Delay() {
float mmToTravel = gauge[selectedGauge] * staggard;
auto revPerGauge = (float) (mmToTravel * .75);
float rpm2 = rpm * revPerGauge;
stepper2Delay.setDuration((rpm == 0) ? 0 : delayCalc(rpm2));
}
void microsteps() {
switch(MICROSTEPS) {
case 1:
digitalWrite(M0_1, LOW);
digitalWrite(M0_2, LOW);
digitalWrite(M1_1, LOW);
digitalWrite(M1_2, LOW);
digitalWrite(M2_1, LOW);
digitalWrite(M2_2, LOW);
break;
case 2:
digitalWrite(M0_1, LOW);
digitalWrite(M0_2, LOW);
digitalWrite(M1_1, LOW);
digitalWrite(M1_2, LOW);
digitalWrite(M2_1, HIGH);
digitalWrite(M2_2, HIGH);
break;
case 4:
digitalWrite(M0_1, LOW);
digitalWrite(M0_2, LOW);
digitalWrite(M1_1, HIGH);
digitalWrite(M1_2, HIGH);
digitalWrite(M2_1, LOW);
digitalWrite(M2_2, LOW);
break;
case 8:
digitalWrite(M0_1, LOW);
digitalWrite(M0_2, LOW);
digitalWrite(M1_1, HIGH);
digitalWrite(M1_2, HIGH);
digitalWrite(M2_1, HIGH);
digitalWrite(M2_2, HIGH);
break;
case 16:
digitalWrite(M0_1, HIGH);
digitalWrite(M0_2, HIGH);
digitalWrite(M1_1, LOW);
digitalWrite(M1_2, LOW);
digitalWrite(M2_1, LOW);
digitalWrite(M2_2, LOW);
break;
case 32:
digitalWrite(M0_1, HIGH);
digitalWrite(M0_2, HIGH);
digitalWrite(M1_1, HIGH);
digitalWrite(M1_2, HIGH);
digitalWrite(M2_1, HIGH);
digitalWrite(M2_2, HIGH);
break;
default:
break;
}
Serial.print(F("Microsteps: "));
Serial.println(MICROSTEPS);
}
void checkSerial() {
String input = Serial.readString();
if(input.startsWith("m")) {
MICROSTEPS = (short) input.substring(1).toInt();
microsteps();
Serial.print(F("Microsteps: "));
Serial.println(MICROSTEPS);
}
else if(input.startsWith("g")) {
selectedGauge = input.substring(1).toInt();
Serial.print(F("Selected Gauge: "));
Serial.println(selectedGauge);
}
else if(input.startsWith("d")) {
int ms = input.substring(1).toInt();
delay(ms);
}
}
void setSpeed() {
static bool lastRun = false;
pot = READ_PEDAL;
rpm = reMap(pot, 25, 1024, 0, 200);
run = rpm > 0;
if (rpm < 0) rpm = 0;
bool changingState = lastRun != run;
if (changingState && run) {
wakeStepper();
}
if (changingState && !run) {
sleepStepper();
}
lastRun = run;
setStepper1Delay();
setStepper2Delay();
}
void sleepStepper() {
run = false;
digitalWrite(SLEEP_1, LOW);
digitalWrite(SLEEP_2, LOW);
}
void wakeStepper() {
run = true;
digitalWrite(SLEEP_1, HIGH);
digitalWrite(SLEEP_2, HIGH);
delay(2);
}
void stepStepper1() {
digitalWrite(STEP_1, HIGH);
delayMicroseconds(3);
digitalWrite(STEP_1, LOW);
}
void stepStepper2() {
digitalWrite(STEP_2, HIGH);
delayMicroseconds(3);
digitalWrite(STEP_2, LOW);
}
void setPins() {
pinMode(SLEEP_1, OUTPUT);
pinMode(STEP_1, OUTPUT);
pinMode(DIRE_1, OUTPUT);
pinMode(M2_1, OUTPUT);
pinMode(M0_1, OUTPUT);
pinMode(M1_1, OUTPUT);
pinMode(SLEEP_2, OUTPUT);
pinMode(STEP_2, OUTPUT);
pinMode(DIRE_2, OUTPUT);
pinMode(M2_2, OUTPUT);
pinMode(M0_2, OUTPUT);
pinMode(M1_2, OUTPUT);
pinMode(POS, OUTPUT);
pinMode(PEDAL, INPUT);
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(BUTTON2, INPUT_PULLUP);
pinMode(BUTTON3, INPUT_PULLUP);
digitalWrite(POS, HIGH); //Set high for BUTTON1 so button can sit directly on the MC pins - used for reversing the motors.
}
[[noreturn]] void core1Entry() {
while (true) {
if (run) {
if (REVERSE) {
digitalWrite(DIRE_1, HIGH);
digitalWrite(DIRE_2, LOW);
} else {
digitalWrite(DIRE_1, LOW);
digitalWrite(DIRE_2, HIGH);
}
if (stepper1Delay.TRIGGERED)
stepStepper1();
if (stepper2Delay.TRIGGERED)
stepStepper2();
}
}
}
void setup() {
Serial.begin(115200);
setPins();
microsteps();
sleepStepper();
multicore_launch_core1(core1Entry);
}
void loop() {
setSpeed();
if(BUTTON2_PRESSED) {
delay(300);
if(staggard == 1) staggard = 2;
else staggard = 1;
}
if(BUTTON3_PRESSED) {
if(dataTimer.TRIGGERED)
showData();
}
if(Serial.available())
checkSerial();
}