I am trying to make a control valve using a stepper motor, using NEMA23 with TB6600 driver. i know the amount of steps to fully open or fully close the valve which was 7000 steps. but the thing was, when i was simulating my codes and everything, my motor would not stop moving open or closing depends on the PV towards the SV.
for example, if my set point was set at 1.7 bar, and the process variable is currently at 1.2 bar, my arduino would command the stepper to close the valve, which is sensible. but the problem is, my motor would not stop to close the valve even the valve has fully closed. this makes the stepper skip all the coils which was supposed to move the rotor.
how can i limit the amount of steps that the motor can move, which is from 0 (valve fully close) to 7000 (valve fully open).
unfortunately, i cant install a physical barier or a limit switch to stop the movement of the motor. since everything else was already welded and glued permanently.
here's the code for my PID
//LCD config
#include <Smoothed.h> // Include the library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>
LiquidCrystal_I2C lcd(0x3f,16,2); //sometimes the adress is not 0x3f. Change to 0x3f if it dosn't work.
AccelStepper myStepper (1,8,9);
/* i2c LCD Module ==> Arduino
* SCL ==> A5
* SDA ==> A4
* Vcc ==> Vcc (5v)
* Gnd ==> Gnd */
//Inputs and outpu`ts
int firing_pin = 3;
int myStepper_pul = 6;
int myStepper_dir = 7;
const int sensorPin = A0;
float analogRaw = 0.0;
float voltageRaw = 0.0;
float realPressure = 0.0;
//Variables
int last_CH1_state = 0;
bool newData, runallowed = false;
int firing_delay = 7400;
int directionMultiplier = 1; // = 1: positive direction, = -1: negative direction
long receivedSteps = 0; //Number of steps
long receivedSpeed = 0; //Steps / second
long receivedAcceleration = 0; //Steps / second^2
float real_pressure_smoothed = 0;
float readPressure(){
analogRaw = analogRead(sensorPin);
voltageRaw = (analogRaw * 5.0 / 1024.0) - 0.92;
// Serial.println("analog");
// Serial.println(analogRaw);
// Serial.println("voltage");
// Serial.println(voltageRaw);
// Serial.println("pressure");
Serial.println((voltageRaw * 16.0 / 4.62) + 0.20);
return (voltageRaw * 16.0 / 4.62) + 0.20;
}
char receivedCommand;
int curPos = 0;
int nexPos = 0;
//////////////////////////////////////////////////////
int maximum_firing_delay = 7400;
/*Later in the code you will se that the maximum delay after the zero detection
* is 7400. Why? Well, we know that the 220V AC voltage has a frequency of around 50-60HZ so
* the period is between 20ms and 16ms, depending on the country. We control the firing
* delay each half period so each 10ms or 8 ms. To amke sure we wont pass thsoe 10ms, I've made tests
* and the 7400us or 7.4ms was a good value. Measure your frequency and chande that value later */
//////////////////////////////////////////////////////
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
int temp_read_Delay = 500;
float real_pressure = 0.0;
float setpoint = 1.75;
bool pressed_1 = false;
bool pressed_2 = false;
int maxRotate = 6000;
//const int minSample = 5;
//int sampleCount = 0;
//const float trigger = 7.0;
//const float rangeTrigger = 0.5;
//bool startTrigger = false;
//PID variables
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
float PID_value = 0;
//PID constants
float kp = 200 ; float ki= 1; float kd = 1;
float PID_p = 0; float PID_i = 0; float PID_d = 0;
int scale = 1000;
unsigned long prevmillis = 0;
Smoothed <float> mySensor;
void setup() {
//Define the pins
Serial.begin(9600);
pinMode (firing_pin,OUTPUT);
pinMode (myStepper_pul,INPUT);
pinMode (myStepper_dir,INPUT);
lcd.init(); //Start the LC communication
lcd.backlight(); //Turn on backlight for LCD
myStepper.setMaxSpeed(1000); //SPEED = Steps / second
myStepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2
myStepper.disableOutputs(); //disable outputs
mySensor.begin(SMOOTHED_AVERAGE, 18);
myStepper.setCurrentPosition (0);
myStepper.moveTo (0);
}
void loop() {
// Serial.println("loop");
// if (real_pressure_smoothed > trigger - rangeTrigger && real_pressure_smoothed < trigger + rangeTrigger){
// sampleCount += 1;
// }
//
// if (sampleCount > minSample){
// startTrigger = true;
// }
//
// if (startTrigger == false){
// lcd.setCursor(0,0);
// lcd.print("belom trigger ");
// return 0;
// }
RunTheMotor(); //function to handle the motor
analogRaw = analogRead(0);
voltageRaw = (analogRaw * 5.0 / 1024.0) - 0.92;
real_pressure = (voltageRaw * 16.0 / 4.62) + 0.54;
mySensor.add(real_pressure);
currentMillis = millis(); //Save the value of time before the loop
/* We create this if so we will read the temperature and change values each "temp_read_Delay"
* value. Change that value above iv you want. The MAX6675 read is slow. Tha will affect the
* PID control. I've tried reading the temp each 100ms but it didn't work. With 500ms worked ok.*/
if(currentMillis - previousMillis >= temp_read_Delay){
previousMillis += temp_read_Delay; //Increase the previous time for next loop
real_pressure_smoothed = mySensor.get();
PID_error = setpoint - real_pressure_smoothed; //Calculate the pid ERROR
// if(PID_error > 30) //integral constant will only affect errors below 30ºC
// {PID_i = 0;}
PID_p = kp * PID_error; //Calculate the P value
PID_i = PID_i + (ki * PID_error); //Calculate the I value
timePrev = Time; // the previous time is stored before the actual time read
Time = millis(); // actual time read
elapsedTime = (Time - timePrev) / 1000;
PID_d = kd*((PID_error - previous_error)/elapsedTime); //Calculate the D value
PID_value = (PID_p + PID_i + PID_d); //Calculate total PID value
//Printe the values on the LCD
if (prevmillis >= millis){
prevmillis = 250;
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set: ");
lcd.setCursor(5,0);
lcd.print(setpoint);
lcd.setCursor(0,1);
lcd.print("Pressure: ");
lcd.setCursor(11,1);
lcd.print(real_pressure_smoothed);
Serial.println (real_pressure_smoothed);
previous_error = PID_error; //Remember to store the previous error.
newData= true;
}
//
// Serial.println ("pid error");
// Serial.println (PID_error);
//
// Serial.println ("D");
// Serial.println (PID_d);
//If the zero cross interruption was detected we create the 100us firing pulse
if (newData)
// Serial.println("PID_value");
// Serial.println(PID_value);
{
if (PID_value > maxRotate){
nexPos = maxRotate;
}else if (PID_value <(-1 * maxRotate)){
nexPos = -1 * maxRotate;
}else{
nexPos= PID_value;
}
//value for the steps
//Run the function
}
RotateRelative();
// Serial.println(readPressure());
// delay(1000);
}
void RotateRelative(){
//We move X steps from the current position of the stepper motor in a given direction.
//The direction is determined by the multiplier (+1 or -1)
// Serial.println("curPos");
// Serial.println(curPos);
if (nexPos > curPos){
receivedSteps = nexPos - curPos;
curPos = nexPos;
}else if (nexPos < curPos){
receivedSteps = -nexPos - curPos;
curPos = nexPos;
}else{
return 0;
}
// Serial.println("received Steps");
// Serial.println(receivedSteps);
// Serial.println("nexPos");
// Serial.println(nexPos);
runallowed = true; //allow running - this allows entering the RunTheMotor() function.
myStepper.setMaxSpeed(1000); //set speed
myStepper.move(receivedSteps); //set relative distance and direction
// Serial.println("STEPS");
// Serial.println(receivedSteps);
}
void RunTheMotor() //function for the motor
{
if (runallowed == true)
{
myStepper.enableOutputs(); //enable pins
myStepper.run(); //step the motor (this will step the motor by 1 step at each loop)
}
else //program enters this part if the runallowed is FALSE, we do not do anything
{
myStepper.disableOutputs(); //disable outputs
return 0;
}
}
thanks for the help, i sorry if the code llokk