Управление серво приводом и регулятором скорости (ESC)
- Войдите на сайт для отправки комментариев
В связи с небольшим опытом программирования, не могу решить задачу.
Плата Arduino Duemilanove (328)
Написал небольшой скетч управление серво приводом (SG-5010) через COM порт.
#include <Servo.h>
int val;
Servo servo;
void setup()
{
servo.attach(9);
Serial.begin(9600);
}
void loop()
{
if (Serial.available())
{
val = Serial.read();
if (val == 119) // w = 119 in dec
{
servo.write(170);
}
else if (val == 115) //s = 115 in dec
{
servo.write(10);
}
}
Купил бесщеточный двигатель A2212/13T + ESC (отдельно для него написал скетч, что бы проверить все работает)
Не получается объединить в рамках 1 скетча управление cерво приводом и ESC.
Хотел нажатием пробела (ASCII = 32) запустить двигатель и с каждым нажатием увеличивать обороты.
Если есть, у кого то опыт поделитесь пожалуйста.
Тогда может кто подскажит как организовать 2-а независимых цикла в 1 скетч ?
Так покажите ваш код для безколлекторника
01
Servo motor1;
02
void
arm(){
03
setSpeed(0);
04
delay(1000);
05
}
06
void
setSpeed(
int
speed){
07
int
angle = map(speed, 0, 100, 0, 180);
08
motor1.write(angle);
09
}
10
11
void
setup
()
12
{
13
motor1.attach(7);
14
arm();
15
}
16
17
void
loop
()
18
{
19
int
speed;
20
for
(speed = 0; speed <= 100; speed += 5) {
21
setSpeed(speed);
22
delay(1000);
23
}
24
for
(speed = 95; speed > 0; speed -= 5) {
25
setSpeed(speed);
26
delay(1000);
27
}
28
setSpeed(0);
29
delay(5000);
30
}
Это тестовый скетч для проверки работы двигателя и регулировки скорости вращения.
Мои попытки написать скетч для одновременной работы с условием значения переменной не привели к успеху, я даже понимаю почему это происходит, при последующих циклах значение переменной исчезает и условие не выполняется, также для двигателя нужен delay (задержка), в цикле с задержкой серва приводы начинают реагировать на 1 сек позже, по этой причине и нужно разделять циклы.
Чтобы значение переменной не "исчезало", ее надо определить как глобальную. Delay() исключить использовав millis() с проверкой периода задержки. Соответственно For Вам здесь не поможет (он даст задержку в любом случае, пока колностью не выполнится), модифицируем на другие методы -
http://arduino.ru/Reference/If
http://arduino.ru/Reference/While
Спасибо по результату отпишусь.
Можете направить как определить глобальную переменую?
01
#include <Servo.h>
02
03
Servo motor1;
04
05
void
setup
(){
06
motor1.attach(7);
07
arm();
08
}
09
10
void
loop
(){
11
for
(
byte
i = 0; i <= 100; i += 5) {
12
setSped(i);
13
delay(1000);
14
}
15
for
(
byte
i = 95; i >= 0; i -= 5) {
16
setSped(i);
17
delay(1000);
18
}
19
setSped(0);
20
delay(5000);
21
}
22
23
void
arm(){
24
setSped(0);
25
delay(1000);
26
}
27
void
setSped(
byte
sped){
28
motor1.write(map(sped, 0, 100, 0, 180));
29
}
если компилятор выделяет цветом названия которые ты даешь, значит лучше их поменять
значит эти названия зарезервированы, и возможны глюки
Спасибо по результату отпишусь.
Можете направить как определить глобальную переменую?
http://arduino.ru/Tutorial/Variables
Решил задачу разбить по шагам, для начала разобраться как использовать цикл while
Написал простой скетч
01
#include <Servo.h>
02
03
Servo motor1;
04
05
void
setSpeed(
int
speed1){
06
//Скорость от 0 до 100, где 0 выключен, и 100, является максимальной скоростью
07
int
angle = map(speed1, 0, 100, 0, 180);
08
motor1.write(angle);
09
}
10
11
void
setup
() {
12
int
speed1;
13
motor1.attach(7);
14
setSpeed(0);
// Начальная скорость
15
delay(1000);
16
}
17
18
void
loop
()
19
{
20
//задал в ручную значение переменной speed1
21
int
speed1 = 40;
22
while
(speed1 <= 100){
23
setSpeed(speed1);
24
delay(1000);
25
}
26
}
Результат: Если двигатель подключен во время прошивки контролера, двигател начинает работать. Выключаю двигател включаю он не работает. После перезагрузки тоже не работает.
Что если так попробывать.
01
#include <Servo.h>
02
03
Servo motor1;
04
05
void
setup
() {
06
int
speed1;
07
motor1.attach(7);
08
// калибровка esc в течении 1 секунды
09
while
(millis() < 1000) {
10
if
(speed1 <= 0) {
11
motor1.write(0);
12
}
13
if
(speed1 > 0) {
14
motor1.write(speed1);
15
}
16
}
17
}
18
void
loop
()
19
{
20
//задал в ручную значение переменной speed1
21
int
speed1 = 40;
22
while
(millis() < 1000){
23
motor1.write(speed1);
24
}
25
}
У меня 1 микроконтроллер я его уже до дыр затер :). Думаю что у него ограниченое количество раз записей.
По этому пишу тут что бы вы как профи посмотрели и сказали где я ошибся до заливки скетча на контроллер.
Если честно, не понятно, что вы за скетч пишите и что вам нужно.
Чётко формулируем задачу, делим на более простые кусочки и в сети находим практически любой ответ.
Если что то не получается, то на форум.
Ну и не плохо было бы почитать вначале http://arduino.ru/forum/obshchii/prezhde-chem-sprosit-pro-servomashinku-servo-posmotri-tut
Цитата из первого поста.
Не получается объединить в рамках 1 скетча управление cерво приводом и ESC.
Хотел нажатием пробела (ASCII = 32) запустить двигатель и с каждым нажатием увеличивать обороты.
Далее весь сюжет проб и ошибок:)
Если вам интересен конечный результат то его пока нет. Есть процесс обучения, но данная схема где используется серво привод и безколекторный двигатель много например: Машины, катер, вертолет, коптер может еще что то.
Касаемо резделения задачи я так и делаю, также использую интернет, учусь и пишу тут свои комментарии.
Надеюсь я ответил на ваш вопрос, что я за скетч пишу и что мне надо.
Взрыв мозга :) я что то не по нимаю почему двигатель не запускается
Вот новый скет, я сделал так что бы он писал в терминал каждый шаг кода
01
#include <Servo.h>
02
03
Servo motor1;
04
unsigned
long
currentTime;
05
unsigned
long
loopTime;
06
07
void
arm(){
08
setSpeed(0);
09
delay(1000);
10
}
11
12
void
setSpeed(
int
speed1){
13
int
angle = map(speed1, 0, 100, 0, 180);
14
motor1.write(angle);
15
}
16
17
void
setup
() {
18
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
19
loopTime = currentTime;
20
Serial
.begin(9600);
21
motor1.attach(7);
// подсоединен к выводу 7
22
Serial
.println(
"Program begin..."
);
23
arm();
//
24
}
25
26
void
loop
() {
27
int
speed1 = 40;
28
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
29
Serial
.print(currentTime);
30
Serial
.println(
"TIME PROGRAM START"
);
31
if
(currentTime >= (loopTime + 1000)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
32
setSpeed(speed1);
// запускаем двигатель
33
loopTime = currentTime;
// в loopTime записываем новое значение
34
Serial
.print(speed1);
// показывает значение переменой
35
Serial
.println(
"SPEED"
);
36
Serial
.print(loopTime);
// новое время
37
Serial
.println(
"NEW TIME"
);
38
}
39
// Здесь могут быть другие команды
40
}
Из лога я делаю вывод, сигнал который задает скорость передается каждую секунду при этом выполнение остальной программы не останавливается.
А минимум-максимум-минимум последовательность вы делаете? https://dronesandrovs.wordpress.com/2012/11/24/how-to-control-a-brushless-motor-esc-with-arduino/
Дабавил вывод лога в рабочий скетч
Понял что 1 цикол от 0 до 100 и от 100 до 0 он проходит не включая двигатель, как бы калибруя ESC
Последующий круг запускает двигатель
А минимум-максимум-минимум последовательность вы делаете? https://dronesandrovs.wordpress.com/2012/11/24/how-to-control-a-brushless-motor-esc-with-arduino/
Да вы скорее всего правы проблема в колибровки, завтра отпишусь по результату.
Не в калибровке, а в безопасности, это последовательность старта моторчика, чтобы лопастями пальцы не отрубило.
Вы хоть раз видели как запускается бесколекторный двигатель? регулятор программируется, часто бывает такая схема -
1 опустить вниз рычаг (для вас - 0 градусов сервы)
2 подождать пока отпикается регулятор
3 поднять рычаг вверх( для вас - 180 градусов)
4 подождать сигнал
5 потом уже с 0 градусов управлять
1 и 3 шаги порядок может быть наоборот
В моем коде есть функция arm () говорит о положении рычага вниз.
Как мне поднять рычаг вверх что бы обозначить двигателю 180 градусов?
Что написать в функцию arm()?
Так я пробовал!
1
void
arm(){
2
setSpeed(0);
//внизу
3
delay(1000);
4
setSpeed(100);
//вверху
5
delay(1000);
6
}
Может задержку увеличить?
Обязательно ставить в положение 0 ?
Да, обязательно на ноль. Добавьте в конце
1
setSpeed(0);
//внизу
ДА, именно рычаг снизу вверх и обратно вниз. И только потом он начнёт управлятся . Я обычно такое сервотестером проверяю.
http://www.ebay.com/itm/Multi-Servo-Tester-3CH-ECS-Consistency-Speed-Con...
01
#include <Servo.h>
02
03
Servo motor1;
04
unsigned
long
currentTime;
05
unsigned
long
loopTime;
06
Servo servo;
07
int
val;
08
int
speed1;
09
10
void
arm(){
11
for
(speed1 = 0; speed1 <= 100; speed1 += 5) {
12
setSpeed(speed1);
13
delay(1000);
14
Serial
.print(speed1);
// показывает значение переменой
15
Serial
.println(
"MIN > MAXI"
);
16
}
17
for
(speed1 = 95; speed1 > 0; speed1 -= 5) {
18
setSpeed(speed1);
19
delay(1000);
20
Serial
.print(speed1);
// показывает значение переменой
21
Serial
.println(
"MAXI > MIN"
);
22
if
( speed1 == 5 )
break
;
//конец теста или колибровки
23
}
24
25
setSpeed(0);
26
delay(1000);
27
}
28
29
void
setSpeed(
int
speed1){
30
int
angle = map(speed1, 0, 100, 0, 180);
31
motor1.write(angle);
32
}
33
34
void
setup
() {
35
servo.attach(9);
36
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
37
loopTime = currentTime;
38
Serial
.begin(9600);
39
motor1.attach(7);
// подсоединен к выводу 7
40
Serial
.println(
"Program begin..."
);
41
arm();
42
}
43
44
void
loop
() {
45
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
46
Serial
.print(currentTime);
47
Serial
.println(
"TIME PROGRAMM START"
);
48
if
(currentTime >= (loopTime + 1000)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
49
if
(
Serial
.available())
50
{
51
val =
Serial
.read();
52
if
(val == 101)
// клавиша e на клавиатуре
53
{
54
speed1 = speed1 + 5;
55
setSpeed(speed1);
// повышение скорости
56
}
57
if
(val == 114)
// клавиша r на клавиатуре
58
{
59
speed1 = speed1 - 5;
60
setSpeed(speed1);
// понижение скорости
61
}
62
}
63
loopTime = currentTime;
// в loopTime записываем новое значение
64
Serial
.print(speed1);
// показывает значение переменой
65
Serial
.println(
"SPEED"
);
66
Serial
.print(loopTime);
// новое время
67
Serial
.println(
"NEW TIME"
);
68
}
69
if
(
Serial
.available())
70
{
71
val =
Serial
.read();
72
if
(val == 119)
// w = 119 in dec
73
{
74
servo.write(170);
// поворот серво привода на 170 градусов
75
}
76
else
if
(val == 115)
//s = 115 in dec
77
{
78
servo.write(10);
// поворот серва привода на 10 градусов
79
}
80
else
if
(val == 106)
//j = 106 in dec
81
{
82
servo.write(80);
// поворост серва привода на 80 градусов
83
}
84
}
85
// Здесь могут быть другие команды
86
}
Этот код работает, при нажатии клавиши e [EN] значение переменной speed1 меняется на +5 (причем двигатель начинает вращается только на speed1 == 15), ну и при нажатии r [EN] значение меняется на -5 он вращается медленнее, при этом как я и хотел серво приводы работают независимо от безколекторника и время реакции очень хорошее.
Но меня не совсем устраивает! Во первых должен быть способ избавиться от цикла в функции arm(). Пока у меня без него не работает. Во вторых клавиши e и r нужна держать бывает секунду для переключения скорости (если делать коптер это существенное время реакции на события, если машинку или катер то и так нормально)
delay(100) попробуйте. А вообще-то на пультах- джойстиках это туда-сюда делается за меньше полсекунды.... Махнул ручкой и всё....
А сразу с мин до мах, 100 паузы и снова минимум без цикла разве не работает?
Все дело в делай.
Сделай типа
void start(){
servo.write(0); //ну мотор, не смотрел как он по коду, бо с телефона
delay(500);
Servo.write(180);
delay(500);
servo.write(0);
}
Вызови ее еще в цикле void setup после того как описал моторы и сервы. - это даст старт моторам.
Я не очень понял смысла цикла в arm . Это просто тест? Зачем через секунду Аж добавлять обороты? Просто когда вызывается эта функция, программа тормозится на 100раз / 5 шаг = 20циклов* 1сек. - за 20 секунд ты ничего не можешь делать, бо выполняется цикл.
Сформулируй свою задачу, ты хочешь квадрокоптер сделать? Чем управлять будешь, если только прототип через сериал , то прикину, напишу програмку, в меру своего понимания, посмотришь
Не хотел расписывать думал, очевидно.
Во первых: При выполнении функция arm () двигатель не вращается! Цикл проходит 1 круг от минимального значения к максимальному и обратно в положение 0 после чего я нажимаю клавишу E увеличивая обороты на +5 и клавишу R уменьшая обороты на -5.
Сказать честно не могу понять что функция arm() делает с ECS, если бы понимял решил задачу без цикла. Есть предположение что выставляет минимальное и максимальное значение, может калибрует обучая ECS на значении в цикле arm и устанавливает таймаут, может просто тест безколекторника, кто то пишет что просто безопасность что бы пальцы не оторвало (у меня нет доку на мой ECS я его в китаи заказал). Но на реакцию клавиатуры он ни как не влияет, потому что он выполняется в:
1
void
setup
() {
2
3
}
и по завершению цикла на минимальном значение выходит из него и больше не запускается.
1
if
( speed1 == 5 )
break
;
Во вторых: на реакцию клавиатуры E и R влияет:
01
if
(currentTime >= (loopTime + 1000)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
02
if
(
Serial
.available())
03
{
04
val =
Serial
.read();
05
if
(val == 101)
// клавиша e на клавиатуре
06
{
07
speed1 = speed1 + 5;
08
setSpeed(speed1);
// повышение скорости
09
}
10
if
(val == 114)
// клавиша r на клавиатуре
11
{
12
speed1 = speed1 - 5;
13
setSpeed(speed1);
// понижение скорости
14
}
15
}
16
loopTime = currentTime;
// в loopTime записываем новое значение
Я выше уже приводил лог из терминала где видно что SPEED1 переменная считывается и передается функции каждую секунду, по этой причине нужно максимум держать 1 секунду клавишу чтобы она в нужный момент изменила значение переменной. Такой способ избавляет нас от использование функции delay(); и не влият на управление серво приводов.
Что касается реализации: Для того что бы что то реализовать коптер или другое, нужно, я считаю понять как это работает. Serial порт дает возможность тестировать код и видит что происходить при выполнении тех или иных действий функци.
За написать под задачу спасибо, но все же это не то чего я хотел бы.
А сразу с мин до мах, 100 паузы и снова минимум без цикла разве не работает?
Нет не получилось.
Мои изыскания привели к тому что цикл все же калибровка ESC и можно сделать в отдельном скетче.
Слизал скетч от суда http://robots.dacloughb.com/project-2/esc-calibration-programming/
01
#include <Servo.h>
02
03
#define MAX_SIGNAL 2000
04
#define MIN_SIGNAL 700
05
#define MOTOR_PIN 7
06
07
Servo motor;
08
09
void
setup
() {
10
Serial
.begin(9600);
11
Serial
.println(
"Program begin..."
);
12
Serial
.println(
"This program will calibrate the ESC."
);
13
14
motor.attach(MOTOR_PIN);
15
16
Serial
.println(
"Now writing maximum output."
);
17
Serial
.println(
"Turn on power source, then wait 2 seconds and press any key."
);
18
motor.writeMicroseconds(MAX_SIGNAL);
19
20
// Wait for input
21
while
(!
Serial
.available());
22
Serial
.read();
23
24
// Send min output
25
Serial
.println(
"Sending minimum output"
);
26
motor.writeMicroseconds(MIN_SIGNAL);
27
28
}
29
30
void
loop
() {
31
}
После чего залил свой код
01
#include <Servo.h>
02
03
Servo motor1;
04
unsigned
long
currentTime;
05
unsigned
long
loopTime;
06
Servo servo;
07
int
val;
08
int
speed1;
09
10
void
setSpeed(
int
speed1){
11
int
angle = map(speed1, 0, 100, 0, 180);
12
motor1.write(angle);
13
}
14
15
void
setup
() {
16
servo.attach(9);
17
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
18
loopTime = currentTime;
19
Serial
.begin(9600);
20
motor1.attach(7);
// подсоединен к выводу 7
21
Serial
.println(
"Program begin..."
);
22
setSpeed (10)
// Нужен что бы избежать травмы, если отключится от терминала двигатель начинает вращаться.
23
}
24
25
void
loop
() {
26
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
27
Serial
.print(currentTime);
28
Serial
.println(
"TIME PROGRAMM START"
);
29
if
(currentTime >= (loopTime + 100)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
30
if
(
Serial
.available())
31
{
32
val =
Serial
.read();
33
if
(val == 101)
// клавиша e на клавиатуре
34
{
35
speed1 = speed1 + 5;
36
setSpeed(speed1);
// повышение скорости
37
}
38
if
(val == 114)
// клавиша r на клавиатуре
39
{
40
speed1 = speed1 - 5;
41
setSpeed(speed1);
// понижение скорости
42
}
43
}
44
loopTime = currentTime;
// в loopTime записываем новое значение
45
Serial
.print(speed1);
// показывает значение переменой
46
Serial
.println(
"SPEED"
);
47
Serial
.print(loopTime);
// новое время
48
Serial
.println(
"NEW TIME"
);
49
}
50
if
(
Serial
.available())
51
{
52
val =
Serial
.read();
53
if
(val == 119)
// w = 119 in dec
54
{
55
servo.write(170);
// поворот серво привода на 170 градусов
56
}
57
else
if
(val == 115)
//s = 115 in dec
58
{
59
servo.write(10);
// поворот серва привода на 10 градусов
60
}
61
else
if
(val == 106)
//j = 106 in dec
62
{
63
servo.write(80);
// поворост серва привода на 80 градусов
64
}
65
}
66
// Здесь могут быть другие команды
67
}
Выводы:
1. Я избавился от цикла.
2. Понял как калибровать ESC.
3. Уменшил время отклика от клавиатуры (loopTime + 100)
Задача решина может кому то мои коментарии помогут.
Немного модернизировал скетч (нет приделу совершенства).
Заменил кусок
01
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
02
Serial
.print(currentTime);
03
Serial
.println(
"TIME PROGRAMM START"
);
04
if
(
Serial
.available())
05
{
06
val =
Serial
.read();
07
if
(val == 101)
// e = 101 in dec
08
{
09
speed1 = speed1 + 5;
10
if
(currentTime >= (loopTime + 100)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
11
setSpeed(speed1);
// повышение скорости
12
loopTime = currentTime;
13
}
14
}
15
if
(val == 114)
// r = 114 in dec
16
{
17
speed1 = speed1 - 5;
18
if
(currentTime >= (loopTime + 100)){
19
setSpeed(speed1);
// понижение скорости
20
loopTime = currentTime;
21
}
22
}
23
24
loopTime = currentTime;
// в loopTime записываем новое значение
25
Serial
.print(speed1);
// показывает значение переменой
26
Serial
.println(
"SPEED"
);
27
Serial
.print(loopTime);
// новое время
28
Serial
.println(
"NEW TIME"
);
29
}
Стало работать почти идиально :)
Идём к совершенству дальше : 101 на 'e' и 114 на 'r' поменяйте- было бы понятнее что это такое...
Это кодировка ASCII, в данной кодировки работает контроллер.
Или эту кодировку преобразует среда Arduino.
Пока опыта не так много, не все понимаю.
http://arduino.ru/Reference/Char
Спасибо понял.