Управление серво приводом и регулятором скорости (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 скетч ?
Так покажите ваш код для безколлекторника
Servo motor1; void arm(){ setSpeed(0); delay(1000); } void setSpeed(int speed){ int angle = map(speed, 0, 100, 0, 180); motor1.write(angle); } void setup() { motor1.attach(7); arm(); } void loop() { int speed; for(speed = 0; speed <= 100; speed += 5) { setSpeed(speed); delay(1000); } for(speed = 95; speed > 0; speed -= 5) { setSpeed(speed); delay(1000); } setSpeed(0); delay(5000); }Это тестовый скетч для проверки работы двигателя и регулировки скорости вращения.
Мои попытки написать скетч для одновременной работы с условием значения переменной не привели к успеху, я даже понимаю почему это происходит, при последующих циклах значение переменной исчезает и условие не выполняется, также для двигателя нужен delay (задержка), в цикле с задержкой серва приводы начинают реагировать на 1 сек позже, по этой причине и нужно разделять циклы.
Чтобы значение переменной не "исчезало", ее надо определить как глобальную. Delay() исключить использовав millis() с проверкой периода задержки. Соответственно For Вам здесь не поможет (он даст задержку в любом случае, пока колностью не выполнится), модифицируем на другие методы -
http://arduino.ru/Reference/If
http://arduino.ru/Reference/While
Спасибо по результату отпишусь.
Можете направить как определить глобальную переменую?
#include <Servo.h> Servo motor1; void setup(){ motor1.attach(7); arm(); } void loop(){ for(byte i = 0; i <= 100; i += 5) { setSped(i); delay(1000); } for(byte i = 95; i >= 0; i -= 5) { setSped(i); delay(1000); } setSped(0); delay(5000); } void arm(){ setSped(0); delay(1000); } void setSped(byte sped){ motor1.write(map(sped, 0, 100, 0, 180)); }если компилятор выделяет цветом названия которые ты даешь, значит лучше их поменять
значит эти названия зарезервированы, и возможны глюки
Спасибо по результату отпишусь.
Можете направить как определить глобальную переменую?
http://arduino.ru/Tutorial/Variables
Решил задачу разбить по шагам, для начала разобраться как использовать цикл while
Написал простой скетч
#include <Servo.h> Servo motor1; void setSpeed(int speed1){ //Скорость от 0 до 100, где 0 выключен, и 100, является максимальной скоростью int angle = map(speed1, 0, 100, 0, 180); motor1.write(angle); } void setup() { int speed1; motor1.attach(7); setSpeed(0); // Начальная скорость delay(1000); } void loop() { //задал в ручную значение переменной speed1 int speed1 = 40; while (speed1 <= 100){ setSpeed(speed1); delay(1000); } }Результат: Если двигатель подключен во время прошивки контролера, двигател начинает работать. Выключаю двигател включаю он не работает. После перезагрузки тоже не работает.
Что если так попробывать.
#include <Servo.h> Servo motor1; void setup() { int speed1; motor1.attach(7); // калибровка esc в течении 1 секунды while (millis() < 1000) { if (speed1 <= 0) { motor1.write(0); } if (speed1 > 0) { motor1.write(speed1); } } } void loop() { //задал в ручную значение переменной speed1 int speed1 = 40; while (millis() < 1000){ motor1.write(speed1); } }У меня 1 микроконтроллер я его уже до дыр затер :). Думаю что у него ограниченое количество раз записей.
По этому пишу тут что бы вы как профи посмотрели и сказали где я ошибся до заливки скетча на контроллер.
Если честно, не понятно, что вы за скетч пишите и что вам нужно.
Чётко формулируем задачу, делим на более простые кусочки и в сети находим практически любой ответ.
Если что то не получается, то на форум.
Ну и не плохо было бы почитать вначале http://arduino.ru/forum/obshchii/prezhde-chem-sprosit-pro-servomashinku-servo-posmotri-tut
Цитата из первого поста.
Не получается объединить в рамках 1 скетча управление cерво приводом и ESC.
Хотел нажатием пробела (ASCII = 32) запустить двигатель и с каждым нажатием увеличивать обороты.
Далее весь сюжет проб и ошибок:)
Если вам интересен конечный результат то его пока нет. Есть процесс обучения, но данная схема где используется серво привод и безколекторный двигатель много например: Машины, катер, вертолет, коптер может еще что то.
Касаемо резделения задачи я так и делаю, также использую интернет, учусь и пишу тут свои комментарии.
Надеюсь я ответил на ваш вопрос, что я за скетч пишу и что мне надо.
Взрыв мозга :) я что то не по нимаю почему двигатель не запускается
Вот новый скет, я сделал так что бы он писал в терминал каждый шаг кода
#include <Servo.h> Servo motor1; unsigned long currentTime; unsigned long loopTime; void arm(){ setSpeed(0); delay(1000); } void setSpeed(int speed1){ int angle = map(speed1, 0, 100, 0, 180); motor1.write(angle); } void setup() { currentTime = millis(); // считываем время, прошедшее с момента запуска программы loopTime = currentTime; Serial.begin(9600); motor1.attach(7); // подсоединен к выводу 7 Serial.println("Program begin..."); arm(); // } void loop() { int speed1 = 40; currentTime = millis(); // считываем время, прошедшее с момента запуска программы Serial.print(currentTime); Serial.println("TIME PROGRAM START"); if(currentTime >= (loopTime + 1000)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда setSpeed(speed1); // запускаем двигатель loopTime = currentTime; // в loopTime записываем новое значение Serial.print(speed1); // показывает значение переменой Serial.println("SPEED"); Serial.print(loopTime); // новое время Serial.println("NEW TIME"); } // Здесь могут быть другие команды }Из лога я делаю вывод, сигнал который задает скорость передается каждую секунду при этом выполнение остальной программы не останавливается.
А минимум-максимум-минимум последовательность вы делаете? 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()?
Так я пробовал!
void arm(){ setSpeed(0); //внизу delay(1000); setSpeed(100); //вверху delay(1000); }Может задержку увеличить?
Обязательно ставить в положение 0 ?
Да, обязательно на ноль. Добавьте в конце
ДА, именно рычаг снизу вверх и обратно вниз. И только потом он начнёт управлятся . Я обычно такое сервотестером проверяю.
http://www.ebay.com/itm/Multi-Servo-Tester-3CH-ECS-Consistency-Speed-Con...
#include <Servo.h> Servo motor1; unsigned long currentTime; unsigned long loopTime; Servo servo; int val; int speed1; void arm(){ for(speed1 = 0; speed1 <= 100; speed1 += 5) { setSpeed(speed1); delay(1000); Serial.print(speed1); // показывает значение переменой Serial.println("MIN > MAXI"); } for(speed1 = 95; speed1 > 0; speed1 -= 5) { setSpeed(speed1); delay(1000); Serial.print(speed1); // показывает значение переменой Serial.println("MAXI > MIN"); if ( speed1 == 5 ) break; //конец теста или колибровки } setSpeed(0); delay(1000); } void setSpeed(int speed1){ int angle = map(speed1, 0, 100, 0, 180); motor1.write(angle); } void setup() { servo.attach(9); currentTime = millis(); // считываем время, прошедшее с момента запуска программы loopTime = currentTime; Serial.begin(9600); motor1.attach(7); // подсоединен к выводу 7 Serial.println("Program begin..."); arm(); } void loop() { currentTime = millis(); // считываем время, прошедшее с момента запуска программы Serial.print(currentTime); Serial.println("TIME PROGRAMM START"); if(currentTime >= (loopTime + 1000)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда if (Serial.available()) { val = Serial.read(); if (val == 101) // клавиша e на клавиатуре { speed1 = speed1 + 5; setSpeed(speed1); // повышение скорости } if (val == 114) // клавиша r на клавиатуре { speed1 = speed1 - 5; setSpeed(speed1); // понижение скорости } } loopTime = currentTime; // в loopTime записываем новое значение Serial.print(speed1); // показывает значение переменой Serial.println("SPEED"); Serial.print(loopTime); // новое время Serial.println("NEW TIME"); } if (Serial.available()) { val = Serial.read(); if (val == 119) // w = 119 in dec { servo.write(170); // поворот серво привода на 170 градусов } else if (val == 115) //s = 115 in dec { servo.write(10); // поворот серва привода на 10 градусов } else if (val == 106) //j = 106 in dec { servo.write(80); // поворост серва привода на 80 градусов } } // Здесь могут быть другие команды }Этот код работает, при нажатии клавиши 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 я его в китаи заказал). Но на реакцию клавиатуры он ни как не влияет, потому что он выполняется в:
void setup() { }и по завершению цикла на минимальном значение выходит из него и больше не запускается.
Во вторых: на реакцию клавиатуры E и R влияет:
if(currentTime >= (loopTime + 1000)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда if (Serial.available()) { val = Serial.read(); if (val == 101) // клавиша e на клавиатуре { speed1 = speed1 + 5; setSpeed(speed1); // повышение скорости } if (val == 114) // клавиша r на клавиатуре { speed1 = speed1 - 5; setSpeed(speed1); // понижение скорости } } loopTime = currentTime; // в loopTime записываем новое значениеЯ выше уже приводил лог из терминала где видно что SPEED1 переменная считывается и передается функции каждую секунду, по этой причине нужно максимум держать 1 секунду клавишу чтобы она в нужный момент изменила значение переменной. Такой способ избавляет нас от использование функции delay(); и не влият на управление серво приводов.
Что касается реализации: Для того что бы что то реализовать коптер или другое, нужно, я считаю понять как это работает. Serial порт дает возможность тестировать код и видит что происходить при выполнении тех или иных действий функци.
За написать под задачу спасибо, но все же это не то чего я хотел бы.
А сразу с мин до мах, 100 паузы и снова минимум без цикла разве не работает?
Нет не получилось.
Мои изыскания привели к тому что цикл все же калибровка ESC и можно сделать в отдельном скетче.
Слизал скетч от суда http://robots.dacloughb.com/project-2/esc-calibration-programming/
#include <Servo.h> #define MAX_SIGNAL 2000 #define MIN_SIGNAL 700 #define MOTOR_PIN 7 Servo motor; void setup() { Serial.begin(9600); Serial.println("Program begin..."); Serial.println("This program will calibrate the ESC."); motor.attach(MOTOR_PIN); Serial.println("Now writing maximum output."); Serial.println("Turn on power source, then wait 2 seconds and press any key."); motor.writeMicroseconds(MAX_SIGNAL); // Wait for input while (!Serial.available()); Serial.read(); // Send min output Serial.println("Sending minimum output"); motor.writeMicroseconds(MIN_SIGNAL); } void loop() { }После чего залил свой код
#include <Servo.h> Servo motor1; unsigned long currentTime; unsigned long loopTime; Servo servo; int val; int speed1; void setSpeed(int speed1){ int angle = map(speed1, 0, 100, 0, 180); motor1.write(angle); } void setup() { servo.attach(9); currentTime = millis(); // считываем время, прошедшее с момента запуска программы loopTime = currentTime; Serial.begin(9600); motor1.attach(7); // подсоединен к выводу 7 Serial.println("Program begin..."); setSpeed (10) // Нужен что бы избежать травмы, если отключится от терминала двигатель начинает вращаться. } void loop() { currentTime = millis(); // считываем время, прошедшее с момента запуска программы Serial.print(currentTime); Serial.println("TIME PROGRAMM START"); if(currentTime >= (loopTime + 100)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда if (Serial.available()) { val = Serial.read(); if (val == 101) // клавиша e на клавиатуре { speed1 = speed1 + 5; setSpeed(speed1); // повышение скорости } if (val == 114) // клавиша r на клавиатуре { speed1 = speed1 - 5; setSpeed(speed1); // понижение скорости } } loopTime = currentTime; // в loopTime записываем новое значение Serial.print(speed1); // показывает значение переменой Serial.println("SPEED"); Serial.print(loopTime); // новое время Serial.println("NEW TIME"); } if (Serial.available()) { val = Serial.read(); if (val == 119) // w = 119 in dec { servo.write(170); // поворот серво привода на 170 градусов } else if (val == 115) //s = 115 in dec { servo.write(10); // поворот серва привода на 10 градусов } else if (val == 106) //j = 106 in dec { servo.write(80); // поворост серва привода на 80 градусов } } // Здесь могут быть другие команды }Выводы:
1. Я избавился от цикла.
2. Понял как калибровать ESC.
3. Уменшил время отклика от клавиатуры (loopTime + 100)
Задача решина может кому то мои коментарии помогут.
Немного модернизировал скетч (нет приделу совершенства).
Заменил кусок
currentTime = millis(); // считываем время, прошедшее с момента запуска программы Serial.print(currentTime); Serial.println("TIME PROGRAMM START"); if (Serial.available()) { val = Serial.read(); if (val == 101) // e = 101 in dec { speed1 = speed1 + 5; if(currentTime >= (loopTime + 100)){ // сравниваем текущий таймер с переменной loopTime + 1 секунда setSpeed(speed1); // повышение скорости loopTime = currentTime; } } if (val == 114) // r = 114 in dec { speed1 = speed1 - 5; if(currentTime >= (loopTime + 100)){ setSpeed(speed1); // понижение скорости loopTime = currentTime; } } loopTime = currentTime; // в loopTime записываем новое значение Serial.print(speed1); // показывает значение переменой Serial.println("SPEED"); Serial.print(loopTime); // новое время Serial.println("NEW TIME"); }Стало работать почти идиально :)
Идём к совершенству дальше : 101 на 'e' и 114 на 'r' поменяйте- было бы понятнее что это такое...
Это кодировка ASCII, в данной кодировки работает контроллер.
Или эту кодировку преобразует среда Arduino.
Пока опыта не так много, не все понимаю.
http://arduino.ru/Reference/Char
Спасибо понял.