Steppermottor control with Loadcell reading

Hi all,

I am creating a compression testing machine for my masters thesis project. I want to control a stepper motor to move in a forward and reverse manner through three differnt push button switches. The three switches are labelled up, down and test. The up switch moves the cross head up, the down switch moces it down and the test switch performs a compression test, which consists of a downward motion to a point then a reversal back to the starting position. Once the test switch is pressed I would like to read in loadcell values from the HX711 amplifier but it doses not seem to allow me to do this while the "stepper.runtoposition" function is operational in the code. Is there a way of moving the motor and reading in loadcell values at the same time? I have attached the files to this post. PLEASE HELP ME - I ONLY HAVE A SHORT AMOUNT OF TIME TO FIX THIS!!!!!`

Welcome to the forum

Start by posting your code correctly

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

1 Like

That's valid for most members. Why are You worth more than them? This forum helpers are usually responding very fast, unless they're in bed sleeping.

I am very sorry for the abruptness, I just am really stuck on this and I must demonstrate a working prototype soon, that's all

OK, I read you are using a stepper motor to run a force into a compression load cell. You are measuring using whatever load cell you have and a HX711.

Where in your code are you looking at your load cell data? This goes much better when your code is properly posted so those reading it can interpret it. Looking at your images of code where are you doing a serial. Print?

I do not see where you are taking your data and making it into something readable?

serial.Print() Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is.

Ron

1 Like

That is not a very good description of the problem. Please elaborate and describe how you have tried to troubleshoot the issue. For example, have you added print statements (why the slow 9600 baud?) or searched on "(accelstepper OR stepper) hx711 interference" or something like that?

Also, the screenshots you posted don't seem to show any HX711 reads. (Yes, please do post your full code correctly, as mentioned in post #2.)

The HX711 can do either 80 sps or 10 sps. Which is yours set to do?

You have a problem in that .runToPosition() is a blocking command and the program can do nothing else while the stepper is moving. You will need to review the non blocking functions in the library. https://hackaday.io/project/183279-accelstepper-the-missing-manual/details

Furthermore, reading the HX711, depending on the library used can also be blocking. Depending on how fast you are trying to move the stepper this can be an issue.

There is a fork from one library which has a non blocking read function.
https://github.com/Srijal97/HX711

1 Like

Thank you very much, I will try these solutions and see if they work.

Are you talking about steps per second? does the rate at which the load cell read values depend on the baud?

Sorry to all answering this post. I have attached screenshots of the code with the loadcell reading values from a function file. This is the file I was meant to originally post. Does this clear the situation up on how I was trying to read in values and print to screen while the motor is running?
image

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

1 Like

Hi all,

I have tried to alter the code slightly to find the point of failure. I have deleted all delays and used the suggestion by @cattledog to use non-blocking functions, but it is still just incrementally moving in steps at the same rate the loadcell velues are being read in. I have turned the baud rate up to the highest value to see if this made any difference, bu there was none. I am sorry to be such a newbie to this arduino coding, it must be trivial for experts like you. I am open to any other suggestions and comments. I have also attached screenshots of the altered code again

Stop posting pictures of code and follow the advice that you have been given twice already in this topic

1 Like
#include <AccelStepper.h>
#include <HX711.h>
#define DOUT  3
#define CLK  2 
HX711 scale;
void CalibrationLoadCell();

AccelStepper stepperforward(AccelStepper::FULL4WIRE, 8, 9, 10, 7);
AccelStepper stepperbackward(AccelStepper::FULL4WIRE, 8, 9, 10, 7);
AccelStepper stepper(AccelStepper::FULL4WIRE, 8, 9, 10, 7);

const int uppin = 6;
const int downpin = 5;
const int testpin=4; 
int uppinstate = 0;
int downpinstate = 0;
int testpinstate = 0;



void setup() {
  // put your setup code here, to run once:
    Serial.begin(2000000);
    scale.begin(3,2);
    scale.set_scale(102.637);
    
    pinMode(uppin, INPUT);
    pinMode(downpin, INPUT);
    pinMode(testpin, INPUT);
    stepperforward.setMaxSpeed(700);
    stepperbackward.setMaxSpeed(-700);
    stepperforward.setSpeed(700);
    stepperbackward.setSpeed(-700);

    digitalWrite(uppin, LOW);
    digitalWrite(downpin, HIGH);
    digitalWrite(testpin, HIGH);
   
}
void loop() {


  testpinstate=digitalRead(testpin);
  uppinstate = digitalRead(uppin);
  downpinstate = digitalRead(downpin);

 if (testpinstate == LOW) 
  {
  stepperforward.setCurrentPosition(0);
  int revolutions = 2;
  stepperforward.move(10000) ;
  while (stepperforward.currentPosition()<stepperforward.targetPosition())
  stepperforward.runSpeedToPosition();
   Serial.print(stepperforward.currentPosition());
   CalibrationLoadCell();
   //else
   //Serial.println("Not Testing");
  }
  //stepperbackward.move(-10000);
  //stepperbackward.runSpeedToPosition()
      
if (uppinstate == HIGH)
 {
  stepperbackward.runSpeed();  
  CalibrationLoadCell();  
 }
if (downpinstate == LOW)
{
  stepperforward.runSpeed();
  CalibrationLoadCell();
} 
      
}  
1 Like

Where’s Calibrationloadcell?

The logic around the while doesn’t match its indenting:

Try tools/autoformat

void CalibrationLoadCell() 
{
  scale.set_scale(102.637);
  float grams=scale.get_units(15);
  float grams_new=grams-822.5-211;
  float newtons= grams_new*0.0098;
  Serial.print(grams_new,1);
  Serial.print(",");
  Serial.print(newtons,1);
  Serial.println();//

}

I have tried the autoformat command but it did not seem to do anything. I have uploaded the calibrationloadcell code also

This looks suspicious. Why would you do it this way? instead of just using the one stepper.* object? I'd bet the objects would lose state when you switched objects and maybe skip a step or two.

ETA: Here's the code posted so far, concatenated, and autoformatted:

#include <AccelStepper.h>
#include <HX711.h>
#define DOUT  3
#define CLK  2
HX711 scale;
void CalibrationLoadCell();

AccelStepper stepperforward(AccelStepper::FULL4WIRE, 8, 9, 10, 7);
AccelStepper stepperbackward(AccelStepper::FULL4WIRE, 8, 9, 10, 7);
AccelStepper stepper(AccelStepper::FULL4WIRE, 8, 9, 10, 7);

const int uppin = 6;
const int downpin = 5;
const int testpin = 4;
int uppinstate = 0;
int downpinstate = 0;
int testpinstate = 0;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(2000000);
  scale.begin(3, 2);
  scale.set_scale(102.637);

  pinMode(uppin, INPUT);
  pinMode(downpin, INPUT);
  pinMode(testpin, INPUT);
  stepperforward.setMaxSpeed(700);
  stepperbackward.setMaxSpeed(-700);
  stepperforward.setSpeed(700);
  stepperbackward.setSpeed(-700);

  digitalWrite(uppin, LOW);
  digitalWrite(downpin, HIGH);
  digitalWrite(testpin, HIGH);

}
void loop() {

  testpinstate = digitalRead(testpin);
  uppinstate = digitalRead(uppin);
  downpinstate = digitalRead(downpin);

  if (testpinstate == LOW)
  {
    stepperforward.setCurrentPosition(0);
    int revolutions = 2;
    stepperforward.move(10000) ;
    while (stepperforward.currentPosition() < stepperforward.targetPosition())
      stepperforward.runSpeedToPosition();
    Serial.print(stepperforward.currentPosition());
    CalibrationLoadCell();
    //else
    //Serial.println("Not Testing");
  }
  //stepperbackward.move(-10000);
  //stepperbackward.runSpeedToPosition()

  if (uppinstate == HIGH)
  {
    stepperbackward.runSpeed();
    CalibrationLoadCell();
  }
  if (downpinstate == LOW)
  {
    stepperforward.runSpeed();
    CalibrationLoadCell();
  }

}

void CalibrationLoadCell()
{
  scale.set_scale(102.637);
  float grams = scale.get_units(15);
  float grams_new = grams - 822.5 - 211;
  float newtons = grams_new * 0.0098;
  Serial.print(grams_new, 1);
  Serial.print(",");
  Serial.print(newtons, 1);
  Serial.println();//

}
1 Like

From reading your code and description, I think you want to get some sort of stress-strain data out of your system. Maybe at every 10000 steps, or maybe within the 10000 steps. it is unclear.

This is still blocking because of the while loop:

    while (stepperforward.currentPosition() < stepperforward.targetPosition())
      stepperforward.runSpeedToPosition();

Do you want load measurements at intervening steps? Or just after the move completes?

I'd suggest adding curly braces {} after the while(), enclosing everything that should be done during the move, or dropping the while blocking completely and just using the loop(). I'd also suggest:

Thank you very much for the help, I will test these suggestions and get back to you. Yes I do want to output a stress strain curve for data that is collected at a certain time iteration while the motor is running not only at the end of the operation. The motor does do a strange thing also, where it switches direction when it is under load, could this be due to the seperate use of the Accelstepper function?