Технический форум по робототехнике.
elmot писал(а):дык программно меняешь шим и все. 2-3сек - очень долго. Если цель - неубиение шестерен, то проще 2-3 ступени мощности за первые 0.2 сек. Хотя меня не оставляет впечатление, что в твоем случае шестерня была убита при постановке ребенка на машинку.
// Скетч для управления через блютус, Wild Thumper 6WD, на ардуино совместимом контролере TREX controller. реализовано движение и стрельба с водомета.
#include <BTCA2ALite.h>// Добавляем библиотеку блютус программы
#include <Servo.h> // Добавляем библиотеку серво
Servo myservoH; // Горизонтальная серва углы от 0 до 180 (центровка 89)
Servo myservoV; // Вертикальная серва углы от 1 до 45
const int H_SERVO_PIN = 7; // Горизонтальная серва подключена к пину 7
const int V_SERVO_PIN = 8; //Пин вертикального сервопривода 8
const float H_L_ANGLE = 180; // Максимальные угл поворота башни налево
const float H_R_ANGLE = 0; // Максимальные угл поворота башни направо
const float H_DEF_ANGLE = 89; // Дефолтный угол (центровка)
const float V_U_ANGLE = 45; // Максимальные угл поворота башни вверх
const float V_D_ANGLE = 0; // Максимальные угл поворота башни вниз
const float V_DEF_ANGLE = 15; // Дефолтный угол (центровка)
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
const float V_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по вертикали.
const float H_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по горизонтали
float curVAngle = V_DEF_ANGLE; //Переменная текущего угла верт. сервы
float curHAngle = H_DEF_ANGLE; //Переменная текущего угла гор. сервы
bool moveServoVUp = false; //Флаг движения верт. сервы вверх
bool moveServoVDown = false; //Флаг движения верт. сервы вниз
bool moveServoHLeft = false; //Флаг движения гор. сервы влево
bool moveServoHRight = false; //Флаг движения гор. сервы вправо
btca2aLite btca2aLite; // Конструктор btca2aLite
// Задаем скорости для движения
int Speed = 80; // Текущая максимальная скорость
int TSpeed = 150; // Скорость медленного мотора при повороте
[b]int RLSpeed; // Скорость танкоаого разворота[/b]
// задаем пины для левого мотора
#define Dir_L 2
#define Pwm_L 3
#define Brake_L 4
// задаем пины для правого мотора
#define Dir_R 10
#define Pwm_R 11
#define Brake_R 9
#define SHOT 12 // пин для водомета
enum States
{
WAITING,
READING,
RUNNING,
ERROR,
TIMEOUT
};
States state;
States onWait();
States onRead();
States onRun();
States onError();
States onTimeout();
void performServo(); // добовляем сервы
void setup(){
Serial.begin(9600); // Скорость BT и порта должна быть 9600
//Моторы
pinMode (Pwm_L, OUTPUT);
pinMode (Dir_L, OUTPUT);
pinMode (Brake_L, OUTPUT);
pinMode (Pwm_R, OUTPUT);
pinMode (Dir_R, OUTPUT);
pinMode (Brake_R, OUTPUT);
digitalWrite (Pwm_L, LOW);
digitalWrite (Pwm_R, LOW);
digitalWrite (Brake_L, LOW);
digitalWrite (Brake_R, LOW);
pinMode(SHOT, OUTPUT); // задаем выход для стрельбы водой
// устанавливаем пин как вывод управления сервой
myservoH.attach(H_SERVO_PIN);
myservoV.attach(V_SERVO_PIN);
myservoH.write(curHAngle);
myservoV.write(curVAngle);
//Светодиод
pinMode(13, OUTPUT); // Инициализируем пин светодиода
digitalWrite(13, HIGH); // Светодиод выключен
}
void loop(){
btca2aLite.ReadCommand(); // Считывание принятых команд (кодов кнопок)
//Вызываем функцию управление сервами
performServo();
//--------— Движение Вперед —-------------
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_UP)) // Едет вперед если нажат курсор ВПЕРЕД
{
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)){ // Поворот направо при нажатии курсора ВПЕРЕД и ВЛЕВО
digitalWrite (Dir_L, HIGH);
analogWrite (Pwm_L, TSpeed);
digitalWrite (Dir_R, HIGH);
analogWrite (Pwm_R, Speed);
}
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT)){ // Поворот налево при нажатии курсора ВПЕРЕД и ВПРАВО
digitalWrite (Dir_L, HIGH);
analogWrite (Pwm_L, Speed);
digitalWrite (Dir_R, HIGH);
analogWrite (Pwm_R, TSpeed);
}
digitalWrite (Dir_L, HIGH);
analogWrite (Pwm_L, Speed);
digitalWrite (Dir_R, HIGH);
analogWrite (Pwm_R, Speed);
}
//-------— Движение Назад —-------------
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_DOWN)) // Едет назад если нажат курсор НАЗАД
{
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)){ // Поворот налево при нажатии курсора НАЗАД и ВЛЕВО
digitalWrite (Dir_L, LOW);
analogWrite (Pwm_L, TSpeed);
digitalWrite (Dir_R, LOW);
analogWrite (Pwm_R, Speed);
}
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT)){ // Поворот направо при нажатии курсора НАЗАД и ВПРАВО
digitalWrite (Dir_L, LOW);
analogWrite (Pwm_L, Speed);
digitalWrite (Dir_R, LOW);
analogWrite (Pwm_R, TSpeed);
}
digitalWrite (Dir_L, LOW);
analogWrite (Pwm_L, Speed);
digitalWrite (Dir_R, LOW);
analogWrite (Pwm_R, Speed);
}
//-------— Движение Влево (Танковый разворот) —-------------
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT )) // разворот на месте в лево
{
digitalWrite (Dir_L, LOW);
analogWrite (Pwm_L, RLSpeed);
digitalWrite (Dir_R, HIGH);
analogWrite (Pwm_R, RLSpeed);
}
//-------— Движение Вправо (Танковый разворот) —-------------
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)) // разворот на месте в право
{
digitalWrite (Dir_L, HIGH);
[b]for (RLSpeed = 80; RLSpeed <= 200; ++RLSpeed)[/b]
analogWrite (Pwm_L, RLSpeed);
digitalWrite (Dir_R, LOW);
[b]for (RLSpeed = 80; RLSpeed <= 200; ++RLSpeed)[/b]
analogWrite (Pwm_R, RLSpeed);
}
//-------— движение в право —-------------
if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)) //
{
digitalWrite (Dir_L, HIGH);
analogWrite (Pwm_L, RLSpeed);
digitalWrite (Dir_R, LOW);
analogWrite (Pwm_R, RLSpeed);
}
//---------- Переключение скоростей —-------------
if(btca2aLite.Button(KEYCODE_BUTTON_START)) // ТУРБО режимпри нажатии кнопки START
{
Speed = 200;
}
if(btca2aLite.Button(KEYCODE_BUTTON_R2)) // 4-я Скорость при нажатии кнопки R2
{
Speed = 150;
}
if(btca2aLite.Button(KEYCODE_BUTTON_R1)) // 3-я Скорость при нажатии кнопки R1
{
Speed = 120;
}
if(btca2aLite.Button(KEYCODE_BUTTON_L2)) // 2-я Скорость при нажатии кнопки L2
{
Speed = 90;
}
if(btca2aLite.Button(KEYCODE_BUTTON_L1)) // 1-я Скорость при нажатии кнопки L2
{
Speed = 70;
}
//-------— включение насоса —-------------
if (btca2aLite.ButtonPressed(KEYCODE_BUTTON_SELECT))
{
digitalWrite (SHOT, HIGH);
}
//-------— выключение насоса происходит автоматически после отпускания кнопки—-------------
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_SELECT))
{
digitalWrite (SHOT, LOW);
}
//--------— Повороты серв при нажатии кнопок —-------------
if(btca2aLite.Button(KEYCODE_BUTTON_X)) // servoV вниз
{
moveServoVDown = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_A)) // servoH движется к 0
{
moveServoHRight = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_B)) // servoV вверх
{
moveServoVUp = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_Y)) // servoH движется к 180
{
moveServoHLeft = true;
}
//--------— чтобы сервы не продолжали движения при отжатых кнопках —-------------
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X))
{
moveServoVDown = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B))
{
moveServoVUp = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A))
{
moveServoHRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y))
{
moveServoHLeft = false;
}
//----------------— Стоп —---------------------
// Если не нажата ни одна кнопка курсора происходит остановка, скорость 0 для каждого мотора
if (btca2aLite.ButtonReleased(KEYCODE_DPAD_UP) && btca2aLite.ButtonReleased(KEYCODE_DPAD_DOWN) && btca2aLite.ButtonReleased(KEYCODE_DPAD_LEFT) && btca2aLite.ButtonReleased(KEYCODE_DPAD_RIGHT)){
analogWrite (Pwm_L, 0);
analogWrite (Pwm_R, 0);
}
}
//Функция управления сервоприводами (вызывается в теле loop на каждой итерации)
//Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения
//Флаги устанавливаются согласно поступившим символам управления сервами
void performServo()
{
//Установлен флаг движения вверх и текущий угол не максимальный
if (moveServoVUp && curVAngle + V_STEP <= V_U_ANGLE)
{
//К текущему верт. углу прибавляем шаг
curVAngle += V_STEP;
}
//Установлен флаг движения вниз и текущий угол не минимален
else if (moveServoVDown && curVAngle - V_STEP >= V_D_ANGLE)
{
//От текущего верт. угла отнимаем шаг
curVAngle -= V_STEP;
}
//Установлен флаг движения влево и текущий угол не максимален
if (moveServoHLeft && curHAngle + H_STEP <= H_L_ANGLE)
{
//К текущему гор. углу прибавляем гор. шаг
curHAngle += H_STEP;
}
//Установлен флаг движения вправо и текущий угол не минимален
else if (moveServoHRight && curHAngle - H_STEP >= H_R_ANGLE)
{
//От текущего угла отнимаем гор. шаг
curHAngle -= H_STEP;
}
//Если было движние по вертикали
if (moveServoVUp || moveServoVDown)
{
myservoV.write(curVAngle);
}
//Если было движение по горизонтали
if (moveServoHLeft || moveServoHRight)
{
myservoH.write(curHAngle);
}
}
Aseris писал(а):Поствить фильтр на значение скорости, чтоб на управляющий вход шло знчение Vi плавно наростающее. нар Vi=(Vi-1*200+Vупр*56)/256
// Скетч для управления через блютус, Wild Thumper 6WD, на ардуино совместимом контролере TREX controller. реализовано движение и стрельба с водомета.
#include <BTCA2ALite.h>// Добавляем библиотеку блютус программы
#include <Servo.h> // Добавляем библиотеку серво
Servo myservoH; // Горизонтальная серва углы от 0 до 180 (центровка 89)
Servo myservoV; // Вертикальная серва углы от 1 до 45
const int H_SERVO_PIN = 5; // Горизонтальная серва подключена к пину 7
const int V_SERVO_PIN = 8; //Пин вертикального сервопривода 8
const float H_L_ANGLE = 120; // Максимальные угл поворота башни налево
const float H_R_ANGLE = 70; // Максимальные угл поворота башни направо
const float H_DEF_ANGLE = 90; // Дефолтный угол (центровка)
const float V_U_ANGLE = 120; // Максимальные угл поворота башни вверх
const float V_D_ANGLE = 0; // Максимальные угл поворота башни вниз
const float V_DEF_ANGLE = 90; // Дефолтный угол (центровка)
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
const float V_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по вертикали.
const float H_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по горизонтали
float curVAngle = V_DEF_ANGLE; //Переменная текущего угла верт. сервы
float curHAngle = H_DEF_ANGLE; //Переменная текущего угла гор. сервы
bool moveServoVUp = false; //Флаг движения верт. сервы вверх
bool moveServoVDown = false; //Флаг движения верт. сервы вниз
bool moveServoHLeft = false; //Флаг движения гор. сервы влево
bool moveServoHRight = false; //Флаг движения гор. сервы вправо
btca2aLite btca2aLite; // Конструктор btca2aLite
// задаем пины для левого мотора
#define Dir_L 2
#define Pwm_L 3
#define Brake_L 4
// задаем пины для правого мотора
#define Dir_R 10
#define Pwm_R 11
#define Brake_R 9
// Задаем скорости для движения
byte MaxSpeed = 250; // Максимальная скорость
byte MinSpeed = 100; // Минимальная скорость
int forw_back = 0;
int righ_left = 0;
byte step_fb = 5; // Шаг изменения скорости движения вперед - назад
byte step_stop = 10; // Шаг изменения скорости остановки
byte step_rl = 20; // Шаг изменения скорости движения вправо - влево
byte step_dir = 10; // Шаг изменения скорости выравнивания
#define SHOT 12 // пин для водомета
enum States
{
WAITING,
READING,
RUNNING,
ERROR,
TIMEOUT
};
States state;
States onWait();
States onRead();
States onRun();
States onError();
States onTimeout();
void performServo(); // добовляем сервы
void setup(){
Serial.begin(9600); // Скорость BT и порта должна быть 9600
//Моторы
pinMode (Pwm_L, OUTPUT);
pinMode (Dir_L, OUTPUT);
pinMode (Brake_L, OUTPUT);
pinMode (Pwm_R, OUTPUT);
pinMode (Dir_R, OUTPUT);
pinMode (Brake_R, OUTPUT);
digitalWrite (Pwm_L, LOW);
digitalWrite (Pwm_R, LOW);
digitalWrite (Brake_L, LOW);
digitalWrite (Brake_R, LOW);
pinMode(SHOT, OUTPUT); // задаем выход для стрельбы водой
// устанавливаем пин как вывод управления сервой
myservoH.attach(H_SERVO_PIN);
myservoV.attach(V_SERVO_PIN);
myservoH.write(curHAngle);
myservoV.write(curVAngle);
//Светодиод
pinMode(13, OUTPUT); // Инициализируем пин светодиода
digitalWrite(13, HIGH); // Светодиод выключен
}
void loop(){
btca2aLite.ReadCommand(); // Считывание принятых команд (кодов кнопок)
//Вызываем функцию управление сервами
performServo();
static unsigned long pre_millis = 0;
if(millis()-pre_millis > 50)
{
pre_millis = millis();
if(btca2aLite.ButtonPressed(KEYCODE_DPAD_UP))
{
forw_back += step_fb;
if(forw_back > 0 && forw_back < MinSpeed) forw_back = MinSpeed;
}
else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_DOWN))
{
forw_back -= step_fb;
if(forw_back < 0 && forw_back > MinSpeed*-1) forw_back = MinSpeed*-1;
}
else
{
if(forw_back < 0) forw_back += step_stop;
else if(forw_back > 0) forw_back -= step_stop;
if(abs(forw_back) < MinSpeed) forw_back = 0;
}
forw_back = constrain(forw_back, MaxSpeed*-1, MaxSpeed);
if(btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT))
{
righ_left += step_rl;
if(righ_left > 0 && righ_left < MinSpeed) righ_left = MinSpeed;
}
else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT))
{
righ_left -= step_rl;
if(righ_left < 0 && righ_left > MinSpeed*-1) righ_left = MinSpeed*-1;
}
else
{
if(righ_left < 0) righ_left += step_dir;
else if(righ_left > 0) righ_left -= step_dir;
if(abs(righ_left) < MinSpeed) righ_left = 0;
}
righ_left = constrain(righ_left, MaxSpeed*-1, MaxSpeed);
int pwm_l = forw_back + righ_left;
int pwm_r = forw_back - righ_left;
pwm_l = constrain(pwm_l, MaxSpeed*-1, MaxSpeed);
pwm_r = constrain(pwm_r, MaxSpeed*-1, MaxSpeed);
digitalWrite(Dir_L, (pwm_l<0)?0:1);
digitalWrite(Dir_R, (pwm_r<0)?0:1);
analogWrite(Pwm_L, abs(pwm_l));
analogWrite(Pwm_R, abs(pwm_r));
}
//-------— включение насоса —-------------
if (btca2aLite.ButtonPressed(KEYCODE_BUTTON_SELECT))
{
digitalWrite (SHOT, HIGH);
}
//-------— выключение насоса происходит автоматически после отпускания кнопки—-------------
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_SELECT))
{
digitalWrite (SHOT, LOW);
}
//--------— Повороты серв при нажатии кнопок —-------------
if(btca2aLite.Button(KEYCODE_BUTTON_X)) // servoV вниз
{
moveServoVDown = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_A)) // servoH движется к 0
{
moveServoHRight = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_B)) // servoV вверх
{
moveServoVUp = true;
}
if(btca2aLite.Button(KEYCODE_BUTTON_Y)) // servoH движется к 180
{
moveServoHLeft = true;
}
//--------— чтобы сервы не продолжали движения при отжатых кнопках —-------------
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X))
{
moveServoVDown = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B))
{
moveServoVUp = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A))
{
moveServoHRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y))
{
moveServoHLeft = false;
}
//----------------— Стоп —---------------------
// Если не нажата ни одна кнопка курсора происходит остановка, скорость 0 для каждого мотора
if (btca2aLite.ButtonReleased(KEYCODE_DPAD_UP) && btca2aLite.ButtonReleased(KEYCODE_DPAD_DOWN) && btca2aLite.ButtonReleased(KEYCODE_DPAD_LEFT) && btca2aLite.ButtonReleased(KEYCODE_DPAD_RIGHT)){
analogWrite (Pwm_L, 0);
analogWrite (Pwm_R, 0);
}
}
//Функция управления сервоприводами (вызывается в теле loop на каждой итерации)
//Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения
//Флаги устанавливаются согласно поступившим символам управления сервами
void performServo()
{
//Установлен флаг движения вверх и текущий угол не максимальный
if (moveServoVUp && curVAngle + V_STEP <= V_U_ANGLE)
{
//К текущему верт. углу прибавляем шаг
curVAngle += V_STEP;
}
//Установлен флаг движения вниз и текущий угол не минимален
else if (moveServoVDown && curVAngle - V_STEP >= V_D_ANGLE)
{
//От текущего верт. угла отнимаем шаг
curVAngle -= V_STEP;
}
//Установлен флаг движения влево и текущий угол не максимален
if (moveServoHLeft && curHAngle + H_STEP <= H_L_ANGLE)
{
//К текущему гор. углу прибавляем гор. шаг
curHAngle += H_STEP;
}
//Установлен флаг движения вправо и текущий угол не минимален
else if (moveServoHRight && curHAngle - H_STEP >= H_R_ANGLE)
{
//От текущего угла отнимаем гор. шаг
curHAngle -= H_STEP;
}
//Если было движние по вертикали
if (moveServoVUp || moveServoVDown)
{
myservoV.write(curVAngle);
}
//Если было движение по горизонтали
if (moveServoHLeft || moveServoHRight)
{
myservoH.write(curHAngle);
}
}