Skip to content

Commit b31fe7a

Browse files
Merge pull request #83 from pvginkel/esp-idf
Added support for ESP-IDF projects.
2 parents cdd729a + cdff6e9 commit b31fe7a

12 files changed

+275
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Build ESP-IDF example project
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
- name: esp-idf build
17+
uses: espressif/esp-idf-ci-action@v1
18+
with:
19+
esp_idf_version: v5.3.2
20+
target: esp32
21+
path: examples/ESPIDFExample

CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
idf_component_register(
2+
SRC_DIRS "src/TMC2209"
3+
INCLUDE_DIRS "src"
4+
REQUIRES arduino-esp32
5+
)

examples/ESPIDFExample/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/build
2+
/.vscode
3+
/managed_components
4+
/sdkconfig
5+
/dependencies.lock

examples/ESPIDFExample/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# For more information about build system see
2+
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
3+
# The following five lines of boilerplate have to be in your project's
4+
# CMakeLists in this exact order for cmake to work correctly
5+
6+
cmake_minimum_required(VERSION 3.16)
7+
8+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
9+
10+
project(idf_project_example)

examples/ESPIDFExample/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
This folder contains a bare bones functional ESP-IDF project.
2+
3+
You can create one using the **ESP-IDF: New Project** command in
4+
Visual Studio code, or use this one as a basis. If you do use this one
5+
as a basis for your own project, review the `.gitignore` file as it
6+
excludes files you would not want to exclude in a normal project.
7+
Normally only the `managed_components` and `build` folders would be
8+
excluded from version control.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FILE(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
2+
3+
idf_component_register(
4+
SRCS ${SOURCES}
5+
INCLUDE_DIRS "."
6+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
dependencies:
2+
TMC2209:
3+
path: ../../..
4+
# Alternatively you can point this directly at the GitHub repository:
5+
# git: https://github.com/janelia-arduino/TMC2209.git

examples/ESPIDFExample/main/main.cpp

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#include <TMC2209.h>
2+
3+
// This example will not work on Arduino boards without HardwareSerial ports,
4+
// such as the Uno, Nano, and Mini.
5+
//
6+
// See this reference for more details:
7+
// https://www.arduino.cc/reference/en/language/functions/communication/serial/
8+
9+
HardwareSerial & serial_stream = Serial1;
10+
11+
const long SERIAL_BAUD_RATE = 115200;
12+
const int DELAY = 2000;
13+
14+
// Instantiate TMC2209
15+
TMC2209 stepper_driver;
16+
17+
extern "C" void app_main()
18+
{
19+
Serial.begin(SERIAL_BAUD_RATE);
20+
21+
stepper_driver.setup(serial_stream);
22+
23+
Serial.println("*************************");
24+
Serial.println("getSettings()");
25+
TMC2209::Settings settings = stepper_driver.getSettings();
26+
Serial.print("settings.is_communicating = ");
27+
Serial.println(settings.is_communicating);
28+
Serial.print("settings.is_setup = ");
29+
Serial.println(settings.is_setup);
30+
Serial.print("settings.software_enabled = ");
31+
Serial.println(settings.software_enabled);
32+
Serial.print("settings.microsteps_per_step = ");
33+
Serial.println(settings.microsteps_per_step);
34+
Serial.print("settings.inverse_motor_direction_enabled = ");
35+
Serial.println(settings.inverse_motor_direction_enabled);
36+
Serial.print("settings.stealth_chop_enabled = ");
37+
Serial.println(settings.stealth_chop_enabled);
38+
Serial.print("settings.standstill_mode = ");
39+
switch (settings.standstill_mode)
40+
{
41+
case TMC2209::NORMAL:
42+
Serial.println("normal");
43+
break;
44+
case TMC2209::FREEWHEELING:
45+
Serial.println("freewheeling");
46+
break;
47+
case TMC2209::STRONG_BRAKING:
48+
Serial.println("strong_braking");
49+
break;
50+
case TMC2209::BRAKING:
51+
Serial.println("braking");
52+
break;
53+
}
54+
Serial.print("settings.irun_percent = ");
55+
Serial.println(settings.irun_percent);
56+
Serial.print("settings.irun_register_value = ");
57+
Serial.println(settings.irun_register_value);
58+
Serial.print("settings.ihold_percent = ");
59+
Serial.println(settings.ihold_percent);
60+
Serial.print("settings.ihold_register_value = ");
61+
Serial.println(settings.ihold_register_value);
62+
Serial.print("settings.iholddelay_percent = ");
63+
Serial.println(settings.iholddelay_percent);
64+
Serial.print("settings.iholddelay_register_value = ");
65+
Serial.println(settings.iholddelay_register_value);
66+
Serial.print("settings.automatic_current_scaling_enabled = ");
67+
Serial.println(settings.automatic_current_scaling_enabled);
68+
Serial.print("settings.automatic_gradient_adaptation_enabled = ");
69+
Serial.println(settings.automatic_gradient_adaptation_enabled);
70+
Serial.print("settings.pwm_offset = ");
71+
Serial.println(settings.pwm_offset);
72+
Serial.print("settings.pwm_gradient = ");
73+
Serial.println(settings.pwm_gradient);
74+
Serial.print("settings.cool_step_enabled = ");
75+
Serial.println(settings.cool_step_enabled);
76+
Serial.print("settings.analog_current_scaling_enabled = ");
77+
Serial.println(settings.analog_current_scaling_enabled);
78+
Serial.print("settings.internal_sense_resistors_enabled = ");
79+
Serial.println(settings.internal_sense_resistors_enabled);
80+
Serial.println("*************************");
81+
Serial.println();
82+
83+
Serial.println("*************************");
84+
Serial.println("hardwareDisabled()");
85+
bool hardware_disabled = stepper_driver.hardwareDisabled();
86+
Serial.print("hardware_disabled = ");
87+
Serial.println(hardware_disabled);
88+
Serial.println("*************************");
89+
Serial.println();
90+
91+
Serial.println("*************************");
92+
Serial.println("getStatus()");
93+
TMC2209::Status status = stepper_driver.getStatus();
94+
Serial.print("status.over_temperature_warning = ");
95+
Serial.println(status.over_temperature_warning);
96+
Serial.print("status.over_temperature_shutdown = ");
97+
Serial.println(status.over_temperature_shutdown);
98+
Serial.print("status.short_to_ground_a = ");
99+
Serial.println(status.short_to_ground_a);
100+
Serial.print("status.short_to_ground_b = ");
101+
Serial.println(status.short_to_ground_b);
102+
Serial.print("status.low_side_short_a = ");
103+
Serial.println(status.low_side_short_a);
104+
Serial.print("status.low_side_short_b = ");
105+
Serial.println(status.low_side_short_b);
106+
Serial.print("status.open_load_a = ");
107+
Serial.println(status.open_load_a);
108+
Serial.print("status.open_load_b = ");
109+
Serial.println(status.open_load_b);
110+
Serial.print("status.over_temperature_120c = ");
111+
Serial.println(status.over_temperature_120c);
112+
Serial.print("status.over_temperature_143c = ");
113+
Serial.println(status.over_temperature_143c);
114+
Serial.print("status.over_temperature_150c = ");
115+
Serial.println(status.over_temperature_150c);
116+
Serial.print("status.over_temperature_157c = ");
117+
Serial.println(status.over_temperature_157c);
118+
Serial.print("status.current_scaling = ");
119+
Serial.println(status.current_scaling);
120+
Serial.print("status.stealth_chop_mode = ");
121+
Serial.println(status.stealth_chop_mode);
122+
Serial.print("status.standstill = ");
123+
Serial.println(status.standstill);
124+
Serial.println("*************************");
125+
Serial.println();
126+
127+
Serial.println();
128+
delay(DELAY);
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Required by the android-esp32 component.
2+
CONFIG_FREERTOS_HZ=1000

idf_component.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
dependencies:
2+
idf:
3+
version: ">=5.3.0"
4+
arduino-esp32:
5+
version: "*"

src/TMC2209.h

+11
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,16 @@ class TMC2209
8686
void setAllCurrentValues(uint8_t run_current_percent,
8787
uint8_t hold_current_percent,
8888
uint8_t hold_delay_percent);
89+
void setRMSCurrent(uint16_t mA,
90+
float rSense,
91+
float holdMultiplier = 0.5f);
8992

9093
void enableDoubleEdge();
9194
void disableDoubleEdge();
9295

96+
void enableVSense();
97+
void disableVSense();
98+
9399
void enableInverseMotorDirection();
94100
void disableInverseMotorDirection();
95101

@@ -279,6 +285,9 @@ class TMC2209
279285
const static uint8_t STEPPER_DRIVER_FEATURE_OFF = 0;
280286
const static uint8_t STEPPER_DRIVER_FEATURE_ON = 1;
281287

288+
const static uint8_t MAX_READ_RETRIES = 5;
289+
const static uint32_t READ_RETRY_DELAY_MS = 20;
290+
282291
// Datagrams
283292
const static uint8_t WRITE_READ_REPLY_DATAGRAM_SIZE = 8;
284293
const static uint8_t DATA_SIZE = 4;
@@ -504,6 +513,8 @@ class TMC2209
504513
const static uint8_t MRES_001 = 0b1000;
505514
const static uint8_t DOUBLE_EDGE_DISABLE = 0;
506515
const static uint8_t DOUBLE_EDGE_ENABLE = 1;
516+
const static uint8_t VSENSE_DISABLE = 0;
517+
const static uint8_t VSENSE_ENABLE = 1;
507518

508519
const static size_t MICROSTEPS_PER_STEP_MIN = 1;
509520
const static size_t MICROSTEPS_PER_STEP_MAX = 256;

src/TMC2209/TMC2209.cpp

+68-21
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,30 @@ void TMC2209::setAllCurrentValues(uint8_t run_current_percent,
223223
writeStoredDriverCurrent();
224224
}
225225

226+
void TMC2209::setRMSCurrent(uint16_t mA,
227+
float rSense,
228+
float holdMultiplier)
229+
{
230+
// Taken from https://github.com/teemuatlut/TMCStepper/blob/74e8e6881adc9241c2e626071e7328d7652f361a/src/source/TMCStepper.cpp#L41.
231+
232+
uint8_t CS = 32.0*1.41421*mA/1000.0*(rSense+0.02)/0.325 - 1;
233+
// If Current Scale is too low, turn on high sensitivity R_sense and calculate again
234+
if (CS < 16) {
235+
enableVSense();
236+
CS = 32.0*1.41421*mA/1000.0*(rSense+0.02)/0.180 - 1;
237+
} else { // If CS >= 16, turn off high_sense_r
238+
disableVSense();
239+
}
240+
241+
if (CS > 31) {
242+
CS = 31;
243+
}
244+
245+
driver_current_.irun = CS;
246+
driver_current_.ihold = CS*holdMultiplier;
247+
writeStoredDriverCurrent();
248+
}
249+
226250
void TMC2209::enableDoubleEdge()
227251
{
228252
chopper_config_.double_edge = DOUBLE_EDGE_ENABLE;
@@ -235,6 +259,18 @@ void TMC2209::disableDoubleEdge()
235259
writeStoredChopperConfig();
236260
}
237261

262+
void TMC2209::enableVSense()
263+
{
264+
chopper_config_.vsense = VSENSE_ENABLE;
265+
writeStoredChopperConfig();
266+
}
267+
268+
void TMC2209::disableVSense()
269+
{
270+
chopper_config_.vsense = VSENSE_DISABLE;
271+
writeStoredChopperConfig();
272+
}
273+
238274
void TMC2209::enableInverseMotorDirection()
239275
{
240276
global_config_.shaft = 1;
@@ -880,32 +916,43 @@ uint32_t TMC2209::read(uint8_t register_address)
880916
read_request_datagram.rw = RW_READ;
881917
read_request_datagram.crc = calculateCrc(read_request_datagram, READ_REQUEST_DATAGRAM_SIZE);
882918

883-
sendDatagramBidirectional(read_request_datagram, READ_REQUEST_DATAGRAM_SIZE);
884-
885-
uint32_t reply_delay = 0;
886-
while ((serialAvailable() < WRITE_READ_REPLY_DATAGRAM_SIZE) and
887-
(reply_delay < REPLY_DELAY_MAX_MICROSECONDS))
919+
for (uint8_t retry = 0; retry < MAX_READ_RETRIES; retry++)
888920
{
889-
delayMicroseconds(REPLY_DELAY_INC_MICROSECONDS);
890-
reply_delay += REPLY_DELAY_INC_MICROSECONDS;
891-
}
921+
sendDatagramBidirectional(read_request_datagram, READ_REQUEST_DATAGRAM_SIZE);
892922

893-
if (reply_delay >= REPLY_DELAY_MAX_MICROSECONDS)
894-
{
895-
return 0;
896-
}
923+
uint32_t reply_delay = 0;
924+
while ((serialAvailable() < WRITE_READ_REPLY_DATAGRAM_SIZE) and
925+
(reply_delay < REPLY_DELAY_MAX_MICROSECONDS))
926+
{
927+
delayMicroseconds(REPLY_DELAY_INC_MICROSECONDS);
928+
reply_delay += REPLY_DELAY_INC_MICROSECONDS;
929+
}
897930

898-
uint64_t byte;
899-
uint8_t byte_count = 0;
900-
WriteReadReplyDatagram read_reply_datagram;
901-
read_reply_datagram.bytes = 0;
902-
for (uint8_t i=0; i<WRITE_READ_REPLY_DATAGRAM_SIZE; ++i)
903-
{
904-
byte = serialRead();
905-
read_reply_datagram.bytes |= (byte << (byte_count++ * BITS_PER_BYTE));
931+
if (reply_delay >= REPLY_DELAY_MAX_MICROSECONDS)
932+
{
933+
return 0;
934+
}
935+
936+
uint64_t byte;
937+
uint8_t byte_count = 0;
938+
WriteReadReplyDatagram read_reply_datagram;
939+
read_reply_datagram.bytes = 0;
940+
for (uint8_t i=0; i<WRITE_READ_REPLY_DATAGRAM_SIZE; ++i)
941+
{
942+
byte = serialRead();
943+
read_reply_datagram.bytes |= (byte << (byte_count++ * BITS_PER_BYTE));
944+
}
945+
946+
auto crc = calculateCrc(read_reply_datagram, WRITE_READ_REPLY_DATAGRAM_SIZE);
947+
if (crc == read_reply_datagram.crc)
948+
{
949+
return reverseData(read_reply_datagram.data);
950+
}
951+
952+
delay(READ_RETRY_DELAY_MS);
906953
}
907954

908-
return reverseData(read_reply_datagram.data);
955+
return 0;
909956
}
910957

911958
uint8_t TMC2209::percentToCurrentSetting(uint8_t percent)

0 commit comments

Comments
 (0)