Using load cell to move servo

Thread Starter

isla

Joined Aug 11, 2020
3
I have a marble sorting project in which I want to use a load cell to move my servo motor a certain degree. I have calibrated the load cell so it measures my weights accurately, but I need to incorporate code that uses this measurement to move the servo. I'm using the Arduino app with an HX711 Library and an Arduino Uno board. Any help is appreciated!!

Calibration Code
#include "HX711.h"
const int LOADCELL_DOUT_PIN = 6;
const int LOADCELL_SCK_PIN = 5;
HX711 scale;
float calibration_factor = 1790; // this calibration factor must be adjusted according to your load cell
float units;
void setup() {
Serial.begin(9600);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
Serial.println("HX711 calibration sketch");
Serial.println("Remove all weight from scale");
Serial.println("After readings begin, place known weight on scale");
Serial.println("Press + or a to increase calibration factor");
Serial.println("Press - or z to decrease calibration factor");
scale.set_scale(calibration_factor); //Adjust to this calibration factor
scale.tare(); //Reset the scale to 0
long zero_factor = scale.read_average(); //Get a baseline reading
Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
Serial.println(zero_factor);
}
void loop() {
scale.set_scale(calibration_factor);
Serial.print("Reading");
units = scale.get_units(), 5;
if (units < 0)
{
units = 0.00;
}
Serial.print("Weight: ");
Serial.print(units);
Serial.print(" grams");
Serial.print(" calibration_factor: ");
Serial.print(calibration_factor);
Serial.println();
if (Serial.available())
{
char temp = Serial.read();
if (temp == '+' || temp == 'a')
calibration_factor += 1;
else if (temp == '-' || temp == 'z')
calibration_factor -= 1;
}
if (Serial.available())
{
char temp = Serial.read();
if (temp == 't' || temp == 'T')
scale.tare(); //Reset the scale to zero
}
}
 

djsfantasi

Joined Apr 11, 2010
9,156
Two things stand out...

The line
units = scale.get_units(), 5;
doesn’t look right. Does it compile?

When you check to see if the input is “t” or “T”, the character may have been gobbled up by your calibration code and you’ll almost never get the temperature character. I wouldn’t do another Serial.read.

As far driving the servo, you have to include the Servo library and initialize the servo properly.

Then, I would consider using the map() command to translate the weight to a servo position. Something like:
servoPos=map(minW,maxW,180,0);
 

Thread Starter

isla

Joined Aug 11, 2020
3
I’m actually not good at coding nor have much knowledge, that’s the code my teacher provided from god knows where. I’ve encoded an LDR to move the servo before and what you’ve put up seems quite similar to part of that code, so i’ll check it out and try incorporate your other suggestions. thankyou :)
 

KeithWalker

Joined Jul 10, 2017
3,063
You can do it in a much simpler way without the servo library. Add a delay at the end of the "void loop()" to make it repeat every 18mS, which is the frame rate of the servo signal. The servo needs a positive pulse, between 1 and 2 mS long to set it's position so take the weight reading from the load cell and scale it to give a result of from 1,000 to 2,000 for the range you require. Make the servo pin HIGH; Then delayMicroseconds (result); and then make the servo pin LOW.
The result will be: Each time round the loop, a new reading will be taken. It will be scaled and a positive pulse with a duration equal to the result will be sent to the servo. Then a delay statement will make the program wait for 18 mS.
Regards,
Keith
 

jpanhalt

Joined Jan 18, 2008
11,087
Then a delay statement will make the program wait for 18 mS.
Regards,
Keith
That works, but ties up the MCU almost full time.

TMR2, or its equivalent, can be set to an 18 ms interrupt. That window is not particularly critical. Inexpensive servos I have used will work with 10 ms to 20 ms easily. TMR2 is used for hardware PWM in PIC's. That is why I suspect any chip capable of hardware PWM will have something equivalent. An interrupt approach frees up the MCU for other stuff, like processing other inputs and driving a display.
 

KeithWalker

Joined Jul 10, 2017
3,063
That works, but ties up the MCU almost full time.

TMR2, or its equivalent, can be set to an 18 ms interrupt. That window is not particularly critical. Inexpensive servos I have used will work with 10 ms to 20 ms easily. TMR2 is used for hardware PWM in PIC's. That is why I suspect any chip capable of hardware PWM will have something equivalent. An interrupt approach frees up the MCU for other stuff, like processing other inputs and driving a display.
My approach to programming is the same as my approach to life; Keep it simple!
I usually use the delay statement to get the frame rate because all the programs I have written for the arduino using servos take a lot less than 18 mS to do everything including checking inputs and updating displays. It's not worth the extra programming needed to play with interrupts.
Regards,
Keith
 

jpanhalt

Joined Jan 18, 2008
11,087
`There is only one time when I have used a micro with only one job. That was my first project when it moved a servo between two positions based on an on/off input. After that , there was usually something else to do, such as read inputs, receive or transmit serial, read switch inputs, calculations, adjust according to user inputs, and of course print to a screen. Of course, except print to/clear a GLCD, nothing took anywhere near a ms.

I didn't mean it was better for a single task, but as a learning exercise for the TS, learning to preserve MCU resources is not wasted effort.
 

djsfantasi

Joined Apr 11, 2010
9,156
Another approach that doesn’t use delays, is to save the number of millis() when an event begins. Then, continue processing while checking if the difference between the current millis() and the start time is >= required delay.

Code:
// event needing a delay
startMS=millis();
while( (millis()-startMS) < delayMS) {
// other processing
}
// next statement after delay
 

Thread Starter

isla

Joined Aug 11, 2020
3
Code:
#include <HX711.h>
const int LOADCELL_DOUT_PIN = 6;
const int LOADCELL_SCK_PIN = 5;
HX711 scale;
float calibration_factor = 1790; // this calibration factor must be adjusted according to your load cell
float units;
void setup() {
Serial.begin(9600);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
Serial.println("HX711 calibration sketch");
Serial.println("Remove all weight from scale");
Serial.println("After readings begin, place known weight on scale");
Serial.println("Press + or a to increase calibration factor");
Serial.println("Press - or z to decrease calibration factor");
scale.set_scale(calibration_factor); //Adjust to this calibration factor
scale.tare(); //Reset the scale to 0
long zero_factor = scale.read_average(); //Get a baseline reading
Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
Serial.println(zero_factor);
}
void loop() {
 #include <Servo.h>
Servo myservo;
 int servoPin = 9;
 ;int pos=0
 // We need to attach the servo to the used pin number
;myservo.attach(9);
myservo.write(pos)=(3.5,66,180,0)
;scale.set_scale(calibration_factor);
Serial.print("Reading");
units = scale.get_units(), 5;
if (units < 0)
{
units = 0.00;
}
scale.set_scale(calibration_factor);
Serial.print("Reading");
units = scale.get_units(), 5;
if (units < 0)
{
units = 0.00;
}
Serial.print("Weight: ");
Serial.print(units);
Serial.print(" grams");
Serial.print(" calibration_factor: ");
Serial.print(calibration_factor);
Serial.println();
if (Serial.available())
{
char temp = Serial.read();
if (temp == '+' || temp == 'a')
calibration_factor += 1;
else if (temp == '-' || temp == 'z')
calibration_factor -= 1;
}
if (Serial.available())
{
char temp = Serial.read();
if (temp == 't' || temp == 'T')
scale.tare(); //Reset the scale to zero
}

Error messages:
Arduino: 1.8.13 (Mac OS X), Board: "Arduino Uno"

sketch_sep16b:62:1: error: expected '}' at end of input
}

exit status 1
invalid use of 'void'

I’m trying to make the weight measured by the load cell move the servo a certain degree :)
Any help with errors or better code options would be much appreciated, this is the first time I've ever used code <3
 

djsfantasi

Joined Apr 11, 2010
9,156
Code:
#include <HX711.h>
const int LOADCELL_DOUT_PIN = 6;
const int LOADCELL_SCK_PIN = 5;
HX711 scale;
float calibration_factor = 1790; // this calibration factor must be adjusted according to your load cell
float units;
void setup() {
Serial.begin(9600);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
Serial.println("HX711 calibration sketch");
Serial.println("Remove all weight from scale");
Serial.println("After readings begin, place known weight on scale");
Serial.println("Press + or a to increase calibration factor");
Serial.println("Press - or z to decrease calibration factor");
scale.set_scale(calibration_factor); //Adjust to this calibration factor
scale.tare(); //Reset the scale to 0
long zero_factor = scale.read_average(); //Get a baseline reading
Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
Serial.println(zero_factor);
}
void loop() {
#include <Servo.h>
Servo myservo;
int servoPin = 9;
;int pos=0
// We need to attach the servo to the used pin number
;myservo.attach(9);
myservo.write(pos)=(3.5,66,180,0)
;scale.set_scale(calibration_factor);
Serial.print("Reading");
units = scale.get_units(), 5;
if (units < 0)
{
units = 0.00;
}
scale.set_scale(calibration_factor);
Serial.print("Reading");
units = scale.get_units(), 5;
if (units < 0)
{
units = 0.00;
}
Serial.print("Weight: ");
Serial.print(units);
Serial.print(" grams");
Serial.print(" calibration_factor: ");
Serial.print(calibration_factor);
Serial.println();
if (Serial.available())
{
char temp = Serial.read();
if (temp == '+' || temp == 'a')
calibration_factor += 1;
else if (temp == '-' || temp == 'z')
calibration_factor -= 1;
}
if (Serial.available())
{
char temp = Serial.read();
if (temp == 't' || temp == 'T')
scale.tare(); //Reset the scale to zero
}

Error messages:
Arduino: 1.8.13 (Mac OS X), Board: "Arduino Uno"

sketch_sep16b:62:1: error: expected '}' at end of input
}

exit status 1
invalid use of 'void'

I’m trying to make the weight measured by the load cell move the servo a certain degree :)
Any help with errors or better code options would be much appreciated, this is the first time I've ever used code <3
You have mismatched braces. The last if statement requires an open brace and then you’ll need another close brace at the end.
 
Top