Роботизированая КПП

invisible13
Offline
Зарегистрирован: 21.09.2012

 Здравствуйте!

Давно ищу инфу, по переделке механики в робота своими усилиями.
Из найденного - автоматическая кпп для велосипеда (правда сейчас не могу найти ролик), там было реализовано последовательное переключение педальных звездочек и задних, в зависимости от оборотов(на педалях).

Так же есть задумка соорудить что-то на ардуино и сервоприводах - сейчас в радиомоделях есть тяговитые по 40+ кг усилия.
Подключить это все к механической кпп (сцепление, кулиса) + возможно к газу
В качестве донора - наш любимый отечественный производитель.
Видимых расходов - порядка 10 тысяч рублей

Цель - создание, проектирование универсального блока для газ,камаз и прочих, да для всего что движется

Попробуем составить тз - что надо для выполнения сего устройства?
два сервопривода для управления кулисой

один сервопривод для управления сцеплением

один сервопривод для управления газом - сделаем его "цифровым"
один сервопривод для управления ручным тормозом - сделать на кнопочку как в ситроен с5
один потенциометр на педаль газа - для определения положения
один потенциометр на педаль тормоза - для определения положения
один блок ардуино для выполнения всех движений.

Так же можно будет добавить круиз-контроль из уже получившегося модуля

Жаль никаких языков программирования не знаю :-)

leshak
Offline
Зарегистрирован: 29.09.2011

invisible13 пишет:

Жаль никаких языков программирования не знаю :-)

Ну вот с этого и начните. Купите ЛЮБУЮ ардуину, парочку любых серв, светодиодов, кнопки. Прочитайте раздел "программирование" (какя-нибудь кинга по С/C++ - тоже пригодится), попробуйте примеры. Научитесь читать кнопки, энкодеры, потенциометры. Крутить сервы синхронно/одновременно, с разными скоростями и т.п.

А уж потом за "супер-универсальные" модули можно будет братся.

До этого - любые ТЗ составлять бессмысленно. Разве что что-бы прикинуть "во что это выльется". И потом смело умножить на что-то от 3-х до 10-ти.  

invisible13
Offline
Зарегистрирован: 21.09.2012

Спасибо за советы :-)

Навыков программирования нет, однако есть представление о структуре кодинга. Есть опыт "рисования" HTML, но это все не то.

С механикой не должно возникнуть вопросов, а вот с чтением инфы с потенциометров пока не могу никак даже вникнуть )

Вобщем изучаю.

zis101
Offline
Зарегистрирован: 15.06.2013

Делаю роботизированную КПП на основе привода от Яриса.

Привод представляет из себя исполнительный механизм из двух коллекторных двигателей и датчиков их положений.

Приобрел контроллер для коллекторных двигателей

monster moto shield

http://pacpac.ru/product/dev-10182/

И решил его использовать для управления приводом.

Для каждого из двигателей нужно поймать три положения:

по датчикам это значения 450, 600 и 800

450 и 800 конечные положения с жесткими упорами их поймать проблем нет, а вот среднее положение 600 я или пролетаю или не дохожу.

Двигатели можут вращаться со скоростью 0...1023, линейный ход всего 16мм.

Замутил такой алгоритм: 0,5 пути который нужно пройти приводу он идет со скоростью 1023, дальше идет тормажение и останов

Посоветуйте как быть..., вот моя функция из скетча:

int ChangeGear_P_135=450;//380;
int ChangeGear_P_N=600;
int ChangeGear_P_24R=800;//850;

float k1m1min=0.3; // коэф. общего пути до которого использовать полную скорость  M1 при малом расстоянии (потеряно например)
float k2m1min=0.5; // коэф. общего пути с которого включать замедляющкю скорость M1
float k1m1=0.3; // коэф. общего пути до которого использовать полную скорость  M1
float k2m1=0.5; // коэф. общего пути с которого включать замедляющкю скорость M1
float k1m1max=0.5; // коэф. общего пути до которого использовать полную скорость  M1 при большом расстоянии (от линии 12 до 5R)
float k2m1max=0.6; // коэф. общего пути с которого включать замедляющкю скорость M1

// Функция привода переключения передач (2ой привод) M1
// В функцию передаются значения скорости (с любым знаком) и положения к которому нужно прийти (P_N12, P_N34, P_N5R)
byte Select_Gear_Motor_On(int Select_Gear_Start_Speed, int Select_Gear_End_Speed, int to_Position)//, boolean Search=false)
{ 
byte Rezult=0;
//int CurrentGearPosition=GetCurrentGearPosition();
boolean MotorToDo=false;
ReadSensors();

int znak_speed=1;

// определяемся со знаком скорости (т.е напралением вращения)
if (Select_Gear_Start_Speed<0){Select_Gear_Start_Speed=-Select_Gear_Start_Speed;} //приводим к положительному знаку
if (Select_Gear_End_Speed<0){Select_Gear_End_Speed=-Select_Gear_End_Speed;} //приводим к положительному знаку


if (to_Position==P_N12)
{
if ((SelectGearSensor1>SelectGear_P_N12)||(SelectGearSensor2>SelectGear_P_N12)) {znak_speed=1;}  
if ((SelectGearSensor1<SelectGear_P_N12)||(SelectGearSensor2<SelectGear_P_N12)) {znak_speed=-1;} 
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N12, SensorPositionLimitForWork))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N12, SensorPositionLimitForWork))) {znak_speed=0;} // дальше крутить не нужно  - нужное положение
if (znak_speed!=0) {MotorToDo=true;}
}

if (to_Position==P_N34)
{
if ((SelectGearSensor1>SelectGear_P_N34)||(SelectGearSensor2>SelectGear_P_N34)) {znak_speed=1;}  
if ((SelectGearSensor1<SelectGear_P_N34)||(SelectGearSensor2<SelectGear_P_N34)) {znak_speed=-1;} 
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N34, SensorPositionLimitForWork))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N34, SensorPositionLimitForWork))) {znak_speed=0;} // дальше крутить не нужно  - нужное положение
if (znak_speed!=0) {MotorToDo=true;}
}

if (to_Position==P_N5R)
{
if ((SelectGearSensor1>SelectGear_P_N5R)||(SelectGearSensor2>SelectGear_P_N5R)) {znak_speed=1;}  
if ((SelectGearSensor1<SelectGear_P_N5R)||(SelectGearSensor2<SelectGear_P_N5R)) {znak_speed=-1;} 
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N5R, SensorPositionLimitForWork))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N5R, SensorPositionLimitForWork))) {znak_speed=0;} // дальше крутить не нужно  - нужное положение
if (znak_speed!=0) {MotorToDo=true;}
}

float End_position=0;
float dystance=0;
float full_dystance=0;
boolean started=false;
boolean endingstarted=false;
boolean stopped=false;
float k1=k1m1;
float k2=k2m1; 
if (MotorToDo) 
{ 

Select_Gear_Start_Speed=Select_Gear_Start_Speed*znak_speed;
Select_Gear_End_Speed=Select_Gear_End_Speed*znak_speed;

#if DEBUG  
//Serial.println("***");  
//Serial.println(SelectGear_P_N);   
//Serial.println(SelectGearSensor1);    
#endif 

 
boolean stopMotor=false;
unsigned long now_timer=0;
unsigned long total_timer=0;
unsigned long control_timer=millis();      
int cyclescount=0;

do {

now_timer=millis();                 
total_timer = now_timer - control_timer; 
if (total_timer>=motor_check_timer) {SET_ERROR_MOTOR(ERROR_TOOLONGWORKINGM1); stopMotor=true;break;} // проверка на время длительности работы приводов
ReadSensors();

if (to_Position==P_N12) 
{
if (((SelectGearSensor1>SelectGear_P_N12)||(SelectGearSensor2>SelectGear_P_N12)) && (cyclescount>0)) {stopMotor=true;break;} // дальше крутить в эту сторону нельзя - конечное положение
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N12, SensorPositionLimitForRotate))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N12, SensorPositionLimitForRotate))) {stopMotor=true;break;} // дальше крутить не нужно  - нужное положение
End_position=SelectGear_P_N12;
}

if (to_Position==P_N34) 
{
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N34, SensorPositionLimitForRotate))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N34, SensorPositionLimitForRotate))) {stopMotor=true;break;} // дальше крутить не нужно  - нужное положение
End_position=SelectGear_P_N34;
}

if (to_Position==P_N5R) 
{
if (((SelectGearSensor1<SelectGear_P_N5R)||(SelectGearSensor2<SelectGear_P_N5R)) && (cyclescount>0)) {stopMotor=true;break;} // дальше крутить в эту сторону нельзя - конечное положение
if ((IsValInRangeEx(SelectGearSensor1,SelectGear_P_N5R, SensorPositionLimitForRotate))||(IsValInRangeEx(SelectGearSensor1,SelectGear_P_N5R, SensorPositionLimitForRotate))) {stopMotor=true;break;} // дальше крутить не нужно  - нужное положение
End_position=SelectGear_P_N5R;
}



dystance=abs(SelectGearSensor1-End_position);
if (full_dystance==0) {full_dystance=dystance;}
if (full_dystance<100) {Select_Gear_Start_Speed=M1MotorMidSpeed*znak_speed;}
if (full_dystance<100){k1=k1m1min; k2=k2m1min;} 
if (full_dystance>300){k1=k1m1max; k2=k2m1max;} 

if (!started)// разгон
{
if (full_dystance-dystance<full_dystance*k1) {
//Pololuqik.setM1Speed(Select_Gear_Start_Speed);
if (znak_speed>0){motorGo(1, CCW, 1023);}
if (znak_speed<0){motorGo(1, CW, 1023);}
started=true;} 

}
	

if (!endingstarted)//малая скорость
{	
if ((full_dystance-dystance>=full_dystance*k1) && (full_dystance-dystance<=full_dystance*k2)) {
//Pololuqik.setM1Speed(Select_Gear_End_Speed);
//if (znak_speed>0){motorGo(1, CCW, 512);}
//if (znak_speed<0){motorGo(1, CW, 512);}
endingstarted=true;}  //малая скорость
}

if (stopped==false) // торможение
{
if (full_dystance-dystance>full_dystance*k2) {
//Pololuqik.setM1Brake(127);
motorGo(1, BRAKEGND, 1023);
stopped=true;}
}

cyclescount++;
} while (stopMotor==false);

//Pololuqik.setM1Brake(127); //останов
motorGo(1, BRAKEGND, 1023);
motorOff(1); 
}  

Rezult=GetCurrentGearPosition();
if (Rezult!=0) {SetSuccessGearPosition_to_RAM(Rezult);}
//else {SetNotSuccessGearPosition_to_RAM(Rezult);}
return Rezult;
       	  }

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

Делайте два концевика с алгоритмом: крайний нижний(выключить двигатель), крайний верхний(выключить двигатель).

Скорость одна - очень медленная, что бы народу ключицы не переломать, если кто случайно будет проходить во время процесса.

Скетч станет очень простым.

zis101
Offline
Зарегистрирован: 15.06.2013

Привод от яриса, там уже все встроено, никаких концевиков нет, только датчик положения.

Маленькую скорость нельзя задавать, така как, для страгивания с шарикого фиксатора (трех позиционного) нужен рывок - читай момент, ну и как следсвие высокая стартовая скорость.

Хоть шариковый фиксатор и трехпозиционый, а пролетать среднее положение получается.

 

Пытался применить функцию map - все равно - пролетаю или недолетаю (в зависимости от стартовой скорости)

spd=map(dystance, 0, full_dystance, 0, 1023);

motorGo(1, CCW, spd);

Клапауций
Offline
Зарегистрирован: 10.02.2013

zis101 пишет:
Хоть шариковый фиксатор и трехпозиционый, а пролетать среднее положение получается.

Если пролёт среднего положения обусловлен спецификой конструкции, то зачем вообще нужно отрабатывать именно в среднем положении что-либо - пусть будет положение "где-то здесь среднее плюс расстояние, которое мы пролетели из-за продуманной конструкции привода".

zis101
Offline
Зарегистрирован: 15.06.2013

Среднее положение обязательно, там 3-4 передачи.

Клапауций
Offline
Зарегистрирован: 10.02.2013

Хорошо, если так всё жёстко обусловлено.

Датчик там какой? - резистор?

zis101
Offline
Зарегистрирован: 15.06.2013

Датчик холла, но выдает значения как резистивный.

// процедура чтения данных с датчиков пложения приводов
void ReadSensors()
{
ChangeGearSensor1=analogRead(ChangeGearSensor1Pin);
ChangeGearSensor2=analogRead(ChangeGearSensor2Pin);
if (IsValInRangeEx(ChangeGearSensor1,ChangeGearSensor2,ErrorSensorLimit)==false) {SET_ERROR_SENSOR(ERROR_CHANGEGEARSENSOR);} // большая разница в показаниях основного и вспомогательного датчиков
SelectGearSensor1=analogRead(SelectGearSensor1Pin);
SelectGearSensor2=analogRead(SelectGearSensor2Pin);
if (IsValInRangeEx(SelectGearSensor1,SelectGearSensor2,ErrorSensorLimit)==false){SET_ERROR_SENSOR(ERROR_SELECTGEARSENSOR);} // большая разница в показаниях основного и вспомогательного датчиков
}

Клапауций
Offline
Зарегистрирован: 10.02.2013

хорошо, а шум датчика случаем не в пределах пролёта?

...так и не могу понять - зачем именно 600 вам нужно?, почему не 600+- 50? или на сколько вы пролетаете.

у вас никак не выйдет на аналоге ловить ровно 600.

maksim
Offline
Зарегистрирован: 12.02.2012

Ловите среднее положение двуми импульсами, импульсом разгона и импульсом торможения. То есть без ШИМа.

zis101
Offline
Зарегистрирован: 15.06.2013

Клапауций

Допуск на позиционирование датчика я задал +-30

На сдвиг в процессе работы +-60 (тряска, вибрация).

Шума датчик не имеет (довольно-таки точный).

Нужно поймать 600+-30 (570-630), лучше конечно точнее.

Вот он датчик: http://toyota-corolla.ru/rm04f1ru/repair2/html/frame_rm0000016op008x.html

maksim

Не совсем понял как без ШИМа ? Буду рад любым идеям...

Штатно вроде вот так:

http://toyota-corolla.ru/rm04f1ru/repair2/html/frame_rm0000017ye00cx.html

maksim
Offline
Зарегистрирован: 12.02.2012

Даете импульс определенной длительности вращения в одну сторону - импульс разгона, затем импульс в другую сторону - импульс торможения. Тем самым повысите точность остановки в нужном месте. Плюс к этому можно еще предусмотреть импульсы корректировки в случае если проскочили или недоехали.

zis101
Offline
Зарегистрирован: 15.06.2013

delay применить для задания длины импульса?

maksim
Offline
Зарегистрирован: 12.02.2012

Хотите delay, хотите millis, без разницы. Для начала проверьте что будет нормальное позиционирование.

maksim
Offline
Зарегистрирован: 12.02.2012

Так же можно попробовать инициировать импульс торможения по показаниям датчика.

kadushkin
Offline
Зарегистрирован: 18.12.2011

О, я тоже подключусь, привод у меня точно такой же только от короллы.

Позиционирование ни к черту, хотя датчики действительно точные. Видимо придется программно гонять привод туда-сюда, пока не попадет в нужное положение.

Только вот

Цитата:
"Допуск на позиционирование датчика я задал +-30"

нужно +-10

Цитата:
"На сдвиг в процессе работы +-60 (тряска, вибрация)."

нужно +-20, это я проверял на коробке, там люфты такие.

Какой-то нужен алгоритм...

kadushkin
Offline
Зарегистрирован: 18.12.2011

Пробовал воссоздать подачу питания на эл. двигатель, как на графике http://arduino.ru/forum/proekty/robotizirovanaya-kpp#comment-33058

макс. импульс длительностью 50 мкс, затем минимальный - длительностью 50 мкс.

5 В/дел., 50 мкс/дел.

Двигатель стоит и жужжит.

Как я понял тойотовцы специально такие интервалы задают, чтобы проверять после них, находится ли двигатель в нужной позиции и этим достигают точности позиционирования. Но у меня не выходит.

motorGo(1, CCW, 1023);

delayMicroseconds(50);

motorGo(1, CCW, 0);

delayMicroseconds(50);

и это все в цикле

Mastino
Offline
Зарегистрирован: 03.12.2011

Как успехи в проекте?

kadushkin
Offline
Зарегистрирован: 18.12.2011

Вчера был пробный выезд, сегодня поднастрою и еще раз.

Mastino
Offline
Зарегистрирован: 03.12.2011

а видео где? :)

kadushkin
Offline
Зарегистрирован: 18.12.2011

Это надо за спиной стоять и снимать, я ж на дорогу смотрю.

Видео и фото отельных частей сборки и настройки выложу, езды чуть позже

Mastino
Offline
Зарегистрирован: 03.12.2011

Как дела с видео? Или все пробные выезды теоретические? :)

kadushkin
Offline
Зарегистрирован: 18.12.2011
Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

kadushkin пишет:

Это надо за спиной стоять и снимать, я ж на дорогу смотрю.

Полезно видеорегистратор в салоне поставить, чтобы заодно и параметры на приборной панели показывал.

kadushkin
Offline
Зарегистрирован: 18.12.2011

Блин, а ведь регистратор-то есть, не додумался его использовать, снимал на фотик.

Сейчас привод снял с машины, проблема в сдыхающем синхронизаторе КПП - он не позволяет очень быстро передачи включать.

Я и раньше знал, что синхронизатор умирает,  на ручной КПП передачи с паузой втыкал, теперь знаю точно, что синхронизатор менять надо. Но пока поезжу еще.

Mastino
Offline
Зарегистрирован: 03.12.2011

круто! большой поклон! вышло прям как заводская коробка передач "робот".

kadushkin
Offline
Зарегистрирован: 18.12.2011

Ну я старался. Механизм от тойоты, переходная плита и деталировка моя, крышка КПП родная с доработкой.

 

Saha pasura
Offline
Зарегистрирован: 06.04.2019

Ребята скинь те скетч акпп для управления на ардуино буду очень благодарен ppetia12@gmail.com.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Никто не скинет.