Проблема с вводом от весов, управляющих клапаном на базе шагового двигателя

Здравствуйте и спасибо за любую помощь в дальнейшем.

Какие изменения мне нужно внести в свой код, чтобы избавиться от проблемы повторного открытия клапана в конце цикла в функции "Авто".

Оборудование:

  • Arduino Мега
  • Биполярный шаговый двигатель,подключенный к клапану.
  • Весы с выходом TTL.

Вот мой код:

//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;
  }

Я продолжаю получать это странное поведение в конце функции "Авто", когда я получаю ложные 0,00 от шкалы, которая заставляет клапан полностью открываться и закрываться в конце.

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

Любые предложения приветствуются.

Спасибо

, 👍1


1 ответ


1

Здесь есть несколько проблем:

  • Serial3.readBytesUntil() не добавляет нулевой символ в конце строки. Вы должны сделать это сами, если хотите правильно завершить строку.

  • Вы пытаетесь прочитать значение с плавающей точкой, начинающееся с восьми байтов строки, даже если у вас меньше восьми байтов.

  • atof() не сообщает об ошибках. Если ему не удается проанализировать значение с плавающей точкой, он просто возвращает ноль.

Просто чтобы посмотреть, что может пойти не так, я предлагаю эту версию readScale() с подробным выводом отладки:

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;
}
,

Это очень помогло! Когда я в первый раз нажимаю кнопку "Авто", она работает идеально. Но чем больше раз я нажимаю на нее, тем чаще возвращается ошибка. Как вы думаете, это как-то связано с переполнением буфера? stepper.runToNewPosition "блокируется, поэтому это может привести к прерыванию" serial3.readBytesUntil, @MikeD

Может быть. Или это могут быть отладочные сообщения, замедляющие код. Делает ли шкала паузу между сообщениями? Помогает ли это установить более высокую скорость передачи данных на "последовательном"?, @Edgar Bonet

серийный номер останавливается на хорошие ~1 с при переходе на "maxOpen". Я увеличил скорость передачи данных до 115200 без изменений. Я думаю, что использование библиотеки accelstepper всегда доставляет мне неприятности и, в конце концов, никогда не использует ее. Время переписать все в millis()., @MikeD

Масштаб -> "US,NT,+ US,NT,+ ", проанализировано "" как 0.00 Масштаб -> "4,34 фунта", проанализировано "" как 0,00 Это последовательная ошибка с вашим лучшим анализом., @MikeD

Как вы думаете, поможет ли добавление " if(Serial.available() > 0)"?, @MikeD

Если вы не хотите, чтобы библиотека Accelstepper блокировалась, то почему бы вам не написать свой код неблокирующим? Библиотека Accelstepper полностью способна на это. Посмотрите примеры, которые регулярно вызывают функцию " run ()". Эта функция предназначена для неблокирующих действий, @chrisl

Я знаю, что это так, но вся причина, по которой я использовал библиотеку accelstepper, заключалась в увеличении скорости, потому что клапан имеет значительное статическое трение, и увеличение скорости позволяет ему преодолеть проблему и работать на максимальной скорости без остановки., @MikeD