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

Dual uart support for tmc2209 #10

Open
Prozpect opened this issue Jan 9, 2025 · 2 comments
Open

Dual uart support for tmc2209 #10

Prozpect opened this issue Jan 9, 2025 · 2 comments

Comments

@Prozpect
Copy link

Prozpect commented Jan 9, 2025

I have a board where the dual build in tmc2209 drivers share the same uart.
Are you planning on adding support?
That would be much appreciated!

I have it working using Arduino, but ESPHome is a much cleaner solution.

Awesome work you have done!

@slimcdk
Copy link
Owner

slimcdk commented Jan 10, 2025

ESPHome enforces the philosophy about UART being a point-to-point interface. Meaning, multiple components can't use the same UART. Control of multiple drivers would have to be worked around directly by the component itself which would break other inherited concepts from the general stepper implementation. It's sadly not feasible at this point nor in the near future. Two TMC2209 drivers require two separate UART connections.

What board do you have? Does it use a bidirectional communication with adressing or multiplexing? And if you don't mind, could you share your Arduino sketch?

@Prozpect
Copy link
Author

Prozpect commented Jan 10, 2025

Thanks for the fast reply. The guys at ESPHome also were very fast to reply, that's awesome.

I first dropped a feature request on the ESPHome github, but they stated it's not a limitation of ESPHome, but the external component. See the request.
https://github.com/esphome/feature-requests/issues/3019

After that I put the request in at you.
Could it be that what you say about a single UART might have been true in the past, but was solved?

The board:
[http://wiki.fluidnc.com/en/hardware/official/TMC2209_Pen_Laser_V2](url)
It was designed for FluidNC. The example code shows two UARTs (GPIO 16/17 and 4/15), but when you look at the PCB, as far as I can see they are linked to the same UART.
And when I use the arduino script, sharing the UART (UART2 16/17), they both work.

[https://easyeda.com/editor#id=373184a84801493a8be75c8b0326f419|eee0760d8de74f0480374f8eba13b889](url)

Schermafbeelding 2025-01-10 091711

This is the sketch:

#include <WiFi.h>
#include <PubSubClient.h>
#include <TMCStepper.h>

const char* ssid = "";
const char* password = "";

const char* mqtt_server = "";
const char* mqtt_user = "";
const char* mqtt_password = "";

WiFiClient espClient;
PubSubClient client(espClient);

#define ACCELERATION_STEPS 300 // Aantal stappen voor acceleratie en vertraging

#define RX 16
#define TX 17
HardwareSerial UART2(1);

#define STEP_PIN_BOVEN 14
#define DIR_PIN_BOVEN 12

#define STEP_PIN_ONDER 25
#define DIR_PIN_ONDER 26

#define EN_PIN 13

TMC2209Stepper driver_boven(&UART2, 0.11f, 0x00);
TMC2209Stepper driver_onder(&UART2, 0.11f, 0x01);

long positie_boven = 0;
long positie_onder = 0;

bool is_moving = false;
long steps_boven_remaining = 0;
long steps_onder_remaining = 0;
long step_delay = 500;
unsigned long last_step_time = 0;

void setup_wifi() {
Serial.begin(115200);
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi!");
}

void reconnect() {
while (!client.connected()) {
Serial.println("Attempting to connect to MQTT...");
if (client.connect("Plisse_Controller", mqtt_user, mqtt_password)) {
Serial.println("Connected to MQTT!");
client.subscribe("home/cover/plisse/command");
client.subscribe("home/cover/plisse/speed");
client.subscribe("home/cover/plisse/position/boven");
client.subscribe("home/cover/plisse/position/onder");
client.publish("home/cover/plisse/status", "ESP32 Connected to MQTT!");
} else {
Serial.print("Connection failed, rc=");
Serial.print(client.state());
Serial.println(" Retrying in 5 seconds...");
delay(5000);
}
}
}

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
String command = "";
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
Serial.print("Received message: ");
Serial.println(command);

if (String(topic) == "home/cover/plisse/command") {
if (command == "open") {
start_preset(0, 0); // Beide open
} else if (command == "overdag") {
start_preset(5000, 15000); // Positie overdag
} else if (command == "dicht") {
start_preset(0, 25000); // Beide dicht
}
} else if (String(topic) == "home/cover/plisse/speed") {
// Update snelheid
step_delay = command.toInt();
Serial.print("Snelheid bijgewerkt: ");
Serial.println(step_delay);
} else if (String(topic) == "home/cover/plisse/acceleration") {
// Update acceleration_steps
acceleration_steps = command.toInt();
Serial.print("Acceleratie bijgewerkt: ");
Serial.println(acceleration_steps);
} else if (String(topic) == "home/cover/plisse/position/boven") {
long target_boven = command.toInt();
start_preset(target_boven, positie_onder);
} else if (String(topic) == "home/cover/plisse/position/onder") {
long target_onder = command.toInt();
start_preset(positie_boven, target_onder);
}
}

void start_preset(long target_boven, long target_onder) {
Serial.println("Starting new preset...");

// Zorg dat boven niet groter is dan onder
if (target_boven > target_onder) {
Serial.println("Boven mag niet groter zijn dan onder. Onder wordt aangepast.");
target_onder = target_boven;
}

// Zorg dat onder niet kleiner is dan boven
if (target_onder < target_boven) {
Serial.println("Onder mag niet kleiner zijn dan boven. Boven wordt aangepast.");
target_boven = target_onder;
}

// Stel de richting in voor beide motoren
digitalWrite(DIR_PIN_BOVEN, target_boven > positie_boven ? HIGH : LOW);
digitalWrite(DIR_PIN_ONDER, target_onder > positie_onder ? HIGH : LOW);

// Bereken het aantal resterende stappen
steps_boven_remaining = abs(target_boven - positie_boven);
steps_onder_remaining = abs(target_onder - positie_onder);

// Start beweging als er stappen nodig zijn
if (steps_boven_remaining > 0 || steps_onder_remaining > 0) {
is_moving = true;
Serial.print("Bovenste motor - Doel: ");
Serial.print(target_boven);
Serial.print(", Huidige positie: ");
Serial.println(positie_boven);
Serial.print("Onderste motor - Doel: ");
Serial.print(target_onder);
Serial.print(", Huidige positie: ");
Serial.println(positie_onder);
} else {
Serial.println("Geen stappen nodig. Preset voltooid.");
}
}

void move_steppers() {
if (!is_moving) {
return;
}

unsigned long now = micros();
if (now - last_step_time >= step_delay) {
last_step_time = now;

long max_steps = max(steps_boven_remaining, steps_onder_remaining);

// Bereken de huidige vertraging voor acceleratie en vertraging
int delay_time = step_delay;
if (max_steps > acceleration_steps) {
  if (steps_boven_remaining > 0 && steps_boven_remaining < acceleration_steps) {
    delay_time += (step_delay - 100) * steps_boven_remaining / acceleration_steps;
  }
  if (steps_onder_remaining > 0 && steps_onder_remaining < acceleration_steps) {
    delay_time += (step_delay - 100) * steps_onder_remaining / acceleration_steps;
  }
}

// Beweeg de bovenste motor
if (steps_boven_remaining > 0) {
  digitalWrite(STEP_PIN_BOVEN, HIGH);
  delayMicroseconds(10);
  digitalWrite(STEP_PIN_BOVEN, LOW);
  steps_boven_remaining--;
  if (digitalRead(DIR_PIN_BOVEN) == HIGH) {
    positie_boven++;
  } else {
    positie_boven--;
  }
}

// Beweeg de onderste motor
if (steps_onder_remaining > 0) {
  digitalWrite(STEP_PIN_ONDER, HIGH);
  delayMicroseconds(10);
  digitalWrite(STEP_PIN_ONDER, LOW);
  steps_onder_remaining--;
  if (digitalRead(DIR_PIN_ONDER) == HIGH) {
    positie_onder++;
  } else {
    positie_onder--;
  }
}

// Controleer of beide motoren klaar zijn
if (steps_boven_remaining == 0 && steps_onder_remaining == 0) {
  is_moving = false;
  Serial.println("Beweging voltooid. Posities bijgewerkt.");
}

}
}

void setup() {
setup_wifi();

Serial.println("Setting up MQTT...");
client.setServer(mqtt_server, 1883);
client.setCallback(mqtt_callback);

reconnect();

Serial.println("Initializing UART...");
UART2.begin(115200, SERIAL_8N1, RX, TX);
Serial.println("UART initialized!");

driver_boven.begin();
driver_boven.rms_current(800);
driver_boven.microsteps(16);
driver_boven.en_spreadCycle(false);

driver_onder.begin();
driver_onder.rms_current(800);
driver_onder.microsteps(16);
driver_onder.en_spreadCycle(false);

pinMode(STEP_PIN_BOVEN, OUTPUT);
pinMode(DIR_PIN_BOVEN, OUTPUT);
pinMode(STEP_PIN_ONDER, OUTPUT);
pinMode(DIR_PIN_ONDER, OUTPUT);
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);

Serial.println("Setup complete!");
}

void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();

move_steppers();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants