Fixing arduino uno problem

#include <Stepper.h>
#include <TM1637Display.h>

const int stepsPerRevolution = 200; // Change this to fit the number of steps per revolution for your motor 
const int switchPin = 2;            // Define the pin connected to the switch (adjust as needed)

// Initialize the stepper library on pins 2 through 4
Stepper myStepper(stepsPerRevolution, 2, 4);

// Define the CLK and DIO pins for the TM1637 display
const int CLK = 7;  // Clock pin
const int DIO = 8;  // Data pin
TM1637Display display(CLK, DIO);

void setup() {
  pinMode(switchPin, INPUT_PULLUP); // Configure the switch pin as input with internal pull-up resistor

  display.setBrightness(0x0f); // Set display brightness (0x0 to 0x0f)
}

void loop() {
  // Read the sensor value
  int sensorReading = analogRead(A2);
  // Map it to a range from 0 to 100
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);

  // Display the speed percentage on the 4-digit display
  display.showNumberDec(motorSpeed, false); // Display number, false means no leading zeros

  // Read the switch state
  int switchState = digitalRead(switchPin);

  // Set the motor direction based on the switch state
  if (switchState == LOW) {
    myStepper.step(stepsPerRevolution / 100);  // Clockwise
  } else {
    myStepper.step(-stepsPerRevolution / 100); // Counter-clockwise
  }

  // Set the motor speed and step
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
  }

  delay(100); // Optional delay to reduce flickering and update rate
}

i am using this code to control a steper motor using a potentiometer and displaying the speed percentage on an 4-digit display but i seems like the arduino "el lego uno " that i am using can't multitask if the speed is dispalyed the motor is not moving(wich is the case in this code" but if i am using the the following code (without display) the motor move in both directions perfectly and i really want to accomplich both tasks controlling the stepper motor and display the speed on the 4-digit screen `#include <Stepper.h>

const int stepsPerRevolution = 200; // Change this to fit the number of steps per revolution for your motor
const int switchPin = 2; // Define the pin connected to the switch (adjust as needed)

// Initialize the stepper library on pins 2 through 4
Stepper myStepper(stepsPerRevolution, 2, 4);

void setup() {
pinMode(switchPin, INPUT_PULLUP); // Configure the switch pin as input with internal pull-up resistor
}

void loop() {
// Read the sensor value
int sensorReading = analogRead(A2);
// Map it to a range from 0 to 100
int motorSpeed = map(sensorReading, 0, 1023, 0, 100);

// Read the switch state
int switchState = digitalRead(switchPin);

// Set the motor direction based on the switch state
if (switchState == LOW) {
myStepper.step(stepsPerRevolution / 100); // Clockwise
} else {
myStepper.step(-stepsPerRevolution / 100); // Counter-clockwise
}

// Set the motor speed and step
if (motorSpeed > 0) {
myStepper.setSpeed(motorSpeed);
}
}`

You probably should do the display only when the speed actually changes, rather than every time through the loop (which should also allow you to get rid of the delay(), which certainly isn't helping the motor speed.)

Hi @a07sohaib ,

Welcome. After taking a look at your code and your comment there are some details to start with, maybe after a little cleanup and work you might be able to go on.

First concept to get clear from the start: the multitask on ANY single core MCU, including the one in an Arduino UNO, is achieved by the magic of software, one with the capabilities of lending the processor time to execute one task, then switch to another task and lending the same processor to other task and so on, giving a little piece of attention to each task to advance them in what appears to be simultaneous advancing.
From the most basic piece of software needed for the basic processor time assignement (let's name it The Scheduler) to the most advanced cappabilities as sharing the data between tasks, and blocking simultaneous data access (a complete Operating System), it's software.
There are implementations of such software designed to run on the MCU of your UNO, but they take great part of the resources (memory and processor time) to manage the tasks... better left for more powerful and resourcefull MCUs.
What you CAN do is use your resources appropiately to run your simple program without problems, that would include:
_ Put the variable definitions in the correct part of the program and don't repeat the declaration and value assignation in every loop. (in this case move the sesorReading, motorSpeed declarations out of te loop())
_ AVOID using blocking methods or functions like your delay(100) in your code, replace it with code checking the time elapsed by the use of millis() for starters.

  • Considering those two previous suggestions given, give it a try and comment on the results.

Good Luck!

Gaby.//

1 Like

if the motor speed is mapped from 0-100, won't the # of steps - stepsPerRevolution / 100 never be > 0 since stepsPerRevolution is 200 and this is integer math?

#include <Stepper.h>
#include <TM1637Display.h>

const int stepsPerRevolution = 200; // Change this to fit the number of steps per revolution for your motor 
const int switchPin = 2;            // Define the pin connected to the switch (adjust as needed)

// Initialize the stepper library on pins 2 through 4
Stepper myStepper(stepsPerRevolution, 2, 4);

// Define the CLK and DIO pins for the TM1637 display
const int CLK = 7;  // Clock pin
const int DIO = 8;  // Data pin
TM1637Display display(CLK, DIO);

// Variables to hold sensor reading and motor speed
int sensorReading = 0;
int motorSpeed = 0;

unsigned long previousMillis = 0;    // Stores the last time the motor was updated
const long interval = 100;           // Interval at which to update (milliseconds)

void setup() {
  pinMode(switchPin, INPUT_PULLUP); // Configure the switch pin as input with internal pull-up resistor

  display.setBrightness(0x0f); // Set display brightness (0x0 to 0x0f)
}

void loop() {
  unsigned long currentMillis = millis();

  // Check if it's time to update the motor and display
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Read the sensor value
    sensorReading = analogRead(A2);
    // Map it to a range from 0 to 100
    motorSpeed = map(sensorReading, 0, 1023, 0, 100);

    // Display the speed percentage on the 4-digit display
    display.showNumberDec(motorSpeed, false); // Display number, false means no leading zeros

    // Read the switch state
    int switchState = digitalRead(switchPin);

    // Set the motor direction based on the switch state
    if (switchState == LOW) {
      myStepper.step(stepsPerRevolution / 100);  // Clockwise
    } else {
      myStepper.step(-stepsPerRevolution / 100); // Counter-clockwise
    }

    // Set the motor speed
    if (motorSpeed > 0) {
      myStepper.setSpeed(motorSpeed);
    }
  }
}
it is always the same issue 

stepsPerRevolution is a constant 200 so the stepper will always take 2 steps, regardless of motorSpeed

1 Like

You are just delaying 100 ms each time through loop, but then updating your display and doing the stepping. Those two tasks need to be on different time scales. Update your display every second, update your stepper every time through loop. Updating the display does take time and will cause a bit of lag in your motor movement

#include <Stepper.h>
#include <TM1637Display.h>

const int stepsPerRevolution = 200; // Change this to fit the number of steps per revolution for your motor
const int switchPin = 2;            // Define the pin connected to the switch (adjust as needed)

// Initialize the stepper library on pins 2 through 4
Stepper myStepper(stepsPerRevolution, 2, 4);

// Define the CLK and DIO pins for the TM1637 display
const int CLK = 7;  // Clock pin
const int DIO = 8;  // Data pin
TM1637Display display(CLK, DIO);

// Variables to hold sensor reading and motor speed
int sensorReading = 0;
int motorSpeed = 0;

unsigned long previousDisplayMillis;
unsigned long previousStepperMillis;

const unsigned long displayInterval = 500;  // Interval to update display
const unsigned long stepperInterval =  10;  // Interval to update stepper

void setup() {
  pinMode(switchPin, INPUT_PULLUP); // Configure the switch pin as input with internal pull-up resistor

  display.setBrightness(0x0f); // Set display brightness (0x0 to 0x0f)
}

void loop() {
  unsigned long currentMillis = millis();

  // Check if it's time to update the motor
  if (currentMillis - previousDisplayMillis >= displayInterval) {
    previousDisplayMillis = currentMillis;

    // Display the speed percentage on the 4-digit display
    display.showNumberDec(motorSpeed, false); // Display number, false means no leading zeros
  }

  // Check if it's time to update the motor
  if (currentMillis - previousStepperMillis >= stepperIinterval) {
    previousStepperMillis = currentMillis;

    // Read the sensor value
    sensorReading = analogRead(A2);
    // Map it to a range from 0 to 100
    motorSpeed = map(sensorReading, 0, 1023, 0, 100);

    // Read the switch state
    int switchState = digitalRead(switchPin);

    // Set the motor direction based on the switch state
    if (switchState == LOW) {
      myStepper.step(stepsPerRevolution / 100);  // Clockwise
    } else {
      myStepper.step(-stepsPerRevolution / 100); // Counter-clockwise
    }

    // Set the motor speed
    if (motorSpeed > 0) {
      myStepper.setSpeed(motorSpeed);
    }
  }
}

Hi @a07sohaib ,

Looking at the changes to your code, first thing first, you still have variables declared once and again in your code:

Second, @blh64 made a good point about the unneeded and time consuming display updating. And I'm using updating instead of refreshing because you're using a TM1637 display module, that keeps the 7 segments display ports refreshed with the last "text/number" you sent it.

That means that -as @blh64 stated- you don't need to rewrite it so often...

But I'll go a step further: you don't need to update your display at all if you don't have a new value to replace the one being exhibited. So the next step I'll suggest is: keep track of the previous value for the motorSpeed, if the value has not changed avoid rewriting the display.

Good Luck!

Gaby.//

There is a solution to this problem through using a different stepper-motor-library.
This library is called MobaTools. The MobaTools-library create the step-pulses based on a timer-interrupt. This means the step-pulse-creation is done in the background always just in the right time regardless of what the main-code is doing in this moment.

Here is a WOKWI-Simulation that demonstrates this

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *


/*  Example for MobaTools
    Moving a stepper back and forth
*/
#include <MobaTools.h>
#include <TM1637Display.h>

// Adjust pins, steps and time as needed
const byte stepPin = 3;
const byte dirPin  = 2;
const int stepsPerRev = 400;   // Steps per Revolution ( example with 1/4 microsteps )
const long  targetPos = 1600;         // stepper moves between 0 and targetpos
int enable = 10;
long nextPos;
long Speed;
long PotVal;
long JoyStick = A2;
long Direction;
long speed;
long ActualStep;



MoToStepper myStepper ( stepsPerRev, STEPDIR );
MoToTimer stepperPause;                    // Pause between stepper moves
bool stepperRunning;

// Define the CLK and DIO pins for the TM1637 display
const int CLK = 7;  // Clock pin
const int DIO = 8;  // Data pin
TM1637Display display(CLK, DIO);


void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Setup-Start");
  myStepper.attach( stepPin, dirPin );
  myStepper.setSpeed( 600 );  // 60 Rev/Min ( if stepsPerRev is set correctly )
  myStepper.setRampLen( 50 );
  stepperRunning = true;
  pinMode(enable, OUTPUT);
  pinMode(PotVal, INPUT);
  digitalWrite(enable, LOW);
  display.setBrightness(0x0f);
}

void loop() {

  Direction = analogRead(JoyStick);         //read value of Joystick
  ActualStep = myStepper.read();            //read the actual step of the motor

  //Serial.println(ActualStep);
  //dbgc("ToL",ActualStep);
  dbgc("ToL",Direction);
  if (Direction <= 500) {                   //move the stepper CW infinitively
    speed = (500 / Direction) * 4;
    dbgc("Dir< 500",speed);
    myStepper.setSpeed(speed);
    myStepper.rotate(1);
  }
  else if (Direction >= 520) {              //move the stepper CCW infinitively
    speed = (500 / (1023 -Direction) ) * 4;
    dbgc("Dir >= 520",speed);
    myStepper.setSpeed(speed);
    myStepper.rotate(-1);

  }
  else {
    myStepper.stop();
  }

  display.showNumberDec(speed, false);
}  

Did you re-write your code so it does as post #3 suggests?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.