Управление радиомоделью
- Войдите на сайт для отправки комментариев
Здравствуйте уважаемые форумчане ! Сразу хочу предупредить - в программировании я ноль (ну может ноль с плюсом)
Моя радиоуправляемая модель, управляется через блютуз.
используется 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 если мотор стоит то крутим, если крутится то останавливаем. Так можно одним символом и вклучать и выключать мотор. Ну это как вариант, я думаю таких вариантов море можно придумать.