расслабление сервы
- Войдите на сайт для отправки комментариев
Всем привет, создал тему т.к ненашел нигде чтобы ктото такое делал.
смысл вот в чем.
сейчас у меня при нажатии на кнопку на серву приходит сигнал сдвинуться на 0,012, если зажать кнопку то эти дискретные значения сумируються и в итоге серва может уйти до предела.
но серва стоит в манипуляторе:
и когда клешня сжимает предмет, серва остаеться в напряжении, делая попытки двигаться дальше. т.к. допустим предмет попался на 45градусах, а команда с пульта пришла закрываться до 100град. серва начинает жрать ток, греться, одна так уже сгорела!
чтобы обезопасить сервы от перегрузки, но в тоже время сохранить функционал, я придумал что немешало бы их "расслоблять"
а именно после каждого отпускания кнопки делать короткое, незаметное глазу движение в обратную сторону, тем самым сбрасывая "желание" сервы двигаться вперед.
при таком раскладе серва продолжит удерживать предмет в клешне но небудет жрать ток и греться.
это я проверил эксперементально, зажимаю кнопку на пульте, клешня сжимает предмет, и продолжает давить, идет просадка по питанию, быстро нажимаю на кнопку разжимания, визуально серва даже не двинулась, но при этом перестала давить и ток в норме, просадка ушла...
помогите это запрограмить. мои попытки не увенчались успехом.
мот мой код:
// Скетч для управления через блютус, 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 = 116; // Максимальные угл поворота башни налево const float H_R_ANGLE = 45; // Максимальные угл поворота башни направо const float H_DEF_ANGLE = 38; // Дефолтный угол (центровка) 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)) { moveServoVUp = true; moveServoVDown = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B)) { moveServoVDown = true; moveServoVUp = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A)) { moveServoHLeft = true; moveServoHRight = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y)) { moveServoHRight = true; 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); } }
вот в этом месте
//--------— чтобы сервы не продолжали движения при отжатых кнопках —------------- if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X)) { moveServoVUp = true; moveServoVDown = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B)) { moveServoVDown = true; moveServoVUp = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A)) { moveServoHLeft = true; moveServoHRight = false; } if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y)) { moveServoHRight = true; moveServoHLeft = false; }
недолжно было быть moveServoVUp = true; и других... это я добавил думая что при отпускании кнопки вначале серва сделает шаг назад а потом стоп, но по факту она стала постоянно открываться.
может какието знаки припинания надо поставить ? :)
может просто датчик тока поставить. ток вырос значит хватит
или измерять питание сервы. питание черзе резистор низкоомный. просадка появилась значит стоп. только питание сервы и ардуины должно быть раздельное. отдельный стабилизатор просто на серву
может датчик тока и просто поставить, но его у меня нет, делать раздельное питание и прочие танцы с бубном тоже очень геморно.
на то ведт он и ардуино что все можно запрограмировать, тем более что в моем случае проблема не в питании и не в серве, а именно в мозгах!
ведь человек взяв предмет в руки не продолжает его лихорадочно со всей силы сжимать, он расслабляет руку но при этом контролирует чтобы она не разжалась, чтоб пальцы оставались в прежнем положении.
этого же эффекта и я хочу добиться.
клешня сожмет предмет и расслабит хватку, при этом серва будет удерживать текущее положение и не даст разжать захват.
так что все что мне нужно это делать очень короткий шаг в обратную сторону, для расслабления....
на руке датчиков дофига. и давления и температуры и так далее. и мозг знает насколько сжато. а твоя серва и ардуина нет
если для тебя линейный стабилизатор очень геморно поставить за 10 рублей с 3 выводами то дело твое
Может для остановки использовать таймер на максимальное возможное время сжатия/разжатия?
а как ардуина узнает маленький или большой предмет сжимается?
да и один и тот же предмет, тот же паравозик на фото, с разных сторон имеет разные габариты
хоть плавно хоть резко ардуина не узнает насколько сжато если ей напрямую не говорить. или с пульта управлять или ставить датчик
на руке датчиков дофига. и давления и температуры и так далее. и мозг знает насколько сжато. а твоя серва и ардуина нет
если для тебя линейный стабилизатор очень геморно поставить за 10 рублей с 3 выводами то дело твое
в серве тоже есть "датчик" резистор, и мозги, которые отслеживают изменение положения и недают его менять.
ардуине при этом ничего думать ненужно и знать тоже. ардуина послала команду, а дальше дело за сервой.
так вот, беда ся в коде ардуино. сейчас при нажатии на кнопки ардуина посылает серве команду например повернуться на 90град.
серва на 50град встретила предмет и сжала его. но поскольку цель, не достигнута, мы стоим на 50 а надо на 90, серва продолжает напрягать мотор, он грееться, просаживает ток всей системы и сам тоже горит, одну серву я уже убил....
если же после отпускания кнопки посылать короткую команду крутить в обратную сторону на 0,001 то визуально серва даже не сдвиниться, зто последнюю полученую команду она выполнит, перебив тем самым команду продолжать движение на 90 град, и спокойно, без напряга будет удерживать положение на 50.
так понятно?
вопрос, как это реализовать, чутье подсказывает что это достаточно просто, но поскольку я не программист, для меня это неподсилу (
Может для остановки использовать таймер на максимальное возможное время сжатия/разжатия?
а смысл? если можно послать последнюю команду, которая даст расслабление.
простой вопрос: сервой управляется в ручном режиме копнками пульта или просто команда сжать или разжать, а она уже должна сама подстроится?
а как ардуина узнает маленький или большой предмет сжимается?
да и один и тот же предмет, тот же паравозик на фото, с разных сторон имеет разные габариты
хоть плавно хоть резко ардуина не узнает насколько сжато если ей напрямую не говорить. или с пульта управлять или ставить датчик
ардуине ничего знать ненужно.
человек зажимает кнопку, пока кнопка зажата, ардуина начинает суммировать дискретные значения поворота по 0,012
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
простой вопрос: сервой управляется в ручном режиме копнками пульта или просто команда сжать или разжать, а она уже должна сама подстроится?
человек жмет кнопки со смартфона, через блютус. на ардуину.
а смысл? если можно послать последнюю команду, которая даст расслабление.
Как раз вместо датчика сжатия. Посжимали 500мс например и хватит=)
И сжать успеет и сгореть не успеет=)
При чем таймер через http://arduino.cc/en/reference/millis
Как раз вместо датчика сжатия. Посжимали 500мс например и хватит=)
И сжать успеет и сгореть не успеет=)
и так тоже можно, но в любом случае, позжимать 500мс нужно после отпускания кнопки :) и ппотом расслабиться.
так что по сути тоже самое что я предлагаю, разница в задержке.
вопрос как это сделать?
типа если нажали, засекаем время и крутим луп, проверяем время затраченное, дошло до 500мс, прерываем сжатие
http://cxem.net/arduino/arduino5.php
Вообще, в системах, где критичен интервал между командами, нужно использовать конструкцию, как в примере по ссылке. delay() он хоть и делает задержку, но не все так просто. В ардуино одна проблема-приостанавливается работа всей программы. В программировании для ПК например возникает проблема неточной задержки, связанная с переключением между процессами, тогда после delay(1000) может поработать другое приложение, после чего через 200мс например только сработает остальной код.
а зачем тогда таймера и тп. аккуратнее кпоками нажимай и все. задержку между шагами чтобы быстро не двигалась и все)))
защита от дурака всегда должна быть=)
а зачем тогда таймера и тп. аккуратнее кпоками нажимай и все. задержку между шагами чтобы быстро не двигалась и все)))
у меня с этим проблем нет, я это понимаю и могу делать все аккуратно, но эта штука будет в руках у детей, и там то ей сразу писец прийдет )
а если дети ставь датчик))
спасешь серву
ох ну и программисты пошли))
нет чтоб пару сточек кода подсказать, так нет же разведут демагогии на 3 страницы :)
или все присутствующие как и я не программисты? :)
если ты знаешь способ как программно узнать размер объекта то не вопрос.
например ребенок нажал и не отпустил кнопку. программа если чуть назад вернет серву неплохо. только если слишком рано то объект не захватится, если поздно то уже серва может сдохнуть, и чуть назад вернуть не поможет
серва это испольнительный инструмент, ей сказали она делает, даже если сгорит от этого, она будет пытаться сделать то что ты сказал
я лично не представляю как программа может это компенсировать если программе неизвестен размер объекта или то что серва уже перегружена, она основе чего она должна решить что все стоп и чуть назад
как по мне ты или наивный или ленивый. без обид
хотя возможно ты хотел сделать следующее: повернуть серву пок ане упрется, а потом вернуть назад, то есть объект сам остановит серву, а в перегрузе она типа будет недолго. это имелось в виду?
но ты же не знаешь насколько вернутся назад. это не шаговый двигатель который крутился уперся и вернул на шаг. серве ты должен сказать не на сколько вернутся назад, она такого не понимает, а какой угол занять))
Жека, да вы правы если кнопку не отпускать долго то серва сгорит, но дети не будут так долго ее держать, кнопку будут нажимать только до тех пор пока серва не захватит обьект, а дальше кнопку отпустят, и вот тут нужно сделать микро возврат сервы на 1 шаг назад.
если вы опытный программист то для вас это рас плюнуть, вы на обсуждении потратили в 5 раз больше времени чем программисту нужно на добавление в мой скетч нескольких строчек, чтобы после каждого отпускания кнопки, последним шла команду сделать шаг в обратную сторону.
и всего то делов :)
или вы как и я новичек и не знаете как это сделать?
я так тут поболтать прихожу. программировать не мое))
кстати на детей я бы не надеялся. они же могут просто не отпустить потому что просто интересно что крепче/сильнее. я бы точно проверил что будет)
хотя возможно ты хотел сделать следующее: повернуть серву пок ане упрется, а потом вернуть назад, то есть объект сам остановит серву, а в перегрузе она типа будет недолго. это имелось в виду?
но ты же не знаешь насколько вернутся назад. это не шаговый двигатель который крутился уперся и вернул на шаг. серве ты должен сказать не на сколько вернутся назад, она такого не понимает, а какой угол занять))
просто 1 шаг назад, и все, ей не нужно знать на сколько куда возвращаться. просто последним что прийдет на серву это задание которое она может выполнить, тогда она его выполняет и не жрет ток, не горит.
а захват предмета, это сейчас для нее задание которое она выполнить не может.
она же незнает что делает, это для нас это манипулятор и захват обьекта, а серве сказали двигайся на 100градусов она и поехала, а попути попался предмет, и ехать она не может, стои и грееться, человек уже кнопку отпустил и забыл, а серва все еще пытаеться стать на 100градусов. но неможет, и горит....
а если она при отпускании кнопки получает команду шаг назад и стоп, то она выполняет задание и замерает.
так понятно?
я так тут поболтать прихожу. программировать не мое))
я уже по аватарке понял :)
а если чуть передержать кнопку она вернется назад, но все равно будет перегружаться
короче одна надежда что ребенок вовремя отпустит. если нет ставь новую серву
бедные сервы. они еще не знают что их на смерть отправили потому что стабилизатор было лень поставить
пробуйте сделать что-то типа этого:
Если кнопка нажата впервые, то засекаем момент времени и в цикле проверяем, держим ее же и пора ли отпускать..так же и для отпускания
fagci спасибо что откликнулись, но чтото не получилось вставить в код, ругаеться на ошибки, одни вроде устраняю, другие вылезают.
if(btca2aLite.Button(KEYCODE_BUTTON_A)){
ругаеться на первую скобку
всеравно на туже скобку ругаеться
ага добавил еще одну скобку, откомпилило, сейчас зпбью другие кнопки и залью в машину)
У Вас машинка какой препарат возит? ЛСД?=)
для детей самое то, пушку еще приделать, чтобы инъекции делать тем, кто боится и кого не догнать=)
а ты название темы прочитай)))
вставил такой код
неработаю, на кнопки не реагируют
У Вас машинка какой препарат возит? ЛСД?=)
для детей самое то, пушку еще приделать, чтобы инъекции делать тем, кто боится и кого не догнать=)
нам спиртное никчему я отвечу почему :)
насчет иньекций мысль хорошая, водой она уже брызгала, но пока убрал, чуть позже вновь добавлю.
https://www.youtube.com/watch?v=zSKRCsBswvI
сначала серву расслабить. потом колеса, шасси, захват уже накакой будет. а машинки с глазами будут водить хороводы
не ну пАцанЫ, реально дайте серву расслабить :)
Вот так скобки должны быть=)
Ту которую ставили - убрать надо=)
стало ругаться на строчку
Надо весь код тогда=)
выкладываю целеком:
сервы раньше водометом управляли, пока водомет убрал, поставил клешню, потом буду водомет ставить, в задней части :)
Как-то так:
Вообще этот код бы почистить, сдается мне, что можно сделать проще=)..но к концу рабочего дня не думается=)
нереагирует на нажатие кнопок, может
if
(buttonId!=KEYCODE_BUTTON_A){ надо не название кнопки а цифру 0, 1, 2.....100 ))?
обще этот код бы почистить, сдается мне, что можно сделать проще=)..но к концу рабочего дня не думается=)
да главное чтоб работал :)
он весит всего 6,7.... а залить можно 30 :)
видео забавное
А тут кстати вес не пропорционально зависит от объема кода, оптимизация, все дела=)
Щас еще посмотрю, что не так=)..попорчу код маленько=)
А тут кстати вес не пропорционально зависит от объема кода, оптимизация, все дела=)
Щас еще посмотрю, что не так=)..попорчу код маленько=)
оптимизация это хорошо, но не в моих руках:)
спасибо за помощь, если вам вдруг нужна будет помощь по 3д обращайтесь:)
Получается, что у Вас сейчас сервы останавливаются когда они уже стоят=)
Вот теперь будут шевелиться, пока время не вышло=)
работает, серва движиться, но после зажима предмета и отпускания кнопки, как и раньше продолжает попытку сжиматься дальше, поидее время ожидания пол секунды? ждил с пол минуты, ничего.. ((