такое дело, подключено у меня 2 сервопривода к ардуинке, через компьютер хотел задавать угол на выбранный сервопривод, не могу решить проблему связанную с тем, что при выборе одного из 2-х моторов цикл проходит 1 раз и не ждет, когда я введу значение... вот код: #include <Servo.h> Servo servo; Servo servo2; String message = ""; String message2 = ""; void setup(){ servo.attach(6); servo2.attach(9); Serial.begin(9600); } void loop(){ if (Serial.available() > 0) { int var = Serial.read() - 48; switch (var) { case 1: Serial.println ("azimuth ="); while (Serial.available()) { char inc = Serial.read(); delay(100); Serial.print(inc); if (inc >= '0' && inc <= '9') { // если пришёл символ-цифра, добавляем его к сообщению message += inc; } else if (inc == ' ') { // если пришел пробел, то поворачиваем серво на заданный угол int agle = message.toInt(); if(agle > 180){agle = 180;} if(agle < 0){agle = 0;} servo.write(agle); message = ""; } } break; case 2: Serial.println("height ="); while (Serial.available()) { char inc2 = Serial.read(); delay(100); Serial.print(inc2); if (inc2 >= '0' && inc2 <= '9') { // если пришёл символ-цифра, добавляем его к сообщению message2 += inc2; } else if (inc2 == ' ') { // если пришел пробел, то поворачиваем серво на заданный угол int agle2 = message2.toInt(); if(agle2 > 180){agle2 = 180;} if(agle2 < 0){agle2 = 0;} servo2.write(agle2); message2 = ""; } } break; default: Serial.println("azimuth-1, heigh-2"); } } }
Оформите, пожалуйста, код как следует, а то читать невозможно. На панели инструментов при добавлении/редактировании сообщения есть кнопочка "code".
Код (C++): #include <Servo.h> Servo servo; Servo servo2; String message = ""; String message2 = ""; void setup(){ servo.attach(6); servo2.attach(9); Serial.begin(9600); } void loop(){ if (Serial.available() > 0) { int var = Serial.read() - 48; switch (var) { case 1: Serial.println ("azimuth ="); while (Serial.available()) { char inc = Serial.read(); delay(100); Serial.print(inc); if (inc >= '0' && inc <= '9') { // если пришёл символ-цифра, добавляем его к сообщению message += inc; } else if (inc == ' ') { // если пришел пробел, то поворачиваем серво на заданный угол int agle = message.toInt(); if(agle > 180){agle = 180;} if(agle < 0){agle = 0;} servo.write(agle); message = ""; } } break; case 2: Serial.println("height ="); while (Serial.available()) { char inc2 = Serial.read(); delay(100); Serial.print(inc2); if (inc2 >= '0' && inc2 <= '9') { // если пришёл символ-цифра, добавляем его к сообщению message2 += inc2; } else if (inc2 == ' ') { // если пришел пробел, то поворачиваем серво на заданный угол int agle2 = message2.toInt(); if(agle2 > 180){agle2 = 180;} if(agle2 < 0){agle2 = 0;} servo2.write(agle2); message2 = ""; } } break; default: Serial.println("azimuth-1, heigh-2"); } } } думаю так будет лучше
Проблема в понимании работы с Serial. Ответьте на вопрос: что будет, если в приёмном буфере UART на момент проверки Код (C++): if (Serial.available() > 0) { int var = Serial.read() - 48; будет всего один символ? Отработают ли у вас при этом строчки Код (C++): while (Serial.available()) { ? Думаю, я ответил на вопрос "проблему связанную с тем, что при выборе одного из 2-х моторов цикл проходит 1 раз и не ждет, когда я введу значение".
к сожалению я не совсем понимаю свою ошибку, когда я ввожу 1 или 2 мне выдает azimuth или heigh, при попытке ввести например 45 после ввода 1 или 2, мне выдаст ("azimuth-1, heigh-2"); т.е. я не могу ввести угол
Ещё раз: ответьте на вопрос: как отработает ваш код, если в приёмном буфере Serial всего один байт? Пока вы не поймёте логику работы вашего кода - вы не увидите в нём ошибки.
а зачем больше ? программа прекрасно работат в вот таком виде Код (C++): #include <Servo.h> Servo servo; String message = ""; void setup(){ servo.attach(6); Serial.begin(9600); } void loop(){ while (Serial.available()) { char inc = Serial.read(); Serial.print(inc); if (inc >= '0' && inc <= '9') { // если пришёл символ-цифра, добавляем его к сообщению message += inc; } else if (inc == ' ') { // если пришел пробел, то поворачиваем серво на заданный угол int agle = message.toInt(); if(agle > 180){agle = 180;} if(agle < 0){agle = 0;} servo.write(agle); message = ""; } } }
ну это одиночкая программа, а сделать так чтобы вводить угол для одного из сервоприводов у меня не получается
Ещё раз: что будет, если на момент вычитывания байта из Serial - он там единственный и, например, имеет значение 2? Отработает ваш код по вычитыванию height или нет? И на следующем проходе loop - что будет? Пока вы не разберётесь в логике работы вашего кода - вы сколько угодно можете склеивать скетчи и утверждать, что всё работает правильно - но ошибки так и не увидите. Вы хотите, чтобы я вам на неё указал? Я и указываю, говоря вам - код работает неправильно. Что именно неправильно? Вот представьте: в буфере Serial лежит один байт со значением 2. Вы получаете этот байт, попадаете в case 2, там пытаетесь читать из буфера, а в буфере - фигушки. Вы вываливаетесь из loop, в это время в буфер попадает следующий байт, пришедший извне, вы в новом проходе loop читаете этот байт, и - пытаетесь сделать что? Правильно - вы ищете там 1 или 2, в то время как этот свежепришедший байт предназначен для сохранения параметра height. Алгоритм у вас построен неправильно.
Исправить - просто: нужен конечный автомат. Т.е. вы должны сохранять состояние между вызовами loop, чтобы понимать, что в данный текущий момент вы ждёте из Serial - это команда? Или этот байт надо записать как параметр команды? Или это пришёл признак конца команды, и надо сбросить состояние в начальное ожидание новой команды?
Ок, вот вам небольшой пример, учтите, что это псевдокод, а не готовое рабочее решение: Код (C++): typedef enum {SLEEP, WANT_COMMAND, WANT_PARAM} MACHINE_STATE; MACHINE_STATE state; String commandBuffer, paramBuffer; void loop() { while(Serial.available()) { char ch = Serial.read(); if(ch == '\r') // пропускаем ненужные символы continue; switch(state) { case SLEEP: // ничего не делаем { state = WANT_COMMAND; // ждём команды commandBuffer += ch; } break; case WANT_COMMAND: // ждём конца команды { if(commandBuffer.length() == 2) // у нас команда из двух символов всегда { state = WANT_PARAM; // будем ждать параметра } } break; case WANT_PARAM: { if(ch == '\n') // параметр пришёл полностью { state = SLEEP; // вываливаемся на ожидание // тут смотрим, чего у нас за команда в commandBuffer // и чего у нас за параметр в paramBuffer, // по факту чего-то делаем } else { paramBuffer += ch; // складываем в буфер для параметра символы } } break; } } }