-
Notifications
You must be signed in to change notification settings - Fork 0
Tyler pit steppers #11
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
Open
Naitry
wants to merge
7
commits into
main
Choose a base branch
from
Tyler-PITSteppers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f28c644
Stepper Pulse Fix
Naitry 783cb34
added some comments, changed some guard statements
Naitry 41dafbc
changed to hpp header names and pragma once guard statements
Naitry 01046ca
making sure PITs are initialized
Naitry d9f0b1c
Remove .idea folder and add it to .gitignore
Naitry 66a5441
resolving missed change of guard style: https://github.com/roboticsat…
Naitry 2fb7243
Switched to more standard timer implementation
Naitry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| .pio | ||
| .idea/ | ||
| .vscode/* | ||
| compile_flags.txt | ||
| .clangd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #pragma once | ||
|
|
||
| #include <Arduino.h> | ||
| #include <IntervalTimer.h> | ||
| #include <functional> | ||
|
|
||
| // There are only 4 timers allowed, as described in the interval timer code | ||
| const int NUM_TIMERS = 4; | ||
| IntervalTimer timers[NUM_TIMERS]; | ||
|
|
||
| // Function pointer array which will be used for timer callbacks | ||
| using TimerCallback = std::function<void()>; | ||
| TimerCallback timerCallbacks[NUM_TIMERS] = {nullptr}; | ||
|
|
||
| /** | ||
| * @brief Attaches a callback function to a specific timer. | ||
| * | ||
| * This function associates a callback function with one of the available timers. | ||
| * The callback will be executed when the timer triggers. | ||
| * | ||
| * @param timerIndex The index of the timer to attach the callback to (0 to NUM_TIMERS-1). | ||
| * @param callback The function to be called when the timer triggers. | ||
| */ | ||
| void attachTimerCallback(int timerIndex, TimerCallback callback) { | ||
| if (timerIndex >= 0 && timerIndex < NUM_TIMERS) { | ||
| timerCallbacks[timerIndex] = callback; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @brief Sets the frequency for a specific timer. | ||
| * | ||
| * This function sets the frequency at which a timer will trigger its callback. | ||
| * If the frequency is set to 0, the timer will be stopped. | ||
| * | ||
| * @param timerIndex The index of the timer to set the frequency for (0 to NUM_TIMERS-1). | ||
| * @param frequency The desired frequency in Hz. Set to 0 to stop the timer. | ||
| */ | ||
| void setTimerFrequency(int timerIndex, uint32_t frequency) { | ||
| if (timerIndex >= 0 && timerIndex < NUM_TIMERS) { | ||
| if (frequency > 0) { | ||
| uint32_t period_us = 1000000 / frequency; | ||
| timers[timerIndex].begin(timerCallbacks[timerIndex], period_us); | ||
| } else { | ||
| timers[timerIndex].end(); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,81 +1,135 @@ | ||
| #ifndef STEPPER_DRIVER_H | ||
| #define STEPPER_DRIVER_H | ||
| #pragma once | ||
|
|
||
| #include <Arduino.h> | ||
| #include "IntervalTimers.hpp" | ||
|
|
||
| #define DEFAULT_MAX_STEPPER_FREQ 1000 | ||
| #define DEFAULT_MIN_STEPPER_FREQ 100 | ||
|
|
||
| class Stepper { | ||
| private: | ||
| int pul_pin; | ||
| int dir_pin; | ||
| int min_freq_hz; | ||
| int max_freq_hz; | ||
| int freq_hz = 0; | ||
| unsigned long period_us = 0; | ||
| float lerp(float x, float a1, float b1, float a2, float b2){return a2 + (x - a1) * (b2 - a2) / (b1 - a1);} | ||
| elapsedMicros pulseTimer; | ||
|
|
||
| public: | ||
|
|
||
| /** | ||
| * Constructor for Stepper motor driver | ||
| * @param pul_pin The pin to use for the pulse signal | ||
| * @param dir_pin The pin to use for the direction signal | ||
| * @param min_freq The minimum frequency to use for the stepper motor. Default is 100 Hz | ||
| * @param max_freq The maximum frequency to use for the stepper motor. Default is 2000 Hz | ||
| */ | ||
| Stepper(int pul_pin, int dir_pin, int min_freq = DEFAULT_MIN_STEPPER_FREQ, int max_freq = DEFAULT_MAX_STEPPER_FREQ) { | ||
|
|
||
| //https://forum.pjrc.com/index.php?threads/using-the-open-drain-capabilities-of-the-teensy-3-1-processor.25393/ | ||
|
|
||
| this->pul_pin = pul_pin; | ||
| this->dir_pin = dir_pin; | ||
| this->min_freq_hz = min_freq; | ||
| this->max_freq_hz = max_freq; | ||
|
|
||
| pinMode(pul_pin, OUTPUT_OPENDRAIN); | ||
| pinMode(dir_pin, OUTPUT_OPENDRAIN); | ||
| } | ||
|
|
||
| /** | ||
| * Set the speed of the stepper motor | ||
| * @param speed The speed to set the motor to. -255 to 255 | ||
| */ | ||
| void setSpeed(int speed) { | ||
| int dir = speed < 0 ? 1 : 0; | ||
| speed = abs(constrain(speed, -255, 255)); | ||
| digitalWriteFast(dir_pin, dir); | ||
| if (speed == 0) { | ||
| digitalWriteFast(pul_pin, LOW); | ||
| freq_hz = 0; | ||
| period_us = 0; | ||
| return; | ||
| } | ||
|
|
||
| freq_hz = (int) lerp(speed, 0, 255, min_freq_hz, max_freq_hz); | ||
| period_us = 100000 / freq_hz; | ||
|
|
||
| Serial.println("Speed: " + String(speed) + " Freq: " + String(freq_hz) + " Period: " + String(period_us)); | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Update the pulse signal for the stepper motor | ||
| * must be called at sufficient frequency. very minimum of 3-4 times the period of the signal per second | ||
| */ | ||
| void updatePin() { | ||
| if (freq_hz == 0) { | ||
| return; | ||
| } | ||
|
|
||
| if (pulseTimer > period_us) { | ||
| pulseTimer = 0; | ||
| digitalToggleFast(pul_pin); | ||
| } | ||
|
|
||
| } | ||
| }; | ||
|
|
||
| #endif // STEPPER_DRIVER_H | ||
| private: | ||
| int pul_pin; | ||
| int dir_pin; | ||
| int freq; | ||
| int min_freq_hz; | ||
| int max_freq_hz; | ||
| int timer_index; | ||
|
|
||
| /** | ||
| * @brief Performs linear interpolation between two ranges. | ||
| * | ||
| * This function calculates the linear interpolation of a value x | ||
| * from one range (a1, b1) to another range (a2, b2). | ||
| * | ||
| * @param x The value to interpolate. | ||
| * @param a1 The lower bound of the first range. | ||
| * @param b1 The upper bound of the first range. | ||
| * @param a2 The lower bound of the second range. | ||
| * @param b2 The upper bound of the second range. | ||
| * @return The interpolated value in the second range. | ||
| * | ||
| * @note This function assumes that x is within the range [a1, b1]. | ||
| * No clamping is performed if x is outside this range. | ||
| */ | ||
| float lerp(float x, | ||
| float a1, | ||
| float b1, | ||
| float a2, | ||
| float b2) { return a2 + (x - a1) * (b2 - a2) / (b1 - a1); } | ||
|
|
||
| public: | ||
| /** | ||
| * Constructor for Stepper motor driver | ||
| * @param pul_pin The pin to use for the pulse signal | ||
| * @param dir_pin The pin to use for the direction signal | ||
| * @param min_freq The minimum frequency to use for the stepper motor. Default is 100 Hz | ||
| * @param max_freq The maximum frequency to use for the stepper motor. Default is 2000 Hz | ||
| */ | ||
| Stepper(int pul_pin, | ||
| int dir_pin, | ||
| int min_freq = DEFAULT_MIN_STEPPER_FREQ, | ||
| int max_freq = DEFAULT_MAX_STEPPER_FREQ) { | ||
| this->pul_pin = pul_pin; | ||
| this->dir_pin = dir_pin; | ||
| this->freq = 0; | ||
| this->min_freq_hz = min_freq; | ||
| this->max_freq_hz = max_freq; | ||
|
|
||
| this->timer_index = -1; | ||
|
|
||
| // iterate to check if any of the timers are available | ||
| for (int i = 0; i < NUM_TIMERS; ++i) { | ||
| // CASE: timer not in use (callback is still null) | ||
| if (timerCallbacks[i] == nullptr) { | ||
| attachTimerCallback(i, [this]() { this->updatePin(); }); | ||
| this->timer_index = i; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // CASE: there were no timers left, stepper was not properly initialized | ||
| if (this->timer_index == -1) { | ||
| Serial.print("More than "); | ||
| Serial.print(NUM_TIMERS); | ||
| Serial.println(" PIT steppers, the newest one will not be active"); | ||
| } | ||
|
|
||
| // set output pins to open drain configuration | ||
| pinMode(pul_pin, | ||
| OUTPUT_OPENDRAIN); | ||
| pinMode(dir_pin, | ||
| OUTPUT_OPENDRAIN); | ||
|
|
||
| // set speed | ||
| this->setSpeed(freq); | ||
| } | ||
|
|
||
| /** | ||
| * Set the speed of the stepper motor | ||
| * @param speed The speed to set the motor to. -255 to 255 | ||
| */ | ||
| void setSpeed(int speed) { | ||
| // get direction based on speed sign | ||
| int dir = speed < 0 ? 1 : 0; | ||
|
|
||
| // calculate magnitude speed | ||
| speed = abs(constrain(speed, | ||
| -255, | ||
| 255)); | ||
| // set direction pin | ||
| digitalWriteFast(this->dir_pin, | ||
| dir); | ||
|
|
||
| // CASE: set to stop | ||
| if (speed == 0) { | ||
| // set pin pulse low | ||
| digitalWriteFast(this->pul_pin, | ||
| LOW); | ||
| // stop timer | ||
| setTimerFrequency(this->timer_index, | ||
| 0); | ||
| return; | ||
| } | ||
|
|
||
| // update frequency | ||
| int freq_hz = (int) lerp(speed, | ||
| 0, | ||
| 255, | ||
| this->min_freq_hz, | ||
| this->max_freq_hz); | ||
| this->freq = freq_hz; | ||
| setTimerFrequency(this->timer_index, | ||
| freq_hz); | ||
|
|
||
| int period_us = 1000000 / freq_hz; | ||
| Serial.println("Speed: " + String(speed) + " Freq: " + String(freq_hz) + " Period: " + String(period_us)); | ||
| } | ||
|
|
||
| /** | ||
| * Update the pulse signal for the stepper motor | ||
| * called by an interrupt timer at the stepper frequency | ||
| */ | ||
| void updatePin() { | ||
| digitalToggleFast(this->pul_pin); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Naitry marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might be a problem. currently we are using every single one of these. If we want to add any more hardware then we will need to find more options. for now I think this is still a better way of doing things but its something to be aware of
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.pjrc.com/teensy/IMXRT1060RM_rev3_annotations.pdf
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, It's not totally ideal.
We have a couple options if we want to add more steppers controlled with common anode pulses in the future::
If we are bored I think these would both be good upgrades, the dedicated hardware would allow for more full utilization of the teensy, imo
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The registers my first version was using via the docs you linked::

Chapters 51-55 have all the info we need on using the other timers available on the teensy if we want to take that route