Проблема с вводом от весов, управляющих клапаном на базе шагового двигателя
Здравствуйте и спасибо за любую помощь в дальнейшем.
Какие изменения мне нужно внести в свой код, чтобы избавиться от проблемы повторного открытия клапана в конце цикла в функции "Авто".
Оборудование:
- 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
Любые предложения приветствуются.
Спасибо
@MikeD, 👍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;
}
- Получение шестнадцатеричных данных с терминала
- Arduino Serial.ReadString() проблема
- Проблемные данные I2C к датчику GY955/BNO055 (Китай)
- Последовательная связь между двумя Arduino не работает при отправке строки в программе с большим количеством функций.
- Серийный монитор, когда порт используется другим приложением
- Отправить пакет данных нескольких датчиков в модуль Bluetooth
- Отправка данных нескольких датчиков в один пакет в Arduino
- Способы поворота ручки с шаговым двигателем и ATmega32U4
Это очень помогло! Когда я в первый раз нажимаю кнопку "Авто", она работает идеально. Но чем больше раз я нажимаю на нее, тем чаще возвращается ошибка. Как вы думаете, это как-то связано с переполнением буфера?
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