Программа
Для управления сервомоторами робота используем стандартную библиотеку Servo. Движение сервомоторов на заданный угол осуществляется при помощи функции write. Для управления сервомоторов, необходимо подать на него ШИМ сигнал управления с помощью функции attach. А функция detach отключит сервомотор.
Ознакомиться с основами работы с сервомоторами в среде Arduino IDE можно в уроке управление сервоприводом.
Вращение сервомоторов
Напишем программу, которая сначала повернёт моторы в исходное положение — угол 90 градусов. Затем последовательно повращает все четыре мотора. В конце — отключит моторы.
#include "Servo.h"
// основание, первый узел, второй узел, захват
byte servoPins[4] = {11,10,9,5};
Servo srv[4];
void setup() {
for(byte i=0; i<4; i++){
srv[i].attach(servoPins[i]);
}
// сброс сервомоторов в центральное положение
for(byte i=0; i<4; i++){
srv[i].write(90);
}
delay(3000);
// вращение в стороны
for(byte i=0; i<4; i++){
srv[i].write(80); // движение против часовой на 10 градусов
delay(1000);
srv[i].write(100); // движение по часовой на 10 градусов
delay(1000);
srv[i].write(90); // возвращение в исходное
delay(1000);
}
delay(3000);
// отключение сервомоторов
for(byte i=0; i<4; i++){
srv[i].detach();
}
}
void loop() {
}
Движение по программе
Пусть теперь рука двигается по заданному алгоритму.
#include <Servo.h>
Servo js[4];
// основание, первый узел, второй узел, захват
int jpins[4] = {11,10,9,5};
// начальные углы
int angles[4] = {90,90,90,90};
// скорость
int sp = 10;
void movej( int jn, int a, int t ){
int d, cnt, ca;
int i = 0;
ca = angles[jn];
d = ca - a;
cnt = abs(d);
while( i<cnt ){
js[jn].write(ca);
if( d<0 )
ca++;
else
ca--;
i++;
delay(t);
}
angles[jn] = ca;
}
void setup() {
for(int i=0; i<4; i++)
js[i].attach(jpins[i]);
for(int i=0; i<4; i++){
js[i].write(angles[i]);
delay(500);
}
}
void loop() {
movej( 0, 130, sp ); // влево
movej( 3, 90, sp ); // открыть клешню
movej( 1, 20, sp ); // вперед
movej( 2, 150, sp ); // вниз
movej( 3, 130, sp ); // закрыть клешню
movej( 2, 90, sp ); // вверх
movej( 1, 110, sp ); // назад
movej( 0, 30, sp ); // вправо
movej( 1, 20, sp ); // вперед
movej( 2, 150, sp ); // вних
movej( 3, 90, sp ); // открыть клешню
movej( 3, 130, sp ); // закрыть клешню
movej( 2, 90, sp ); // вверх
movej( 1, 110, sp ); // назад
}
Загружаем программу на Arduino и подаём питание.
Управление джойстиками
Напишем программу, которая будет анализировать сигнал с джойстиков и поворачивать соответствующие элементы робота.
#include <Servo.h>
#define MAX_J 768
#define MIN_J 256
uint8_t pos[4] = {90,90,90,90}; // начальные углы сервомоторов
// контакты джойстиков по порядку:
// левый вертикальный, левый горизонтальный
// правый горизонтальный, правый вертикальный
uint16_t pot_pins[4] = {A0,A1,A2,A3}; // lv, lh, rh, rv
uint8_t sn = 255;
int8_t sd = 0;
uint32_t st_next = 0;
uint16_t st_to = 10;
// таймаут отключения моторов
uint32_t idle_next = 0;
uint16_t idle_to = 500;
uint8_t servo_pins[4] = {11,10,9,5}; // контакты сервомоторов
uint8_t servo_inv[4] = {-1,-1,-1,1}; // инверсия управления
// предельные углы поворота
uint8_t servo_minmax[4][2] = {{45,135},{45,135},{45,135},{70,135}};
Servo arm[4];
void handleIdle(){
uint32_t t = millis();
if( idle_next && idle_next < t ){
idle_next = 0;
for( uint8_t i=0; i<4; i++ ){
arm[i].detach();
}
}
}
void handleServo(){
uint32_t t = millis();
if( sn!=255 ){
if( st_next && t < st_next )
return;
idle_next = t + idle_to;
st_next = t + st_to;
pos[sn] += servo_inv[sn]*sd;
if( pos[sn]<servo_minmax[sn][0] )
pos[sn] = servo_minmax[sn][0];
else
if( pos[sn]>servo_minmax[sn][1] )
pos[sn] = servo_minmax[sn][1];
if( !arm[sn].attached() )
arm[sn].attach(servo_pins[sn]);
arm[sn].write( pos[sn] );
} else {
arm[sn].detach();
st_next = 0;
}
}
void setup() {
//Serial.begin(115200);
for( uint8_t i=0; i<4; i++ ){
pinMode(pot_pins[i], INPUT);
}
// движение в начальные позиции
for( uint8_t i=0; i<4; i++ ){
arm[i].attach(servo_pins[i]);
arm[i].write(pos[i]);
delay(1000);
arm[i].detach();
}
}
void loop() {
sn = 255;
uint16_t v;
for( uint8_t i=0; i<4; i++ ){
v = analogRead( pot_pins[i] );
if (v > MAX_J || v < MIN_J){
sn = i;
sd = (v > MAX_J) ? 1 : -1;
}
}
handleServo();
handleIdle();
}
