Синхронизация 2 колес у машинки
- Войдите на сайт для отправки комментариев
Всем доброго, друзья! Продолжаю долго и упорно пилить свою машинку радиоуправляемую (робо-хоккей).
В целом всё ок- но никак не могу сделать синхронизацию 2 колес-чтобы машинка ехала строго вперед.
Переписал код, отвечающий за синхронизацию - уже раз 100 наверное :-))). И когда уже совсем задолбался-пишу сюда...
В общем, суть такая: на каждом колесе стоит 12-ти сегментный энкодер и оптический цифровой датчик-который это дело считывает.
С какими трудностями столкнулся:
1) когда еще без попыток сихнронизации - просто сделал вывод на экран скоростей 2 двигателей - то стало видно, что скорость кардинально скачет на одном колесе и на соседних срабатываниях. Типичные прыжки 0-25-63-0 и т.д. То есть, система видит малейшие неточности в изготовлении колеса и даже малейшую "восьмерку" на нем.
Как боролся: брал 4 срабатывания- суммировал и делил на 4. В итоге получал некую среднюю скорость;
2) Много всего прочитал про прерывания и делал по разному:
вариант а): функция, вызываемая по прерыванию - только регистрирует время, когда оно произошло, а коррекция скорости происходит уже в главном методе loop (так рекомендуют делать);
вариант б): функция корректирует скорости двигателей - мне этот вариант кажется более простым и логичным- но с ним вылазит ошибка - система вываливается с ошибкой.
Пишет "Guru Meditation Error: Core 1 panic'ed (Coprocessor exception)"
Нашел примерно в суть этой ошибки- в том, что постоянно перезаписывается переменная и что то там с кучей.
Пробовал менять тип переменной, в которую пишется время (uint32_t)- на любой другой - не работает.
Короче говоря, по итогам всех мытарств- "поможайте чем можете" :-))))
P.S. корректировку скоростей веду по-умному, с помощью ПИД регулятора. Пытался применить известный GyverPID - но он у меня не завелся, по причине, что у меня Windows 7. А ему надо Windows 10 и более свежую Arduino IDE.
Вот сам код-вернее выжимки из него, относящиеся к вопросу):
String state; //сюда будет писаться состояние, т.е. куда едет машинка в данный момент volatile long lasttime1 = 0; volatile long lasttime2 = 0; //Куда подключены оптические датчики энкодера: int SensorPin1 = 13; int SensorPin2 = 14; // подключаем контакты оптических датчиков к пину, в режим «INPUT»: pinMode (SensorPin1, INPUT); pinMode (SensorPin2, INPUT); // подключаем реакцию на прерывания - к пинам датчиков: attachInterrupt(digitalPinToInterrupt(SensorPin1), sensor_test, HIGH); attachInterrupt(digitalPinToInterrupt(SensorPin2), sensor_test2, HIGH);
//ПАМЯТКА: тут перепутаны pwmChannel: по идее - первому датчику должен соответствовать pwmChannel, // а второму- pwmChannel2. Но нет! Всё наоборот: Sensor1 - pwmChannel2, Sensor2 - pwmChannel, //причина-мой локальный бардак :-))) // Функция, запускающаяся при возникновении прерывания - с датчика 1: void sensor_test () { detachInterrupt(SensorPin1); lasttime1 = millis(); if (state.equals ("Forward")) //анализ ведем только для случая, если едем вперед { if (lasttime1>lasttime2) { ledcWrite(pwmChannel2, computePID (lasttime1,lasttime2, 1, 0, 0, 10, 0, 55)); //замедляем скорость быстрого двигателя. Пока все значения выставлены в ноль-чтобы настроить из ПИД-а хотя бы П //ПАМЯТКА: 255 - максимум оборотов } else { ledcWrite(pwmChannel, computePID(lasttime2, lasttime1, 1, 0, 0, 10, 0, 55)); //замедляем скорость быстрого двигателя. Пока все значения выставлены в ноль-чтобы настроить из ПИД-а хотя бы П //ПАМЯТКА: 255 - максимум оборотов
} } attachInterrupt(digitalPinToInterrupt(SensorPin1), sensor_test, HIGH); }
// Функция, запускающаяся при возникновении прерывания - с датчика 2: void sensor_test2 () { detachInterrupt(SensorPin2); lasttime2 = millis(); if (state.equals ("Forward")) //анализ ведем только для случая, если едем вперед { if (lasttime1>lasttime2) { ledcWrite(pwmChannel2, computePID (lasttime1,lasttime2, 1, 0, 0, 10, 0, 55)); //замедляем скорость быстрого двигателя. Пока все значения выставлены в ноль-чтобы настроить из ПИД-а хотя бы П //ПАМЯТКА: 255 - максимум оборотов
} else { ledcWrite(pwmChannel, computePID(lasttime2, lasttime1, 1, 0, 0, 10, 0, 55)); //замедляем скорость быстрого двигателя. Пока все значения выставлены в ноль-чтобы настроить из ПИД-а хотя бы П //ПАМЯТКА: 255 - максимум оборотов
} } attachInterrupt(digitalPinToInterrupt(SensorPin2), sensor_test, HIGH); }
Код ПИД регулятора:
int computePID(float input, float setpoint, float kp, float ki, float kd, float dt, int minOut, int maxOut) { float err = setpoint - input; static float integral = 0, prevErr = 0; integral = constrain(integral + (float)err * dt * ki, minOut, maxOut); float D = (err - prevErr) / dt; prevErr = err; return constrain(err * kp + integral + D * kd, minOut, maxOut); }
В строках 03-04 -в первом куске кода ошибка - там у меня обычно стояло
Один черт неправильно :-). Надо попробовать на float поменять.
P.S. забыл сказать -система построена на ESP32.
Извиняюсь, что ответ не по теме, но боюсь, что по теме и не будет с такой постановкой вопроса. К чему приведены эти огрызки кода, да ещё с комментариями типа "ой, тут что-то перепутано", "а тут временно подставлено", "а тут ошибка". Ладно хоть в последней строчке не забыли сказать про то, что это ESP32!
Напишите минимальный скетч с вашим способом коррекции хода, в котором машинка при включении просто едет вперёд. Без какого либо внешнего управления или других действий совсем. По нему может кто чего и подскажет. Лучше без библиотек Гайвера, иначе к нему и пошлют!
//суть этой ошибки- в том, что постоянно перезаписывается переменная и что то там с кучей.
очень распастраненная проблема, когда решите - отпишитесь здесь обязательно! Вы спасете ИТ-индустрию.
Машинка симпатичная!
Спасибо!
Никто дельного не написал по поводу синхронизации-сел сам. В 101-й раз пытаться допилить :-)))
Никто дельного не написал по поводу синхронизации-сел сам. В 101-й раз пытаться допилить :-)))
почему же, в сообщении #1 вам вполне по делу написали. Задавайте вопросы нормально, приводите полный код - тогда будет хоть какая-то надежда на ответ.
А сейчас я все ваши вкладки с кодом даже открывать не стал, открыл первую - мне хватило
обижаться не надо.
от правильной постановки вопроса зависит получение ответа .
ну и программу показать отформатированную и со строками.
и ещё - здесь гайверовские программные изыски не особо приветствуются, обычно отправляют к афтору.
и ещё - здесь гайверовские программные изыски не особо приветствуются, обычно отправляют к афтору.
Всё-решил вопрос. Вопрос оказался даже не совсем в области алгоритмов: тупо перепутаны датчики крест-накрест в программе (мотор1 регулируем, ориентируясь на датчик2).
А насчет гайвера кстати в первый раз слышу. А почему так? хреново пишет или что?
А насчет гайвера кстати в первый раз слышу. А почему так? хреново пишет или что?
Более того, доведение чего-то "до ума" требует некоторого времени, а блогеру нужно публиковать очередной репортаж.
Вот на примере проекта:
http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-sp...
Ок, понял...Спасибо за развернутый ответ!
Видите ли, Гайвер - талантливый блогер, но весьма посредственный программист.
С первым утверждением не вполне соглашусь, есть и поживее блохеры. Со вторым спорить не стану. Тут доверяю мнению программистов, поскольку сам, к сожалению, еще не дорос до права иметь свое в этой сфере. Но надо отдать ему должное, как популяризатору программизма среди малообразованного народонаселения:) Между сайтом ардуино.СС с кратким перечнем функций "языка wire" и книгами трупа страуса и Шилдта лежит огромный информационный вакуум. А вселенная, как известно, не терпит пустоты.