While loop is slowing down stepper speed

Hello! I'm making honey filling machine with scale (as a feedback). For this project I'm using ACS606 servo drive, BLM57180-1000 servo motor (which is using PWM control),arduino scale, ultrasonic sensor and button. Working principle is : when you press button and ultrasonic sensor sees tare on the scale and program starts. At this moment servo motor is starting and will rotate till tare will be full (reach 600 grams).

But there is a problem: in while loop(marked red) my servo motor is rotating very, very slow. In a clean arduino sketch servo control program piece is working very well and reaches almost max speed. But when I write code here in main program, it almost rotating. When i delete all those Serial.print and etc. only leave servo control program piece , servo is working good. And at that moment my servo never stops, becouse my while loop cant read scale variable (x = scale.get_units(1));

Serial.print(x) using to see if my while loop variable is reading scale value.

Wiring (using arduino MEGA2560):

PUL+ and DIR+ ---- +5V;
PUL- and DIR- ---- 13 and 4 pin.

Scale pins are: DOUT - 40; SCK - 41;

Maybe there is a way how to do it in other way or I dont know something?

#include <Wire.h>
#include "HX711.h"


#define PULS_Pin 13;
#define PULSminus_Pin 12;
#define DIR_Pin 4;
#define DIRminus_Pin 10;

#define DOUT 40
#define SCK 41


// SDA SCL(SCK)
HX711 scale(DOUT, SCK);
float seed = 206.41;          // scale calibration
float x = scale.get_units(1);


int const echoPin = 2;        //ultrasonic sensor
int const trigPin = 3;
int duration, distance;

const int buttonPin = 8;     //button
int buttonState = 0;


void setup() {
  Serial.begin(9600);

  pinMode(buttonPin, INPUT);

  pinMode(13, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  digitalWrite(13, LOW);
  digitalWrite(8, LOW);

  pinMode(echoPin, INPUT);
  pinMode(trigPin, OUTPUT);


  scale.set_scale(seed);
  scale.tare();


}
void loop() {
  x = scale.get_units(1);
  buttonState = digitalRead(buttonPin);

  digitalWrite(trigPin,  HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) / 29.1;



  if (buttonState == HIGH && distance <= 10 && distance >= 0) {

    [color=red]while (x <= 600 )
    {

      Serial.print(x);
      Serial.print("    ");
      x = scale.get_units(1);     //I think this place is stopping motor speed
      Serial.print(x);
      Serial.print("    ");

      digitalWrite(4, HIGH);     //servo motor rotation direction and start
      delayMicroseconds(51);
      digitalWrite(13, HIGH);
      delayMicroseconds(0.85);
      digitalWrite(13, LOW);
      delayMicroseconds(0.85);
      Serial.println("    rotating");

    }[/color]
    
    while (x > 600) {
      Serial.print(x && "   ");
      Serial.println("Done");
      delay(5000);
      break;
    }
  }
  
  else {
    Serial.println("default");
    delay(500);
  }
}

The functions delay() and delayMicroseconds() only take integer arguments. You can’t delay 0.85 microseconds.

johnwasser:
The functions delay() and delayMicroseconds() only take integer arguments. You can’t delay 0.85 microseconds.

Still nothing changes,when i change value to integer.

What does the loop do when you fix the delay and get rid of the serial prints?

CtrlAltElite:
What does the loop do when you fix the delay and get rid of the serial prints?

still it rotates slowly. When i delete x=scale.get_units(1), then my servo reaches max RPM , but my while(x) only reads first value of scale and saves, so servo is rotating all the time. Becouse loop cant reach it goals while (x <=600). For example: serial monitor prints 0.01 0.01 0.01 and etc. Scale variable is not changing.

Which HX711 library are you using? Looking at the first one on google ( https://github.com/bogde/HX711/blob/master/HX711.cpp ) they use shiftin to shift 24 bits.

shiftin uses 2 digitalWrite operations and a digitalRead operation per bit... so that means 24*15 = 360 uS per reading just to read the data... plus, what about is_ready()? is that often not true immediately during normal operation?

IIRC the HX711 was much slower than that, which i suspect is accounted for by the delay in is_ready() - > the problem is a slow sensor read in a time-critical part of the code. If you need to be able to take readings that that fast, I think you'll need a faster ADC.

Also:
delayMicroseconds won't give you less than 1 uS delay, if that (it's not very good at really short delays). But digitalWrite takes around 5uS! (see the benchmark thread over in microcontroller section); you can use direct port manipulation to get it to much less than that, though (most of the time taken for digitalWrite is taken to look up which port and pin the arduino pin number corresponds to).

Are you certain the servo timing is correct?
An 850 nanosecond pulse seems awfully short and overly precise in a mechanical system

You could use the tone() function to generate square waves on the Step pin. It works in the background so your motor can be moving while you are waiting for new data from the scale.

Note: the allowed frequency range is not documented in the official reference. Maybe someone else knows.

johnwasser:
You could use the tone() function to generate square waves on the Step pin. It works in the background so your motor can be moving while you are waiting for new data from the scale.

tone() - Arduino Reference

Note: the allowed frequency range is not documented in the official reference. Maybe someone else knows.

Thanks for help. For know it seems that everything is working well and i can control motor speed via frequency. But another problem appears. When scale reaches 600g. servo motor cant stop rotating. Edit my code a little. Added tone() function in several places. Read program comments.

while (scale.get_units(1) <= 600 )
{

Serial.println(scale.get_units(1));

digitalWrite(4, HIGH); //servo motor rotation direction and start
delayMicroseconds(55);
tone(11,1500); //motor rotation
Serial.println(" rotating");

}

while (scale.get_units(1) > 600) {
tone(11, 0); //by all logic it should stop, but motor still turns very slow noTone() doesnt helpslowly

Serial.print(x && " ");
Serial.println("Done");
delay(5000);
break;
}

Thank you for your help. Tried some other options with noTone() function and it seems that everything is working. :kissing: :kissing: :kissing: :kissing:

As far as I see you are using a stepper motor and NOT a servo. If you edit your Original Post you can correct the title.

A WHILE loop blocks until it completes so it is natural that it would cause things to slow down. Use an IF and allow loop() to do the repetition.

Also, as others have said, you need to get rid of all the delay()s.

...R

I understand it's working now but you're printing 10 or more bytes in your while loop. That's probably not a problem on a Leonardo or Micro because they don't use a uart but native usb, but on e.g. a 328P it will slow down the loop if you do that 600 times. Serial.print writes to a buffer (max size 64 bytes) and when that buffer is full, it will wsit till there is space. And it takes 1 ms @ 9600 baud to get space to place another character in the buffer.

I forgot to include these links in my earlier Reply

Stepper Motor Basics
Simple Stepper Code

...R

Robin2:
As far as I see you are using a stepper motor and NOT a servo. If you edit your Original Post you can correct the title.

He's not using a hobby servo but an ACTUAL industrial servomotor. It's a motor with feedback and a controller that allows absolute positioning: Servomotor - Wikipedia The controller, in this case, uses Step and Direction signals for setting the desired position/speed. To us it looks like a stepper with a Step and Direction control but it can spin much faster and won't lose steps.