1

Hello and thanks for any help in advanced.

What changes do I need to make to my code to get rid of the issue of the valve opening up again at end of cycle in "Auto" function.

Hardware:

  • Arduino Mega
  • Bi-polar Stepper Motor connected to Valve.
  • Weighing scale with TTL output.

Here is my code:

//Buttons
#include <mechButton.h> //Button Library
#define BTNa_PIN  10    //Button Pins
#define BTNb_PIN  6
mechButton aButton(BTNa_PIN);  // Set button to pin BTN_PIN.
mechButton bButton(BTNb_PIN);

//Stepper
#include <AccelStepper.h> //Stepper Library
#define dirPin 4          //Stepper Pins
#define stepPin 2
#define motorInterfaceType 1 //Interface set to driver
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);// Create a new instance 

//Analog inputs for setting Max and Min Distance
const int analogPin = A0;
const int analogPin2 =A1;

//Data types for Scale Reading for Optima OP900a
char inString[32];
float Input;
float Setpoint;
float fSetpoint;

//Setup
void setup() {
   
  Serial.begin(9600);           // Fire up our serial monitor for arduino and computer
  Serial3.begin(9600);          //Fire up Serial for Scale for input
  
  aButton.setCallback(Manual);    // Set up our callback. (Also calls hookup() for idling.)
  bButton.setCallback(Auto);
  stepper.setMaxSpeed(3500);      // Set the maximum speed and acceleration for stepper motor:
  stepper.setAcceleration(5000);
  
  Setpoint = 4.44;               // Auto parameters
  fSetpoint = (Setpoint*0.9);

}  
// Main Loop
void loop() {
   bool abuttonState;
   bool bButtonState;
   
   idle();                      // Let all the idlers have time to do their thing.
   abuttonState = aButton.trueFalse();    // Have a look at what the current button state is.
   bButtonState = bButton.trueFalse();
}
//Sub Functions
void Manual(void) {
    int maxOpen = analogRead(analogPin);
    maxOpen = map(maxOpen, 0, 1023, 0,100);

   Serial.print("Manual ");
   if (aButton.trueFalse()) {
      stepper.moveTo(0);
      stepper.runToPosition();
   } else {
      stepper.moveTo(maxOpen*40);
      stepper.runToPosition();
      
   }
}

void Auto(void) {
    int maxOpen = analogRead(analogPin);
    int minOpen = analogRead(analogPin2);
    maxOpen = map(maxOpen, 0, 1023, 0,100);
    minOpen = map(minOpen, 0, 1023, 0,100);
   
   while (Input < Setpoint){
     readScale();
     if (Input >= fSetpoint && Input < Setpoint){
     stepper.runToNewPosition((minOpen*10)+400);  //Blocking function research work around...
     Serial.print("Min");Serial.print(",");       //debugging
     Serial.println(Input);                       //debugging
     }
     else if (Input < fSetpoint) {
     stepper.runToNewPosition(maxOpen*40);         //Blocking function research work around...
     Serial.print("Max");Serial.print(",");       //debugging
     Serial.println(Input);                       //debugging
     }
     else{
     stepper.runToNewPosition(0);                 //Blocking function research work around...
     Serial.print("Close");Serial.print(",");     //debugging
     Serial.println(Input);                       //debugging
     }
     }
}

void readScale(void){
    byte inChar = Serial3.readBytesUntil('\n', inString, 18); //Scale reading for input
    float scaleInput = atof(&inString[7]);
    Input = scaleInput;
  }

I keep getting this strange behavior at the end of the "Auto" function where I am getting false 0.00 from the scale that causes the valve to open and close fully at the end.

Max,0.01
Max,0.01
Max,0.01
Max,0.00
Max,0.00
Max,0.00
Max,0.00
Max,0.35
Max,0.42
Max,0.51
Max,0.60
Max,0.66
Max,0.69
Max,0.75
Max,0.83
Max,0.88
Max,0.93
Max,1.00
Max,1.05
Max,1.11
Max,1.16
Max,1.21
Max,1.26
Max,1.32
Max,1.38
Max,1.43
Max,1.48
Max,1.53
Max,1.59
Max,1.64
Max,1.68
Max,1.74
Max,1.80
Max,1.84
Max,1.89
Max,1.94
Max,1.99
Max,2.04
Max,2.09
Max,2.14
Max,2.18
Max,2.23
Max,2.27
Max,2.32
Max,2.37
Max,2.41
Max,2.45
Max,2.50
Max,2.55
Max,2.59
Max,2.62
Max,2.68
Max,2.72
Max,2.76
Max,2.81
Max,2.85
Max,2.88
Max,2.93
Max,2.97
Max,3.00
Max,3.04
Max,3.08
Max,3.13
Max,3.17
Max,3.20
Max,3.23
Max,3.27
Max,3.31
Max,3.35
Max,3.39
Max,3.42
Max,3.46
Max,3.50
Max,3.52
Max,3.55
Max,3.60
Max,3.63
Max,3.66
Max,3.69
Max,3.73
Max,3.77
Max,3.80
Max,3.83
Max,3.87
Max,3.91
Max,3.94
Max,3.95
Max,3.98
Min,4.03
Min,4.06
Min,4.09
Min,4.13
Max,0.00
Max,0.00
Min,4.35
MZ��r��j
Min,4.36
Close,4.46

Any suggestions are welcome.

Thanks

1 Answer 1

1

There are a few issues here:

  • Serial3.readBytesUntil() does not add a null character at the end of the string. You have to do it yourself if you want a properly terminated string.

  • You are attempting to read a float starting at the eight byte of the string, even if you got less than eight bytes.

  • atof() does not report errors. If it fails to parse a float, it just returns zero.

Just to see what may be going wrong, I suggest this version of readScale() with verbose debug output:

void readScale(void) {
    byte inChar = Serial3.readBytesUntil('\n', inString, 18);
    inString[inChar] = '\0';  // terminate the string
    const char *start = &inString[7];  // where the number is expected
    char *end;  // where strtod() found it ends
    float scaleInput = strtod(start, &end);
    Serial.print("Scale -> \"");
    Serial.print(inString);
    Serial.print("\", parsed \"");
    *end = '\0';  // terminate the string after the number
    Serial.print(start);
    Serial.print("\" as ");
    Serial.println(scaleInput);
    Input = scaleInput;
}
7
  • That helped a lot! The first time I hit the auto button it works perfectly. But the more times I hit it the error keeps coming back. Do you think this has something to do with buffer overflow? stepper.runToNewPosition is blocking therefore it could be interrupting the serial3.readBytesUntil
    – MikeD
    Nov 19, 2021 at 12:13
  • Maybe. Or it could be the debug messages slowing down the code. Does the scale pause between messages? Does it help to set a higher baud rate on Serial? Nov 19, 2021 at 12:29
  • the serial stalls for a good ~1s while moving to maxOpen. I cranked the baud to 115200 no change. I think using the accelstepper library always get me into trouble and in the end never use it. Time to rewrite everything in millis().
    – MikeD
    Nov 19, 2021 at 12:45
  • Scale -> "US,NT,+ US,NT,+ ", parsed "" as 0.00 Scale -> " 4.34lb", parsed "" as 0.00 This is the serial error with your better parsing.
    – MikeD
    Nov 19, 2021 at 12:50
  • Do you think adding an if(Serial.available() > 0) would help?
    – MikeD
    Nov 19, 2021 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.