Hello,
I am working on a project regarding tension control, however, this issue seems to possibly be a misunderstanding of sensors.
In this setup, tension is measured by using a dancer to apply force to a load cell (FSG15N1A).
As far as I understand, the HX711 amplifier uses the DAT pin and the CLK pin primarily for transmitting data. The CLK pin tells the DAT pin when to go to "low" and transmit data. We are clearly able to see values using the pins and code that have been developed for the HX711 amplifier and have calibrated it well.
However, we are not able to see a variable input from the amplifier when putting the Arduino pins for HX711 measurement and a PID input in series on a breadboard.
When they are in series, the A0 PID input reads 790 constantly, but the output adjusts to applied loads.
If I simply hook up the DAT pin to the A0 PID input, it reads 676.
I am very confused as to why the PID loop is clearly adjusting for tension in the output but we never read a change in input due to loading.
Wiring schematic attached. NOTE: The area labeled "series" connecting pin AO, 26, and DAT are truly in series on a breadboard unlike they are drawn.
//----------------- AMPLIFIER -----------------
#include "HX711.h"
#define DOUT 26
#define CLK 24
HX711 scale(DOUT, CLK);
float calibration_factor = -69360; //-7050 worked for my 440lb max
//----------------- MOTOR DRIVER --------------
// Motor A
int in1 = 8;
int in2 = 7;
// Motor B
int in3 = 6;
int in4 = 5;
// ----------------------------PID-----------------
#include <PID_v1.h>
#define Constant 2
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
int inputPin=0, outputPin=3;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,0.7,0.5,.1,P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used
//P_ON_E (Proportional on Error) is the default behavior
unsigned long serialTime; //this will help us know when to talk with processing
void setup()
{
// -----------------AMPLIFIER -------------
Serial.begin(9600);
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();
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);
// ----------------------PID ------------------
{
//initialize the variables we're linked to
//initialize the serial link with processing
Serial.begin(9600);
Input = analogRead(inputPin);
Setpoint = 815;
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
//-----------------MOTOR DRIVER -------------
// Set all the motor control pins to outputs
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
}
void loop() {
// -----------------AMPLIFIER --------------
scale.set_scale(calibration_factor); //Adjust to this calibration factor
Serial.print("Reading: ");
Serial.print(scale.get_units(), 3);
Serial.print(" g");
Serial.print(" calibration_factor: ");
Serial.print(calibration_factor);
Serial.println();
if(Serial.available())
{
char temp = Serial.read();
if(temp == '+' || temp == 'a')
calibration_factor += 10;
else if(temp == '-' || temp == 'z')
calibration_factor -= 10;
}
// -----------------PID ------------------------------
{
//pid-related code
Input = analogRead(inputPin);
myPID.Compute();
analogWrite(outputPin,Output);
analogWrite(Constant, 255);
//send-receive with processing if it's time
if(millis()>serialTime)
{
SerialReceive();
SerialSend();
serialTime+=500;
}
}
//MOTOR DRIVER ----------
// Set Motor A forward
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set Motor B forward
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(Constant, 255);
}
/********************************************
* Serial Communication functions / helpers
********************************************/
union { // This Data structure lets
byte asBytes[24]; // us take the byte array
float asFloat[6]; // sent from processing and
} // easily convert it to a
foo; // float array
// getting float values from processing into the arduino
// was no small task. the way this program does it is
// as follows:
// * a float takes up 4 bytes. in processing, convert
// the array of floats we want to send, into an array
// of bytes.
// * send the bytes to the arduino
// * use a data structure known as a union to convert
// the array of bytes back into an array of floats
// the bytes coming from the arduino follow the following
// format:
// 0: 0=Manual, 1=Auto, else = ? error ?
// 1: 0=Direct, 1=Reverse, else = ? error ?
// 2-5: float setpoint
// 6-9: float input
// 10-13: float output
// 14-17: float P_Param
// 18-21: float I_Param
// 22-245: float D_Param
void SerialReceive()
{
// read the bytes sent from Processing
int index=0;
byte Auto_Man = -1;
byte Direct_Reverse = -1;
while(Serial.available()&&index<26)
{
if(index==0) Auto_Man = Serial.read();
else if(index==1) Direct_Reverse = Serial.read();
else foo.asBytes[index-2] = Serial.read();
index++;
}
// if the information we got was in the correct format,
// read it into the system
if(index==26 && (Auto_Man==0 || Auto_Man==1)&& (Direct_Reverse==0 || Direct_Reverse==1))
{
Setpoint=double(foo.asFloat[0]);
//Input=double(foo.asFloat[1]); // * the user has the ability to send the
// value of "Input" in most cases (as
// in this one) this is not needed.
if(Auto_Man==0) // * only change the output if we are in
{ // manual mode. otherwise we'll get an
Output=double(foo.asFloat[2]); // output blip, then the controller will
} // overwrite.
double p, i, d; // * read in and set the controller tunings
p = double(foo.asFloat[3]); //
i = double(foo.asFloat[4]); //
d = double(foo.asFloat[5]); //
myPID.SetTunings(p, i, d); //
if(Auto_Man==0) myPID.SetMode(MANUAL);// * set the controller mode
else myPID.SetMode(AUTOMATIC); //
if(Direct_Reverse==0) myPID.SetControllerDirection(DIRECT);// * set the controller Direction
else myPID.SetControllerDirection(REVERSE); //
}
Serial.flush(); // * clear any random data from the serial buffer
}
void SerialSend()
{
Serial.print("PID ");
Serial.print(Setpoint);
Serial.print(" ");
Serial.print(Input);
Serial.print(" ");
Serial.print(Output);
Serial.print(" ");
Serial.print(myPID.GetKp());
Serial.print(" ");
Serial.print(myPID.GetKi());
Serial.print(" ");
Serial.print(myPID.GetKd());
Serial.print(" ");
if(myPID.GetMode()==AUTOMATIC) Serial.print("Automatic");
else Serial.print("Manual");
Serial.print(" ");
if(myPID.GetDirection()==DIRECT) Serial.println("Direct");
else Serial.println("Reverse");
}
