Управлять 2 сервоприводами с последовательным считыванием
Я хочу использовать 2-й сервопривод только тогда, когда 1-й находится в рабочем состоянии, спрашивая пользователя, хочет ли он запустить или нет. (код, выделенный жирным шрифтом, не работает)
#include <Servo.h>
Servo myservo;
Servo trigervo;
int pos = 0;
int u = 0, p = 0, t = 0;
int incomingByte = 0; // для входящих последовательных данных
void setup() {
Serial.begin(9600);
myservo.attach(9);
trigervo.attach(10);
pinMode(13, OUTPUT);
myservo.write(0);
}
void loop() {
if (Serial.available() > 0) {
// считывает входящий байт:
incomingByte = Serial.read();
Serial.print("I received: ");
if (incomingByte == 111 && u == 0) {
for (pos = 0; pos <= 80; pos += 1) {
myservo.write(pos);
delay(5); //
digitalWrite(13, HIGH);
}
u = 1;
p = 0;
Serial.println(incomingByte, DEC);
Serial.print("Want to Shoot? \n");
Serial.print("1\n");
***t = Serial.read(); // отсюда
if (t == 107) {
Serial.print("2\n");
trigervo.write(60);
trigervo.write(0);
} // здесь, это не работает***
} else if (incomingByte == 102 && p == 0) {
for (pos = 100; pos >= 0; pos -= 1) {
myservo.write(pos);
delay(7);
digitalWrite(13, HIGH);
}
u = 0;
p = 1;
Serial.println(incomingByte, DEC);
}
Serial.println(incomingByte, DEC);
}
}
@Aditya Raj, 👍2
Обсуждение1 ответ
Лучший ответ:
Не зная, что именно вы хотите, чтобы это делало (поскольку вы нам не сказали), я вижу в вашем коде 2 проблемы:
Код вокруг строки, отмеченной "отсюда", запросит пользователя по Serial, хочет ли он снимать, но сразу после этого он будет считывать значение, не дожидаясь, пока пользователь что-то введет.
Serial.read()
не будет ждать поступления данных, он просто вернет -1, если в буфере ничего нет. Вы должны проверить, действительно ли что-то есть в буфере спомощью Serial.available()
, и продолжить, только если на самом деле есть данные для чтения.В следующем if-операторе вы сначала записываете значение 60 в сервопривод, а непосредственно после него, без какой-либо задержки, значение 0. У сервопривода недостаточно времени, чтобы добраться до 60 - или даже начать движение, - прежде чем вы скажете ему перейти на 0. Сервоприводу нужно время для перемещений.
Помимо конкретных проблем с вашим кодом, я бы использовал для его реализации конечный автомат (FSM). Вы объявляете глобальную переменную состояния, которая представляет возможные состояния, в которых может находиться ваша машина. Если я предполагаю какой-то тип оружия / стреляющего устройства, этими состояниями могут быть ASK_USER_TO_POSITION_GUN' и 'ASK_USER_TO_SHOOT'. В каждом состоянии вы проверяете последовательный интерфейс (сначала с
помощью Serial.available(), затем считываете с
помощью Serial.read()`, если он возвращает что-то большее 0), и на основе этого ввода вы сначала выполняете соответствующее действие, а затем выполняете переход состояния, изменяя переменную состояния.
В качестве примера общей структуры:
int state = 0;
void loop(){
switch(state){
case 0:
if(Serial.available()>0){
int input = Serial.read();
//принять надлежащие меры
state = 1; //выполнить переход состояния
}
break;
case 1:
if(Serial.available()>0){
int input = Serial.read();
//принять надлежащие меры
state = 0; //выполнить переход состояния
}
break;
}
}
В зависимости от конкретных действий, которые необходимо выполнить, вы также можете настроить это, прочитав Serial вне инструкции switch и в инструкции case проверяя только входную переменную. В этом случае сбрасывайте входную переменную после каждого взаимодействия.
РЕДАКТИРОВАТЬ: Чтобы дать лучшее объяснение о конечных автоматах, я нарисовал графическое представление состояний. В основном это намного проще кодировать, когда вы впервые нарисовали такой график, чтобы визуализировать функциональность кодов. Обратите внимание, что это логика из вашего кода. Возможно, вы захотите, чтобы это работало по-другому, но это выходит за рамки и только для понимания. Также обратите внимание на другое количество состояний, чем я использовал выше, которое я меняю только потому, что мне нужно было больше состояний.
Посмотрите сначала на этот график:
Мы начинаем с состояния 0, где мы ожидаем ввода данных пользователем через serial. Если мы вводим какой-то ввод, мы принимаем решение: если значение равно 111, мы перейдем в следующее состояние (состояние 1), чтобы установить пистолет, в противном случае мы снова будем ждать дополнительных входных данных. На этапе 1 мы устанавливаем пистолет и переходим непосредственно к состоянию 2. Там мы снова ждем ввода данных пользователем. Если мы что-то получили, мы снова примем решение: при значении 107 мы осуществим переход в состояние 3 для съемки, иначе мы перейдем в состояние 0, чтобы снова запросить позиционирование, как мы делали раньше. В состоянии 3 мы снимаем и сразу снова переходим в состояние 0. Это довольно строгое деление на государства.
Поскольку в состояниях 1 и 3 мы выполняем только короткое действие, а затем переходим непосредственно в другое состояние, мы могли бы отключить эти состояния, реализуя соответствующий код при переходе из состояния 0 в состояние 2 и наоборот. Это логика из моего примера кода FSM выше (действие вместе с переходом). График будет выглядеть следующим образом:
Какую версию вы должны реализовать, зависит от других факторов. Если вас устраивает код действия для блокировки, вы можете реализовать версию 2, поскольку в ней меньше состояний. Если вы хотите написать действие в неблокирующем стиле, возможно, вам будет проще реализовать версию 1.
Как вы и просили, я изменил вопрос, чтобы быть точным, пожалуйста, помогите мне......, @Aditya Raj
Ответ остается прежним. Ваши прямые проблемы - это две указанные выше проблемы. Помогает ли это? Если нет: Что мешает вам реализовать это? Может быть, я смог бы написать ответ более понятным, если бы знал, что в нем непонятно., @chrisl
В случае 0 я хочу снова получить значение с помощью последовательного чтения и реализовать его, вызвав функцию, в данном случае вызывающую триггерную функцию., @Aditya Raj
Я отклонил вашу правку, потому что FSM работает не так. В штатах вы ожидаете ввода данных пользователем. Вместо того, чтобы напрямую (все еще в случае 0) пытаться прочитать больше данных, вы совершаете переход в следующее состояние, где вы ожидаете новых данных. Это делает код лучше структурированным, а также ожидание ввода пользователем не будет блокировать выполнение кода, в случае, если вы хотите сделать что-то одновременно (например, мигание светодиода или другие задачи). Я добавлю графическое представление FSM для вашего случая, чтобы оно было более понятным., @chrisl
Хорошо, теперь я получаю представление об этом, @Aditya Raj
- Float печатается только 2 десятичных знака после запятой
- Связь Arduino master/slave с использованием RS485
- Как получить правильный последовательный порт?
- Как отобразить всю входящую строку с serial monitor в arduino ide?
- SoftwareSerial данные недоступны
- Как остановить серводвигатель в текущем положении при использовании последовательного порта? Я хочу, чтобы он оставался в одном положении при получении «0».
- Удерживайте кнопку/нажмите кнопку/нажмите кнопку
- Использование Serial.begin() дважды
read()
не ждет. он возвращает -1, если в буфере RX ничего нет, @Jurajвы забыли задать вопрос ... вы также забыли описать, что происходит при запуске программы, @jsotola