/////////////////////////////////
// Generated with a lot of joy and love//
// Started with TUNIOT FOR ESP32 //
// and based on a bunch of internet tutorials //
/////////////////////////////////
/**
* FreeRTOS Stepper Control Multitasking
*
* Based on Digikey Tutorial
* Paralell Stepper Control
* Date: February, 6, 2023
* Author: Paulo Royer
* License: 0BSD
*/
// Needed for atoi()
#include <stdlib.h>
// Include the AccelStepper library:
#include <AccelStepper.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#define CONFIG_FREERTOS_HZ 1000
// Define stepper motor connections and motor interface type. Motor
// interface type must be set to 1 when using a driver:
#define dirPin1 12
#define stepPin1 14
#define motorInterfaceType1 1
#define dirPin2 26
#define stepPin2 27
#define motorInterfaceType2 1
AccelStepper stepper1 = AccelStepper(motorInterfaceType1, stepPin1, dirPin1);
AccelStepper stepper2 = AccelStepper(motorInterfaceType2, stepPin2, dirPin2);
const int potPin = 4;
// variable for storing the potentiometer value
int potValue = 0;
int valueTarget, Target, speed;
String msg = "Valor alvo";
// Use only core 1 for demo purposes
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
// Settings
static const uint8_t buf_len = 20;
// Pins
static const int led_pin = 2;
static const int led_pin_green = 5;
// Globals
static int led_delay = 0; // ms
//*****************************************************************************
// Tasks
void drivein( void * pvParameters ){
while (true){
if(Target==0){
digitalWrite(led_pin_green, HIGH);}
speed = Target - potValue;
if(speed<50 & speed>0){speed=50;}
if(speed>-50 & speed<0){speed=-50;}
// Run the motor forward at (+ or - )200 steps/second until the motor
// reaches potValue steps (2 revolutions):
// Serial.print("| Task motor ");
if(Target !=0){
if(Target == potValue)
{ stepper2.stop();
stepper1.stop();
delay(20);
} else {
if(Target < potValue)
{
stepper2.stop();
stepper1.stop();
delay(20);
} else {
stepper2.setSpeed(speed);
stepper2.runSpeed();
stepper1.setSpeed(speed);
stepper1.runSpeed();
}
if(Target > potValue)
{
stepper2.stop();
stepper1.stop();
delay(20);
} else {
stepper2.setSpeed(speed);
stepper2.runSpeed();
stepper1.setSpeed(speed);
stepper1.runSpeed();
}}}
digitalWrite(led_pin_green, LOW);
}
}
// Task: Blink LED at rate set by global variable
void toggleLED(void *parameter) {
while (1) {
digitalWrite(led_pin, HIGH);
//delay(300);
vTaskDelay(400 / portTICK_PERIOD_MS);
digitalWrite(led_pin, LOW);
vTaskDelay(200 / portTICK_PERIOD_MS);
//delay(300);
}
}
// Task: Read from serial terminal
// Feel free to use Serial.readString() or Serial.parseInt(). I'm going to show
// it with atoi() in case you're doing this in a non-Arduino environment. You'd
// also need to replace Serial with your own UART code for non-Arduino.
void readSerial(void *parameters) {
char c;
char buf[buf_len];
uint8_t idx = 0;
// Clear whole buffer
memset(buf, 0, buf_len);
// Loop forever
while (1) {
// Read characters from serial
if (Serial.available() > 0) {
c = Serial.read();
// Update delay variable and reset buffer if we get a newline character
if (c == '\n') {
led_delay = atoi(buf);
//Serial.print("Valor Alvo: ");
//Serial.println(led_delay);
memset(buf, 0, buf_len);
idx = 0;
} else {
// Only append if index is not over message limit
if (idx < buf_len - 1) {
buf[idx] = c;
idx++;
}
}
}
Target = led_delay;
}
}
void readPot( void * pvParameters ){
while (1){
// Reading potentiometer value
potValue = analogRead(potPin);
vTaskDelay(1 / portTICK_PERIOD_MS);
}
//vTaskDelete(NULL);
}
void SerialOut( void * pvParameters ){
while (1){
Serial.print("| Valor da Serial: ");
Serial.print(led_delay);
Serial.print("| Valor Alvo: ");
Serial.print(Target);
Serial.print("| Valor Potenciômetro: ");
Serial.print(potValue);
Serial.print("| Velocidade: ");
Serial.print(speed);
Serial.println();
//Serial.print(portTICK_PERIOD_MS);
vTaskDelay(2600 / portTICK_PERIOD_MS);
}
//
}
//*****************************************************************************
// Main
void setup() {
// Configure pin
pinMode(led_pin, OUTPUT);
pinMode(led_pin_green, OUTPUT);
speed=100;
// Set the maximum speed in steps per second:
stepper1.setMaxSpeed(2000);
// Set the maximum Acc in steps per square second :
stepper1.setAcceleration(10);
// Set the maximum speed in steps per second:
stepper2.setMaxSpeed(2000);
// Set the maximum Acc in steps per square second :
stepper2.setAcceleration(10);
// Set the current position to 0:
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Configure serial and wait a second
Serial.begin(115200);
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println("Multi-task Stepper Control");
Serial.println("Enter a number 1-4095 that represents the target showed in Potentiometer");
// Start Read Potentiometer
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
readPot, // Function to be called
"Read Pot", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
2, // Task priority
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
// Start blink task
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
toggleLED, // Function to be called
"Toggle LED", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
2, // Task priority
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
// Start serial read task
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
readSerial, // Function to be called
"Read Serial", // Name of task
1024, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
2, // Task priority (must be same to prevent lockup)
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
// Start drivestepper
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
drivein, // Function to be called
"DriveStepper", // Name of task
10000, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
5, // Task priority
NULL, // Task handle
1); // Run on one core for demo purposes (ESP32 only)
// Start SerialOut
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
SerialOut, // Function to be called
"Serial Out", // Name of task
1000, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
2, // Task priority
NULL, // Task handle
0); // Run on one core for demo purposes (ESP32 only)
// Delete "setup and loop" task
vTaskDelete(NULL);
}
void loop() {
// Execution should never get here
}