Управление радиомоделью
- Войдите на сайт для отправки комментариев
Здравствуйте уважаемые форумчане ! Сразу хочу предупредить - в программировании я ноль (ну может ноль с плюсом)
Моя радиоуправляемая модель, управляется через блютуз.
используется Arduino и Adafruit Motor Shield + bluetooth HC-06
Схема модели такая:
двигатель 1 - (управляет поворотом передних колес - влево/вправо)
двигатель 2 - (управляет задними колесами - вперед/назад)
Управляется модель с помощью приложения Bluetooth RC Controller (Android).
По сусекам на просторах интернета собрал скетч. Ну вот тут возникла проблема с управлением.
И так: Нажимаем "вперед" - начинает вращение задний двигатель (пока держим кнопку едем вперед, когда отпускаем он останавливается), не отпуская кнопки вперед нажимаем влево - и вот тут проблема - двигатель нажинает движение, а при отпускании кнопки влево моторчик не останавливается, а останавливается только при отпускании кнопки вперед. Картина с точностью до наоборот если сначала поворачиваем, а потом едем вперед.
#include <AFMotor.h> // Подключаем библиотеку для работы с шилдом const int TIMEOUT_TIME_MS = 150; unsigned long lastPilotSymbolTime; char symbol; int val; // Подключаем моторы к клеммникам M3, M4 AF_DCMotor motor3(3); AF_DCMotor motor4(4); int LED = 13; // используем встроенный светодиод для индикации работы enum States { WAITING, READING, RUNNING, ERROR, TIMEOUT }; States state; States onWait(); States onRead(); States onRun(); States onError(); States onTimeout(); void setup() { Serial.begin(9600); lastPilotSymbolTime = 0; // Задаем максимальную скорость вращения моторов (аналог работы PWM) motor3.setSpeed(255); motor3.run(RELEASE); motor4.setSpeed(255); motor4.run(RELEASE); //используем 13 пин как индикатор включённой ардуины pinMode(LED, OUTPUT); digitalWrite(LED, HIGH); } void loop() { switch (state) { case WAITING: state = onWait(); break; case READING: state = onRead(); break; case RUNNING: state = onRun(); break; case TIMEOUT: state = onTimeout(); break; default: state = onError(); } } States onWait() { if (Serial.available() > 0) { return READING; } if (lastPilotSymbolTime && (millis() - lastPilotSymbolTime > TIMEOUT_TIME_MS)) { return TIMEOUT; } return WAITING; } States onRead() { symbol = Serial.read(); return RUNNING; } States onRun() { switch (symbol) { case 'F': //начало действий при полученном символе 'F' (вперед) motor4.run(BACKWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'G': //начало действий при полученном символе 'G' (вперед-влево) motor3.run(FORWARD); motor3.setSpeed(255); motor4.run(BACKWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'I': //начало действий при полученном символе 'F' (вперед-вправо) motor3.run(BACKWARD); motor3.setSpeed(255); // Задаем скорость движения motor4.run(BACKWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'B': //начало действий при полученном символе 'B' (назад) motor4.run(FORWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'H': //начало действий при полученном символе 'B' (назад-влево) motor3.run(FORWARD); motor3.setSpeed(255); // Задаем скорость движения motor4.run(FORWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'J': //начало действий при полученном символе 'B' (назад-вправо) motor3.run(BACKWARD); motor3.setSpeed(255); // Задаем скорость движения motor4.run(FORWARD); motor4.setSpeed(255); // Задаем скорость движения break; case 'R': //начало действий при полученном символе 'R' (вправо) motor3.run(BACKWARD); motor3.setSpeed(255); // Задаем скорость движения break; case 'L': //начало действий при полученном символе 'L' (влево) motor3.run(FORWARD); motor3.setSpeed(255); // Задаем скорость движения break; case 'S': //начало действий при полученном символе 'S' (остановка) //[ДОБАВИТЬ СВОЙ КОД НИЖЕ] motor3.run(RELEASE); motor4.run(RELEASE); break; case 'P': //получили контрольный символ, не изменяйте этот код lastPilotSymbolTime = millis(); break; default: return ERROR; } return WAITING; } States onError() { //Получены неоговоренные символы. Очищаем ввод и продолжаем. while (Serial.available()) { Serial.read(); } return WAITING; } States onTimeout() { //Действия при таймауте. //Вероятно, связь утеряна, //но при получении контрольного символа она будет восстановлена. //Здесь, например, уместно выключить двигатели //[ДОБАВИТЬ СВОЙ КОД НИЖЕ] motor3.run(RELEASE); // останавливаем двигатели motor4.run(RELEASE); if (Serial.available()) { return READING; } return TIMEOUT; }
Вообще я собирал свою модель на модуле L298N и все работало, Вот хотел попробовать с шилдом собрать, тут возникла проблема.
Помогите пожайлуста решить проблему.
По коду так и должно работать. Нажимаем F и держим включается и работает ходовой движок. Нажимаем и держим L включается и работает движок поворота. При отпускании L мотор поворота не остановится, т.к. он останавливается в двух случаях, либо S пришло либо 150 мс НИЧЕГО не приходило, а так как F остается зажатая то всё и продолжает работать.
Дело в том, что мне необходимо сделать так, чтобы при движении вперед нажимая например влево - модель поворачивала, при отпускании кнопки влево - модель движется прямо.
Это понятно, но тогда надо не просто читать символы и выполнять условия, а надо еще анализировать что там за символ был и когда он пропал. Т.е. в буфере будет например FFFLFLFLFFFFFF получается что надо поворотный двигатель выключить как тоьлко перестали L идти, например так же через таймаут. Если 150мс не приходит L а до этого была, то гасить поворотный мотор.
Ну это один из возможных вариантов, думаю если подольше подумать то придумается что-то более красивое
Посоветуйте, может мне добавить условие , которое будет выполнятся при отпускании кнопки? - т.е отпускаем кнопку моторчик останавливается.
Получается что при нажатии - 'L' , а при отпускании 'l' . Просто думаю, что необходимо будет дорабатывать приложение по управлению, т.к. про 'L' приложение знает , а про 'l' - не знает.
Я не знаю как верхний уровень устроен (само приложение на аедроиде) Если бы оно при нажатии влево слало L а при отпускании слало что-то еще признак какой-то, например Z, по которому можно остановить мотор, тогда бы было совсем хорошо и доработок было бы минимум. I это же у вас вправо-вперед написано. Моторы у вас останавливаются тоьлко если пришло S или вообще ничего не приходит.
Если дорабатывать приложение на андроиде то как вариант при нажатии один раз послать L при отпускании снова послать L, а в скетче ввести флаг состояния мотора. Тогда при получении L если мотор стоит то крутим, если крутится то останавливаем. Так можно одним символом и вклучать и выключать мотор. Ну это как вариант, я думаю таких вариантов море можно придумать.