Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stepper motor control w/ TMC2209 #69

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ build_src_filter = +<*> -<./angular/>
board_build.filesystem = littlefs
check_tool = cppcheck, clangtidy
build_flags =
-D OLED_ENABLED=false
-D OLED_ENABLED=true
-D PWM_MOTOR_CONTROL=false
-D STEPPER_MOTOR_CONTROL=true
-D HOME_ASSISTANT_ENABLED=false
Comment on lines +24 to 27
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set all to false before merging

check_flags =
clangtidy: -fix-errors,--format-style=google
Expand All @@ -36,3 +37,5 @@ lib_deps =
adafruit/Adafruit SSD1306@^2.5.9
electromagus/ESPMX1508@^1.0.5
dawidchyrzynski/home-assistant-integration@^2.1.0
teemuatlut/TMCStepper@^0.7.3
plerup/EspSoftwareSerial@^8.2.0
31 changes: 28 additions & 3 deletions src/platformio/osww-server/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,19 @@ AsyncWebServer server(80);
HTTPClient http;
WiFiClient client;
ESP32Time rtc;
String winderooVersion = "3.0.0";
String winderooVersion = "3.1.0";

#if PWM_MOTOR_CONTROL
#if PWM_MOTOR_CONTROL && STEPPER_MOTOR_CONTROL
#error "You can only have one optional motor control method enabled at a time. You must disable either PWM_MOTOR_CONTROL or STEPPER_MOTOR_CONTROL in the platformio.ini file."
#endif

// PWM control
#if PWM_MOTOR_CONTROL && !STEPPER_MOTOR_CONTROL
MotorControl motor(directionalPinA, directionalPinB, true);
#else
#endif

// Stepper motor control || Regular DC motor control
#if STEPPER_MOTOR_CONTROL && !PWM_MOTOR_CONTROL || !STEPPER_MOTOR_CONTROL && !WM_MOTOR_CONTROL
MotorControl motor(directionalPinA, directionalPinB);
#endif

Expand Down Expand Up @@ -389,6 +397,17 @@ unsigned long calculateWindingTime()
*/
void beginWindingRoutine()
{


if (userDefinedSettings.direction == "CW" )
{
motor.setMotorDirection(1);
}
else if (userDefinedSettings.direction == "CCW")
{
motor.setMotorDirection(0);
}

startTimeEpoch = rtc.getEpoch();
previousEpoch = startTimeEpoch;
routineRunning = true;
Expand Down Expand Up @@ -1184,6 +1203,11 @@ void setup()
display.invertDisplay(OLED_INVERT_SCREEN);
display.setRotation(rotate);
drawNotification("Winderoo");


String savedNetworkMessage[2] = {"Winderoo build", "v" + winderooVersion};
drawMultiLineText(savedNetworkMessage);
delay(1200);
}

String savedNetworkMessage[2] = {"Connecting to", "saved network..."};
Expand Down Expand Up @@ -1302,6 +1326,7 @@ void setup()

drawNotification("Starting webserver...");
startWebserver();
delay(750); // delay to show notification

if (strcmp(userDefinedSettings.status.c_str(), "Winding") == 0)
{
Expand Down
154 changes: 145 additions & 9 deletions src/platformio/osww-server/src/utils/MotorControl.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,133 @@
#include "MotorControl.h"

// Define the static instance variable
MotorControl* MotorControl::instance = nullptr;

#if PWM_MOTOR_CONTROL
#include <ESP32MX1508.h>
#define CH1 1
#define CH2 2
int motorSpeed = 145;
#endif

#ifdef STEPPER_MOTOR_CONTROL
#include <TMCStepper.h>
#include <SoftwareSerial.h>

const uint16_t EN_PIN = 4; // Enable
const uint16_t DIR_PIN = 16; // Direction
const uint16_t STEP_PIN = 17; // Step

const signed long RUN_VELOCITY = 20000;
const signed long STOP_VELOCITY = 0;

#define SW_RX 3 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX 1 // TMC2208/TMC2224 SoftwareSerial transmit pin
#define SERIAL_PORT Serial1 // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2

const uint16_t R_SENSE = 0.11f; // TMC2209 - SilentStepStick series use 0.11

SoftwareSerial softwareSerial(SW_RX, SW_TX); // Create SoftwareSerial object
TMC2208Stepper driver = TMC2208Stepper(&softwareSerial, R_SENSE); // Use SoftwareSerial object

// For non-blocking stepper movement
hw_timer_t *timer = NULL;
volatile bool stepPinState = LOW;
static bool timerConfigured = false;

// For stepper timing control (RPM)
uint16_t microSteps = 4;
uint16_t rmsCurrent = 600;
uint64_t timerMicroSecondInterval = 400; // 937 microseconds for 40 RPM / 400 microseconds for 100 RPM

#endif

MotorControl::MotorControl(int pinA, int pinB, bool pwmMotorControl)
{
_pinA = pinA;
_pinB = pinB;
_motorDirection = 0;
_pwmMotorControl = pwmMotorControl;
#ifdef STEPPER_MOTOR_CONTROL
instance = this;
stepperSetup();

_motorDirection = 0;
#else
_pinA = pinA;
_pinB = pinB;
_motorDirection = 0;
_pwmMotorControl = pwmMotorControl;
#endif
}

void MotorControl::stepperSetup() {

softwareSerial.begin(9600);

pinMode(EN_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);

driver.begin();
driver.toff(5); // Enables driver in software
driver.rms_current(rmsCurrent); // Set motor RMS current in mA
driver.microsteps(microSteps); // Set microsteps to 1/8th because reasons
driver.stealth(); // Enable stealthChop
}

// This private function is used to toggle the step pin by the timer
void IRAM_ATTR MotorControl::onTimer()
{
digitalWrite(STEP_PIN, stepPinState);
stepPinState = !stepPinState;
}

void IRAM_ATTR MotorControl::onTimerStatic()
{
instance->onTimer();
}

void killTimer()
{
Serial.println("[INFO] - Killing timer");

timerAlarmDisable(timer); // Disable the timer to stop
timerDetachInterrupt(timer); // Detach the interrupt
timerEnd(timer); // End the timer

stepPinState = LOW;
digitalWrite(STEP_PIN, stepPinState);

timer = NULL;
timerConfigured = false;
}

void MotorControl::configureHardwareTimer()
{
if (!timerConfigured)
{
timer = timerBegin(0, 80, true); // Timer 0, prescaler 80 (1 MHz clock)
timerAttachInterrupt(timer, &onTimerStatic, true); // Attach onTimer function to timer
timerAlarmWrite(timer, timerMicroSecondInterval, true); // Set timer interval 937 microseconds for 40 RPM
timerAlarmEnable(timer); // Enable the timer
timerConfigured = true;
}

}

void MotorControl::clockwise()
{
#if PWM_MOTOR_CONTROL
MX1508 pwmControl(_pinA, _pinB, CH1, CH2);
pwmControl.motorGo(motorSpeed);
#elif STEPPER_MOTOR_CONTROL
// Set the direction pin
if (timerConfigured) timerAlarmDisable(timer);

digitalWrite(DIR_PIN, HIGH);
delay(10);

if (timerConfigured) timerAlarmEnable(timer);
// Non-blocking step handling is now through the timer function; "configureHardwareTimer()"
#else
digitalWrite(_pinA, HIGH);
digitalWrite(_pinB, LOW);
Expand All @@ -32,6 +140,15 @@ void MotorControl::countClockwise()
#if PWM_MOTOR_CONTROL
MX1508 pwmControl(_pinA, _pinB, CH1, CH2);
pwmControl.motorRev(motorSpeed);
#elif STEPPER_MOTOR_CONTROL
// Set the direction pin
if (timerConfigured) timerAlarmDisable(timer);

digitalWrite(DIR_PIN, LOW);
delay(10);

if (timerConfigured) timerAlarmEnable(timer);
// Non-blocking step handling is now through the timer function; "configureHardwareTimer()"
#else
digitalWrite(_pinA, LOW);
digitalWrite(_pinB, HIGH);
Expand All @@ -44,6 +161,11 @@ void MotorControl::stop()
#if PWM_MOTOR_CONTROL
MX1508 pwmControl(_pinA, _pinB, CH1, CH2);
pwmControl.motorBrake();
#elif STEPPER_MOTOR_CONTROL
if (timerConfigured)
{
killTimer();
}
#else
digitalWrite(_pinA, LOW);
digitalWrite(_pinB, LOW);
Expand All @@ -53,16 +175,27 @@ void MotorControl::stop()

void MotorControl::determineMotorDirectionAndBegin()
{
// @todo - investigate if this is still needed
// stop();

if (_motorDirection)
{
clockwise();
#if STEPPER_MOTOR_CONTROL
clockwise(); // We call this for logging purposes
if (!timerConfigured) {
configureHardwareTimer();
}
#else
clockwise();
#endif
}
else
{
countClockwise();
#if STEPPER_MOTOR_CONTROL
countClockwise(); // We call this for logging purposes
if (!timerConfigured) {
configureHardwareTimer();
}
#else
countClockwise();
#endif
}
}

Expand All @@ -74,4 +207,7 @@ int MotorControl::getMotorDirection()
void MotorControl::setMotorDirection(int direction)
{
_motorDirection = direction;

Serial.print("[INFO] - MOTOR CONTROLLER - Setting direction to: ");
Serial.println(_motorDirection ? "CW" : "CCW");
}
10 changes: 10 additions & 0 deletions src/platformio/osww-server/src/utils/MotorControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ class MotorControl
int _motorDirection;
bool _pwmMotorControl;

void stepperSetup();

static void IRAM_ATTR onTimerStatic(); // Add this line

void onTimer();

void configureHardwareTimer();

static MotorControl* instance; // Add this line

public:
MotorControl(int _pinA, int _pinB, bool pwmMotorControl = false);

Expand Down
Loading