Являюсь начинающим пользователем Arduino. Повторил робота ездящего по линии Прошу пояснить следующие моменты в скетче, размещенном на вашем сайте 1) #define STATE_FORWARD 0 - что такое "0" ? #define STATE_RIGHT 1 - что такое "1" ? #define STATE_LEFT 2 - что такое "2" ? #define SPEED_STEP 2 - что такое "2" ? #define FAST_TIME_THRESHOLD 500 - что есть FAST _TIME_TRHESHOLD и соответственно 500 int state = STATE_FORWARD; int currentSpeed = SPEED; int fastTime = 0; -что есть fastTime и "0" соответственно 2) Программный модуль движения вперед: void runForward() { state = STATE_FORWARD; fastTime += 1; if (fastTime < FAST_TIME_THRESHOLD) { - прошу пояснить currentSpeed = SLOW_SPEED; } else { currentSpeed = min(currentSpeed + SPEED_STEP, SPEED); } analogWrite(SPEED_LEFT, currentSpeed); analogWrite(SPEED_RIGHT, currentSpeed); digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } При компиляции модуля движения вперед выдается ошибка: выделяется строка } else { и идет описание ошибки : expected unqulified-id before 'else' Вопрос - в чем может быть проблема Благодарю
День добрый. Не очень понимаю, что Вы спрашиваете. Вас интересует описание синтаксис языка? Если да, то тут все просто #define Команда объявления константы STATE_FORWARD - имя константы 0 - значение константы Объявление переменой. int - тип данных fastTime - имя 0 - значение Если FAST_TIME_THRESHOLD больше, чем fastTime будет выполнено условие в скобочках { } Если, нужно понять в контексте программы, то нужен код. Будьте добры код который Вы используете, выложите здесь. Чтобы можно было проверить. UPD. Нужно прерваться, свое сделать, вечером вернусь
Благодарю за содействие. Скетч был представлен на Амперке http://wiki.amperka.ru/робототехника:робот-с-датчиками-линии-на-arduino см. файл "Robot_v02.ino" Его то я и пытался повторить и понять. Если скопировать код как он представлен на сайте и скомпиллировать, то все ОК и робот ездит по линии без проблем, но ряд цепочек кода по сути не используется, как я понимаю и являются балластными (например часть скетча - движение назад). Детального описания скетча нет, поэтому и вопросы для понимания сути программного кода. Всегда все кажется просто, но у авторов была своя идея решения и мне хотелось бы ее осознать. Я решил модифицировать код под свои нужды и тут возникают ошибки при компиляции. Я так понял, что значения 0,1,2 в определении состояния движения, это некие номера состояний. Я не понимаю, где эти значения и как далее используются при исполнении программы. Вот мой слегка модифицированный код. И он дает ошибки при компиляции. Ниже красным выделил также то, что я не понимаю *Двухколесная платформа Turtle*/ // Ходовые моторы подключены к контроллеру через Motor Shield на микросхеме L298P // Распиновка //Для коммуникации Motor shield с микроконтроллером используются цифровые контакты Arduino: //4 — направление, правый //5 — скорость (ШИМ), правый //6 — скорость (ШИМ), левый //7 — направление, левый // Правый мотор MR подключен к клеммам Motor Shield M1+,M1- // Левый мотор ML подключен к клеммам Motor Shield M2+,M2-с обратной полярностью //Назначение выводов контроллера для управления моторами #define SPEED_LEFT 6 // скорость вращения левого мотора #define DIR_LEFT 7 // направление вращения левого мотора #define SPEED_RIGHT 5 // скорость вращения правого мотора #define DIR_RIGHT 4 // направление вращения правого мотора //Назначение выводов контроллера для подключения датчиков линии #define LEFT_SENSOR_PIN 12 #define RIGHT_SENSOR_PIN 11 // Задаем скорость, с которой происходит движение вперёд (0-255) #define SPEED 150 // Задаем скорости прохождения сложных участков(0-255) #define SLOW_SPEED 40 #define BACK_SLOW_SPEED 30 - принял из скетча с сайта, но где это используется не понимаю #define BACK_FAST_SPEED 50 принял из скетча с сайта, но где это используется не понимаю #define STATE_FORWARD 0 -что такое 0 #define STATE_RIGHT 1 - что такое 1 #define STATE_LEFT 2 - что такое 2 #define STATE_BACK 3 - ввел в программу, поскольку по идее есть модуль движения назад, но он не используется. Не понимаю, по сути не нужно #define SPEED_STEP 2 - как я понимаю, шаг приращения скорости, заданной в диапазоне 0-255 #define FAST_TIME_THRESHOLD 500 - по сути время в мс ? //Задаем переменные состояния int state = STATE_FORWARD; - что задается в этом месте - исходное состояние движения и где эта переменная далее используется при исполнении программного модуля? int currentSpeed = SPEED; int fastTime = 0; - что есть 0 ? время ? // Программный модуль движения вперед void runForward() { state = STATE_FORWARD; - для чего здесь нужна строка и что она определяет, на мой взгляд можно просто задать врашение моторов с определенной скоростью и направлением и все. fastTime += 1; для чего здесь эта строка ? по сути робот как я понял из описания с сайта увеличивает скорость своего движения с начала выполнения программы - для чего здесь эта строка ? Что она задает при исполнении ? if (fastTime < FAST_TIME_THRESHOLD) { currentSpeed = SLOW_SPEED; } else { -здесь возникает ошибка при компиляции currentSpeed = min(currentSpeed + SPEED_STEP, SPEED); } analogWrite(SPEED_LEFT, currentSpeed); analogWrite(SPEED_RIGHT, currentSpeed); // Если в DIR_LEFT или DIR_RIGHT пишем HIGH, мотор будет двигать соответствующее колесо // вперёд, если LOW - назад. digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } // Программный модуль поворота направо void steerRight() { state = STATE_RIGHT; fastTime = 0; -- для чего здесь эта строка ? Что она определяет в этом модуле ? // Останавливаем правое колесо относительно левого, // чтобы начать поворот analogWrite(SPEED_RIGHT, 0);// Останавливаем правый мотор analogWrite(SPEED_LEFT, SPEED);// Левый мотор в работе digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } // Программный модуль поворота налево void steerLeft() { state = STATE_LEFT; fastTime = 0; - для чего здесь эта строка ? Что она определяет в этом модуле ? // Останавливаем левое колесо относительно правого, // чтобы начать поворот analogWrite(SPEED_LEFT, 0);//Останавливаем левый мотор analogWrite(SPEED_RIGHT, SPEED); // Правый мотор в работе digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } //Программный модуль движения назад - модуль далее в программе по сути не используется - зачем он нужен - автор забыл удалить ? При компиляции к тому же происходит остановка на данном модуле void stepBack(int duration, int state) { - не понимаю на каком этапе задается переменная duration if (!duration) return; // В зависимости от направления поворота при движении назад будем // делать небольшой разворот int leftSpeed = (state == STATE_RIGHT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; int rightSpeed = (state == STATE_LEFT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; analogWrite(SPEED_LEFT, leftSpeed); analogWrite(SPEED_RIGHT, rightSpeed); // реверс колёс digitalWrite(DIR_RIGHT, LOW); digitalWrite(DIR_LEFT, LOW); delay(duration); } // Инициализация робота после включения питания void setup() { // Настраиваем выводы контроллера №№ 4,5,6,7 на вывод сигналов на электродвигатели for(int i = 4; i <= 7; i++) pinMode(i, OUTPUT); // едем вперёд runForward(); // Исполняемый программный модуль void loop() /* Режим движения с использованием датчиков линии */ { // Наш робот ездит по белому полю с чёрным треком. В обратном случае не нужно // инвертировать значения с датчиков boolean left = !digitalRead(LEFT_SENSOR_PIN); boolean right = !digitalRead(RIGHT_SENSOR_PIN); // В какое состояние нужно перейти? int targetState; if (left == right) { // под сенсорами всё белое или всё чёрное // едем вперёд targetState = STATE_FORWARD; } else if (left) { // левый сенсор упёрся в трек // поворачиваем налево targetState = STATE_LEFT; } else { targetState = STATE_RIGHT; } if (state == STATE_FORWARD && targetState != STATE_FORWARD) { int brakeTime = (currentSpeed > SLOW_SPEED) ? currentSpeed : 0; stepBack(brakeTime, targetState); } switch (targetState) { case STATE_FORWARD: runForward(); break; case STATE_RIGHT: steerRight(); break; case STATE_LEFT: steerLeft(); break; } }
Код приведен полностью? В смысле слэш, начинающий комментарий, в самом начале кода отсутствует, или просто потерялся при копировании сюда? Сама ошибка возникает обычно в том случае, если нарушен баланс скобок или иных конструкций языка. В данном случае все похоже на то, что фигурная скобка перед else завершает функцию, и else в результате "повисает" в пространстве между функциями. Но судя по коду таких проблем вроде нет. С другой стороны, пес его знает, как компилятор скобки считает. Баланс их в коде точно нарушен. У функции setup завершающей скобки явно не хватает, и ошибка у else чисто теоретически может быть наведена этим, хотя выглядит такое несколько странно. Функция движения назад выполняется, когда робот вылетает с траектории, если линия, по которой он идет, поворачивает. BACK_SLOW_SPEED и BACK_FAST_SPEED используются в этой функции, чтобы выполнить правильный поворот при движении назад и вернуться на линию. duration задается в момент вызова функции. Судя по коду, если робот ехал медленно, то эта переменная устанавливается в 0 и робот не сдает назад, поскольку сразу вываливается из этой функции. Если ехал быстро, чуть сдает назад.
fasttime - это счетчик, не дающий роботу сразу резво рвануть вперед. Сначала он должен отсчитать FAST_TIME_THRESHOLD вызовов функции runForward, двигаясь на минимальной скорости. И только потом начинает наращивать скорость, добавляя к ней SPEED_STEP, пока она не станет равна SPEED. state - текущее состояние робота (движение вперед, влево, вправо). Устанавливается при вызове соответствующей функции и сравнивается затем с targetState, чтобы решить, надо ли делать stepBack, Состояние targetState определяет затем, как робот будет двигаться дальше, определяя вызов соответствующей функции. Функция stepBack состояние state не меняет. После ее вызова будет осущетсвлен вызов функции движения влево, вправо или прямо, что установит новое состояние робота. И, соответственно, состояние STATE_BACK в данном коде излишне. Нужно понимать, что state в функции stepBack и глобальная state - разные сущности. В функции stepBack используется переданный ей параметр, в остальном коде глобальная переменная.
И для лучшего понимания код неплохо бы оформить отступами. Сразу бы вылезли случаи дисбаланса языковых конструкций. А для вставки кода в текст лучше использовать кнопку "Код"
Да ошибка у Вас, именно, там где сказал geher. Немного помучился, привел его в приемлемый вид. Исправив ошибку, сразу начал компилироваться. Если писать, так как Вы, то ошибки очень сложно найти, даже бывалым. Вот о чем говорил geher, отступы, так намного проще читать. Код (Text): /*Двухколесная платформа Turtle*/ // Ходовые моторы подключены к контроллеру через Motor Shield на микросхеме L298P // Распиновка //Для коммуникации Motor shield с микроконтроллером используются цифровые контакты Arduino: //4 — направление, правый //5 — скорость (ШИМ), правый //6 — скорость (ШИМ), левый //7 — направление, левый // Правый мотор MR подключен к клеммам Motor Shield M1+,M1- // Левый мотор ML подключен к клеммам Motor Shield M2+,M2-с обратной полярностью //Назначение выводов контроллера для управления моторами #define SPEED_LEFT 6 // скорость вращения левого мотора #define DIR_LEFT 7 // направление вращения левого мотора #define SPEED_RIGHT 5 // скорость вращения правого мотора #define DIR_RIGHT 4 // направление вращения правого мотора //Назначение выводов контроллера для подключения датчиков линии #define LEFT_SENSOR_PIN 12 #define RIGHT_SENSOR_PIN 11 // Задаем скорость, с которой происходит движение вперёд (0-255) #define SPEED 150 // Задаем скорости прохождения сложных участков(0-255) #define SLOW_SPEED 40 #define BACK_SLOW_SPEED 30 //- принял из скетча с сайта, но где это используется не понимаю #define BACK_FAST_SPEED 50 //принял из скетча с сайта, но где это используется не понимаю #define STATE_FORWARD 0 //-что такое 0 #define STATE_RIGHT 1 //- что такое 1 #define STATE_LEFT 2 //- что такое 2 #define STATE_BACK 3 //- ввел в программу, поскольку по идее есть модуль движения назад, но он не используется. Не понимаю, по сути не нужно #define SPEED_STEP 2 //- как я понимаю, шаг приращения скорости, заданной в диапазоне 0-255 #define FAST_TIME_THRESHOLD 500 //- по сути время в мс ? //Задаем переменные состояния int state = STATE_FORWARD; //- что задается в этом месте - исходное состояние движения и где эта переменная далее используется при исполнении программного модуля? int currentSpeed = SPEED; int fastTime = 0;// - что есть 0 ? время ? // Программный модуль движения вперед void runForward() { state = STATE_FORWARD; //- для чего здесь нужна строка и что она определяет, на мой взгляд можно просто задать врашение моторов с определенной скоростью и направлением и все. fastTime += 1; //для чего здесь эта строка ? по сути робот как я понял из описания с сайта увеличивает скорость своего движения с начала выполнения программы //- для чего здесь эта строка ? Что она задает при исполнении ? if (fastTime < FAST_TIME_THRESHOLD) { currentSpeed = SLOW_SPEED; } else { //-здесь возникает ошибка при компиляции currentSpeed = min(currentSpeed + SPEED_STEP, SPEED); } analogWrite(SPEED_LEFT, currentSpeed); analogWrite(SPEED_RIGHT, currentSpeed); // Если в DIR_LEFT или DIR_RIGHT пишем HIGH, мотор будет двигать соответствующее колесо // вперёд, если LOW - назад. digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } // Программный модуль поворота направо void steerRight() { state = STATE_RIGHT; fastTime = 0; //-- для чего здесь эта строка ? Что она определяет в этом модуле ? // Останавливаем правое колесо относительно левого, // чтобы начать поворот analogWrite(SPEED_RIGHT, 0);// Останавливаем правый мотор analogWrite(SPEED_LEFT, SPEED);// Левый мотор в работе digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } // Программный модуль поворота налево void steerLeft() { state = STATE_LEFT; fastTime = 0; //- для чего здесь эта строка ? Что она определяет в этом модуле ? // Останавливаем левое колесо относительно правого, // чтобы начать поворот analogWrite(SPEED_LEFT, 0);//Останавливаем левый мотор analogWrite(SPEED_RIGHT, SPEED); // Правый мотор в работе digitalWrite(DIR_LEFT, HIGH); digitalWrite(DIR_RIGHT, HIGH); } //Программный модуль движения назад - модуль далее в программе по сути не используется - зачем он нужен - автор забыл удалить ? //При компиляции к тому же происходит остановка на данном модуле void stepBack(int duration, int state) { //- не понимаю на каком этапе задается переменная duration if (!duration) { return; } // В зависимости от направления поворота при движении назад будем // делать небольшой разворот int leftSpeed = (state == STATE_RIGHT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; int rightSpeed = (state == STATE_LEFT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; analogWrite(SPEED_LEFT, leftSpeed); analogWrite(SPEED_RIGHT, rightSpeed); // реверс колёс digitalWrite(DIR_RIGHT, LOW); digitalWrite(DIR_LEFT, LOW); delay(duration); } // Инициализация робота после включения питания void setup() { // Настраиваем выводы контроллера №№ 4,5,6,7 на вывод сигналов на электродвигатели for(int i = 4; i <= 7; i++) { pinMode(i, OUTPUT); } // едем вперёд runForward(); } // Исполняемый программный модуль void loop() /* Режим движения с использованием датчиков линии */ { // Наш робот ездит по белому полю с чёрным треком. В обратном случае не нужно // инвертировать значения с датчиков boolean left = !digitalRead(LEFT_SENSOR_PIN); boolean right = !digitalRead(RIGHT_SENSOR_PIN); // В какое состояние нужно перейти? int targetState; if (left == right) { // под сенсорами всё белое или всё чёрное // едем вперёд targetState = STATE_FORWARD; } else if (left) { // левый сенсор упёрся в трек // поворачиваем налево targetState = STATE_LEFT; } else { targetState = STATE_RIGHT; } if (state == STATE_FORWARD && targetState != STATE_FORWARD) { int brakeTime = (currentSpeed > SLOW_SPEED) ? currentSpeed : 0; stepBack(brakeTime, targetState); } switch (targetState) { case STATE_FORWARD: runForward(); break; case STATE_RIGHT: steerRight(); break; case STATE_LEFT: steerLeft(); break; } }
Спасибо. Слэш комментария действительно при копировании в начале кода обрезался. Он есть. И с Вашей помощью проверил расстановку скобок. Причина действительно была в отсутствующей скобке в конце функции Setup. Глаз замылился. Как говорится одна голова хорошо а много лучше. Компиляция прошла успешно, благодарю еще раз. Но все равно остаются вопросы. В исполняемом коде VOID LOOP () нет функции движения по линии назад. Тогда вопрос - как исполняется и самое главное на каком этапе программный модуль движения назад // В зависимости от направления поворота при движении назад будем // делать небольшой разворот int leftSpeed = (state == STATE_RIGHT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; int rightSpeed = (state == STATE_LEFT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED; analogWrite(SPEED_LEFT, leftSpeed); analogWrite(SPEED_RIGHT, rightSpeed); // реверс колёс digitalWrite(DIR_RIGHT, LOW); digitalWrite(DIR_LEFT, LOW); delay(duration); }
Благодарю Вас коллеги ! Век живи век учись. Учту про отступы в дальнейшей работе. Однако выделенные красным значения переменных 0, 1 ,2 в начале кода для меня остаются непонятными. Это номера состояний или что ?
Он есть, гляньте тот код, который я подправил. Код (Text): if (state == STATE_FORWARD && targetState != STATE_FORWARD) { int brakeTime = (currentSpeed > SLOW_SPEED) ? currentSpeed : 0; stepBack(brakeTime, targetState); } Да это текущее, состояние. То есть куда едем сейчас. UPD. Не за что, все учимся. Но посоветовал, бы почитать основы, прежде, чем менять код под себя. Не знаю, даже что посоветовать из литературы, может geher, что-то предложит. UPD. 2 Совет, старайтесь избегать, такого кода Код (Text): for(int i = 4; i <= 7; i++) pinMode(i, OUTPUT); и if (!duration) return; Он правильный, просто можно ошибиться, лучше так Код (Text): for(int i = 4; i <= 7; i++) { pinMode(i, OUTPUT); } и if (!duration) { return; } Так, меньше шансов ошибиться.
Буду благодарен, если дадите ссылку на грамотную литературу. Пока черпаю знания от Вас и различных ресурсов интернета, в том числе англоязычного. Исправил код, все скомпилировалось. Далее решил его расширить. Что сделал - сделал по подобию найденных материалов в интернете возможность выбора ряда режимов работы, а именно режим работы с объездом препятствий с использованием УЗ дальномера и второй режим оставил как был - движение по линии. Выбор режимов переключаю двумя кнопками на плате режимов. Как только добавил дополнительный код в вышеуказанный скетч компилятор снова споткнулся на том, с чего я начал тему при компиляции остановка на программном модуле движения вперед и надпись: пишет опять "expected unqulified-id before 'else'" Все скобки перепроверил. Странно, по ващему совету сделал все работает, добавил вставку и все опять на круги своя. В чем проблема не вижу. Помогите. Код прилагаю.
Сложно рекомендовать, не педагог. Не давно пытался пояснить начинающему другу. Так и не смог. Попробуйте, то, что уже написано. https://amperka.ru/product/exploring-arduino http://www.ozon.ru/context/detail/id/7353698/ Можно найти и в интернете, хотя мне нравится бумажные варианты. Хороший справочник на русском. http://robocraft.ru/files/books/arduino_notebook_rus_v1-1.pdf Если серьезно хотите изучить программирование, но после того как прочтете книги описанные выше. http://forum.amperka.ru/threads/Книги-для-начинающих.2344/#post-18913 Сейчас по ошибкам
Ошибок много. Что это, зачем там скобки. Удалить. UPD. 2 stepBack(); Вызов данной функции, не корректен в принципе. Вот Ваша функция //Программный модуль движения назад void stepBack(int duration, int state) У нее 2 параметра, как следствие вызов должен быть таким stepBack(9,9); // то есть нужно передать параметры, к примеру кинул 2 9-ки. UPD.3 Замените свою vultrasoundmode, этой, там скобка пропущена Код (Text): /* Режим движения с использованием ультразвукового дальномера */ void vultrasoundmode() { vservo.write(90); delay(200); Serial.print("Now"); Serial.println(vHC_SR04()); // Если расстояние меньше наименьшего, то if (vHC_SR04() < vmindistance) { // Останавливаем двигатели //vrelease(); // Крутим серву измеряя расстояния и занося данные в массив for (vservo_int = 0; vservo_int < 13; vservo_int = vservo_int + 1) { vservo.write(vservo_array[vservo_int]); delay(200); vHC_SR04_array[vservo_int] = vHC_SR04(); // Выводим данные для отладки Serial.print(vservo_int); Serial.print(" "); Serial.println(vHC_SR04_array[vservo_int]); } vservo.write(90); delay(300); // Поиск в массиве позиции с максимальным значением vmaxarrayindex_int = 0; vmaxarrayvalue_int = 0; for (vservo_int = 0; vservo_int < 13; vservo_int = vservo_int + 1) { if (vHC_SR04_array[vservo_int] > vmaxarrayvalue_int) { vmaxarrayindex_int = vservo_int; vmaxarrayvalue_int = vHC_SR04_array[vservo_int]; } } Serial.print("Max index "); Serial.println(vmaxarrayindex_int); // Проверка - если максимальное значение массива меньше минимального расстояния, то едем назад if (vHC_SR04_array[vmaxarrayindex_int] < vmindistance) { ////stepBack(); delay(500); } /* Проверка - если индекс максимального значения массива меньше 6 то поворачиваем вправо, иначе влево */ if (vmaxarrayindex_int < 6) { steerRight(); // Поворот вправо delay(500); } else { steerLeft();// Поворот влево delay(500); } } else { // Движение прямо runForward(); } } UPD.4 Вставьте в void setup строку Serial.begin(9600); Иначе не сможете работать с Serial UPD.5 Такой функции нет // Останавливаем двигатели vrelease(); Поэтому вызывать ее нельзя.
Ошибок больше нет. Завтра вечером, постараюсь рассказать вам о стиле оформления. Он существено упрощает поиск ошибок и позволяет их не совершать.