(Solved)Steppermotor and serial.print and read combined

Paco, As far as I can see the only speed limitation is the frequency of getting samples from the scale. I don't think that has anything to do with digitalWrite() being slow and using any other function won't speed it up.

If you are content with 10 (or 80) samples per second (sps) then all you need to do is decouple the reading of the scale from the individual steps of the motor.

For simplicity, let's work on 10sps.

You say you want the motor to cause 1mm of movement in one second, or, more usefully 0.1mm of movement between samples. How many steps must the motor make to acheive 0.1mm of movement?

When we know this, we can work out how to program things. It may be necessary/convenient/useful to make a small change to the library but let's leave that for the moment.

...R

Hi Robin,

Sorry I confused you with the steps.
I reframe.....
200 stepper steps is 360 degree = 2 mm pitch/compression
100 stepper steps is 180 degree = 1 mm pitch/compression
1mm over 1 second is 10 samples = 1 sample per 0,1 mm
I have no objection to step slower but then measuring takes a longer time.
Lets say the average compression is 35 mm that would take 35 seconds to go down.
If you measure 5 times in a row that would be 10 times 35 seconds as we also have to return the motor to its original position.
For this debugging I have no problem stay with this timeframe.
In a later stage I can always enhance.

then all you need to do is decouple the reading of the scale from the individual steps of the motor.

You mean controlling the stepper with its own controller?

backbone:

then all you need to do is decouple the reading of the scale from the individual steps of the motor.

You mean controlling the stepper with its own controller?

No. Based on the numbers you have supplied all I mean is that you get the stepper to move 10 steps at 0.01 second intervals between each reading of the scale. If I recall correctly, your earlier code only moved it one step between each reading.

...R

OK so the timingtable/storyboard should look like this:
1]
Start puls received from PC
Startflag = 1
Read in maximum value of compression ....35 mm from PC so counterMax is 35
Save current raw force value > rawValue.
Start rotation downwards in 18 degree steps = 0.1 mm
1 sample per 18 degree step = 0.1 mm
Measure raw force value each 18 degree step
rawValueOld = rawValue

2]
If rawValue > rawValueOld
counter = 0
Recordingflag = 1
send reset signal to pc so force value is set to zero
send reset signal to pc to start recording force and step value
Rotate motor in 180 degree steps
Serial.print(rawvalue)
Serial.print(counter)
Counter--
3]
if counter == counterMax (35)
Recordingflag = 0
Returnflag = 1
send reset signal to pc to stop recording force and step value
Rotate motor in 180 degree steps upwards
counter++
4]
if counter = - 4
Stop motor
Startflag = 0
Returnflag = 0

Paco

Hi Paco,
I have to confess I can't follow your steps (perhaps because I am not as familiar with the experiment).

I'm not sure if this helps but the logic in my head is a bit like this

for (number of scale readings) {
read scale
for (10 steps) {
step motor
wait 0.01 sec
}
}

...R

Robin,

I have viewed your idea several times but I cant get the grip on it. Sorry.
What can we do to solve that (if we can :slight_smile: )
Do I understand correct that the motor will stop for 0.01 sec?

On facebook I have a video of what the software at the PC side can do although that was with a manual drillstand and encoder strip recorded!.Maybe that gives a better feeling on it.

Do not know if you can view it.
Let me know otherwise I have to search for an other option.

I have looked at your video but it doesn't tell me anything about the Arduino system.

I have been trying to match the information you have given me and the information I got from a brief read of the PDF for the scale interface.

I thought you said that 10 steps of the motor cause 1mm movement of the spring (or whatever). And that one reading of the scale every 0.1 seconds would be adequate. I put those together and came to the conclusion (perhaps wrong) that you need 10 steps of the motor between every scale reading and that would correspond with one step of the motor every 1/100th of a second. (And, yes, I know this is not watertight logic, but it explains my thinking).

Can you confirm if I have understood you properly, and if not please correct me.

Then you ask if the stepper motor will stop every 1/100th of a second and the answer is probably YES. That's how stepper motors work. I say "probably" because the momentum of the motor may carry it forward while the load will try to stop it.

Hope this helps.

if not, please try to explain what you don't understand.

...R

Hi Robin,

The video was more to show that all should go in a fluent motion.

Ok here he comes again, no problem
The basic of the hardware.
1 stepper motor
1 leadscrew axle with 2 mm pitch
1 load cell.
Stepper motor full rotation = 360 degrees
With a leadscrew pitch of 2 mm each full rotation of 360 degrees of the motor the spring is compressed 2 mm.
2 mm steps are to large for fine measurments so we prefer avalue like 1 mm or less.
So to get 1mm compression we only have to turn 180 degrees.
If we want to compress 0.1 mm we ony have to turn 18 degrees.
The steppermotor I use has 200 steps for 360 degrees rotation.
100 steps is 180 degrees = 1 mm
10 steps is 18 degrees = 0.1 mm

Are you still with me? :slight_smile:

I put the spring on the loadcell bottomcone and the loadcell now will give a certain value if we would measure it.
The spring is still uncompressed as the topcone part that moves down is not in contact yet. So first basic point is to find that TOUCHING POINT.
Now we can do this manually but turning the steppermotor by hand and look at the loadcell value when it starts to become higher, but we are trying to automate the measurement so we like to skip that manual part and do it fully automaticly to reduce time. Now we have to electronicly find the point where the topcone touches the top of the spring.
We can do that easily by measuring the point where the value on the loadcell starts to rise.
The HX711 lib slows down the steppermotor as each reading takes average 90 ms and we cant speed this up we found out.
So catching this first TOUCHING POINT is the key problem of this combo stepper and HX711.

Am I correct sofar and can you folow the basics of the project?

Paco

I think I understand what you want to do.

I will try to write a complete demo sketch later today (well, give me 24hrs).

Perhaps the concept you are missing is that, although you can't read the scale more than (say) 10 times per second it doesn't take long to read it if the scale is ready to provide data. So my notion is to move the motor while the scale is getting itself ready.

...R

I've written the following demo code. It compiles for me on an Uno but, of course I can't run it.

The code just tests how long it takes to move the motor 10 steps followed by a single read of the scales. The steps happen at intervals of 10 millisecs. As far as I can see that should give enough time for the scale to be ready so the scale.read() should return a value almost instantly. My plan is to prove (or disprove) this assumption by running the tests with the scale.read() line commented out and then with it active. If my assumption is correct there will be very little difference in the two sets of timings.

If there is a signficant difference in the timings perhaps you would increase the interval to 20 msecs and try again. If that solves the problem find the smallest interval that works.

Note that I added the line #include "HX711.h" because I didn't save the HX711 stuff into my libraries directory. You can delete that line.

I hope this brings you forward a little bit.

...R

// this is just to test the understanding of using the HX711

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

// HX711.DOUT	- pin #A1
// HX711.PD_SCK	- pin #A0

HX711 scale(A1, A0); // 24 bit load cell amplifier

unsigned long startMillis;
unsigned long endMillis;
unsigned long currMillis;
unsigned long prevMillis;
unsigned long intervalMillis = 10;

byte maxTests = 5;
byte curTest = 1;

byte maxSteps = 10;
byte curStep = 1;

long scaleData = 0;

byte ledPin = 13; // onboard led

void setup() {

  Serial.begin(9600);
  Serial.println("Starting DemoCode1.ino");
  
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); 

  prevMillis = millis();
}

void loop() {

  if (curTest > maxTests) {
    return;
  }
  startMillis = millis();
  curStep = 0;
  testTiming();
  endMillis = millis();
  Serial.print("Test ");
  Serial.print(curTest);
  Serial.print(" Time  ");
  Serial.println(endMillis - startMillis);
  curTest ++;

}

void testTiming() {
  
  while (curStep < maxSteps) {  // will loop through the steps at the speed set by intervalMillis
    currMillis = millis();
    if (currMillis - prevMillis >= intervalMillis) {
       stepMotor();
       prevMillis += intervalMillis;
       curStep ++;
    }
  }
  // now the Scale should be ready for reading
  scaleData = scale.read();
}

void stepMotor() {
  // something visible as an alternative to actually doing motor code
  digitalWrite(ledPin, ! digitalRead(ledPin));
}

Edited code to correct an error in the placement of currMillis = millis(); ...R

Robin,

Thanks for the demo code and the time.
I tried it with all suggested options like 10 up to 100 ms
With and without comment line for scaleData = scale.read();
Also removed the extra HX711.h line in the top.
Only line that is printed in the serial monitor = Starting DemoCode1.ino.

:~

Paco

Look at my code carefully - there is probably some stupid mistake.

I will look at it in the morning.

...in the morning.

Just as I thought - stupid mistake. I had currMillis = millis(); in the wrong place and it was never being updated.

I have corrected the code in the earlier post.

I realized that I can run the program on my Uno with the call to scale.read() commented out.

...R

We have a BINGO.
If 10 is selected all readings are 100.
I raised the sample numbers from 5 to 100.
All OK.
Then I lowered to 90 but then I get readings radom ranging from 89 to 91.
So no need to go higher but low is not prefered. :slight_smile:

Paco

backbone:
We have a BINGO.
If 10 is selected all readings are 100.
I raised the sample numbers from 5 to 100.
All OK.
Then I lowered to 90 but then I get readings radom ranging from 89 to 91.
So no need to go higher but low is not prefered. :slight_smile:

Paco

You need to be a lot more precise.
Do you mean that you changed the maxTests value from 5 to 100 and it still worked?
By "alll readings" do you mean with and without the scale.read() command?

What did you lower to 90?
I wonder if you mean that you lowered intervalMillis to 9 (not 90)?
In what circumstances did you get 89 and when did you get 91?

Did you get it to print scaleData so you could see if it is giving correct values? (I have no way to test that).

Do you know what to do next or do you need some more advice?

...R

Sorry for half info.

Do you mean that you changed the maxTests value from 5 to 100 and it still worked?
YES

I wonder if you mean that you lowered intervalMillis to 9 (not 90)?

YES and then the result is random between 89 and 91.
If I lower intervalMiliis to a lower value like 8 or 7 the random numbers are more and more varying in larger up and down values like 65 to 73 for 7 intervalMiliis value.

By "alll readings" do you mean with and without the scale.read() command?

did not changed the standard setting yet.

Did you get it to print scaleData so you could see if it is giving correct values? (I have no way to test that).

Will test this evening.

I let you know if I need more of your time :slight_smile:

Paco

backbone:
did not changed the standard setting yet.

[sound] grinding of teeth in frustration [/sound]

The whole / the ONLY / point of the code was to try it with and without the call to scale.read().

Looking at the results with and without scale.read() makes even MORE sense when you change intervalMillis.

And checking that scale.read() gets sensible values will, of course, also be essential.

My jaw has now unclenched - have fun :slight_smile:

...R

Robin,

Please do not be frustrated. Sorry if I made you feel that way. Not my intention.
I have limited time sometimes.
See the pictures.
One with the commented line the other without.
Also the added line for the serial print of the load cell does not change the timing reading.
Results for 20 readings all the same except for the first one.
The reading of the loadcell value also stays the same.

Paco

It looks a bit strange to be showing scaleData values when the scale.read() is commented out ?????

Also, you haven't said whether the scaleData values are correct. Not much point moving forward until they are.

...R

Robin,
Your correct about the two files showed.
My mistake. It seems I only make mistakes lately.
I forgot to upload the new sketch so the serial monitor showed same sketch.
This added file3.jpg with the serial monitor shows the values with lines commented out.
The value of the load cell is correct.
This just a raw value of the milivolts from the load cell amplified by the HX711.

Paco

Thanks Paco.

Now you can see how it is possible to move the motor and read the scale without the process of reading the scale slowing things down.

What next?

...R