/////////////////////////////////
// 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
}
A4988
A4988