PCCar.ru - Ваш автомобильный компьютер

PCCar.ru - Ваш автомобильный компьютер (http://pccar.ru/index.php)
-   Сделай сам (http://pccar.ru/forumdisplay.php?f=17)
-   -   Система перемещения монитора (http://pccar.ru/showthread.php?t=22812)

skanch 08.02.2015 00:46

Система перемещения монитора
 
Вложений: 20
Хочу поделиться одним из вариантов изготовления СИСТЕМЫ ПЕРЕМЕЩЕНИЯ Вложение 39591 монитора в машине. Сразу скажу- не бюджетно. Цель - попытаться сделать достаточно надежную и качественную систему. В варианте, который буду описывать, использована реечная передача для перемещения каретки и коническая передача для подъема монитора в вертикальное положение. Компоненты системы: рейка модуль 1. Шестерни пока еще нет- где-то в пути. Конические шестерни . Сервомашинка SM-S4315R непрерывного вращения для перемещения каретки по горизонтали. Сервомашинка SM-S8166M для подъема монитора.
Линейные подшипники серии MGN 15.
Контроллер Arduino Nano. DC_DC преобразователи для питания сервомашинок.
Оптические прерыватели (концевики). Вся конструкция выполнена из алюминиевого профиля.
Для начала сделаем основу-раму. Размеры всех заготовок и деталей должны быть максимально точны. Сотки миллиметров можно игнорировать, даже десятки можно не брать в расчет, но в миллиметрах все должно быть точно. Итак делаем раму. Используем тяговые заклепки. Углы проверяем- 90° обязательное условие. Крепим линейные подшипники. Я использовал заклепки - гайки из алюминия для снижения веса. Но крайние крепления направляющих подшипника сделал на соединении винт-гайка для большей надежности. Все резьбовые соединения ставлю на вот такой фиксатор - защита от вибрации и все такое... Ставим одну коническую шестерню на большую серву. Использую все тот же фиксатор для резьбы. Делаем каретку. Уголок из алюминия использовал толщиной 3 мм. Он должен нести основную нагрузку. Делаем разметку под большую серву и боковые кронштейны. Боковые кронштейны сделал по такому принципу: в прямоугольную трубу 30х15х1.5 мм вставил квадрат 12х12 мм и все обжал винтами. Весь алюминий, который использую в работе конструкционный и размеры ГОСТ-овские, поэтому можно подобрать все по размеру. Итак внутренний размер прямоугольной трубы идеально совпал с наружным размером квадрата. Высверливаем отверстия под радиальные миниатюрные подшипники. Здесь я использую такие размером 6 x 10 x 3 мм.
Хочу обратить внимание на такой момент-сначала сверлим глухое отверстие Ø6 и глубиной не более 10 мм. Затем расширяем отверстие до Ø10 и глубиной max 5 мм. Объясню для чего это нужно. У подшипника, который я использую есть реборда-она не даст ему провалиться в отверстие и в дальнейшем позволит удобно зафиксировать. А в углубление Ø6 кладем шарик от подшипника Ø 5-5,5 мм для того, чтобы в дальнейшем наша ось не «клинила», упираясь торцом. Теперь изготовим саму площадку для монитора. Хочу добавить, что описанный вариант делается под планшет размером 190х112х10. Прикинув размеры вырезал такой «подиум». «Ноги» сделаны по принципу вышеописанных кронштейнов. Ось из латунного прутка Ø6 мм. «Ноги» прикручены и приклеены намертво вот таким клеем. Оказался очень достойный клей . Удобно работать. Сразу не «встает». После отверждения становиться очень прочным.

skanch 08.02.2015 01:01

Вложений: 2
Примерил "узел"

skanch 08.02.2015 02:36

Вложений: 1
Так выглядит первый вариант каретки с "навеской".

skanch 08.02.2015 02:46

Вложений: 4
Чтобы закрыть узел с шестеренками была изготовлена такая деталь.
Сделал ее из трубы и двух уголков. Сначала приклеил клеем, а потом залил полости эпоксидкой. Затем вырезал все лишнее и получил такое.

skanch 08.02.2015 02:53

Вложений: 1
Напрягают эти зияющие дыры.

skanch 08.02.2015 10:53

Вложений: 1
Сделал вставки.
Стало получше. После полной покраски думаю будет выглядеть хорошо.

skanch 08.02.2015 22:38

Вложений: 4
Очередная примерка.

http://www.pccar.ru/attachment.php?a...1&d=1423506867

http://www.pccar.ru/attachment.php?a...1&d=1423506910

http://www.pccar.ru/attachment.php?a...1&d=1423506915

http://www.pccar.ru/attachment.php?a...1&d=1423506919

skanch 09.02.2015 18:22

Вложений: 12
Продолжаем процесс. Разметил и вырезал посадочное место под серву горизонтального перемещения.
http://www.pccar.ru/attachment.php?a...1&d=1423509561
http://www.pccar.ru/attachment.php?a...1&d=1423509568

Закрепить пока нельзя- жду зубчатую шестерню.

Решил установить оптические прерыватели (концевики). Из-за не хватки места выбрал другие-меньшего размера.


http://www.pccar.ru/attachment.php?a...1&d=1423509625

Место для установки нашлось только одно.

http://www.pccar.ru/attachment.php?a...1&d=1423509658
Поскольку отверстие под крепление только одно и нужно исключить смещение- сделал вот такие штуки.
http://www.pccar.ru/attachment.php?a...1&d=1423509689
http://www.pccar.ru/attachment.php?a...1&d=1423509695
http://www.pccar.ru/attachment.php?a...1&d=1423509701
http://www.pccar.ru/attachment.php?a...1&d=1423509713
Одной стороной плата прижата к рейке, а вторую сторону фиксирует борт этого, если можно назвать -короба. Еще и функции диэлектрика. Но на всякий случай поставил изоляторы.

http://www.pccar.ru/attachment.php?a...1&d=1423509803


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

http://www.pccar.ru/attachment.php?a...1&d=1423509836
http://www.pccar.ru/attachment.php?a...1&d=1423509842
http://www.pccar.ru/attachment.php?a...1&d=1423509851

skanch 09.02.2015 21:30

Вложений: 1
Вот схемка оптического прерывателя, который я установил. В отличии от большего по габаритам-этот модуль имеет выводы, как высокого уровня, так и низкого. Может кому пригодится.

http://www.pccar.ru/attachment.php?a...1&d=1423509489

skanch 09.02.2015 22:58

Вложений: 1
Цитата:

Сообщение от жека 3 (Сообщение 320177)
сколько приблизительно нужно оборотов в минуту на горизонталь,так средне.

У меня серва крутит примерно 60 об.мин.. Каретка проходит расстояние в 13 см. примерно за 3,5 оборота вала. Но все зависит от количества зубьев на шестерне. У меня пара Модуль 1. Шестерня 12 зубов. Расчет такой 3,1415Х12=37,698
130мм/37,698=3,44 оборота.
Исправил. Тут параметры шага.

skanch 15.02.2015 21:54

Вложений: 8
Продолжаем сборку. Вчера получил шестерни.
Вал на серве диаметром 6 мм , а посадочный диаметр шестерни 5 мм- рассверлил до нужного размера и посадил на супер клей, о котором упоминал выше. Сегодня обрезал лишнее и смонтировал на каретку.
Серву установил через штатные резиновые втулки. Причем верхние крепления еще и с металлическими гильзами, которые шли в комплекте с сервомотором. На нижние ставить их не стал- серва стала с небольшим наклоном в сторону зубчатой рейки. Это создает нужный прижим.
Вчера окончательно подогнал и собрал крышку для монитора-планшета (новая ось,опорный подшипник). Намертво приклеил саму крышку к оси-теперь узел этот не разборный. Осталось сделать замки крепления планшета, лицевую панель и все отдать в покраску.
Смонтировал электрическую часть. Собрал по временной схеме питание сервомоторов, чтобы посмотреть в работе. Вот ролик работы механизма.
http://www.pccar.ru/attachment.php?a...1&d=1424030475

skanch 16.02.2015 22:33

Цитата:

Сообщение от anton2204 (Сообщение 320863)
Красиво!Серьезный подход!
P.S. Не доверяю я этим моментальным клеям–отвалятся со временем. Эпоксидка еще куда ни шло...Штифт лучше/надежнее!:)

На фото видно, что и винт прижимной присутствует, и супер клей-это EPOXY metal, проверенный в работе.

skanch 19.02.2015 22:15

Вложений: 6
Чтобы сервомоторы не дергались в момент подачи питания, а такое встречается очень часто и мой случай не исключение, использовал готовый IRF520 MOSFET-модуль для Arduino. Немного его подправил для экономии места. Управление модулем через ШИМ. Плавное включение питания полностью решило проблему "дергания" сервоприводов. Обязательное условие- плавно включать нужно то питание, которое идет после DC-DC преобразователя. Мои сервы питаются 6,5 V.

skanch 21.02.2015 00:50

Вложений: 7
Делаем кабель-канал для прокладки проводов от электрооборудования, установленного на каретке (сервы, модуль MOSFET, DC-DC преобразователь, а также для вывода с планшета необходимых проводов). Для этой цели я использую гибкую пружину-трубогиб с наружным диаметром 12 мм. Больший диаметр менее гибок. Пружина имеет антикоррозийное покрытие.
Один конец пружины крепим на каркасе с линейными направляющими, второй на самой каретке.
Провода внутри пружины нужно скрутить в сторону изгиба кабель-канала, для того, чтобы создать дополнительную разгрузку жгута при изгибании пружины и максимально исключить продольное движение проводов внутри. Когда все соберу-будет выглядеть примерно так.

skanch 01.03.2015 16:05

Вложений: 5
Цитата:

Сообщение от жека 3 (Сообщение 321972)
Как, окончательный результат не созрел?

Все в процессе... Доделываю... Сделал крепеж для планшета, переднюю рамку с крышкой. Сейчас делаю привод управления этой самой крышкой. Хочу сделать чисто механический-без двигателей, на рычагах. Работа идет. Скоро отдам в покраску детали, а после и сборка готового изделия...

skanch 15.03.2015 14:16

Вложений: 18
Готовый вариант системы.

skanch 15.03.2015 14:21

Здесь небольшое видео:
https://youtu.be/97YyrZYBzcA

skanch 06.04.2015 16:30

Цитата:

Сообщение от Maddeath (Сообщение 324937)
...новый проект делаем?

Благодарю за отзыв.
По новому проекту отправил тебе на почту вариант механизма.
Это "тот самый костыль, который заставляет шевелиться всю электро-механику".

PHP код:

#include <Servo.h> 
#include <EEPROM.h>
  
  
int value 0;                                                                // переменная для хранения значения ШИМ ( модуль MOSFET управления питанием сервомоторов)
  
int Mosfet1 11;                                                             // контакт, к которому подключен модуль MOSFET управления питанием сервомоторов

  
int pos 0;
  
// Создадим класс управления серво-приводом горизонтального перемещения
  
Servo Horizontal_Motor;                                                      // Класс управления серво-приводом горизонтального перемещения
  
int  HM_Pin                  10;                                           // Контакт, к которому подключен серво-привод горизонтального перемещения

  // Создадим класс управления серво-приводом вертикального перемещения
  
Servo Vertical_Motor;                                                        // Класс управления серво-приводом вертикального перемещения
  
int  VM_Pin                  9;                                            // Контакт, к которому подключен серво-привод вертикального перемещения
  
int  Mosfet2                 14;                                           // Контакт, к которому подключен MOSFET управления питанием планшета
  
int  VM_Max_Angle_Position   95;                                           // Максимальный угол открытия монитора
  
int  VM_Min_Angle_Position   0;                                            // Минимальный угол открытия монитора
  
long VM_Timer                0;                                            // Задержка перед сменой направления
  
int  VM_Working_Mode         0;                                            // Режим работы вертикального привода: 0 - постоянное кручение, 1 - поправка

  // Команды для серво-приводов
  
int  Servo_Stop_Command      90;                                           // Команда остановки серво-привода
  
int  Servo_Close_Command     0;                                            // Команда закрытия серво-привода (движение каретки назад)
  
int  Servo_Open_Command      180;                                          // Команда открытия серво-привода (движение каретки вперед)


  // Оптические датчики
  
int  Opt_Sensor_Fwd_Ctrl_Pin 7;                                            // Оптический прерыватель «вперед» управляющий PIN7, питание PIN8
  
int  Opt_Sensor_Fwd_ACC_Pin  8;                                            // Оптический прерыватель «вперед» управляющий PIN7, питание PIN8
  
int  Opt_Sensor_Bwd_Ctrl_Pin 5;                                            // Оптический прерыватель «назад» управляющий PIN5, питание PIN6
  
int  Opt_Sensor_Bwd_ACC_Pin  6;                                            // Оптический прерыватель «назад» управляющий PIN5, питание PIN6

  // Диагностический светодиод
  
int  Led_Pin                 13;                                           // Контакт, к которому подключен диагностический светодиод

  // Кнопки управления системой
  
int  Btn_Open_Close_Pin      2;                                            // Контакт, к которому подключена кнопка управления открытия/закрытия монитора
  
int  Btn_Adjust_Position_Pin 3;                                            // Контакт, к которому подключена кнопка управления настройкой вертикальной позиции монитора

  // Переменные для хранения состояния кнопкок управления системой
  
int  Btn_Open_Close_State;                                                   // Переменная состояния кнопки управления открытия/закрытия монитора
  
int  Btn_Adjust_Position_State;                                              // Переменная состояния кнопки управления настройкой вертикальной позиции монитора
  
int  Btn_Adjust_Position_Course;                                             // Переменная, в которой хранится вертикальное направление движения позиции монитора
  
long Btn_Open_Close_Last_Time;                                               // Переменная, в которой хранится последнее время мажатия кнопки управления открытия/закрытия монитора
  
long Btn_Adjust_Position_Last_Time;                                          // Переменная, в которой хранится последнее время мажатия кнопки управления настройкой вертикальной позиции монитора

  // Значения для обработки кнопок
  
int  Btn_Pressed              LOW;
  
int  Btn_Released             HIGH;
  
int  Btn_Direction_Up         0;
  
int  Btn_Direction_Down       1;
  
long Btn_Open_Close_Debounce  200;                                         // Временная константа дребезга клавиши (миллисекунды) открытия/закрытия
  
long Btn_Adjust_Debounce      8;                                           // Временная константа дребезга клавиши (миллисекунды) угла наклона монитора
  
long Btn_Adjust_Debounce_Sleep 7;                                          // Задержка перед обработкой клавиши угла....


  // Сохранение состояния системы в EEPROM
  
int  HM_State_Offset         0;
  
int  VM_State_Offset         4;
  
int  VM_Working_Angle_Offset 8;
  
int  VM_Temp_Angle_Offset    16;
  
long Check_Sum_Offset        32;

  
// Значения состояния системы
  
int  SM_Opened_State          0;
  
int  SM_Opening_State         1;
  
int  SM_Closing_State         2;
  
int  SM_Closed_State          3;

  
// Переменные хранения состояния системы
  
int  HM_State;                                                               // Переменная хранения текущего состояния горизонтального серво-привода
  
int  VM_State;                                                               // Переменная хранения текущего состояния вертикального серво-привода
  
int  VM_Working_Angle_Position;                                              // Переменная хранения рабочей позиции монитора
  
int  VM_Temp_Angle_Position;                                                 // Переменная для хранения угла монитора при открывании/складывании
  
long CheckSum




void setup() 

  
// !!! Наверное надо проверять на запуск с зажатой кнопкой "Открыть"
  // !!! и при таком состоянии нам пользователь сообщает, что 
  // !!! система закрыта и необходимо просто обновить ее состояние в EEPROM
 
  
  // Подаем питание на модуль MOSFET управления питанием сервомоторов
  
for(value value <= 255value+=5// напряжение постепенно увеличивается (от 0V до 5V)
  

    
analogWrite(Mosfet1value);           
    
delay(5);  // ждём 5 миллисекунд (время подбираем опытным путем)
     // Сконфигурируем контакт питания модуля MOSFET управления питанием планшета
   
pinMode(Mosfet2OUTPUT);
  }  
  
  
  
// Отладка 
  
Serial.begin(9600);
  while (!
Serial) {
    ; 
// wait for serial port to connect. Needed for Leonardo only
  
}


  
//----------------------//
  // Настроим всю систему //
  //----------------------//

  // Обнулим переменную, в которой хранится последнее время мажатия кнопки управления открытия/закрытия монитора
  
Btn_Open_Close_Last_Time      0;                                      
  
// Обнулим переменную, в которой хранится последнее время мажатия кнопки управления настройкой вертикальной позиции монитора
  
Btn_Adjust_Position_Last_Time 0;                                      

  
// Установим переменную, в которой хранится вертикальное направление движения позиции монитора на движение "вниз"
  
Btn_Adjust_Position_Course    Btn_Direction_Down;                                             

  
// Сконфигурируем контакт кнопки управления открытием/закрытием как "Вход" и подключим к контакту внутренний резистор
  
pinMode(Btn_Open_Close_PinINPUT);

  
// Сконфигурируем контакт кнопки управления настройкой вертикальной позиции монитора как "Вход" и подключим к контакту внутренний резистор
  
pinMode(Btn_Adjust_Position_PinINPUT);


  
// Сконфигурируем контакт диагностического светодиода как "Выход" (будем зажигать/гасить)
  //pinMode(Led_Pin, OUTPUT);

  // Подключим контакт управления серво-приводом горизонтального перемещения
  
Horizontal_Motor.attach(HM_Pin);

  
// Остановим и удержим серво-привод горизонтального перемещения в положении "Стоп"
  
Horizontal_Motor.write(Servo_Stop_Command);


 



  
// Инициализируем оптические датчики
  
pinMode(Opt_Sensor_Fwd_Ctrl_PinINPUT);
  
pinMode(Opt_Sensor_Fwd_ACC_Pin,  OUTPUT);

  
pinMode(Opt_Sensor_Bwd_Ctrl_PinINPUT);
  
pinMode(Opt_Sensor_Bwd_ACC_Pin,  OUTPUT);

  
// Подадим питание на оптические датчики
  //digitalWrite(Opt_Sensor_Fwd_ACC_Pin, HIGH);
  //digitalWrite(Opt_Sensor_Bwd_ACC_Pin, HIGH);


  //---------------------------------------//
  // Проверим предыдущее состояние системы //
  //---------------------------------------//

  // Считаем предыдущее состояние системы
  
HM_State                  EEPROM.read(HM_State_Offset); 
  
VM_State                  EEPROM.read(VM_State_Offset); 
  
VM_Working_Angle_Position EEPROM.read(VM_Working_Angle_Offset); 
  
VM_Temp_Angle_Position    EEPROM.read(VM_Temp_Angle_Offset); 

  
// Проверим угол наклона монитора на максимальный и минимальный
  
if (VM_Working_Angle_Position VM_Max_Angle_Position VM_Working_Angle_Position 0) {
    
VM_Working_Angle_Position VM_Max_Angle_Position;

    
// Сохраним угол наклона монитора в EEPROM
    
EEPROM.write(VM_Working_Angle_OffsetVM_Working_Angle_Position); 
  }

  
// Считаем контрольную сумму из EEPROM
  
CheckSum EEPROM.read(Check_Sum_Offset); 

  
// Проверим контрольную сумму - совпала и состояние серво-приводов = SM_Closed_State легко продолжаем работу
  
if ( (CheckSum == (HM_State 256) + VM_State) & (HM_State == SM_Closed_State) & (VM_State == SM_Closed_State) ) {
    return;
  }

  
//--------------------------------------------------------------//
  // Надо сначала все механизмы привести в стартовое состояние    //
  //--------------------------------------------------------------//


  
delay(2000);

  
Serial.print("VM_Temp_Angle_Position");
  
Serial.print("\t  = \t");
  
Serial.print(VM_Temp_Angle_PositionDEC);
  
Serial.println();


  if (
VM_Temp_Angle_Position 0) {

    
// Выпрямим монитор с сохраненной временной позиции до 0
    
VM_Working_Angle_Position VM_Temp_Angle_Position;
    
Start_Vertical_Motor(Servo_Close_Command);
  } else {

    
// Выпрямим монитор для страховки в 0
    
Vertical_Motor.write(0);
  }
  
// Теперь сохраним правильное значение временной позиции
  
VM_Temp_Angle_Position 0;
  
EEPROM.write(VM_Temp_Angle_OffsetVM_Temp_Angle_Position); 

  
// Считаем реальное рабочее положение монитора
  
VM_Working_Angle_Position EEPROM.read(VM_Working_Angle_Offset); 

  
// Сохраним вертикальное положение монитора в EEPROM
  
VM_State SM_Closed_State;
  
EEPROM.write(VM_State_OffsetSM_Closed_State); 

  
// Затем затянем его обратно
  
Start_Horizontal_Motor(Servo_Close_Command10000);

  
// Теперь сохраним состояние системы в "хорошем" состоянии
  
HM_State SM_Closed_State;

  
// Сохраним положение монитора в EEPROM
  
EEPROM.write(HM_State_OffsetHM_State); 

  
// Пересчитаем контрольную сумму в EEPROM
  
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 



//
// Поворот на один градус вертикального привода в зависимсоти от переменной  Btn_Adjust_Position_Course
//
void VM_Move()
{
          
// Проверим переменную, в которой хранится вертикальное направление движения позиции монитора
          
if (Btn_Adjust_Position_Course == Btn_Direction_Down) {


  
Serial.print("Direction = DOWN. Angle ");
  
Serial.print("\t  = \t");
  
Serial.print(VM_Working_Angle_PositionDEC);
  
Serial.println();

            
// Теперь сохраним состояние системы в "не очень хорошем" состоянии
            
VM_State SM_Closing_State;
            
// Сохраним положение монитора в EEPROM
            
EEPROM.write(VM_State_OffsetVM_State); 

            
//
            // Необходимо наклонить монитор на один градус "вниз"
            //

            // Проверим на достижение "критического угла наклона"
            
if (VM_Working_Angle_Position == VM_Min_Angle_Position) {
              
// Угу. Встали в крайнюю позицию. Надо начинать движение "вверх".
              
Btn_Adjust_Position_Course Btn_Direction_Up;
              return;

            } else {
              
// Нам еще есть куда двигаться "вниз" - значит подвинемся
              
VM_Working_Angle_Position VM_Working_Angle_Position 1;

              
// Теперь надо сам монитор выставить на нужный угол
              
Vertical_Motor.write(VM_Working_Angle_Position);

              
// Сохраним угол наклона монитора в EEPROM
              
EEPROM.write(VM_Working_Angle_OffsetVM_Working_Angle_Position); 
              
EEPROM.write(VM_Temp_Angle_OffsetVM_Working_Angle_Position); 

            }
          } else {

  
Serial.print("Direction = UP. Angle = ");
  
Serial.print("\t  = \t");
  
Serial.print(VM_Working_Angle_PositionDEC);
  
Serial.println();

            
// Теперь сохраним состояние системы в "не очень хорошем" состоянии
            
VM_State SM_Opening_State;
            
// Сохраним положение монитора в EEPROM
            
EEPROM.write(VM_State_OffsetVM_State); 

            
//
            // Необходимо поднять монитор на один градус "вверх"
            //

            // Проверим на достижение "критического угла наклона"
            
if (VM_Working_Angle_Position == VM_Max_Angle_Position) {
              
// Угу. Встали в крайнюю позицию. Надо начинать движение "вниз".
              
Btn_Adjust_Position_Course Btn_Direction_Down;
              return;

            } else {
              
// Нам еще есть куда двигаться "вверх" - значит подвинемся
              
VM_Working_Angle_Position VM_Working_Angle_Position 1;

              
// Теперь надо сам монитор выставить на нужный угол
              
Vertical_Motor.write(VM_Working_Angle_Position);

              
// Сохраним угол наклона монитора в EEPROM
              
EEPROM.write(VM_Working_Angle_OffsetVM_Working_Angle_Position); 
              
EEPROM.write(VM_Temp_Angle_OffsetVM_Working_Angle_Position); 

            }
          }
 
          
// Сохраним угол наклона монитора в EEPROM
          
EEPROM.write(VM_Working_Angle_OffsetVM_Working_Angle_Position); 
          
EEPROM.write(VM_Temp_Angle_OffsetVM_Working_Angle_Position); 
}
 
 
void loop() 

  
// Проверим режим работы вертикального привода
  
if (VM_Working_Mode == 1) {
    
// Режим поправки
    // Проверим на окончание времени действия режима поправки
    
if (millis() - VM_Timer 1000) {
      
// Время вышло сменим режим и угол наклона
      
VM_Working_Mode 0;

      
// Время закончилось. И нам надо сменить направление движения монитора
      
if (Btn_Adjust_Position_Course == Btn_Direction_Up) {
        
Btn_Adjust_Position_Course Btn_Direction_Down;
      } else {
        
Btn_Adjust_Position_Course Btn_Direction_Up;
      }
    }
  }




  
//
  // Проверим на нажатие контрольных кнопок
  //

  // Сначала проверим на одновременное нажатие двух кнопок.
  // Есть возможность одновременного нажатия двух кнопок - мы такое отсекаем.
  
if (digitalRead(Btn_Open_Close_Pin) == Btn_Pressed && digitalRead(Btn_Adjust_Position_Pin) == Btn_Pressed) {
    
// Нажаты одновременно две кнопки. Тупо запомним время их нажатия и ничего делать не будем
    
Btn_Open_Close_Last_Time      millis();
    
Btn_Adjust_Position_Last_Time millis();
  } else {

    
//
    // Теперь проверим в каком состоянии находится система (открыта/закрыта)
    //

    
if (HM_State == SM_Opened_State) {
      
// Система находится в открытом состоянии. Значит можно сделать два действия
      // - закрыть монитор через кнопку Btn_Open_Close_Pin;
      // - изменить угол наклона монитора через кнопку Btn_Adjust_Position_Pin

      // Начнем проверять кнопки отдельно.

      //
      // Проверим текущее состояние кнопки Btn_Open_Close_Pin
      //
      
Btn_Open_Close_State digitalRead(Btn_Open_Close_Pin);

      
// Проверим на нажатие кнопки и исключим "дребезг" кнопки
      
if (Btn_Open_Close_State == Btn_Pressed && millis() - Btn_Open_Close_Last_Time Btn_Open_Close_Debounce) {
        
// Запомним время нажатия кнопки
        
Btn_Open_Close_Last_Time millis();

        
// Начнем действия по закрытию всей системы. 

        // Отправим команду вертикальному серво-приводу на движение "Вниз"
        
Start_Vertical_Motor(Servo_Close_Command);
       
        
// Отправим команду горизонтальному серво-приводу на движение "Назад"
        
Start_Horizontal_Motor(Servo_Close_Command10000);

        return;
      }


      
//
      // Проверим текущее состояние кнопки Btn_Adjust_Position_Pin
      // Надо учитывать, что при отпускании кнопки должно переключаться 
      // направление наклона монитора. 
      // Т.е. как только мы поняли, что кнопку нажали - заходим в цикл
      // до отжатия кнопки и начинаем изменять угол монитора. Причем
      // если угол наклона достиг критической точки (0 или VM_Max_Position)
      // автоматически сменим направление!
      //

      //Проверим на нажатие и начнем цикл
      
Btn_Adjust_Position_State digitalRead(Btn_Adjust_Position_Pin);

      
// Проверим на нажатие кнопки только для того, чтобы потом сменить направление движения
      
if (Btn_Adjust_Position_State == Btn_Pressed && millis() - Btn_Adjust_Position_Last_Time Btn_Adjust_Debounce) {

        
// Подключим контакт управления серво-приводом вертикального перемещения
        
Vertical_Motor.attach(VM_Pin);


        
// Проверим режим работы вертикального привода
        
if (VM_Working_Mode == 1) {
          
// Режим поправки

  
Serial.print(" VM_Mode ");
  
Serial.print("\t  = \t");
  
Serial.print(VM_Working_ModeDEC);
  
Serial.println();

          
// Запомним время нажатия кнопки
          
Btn_Adjust_Position_Last_Time millis();

          
// Время есть можно править угол
          
VM_Move();
            
          
// Начнем новый отсчет 3-х секунд
          
VM_Timer millis();

          
// Сделаем задержку во избежание дребезга клавиш
          
delay(Btn_Adjust_Debounce_Sleep);

        } else {
          
// Режим кручения

  
Serial.print(" VM_Mode ");
  
Serial.print("\t  = \t");
  
Serial.print(VM_Working_ModeDEC);
  
Serial.println();

          
// Проверим на нажатие кнопки и исключим "дребезг" кнопки
          
while (Btn_Adjust_Position_State == Btn_Pressed && millis() - Btn_Adjust_Position_Last_Time Btn_Adjust_Debounce) {

            
// Запомним время нажатия кнопки
            
Btn_Adjust_Position_Last_Time millis();

            
// И так... кнопка нажата - значит надо наклонить монитор на 1 градус в заданном направлении
            
VM_Move();
  
            
// Сделаем задержку во избежание дребезга клавиш
            
delay(Btn_Adjust_Debounce_Sleep);

            
// Снова считаем состояние кнопки
            
Btn_Adjust_Position_State digitalRead(Btn_Adjust_Position_Pin);
          }

          
// Цикл закончился. Значит кнопарь отпустили и нам надо дать задержку на 3 секунды для поправки угла монитора

          // Начнем отсчет 3-х секунд
          
VM_Timer millis();
          
VM_Working_Mode 1;

        }

        
// Теперь сохраним состояние системы в "не очень хорошем" состоянии
        
VM_State SM_Opened_State;
        
// Сохраним положение монитора в EEPROM
        
EEPROM.write(VM_State_OffsetVM_State); 

        
// Пересчитаем контрольную сумму в EEPROM
        
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 



        
// Отключим контакт управления серво-приводом вертикального перемещения, чтобы не жужжала бестолку
        
Vertical_Motor.detach();

        
      }
    } else {
      
// Система находится в закрытом состоянии. Ее можно только открыть через кнопку Btn_Open_Close_Pin

      // Проверим текущее состояние кнопки Btn_Open_Close_Pin
      
Btn_Open_Close_State digitalRead(Btn_Open_Close_Pin);

      
// Проверим на нажатие кнопки и исключим "дребезг" кнопки
      
if (Btn_Open_Close_State == Btn_Pressed && millis() - Btn_Open_Close_Last_Time Btn_Open_Close_Debounce) {
        
// Запомним время нажатия кнопки
        
Btn_Open_Close_Last_Time millis();

        
// Начнем действия по открытию всей системы. 
         // Подключим питание модуля MOSFET управления питанием планшета
        
digitalWrite(Mosfet2HIGH);
        
// Отправим команду горизонтальному серво-приводу на движение "Вперед"
        
if (Start_Horizontal_Motor(Servo_Open_Command10000)) 
        
        {
          
// Отправим команду вертикальному серво-приводу на движение "Вверх"
          
Start_Vertical_Motor(Servo_Open_Command);
        }
      }
    }
  }

  
delay(100);




bool Start_Horizontal_Motor(int HM_Directionlong MaxTimeOut)
{
  
int  Sensor_Pin;
  
int  Sensor_ACC;

  
// Теперь сохраним состояние системы
  
if (HM_Direction == Servo_Close_Command) {
    
// Теперь сохраним состояние системы в "хорошем" состоянии
    
HM_State SM_Closing_State;
    
// Сохраним положение монитора в EEPROM
    
EEPROM.write(HM_State_OffsetHM_State); 
    
// Пересчитаем контрольную сумму в EEPROM
    
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 

    
HM_State SM_Closed_State;
  } else {
    
// Теперь сохраним состояние системы в "хорошем" состоянии
    
HM_State SM_Opening_State;
    
// Сохраним положение монитора в EEPROM
    
EEPROM.write(HM_State_OffsetHM_State); 
    
// Пересчитаем контрольную сумму в EEPROM
    
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 

    
HM_State SM_Opened_State;
  }


  
// Выберем соответствующий контрольный датчик
  
if (HM_Direction == Servo_Close_Command) {
    
// Выберем ногу для контрольного датчика
    
Sensor_Pin Opt_Sensor_Bwd_Ctrl_Pin;
    
Sensor_ACC Opt_Sensor_Bwd_ACC_Pin;
  } else {
    
// Выберем ногу для контрольного датчика
    
Sensor_Pin Opt_Sensor_Fwd_Ctrl_Pin;
    
Sensor_ACC Opt_Sensor_Fwd_ACC_Pin;
  }
  
// Подадим питание на оптический датчик
  
digitalWrite(Sensor_ACCHIGH);

  
// Задержка для сработки датчика, если стоим у края
  
delay(15);

  
// Проверим на наличие сигнала с оптического датчика
  
if (digitalRead(Sensor_Pin) == HIGH) {

    
// Снимем питание с оптического датчика
    
digitalWrite(Sensor_ACCLOW);
    return 
true;
  }

  
// Теперь начнем горизонтальное движение серво-приводом
  
Horizontal_Motor.write(HM_Direction);
 
  
// Запомним время начала движения
  
long StartTime millis();

  
// Начнем цикл ожидания сигнала от оптических датчиков или прервемся по таймауту
  
while (millis() <= StartTime MaxTimeOut) {
    
// Проверим на наличие сигнала с оптического датчика
    
if (digitalRead(Sensor_Pin) == HIGH) {
      
// Сигнал пришел - тормознем серво-привод
      
Horizontal_Motor.write(Servo_Stop_Command);

      
// Теперь сохраним состояние системы в "хорошем" состоянии
      // Сохраним положение монитора в EEPROM
      
EEPROM.write(HM_State_OffsetHM_State); 
      
// Пересчитаем контрольную сумму в EEPROM
      
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 

      
// Снимем питание с оптического датчика
      
digitalWrite(Sensor_ACCLOW);

      
// Возвращаемся из функции с разрешением на дальнейшие действия
      
return true;
    }

    
// Подождем 15 миллисекунд
    
delay(15);
  }

  
// Тормознем серво-привод
  
Horizontal_Motor.write(Servo_Stop_Command);



  
// Снимем питание с оптического датчика
  
digitalWrite(Sensor_ACCLOW);
  return 
false;
}



void Start_Vertical_Motor(int VM_Direction)
{
  
int StartPos;

  
// Теперь сохраним состояние системы
  
if (VM_Direction == Servo_Close_Command) {
    
// Теперь сохраним состояние системы в "хорошем" состоянии
    
VM_State SM_Closing_State;

    
// Сохраним положение монитора в EEPROM
    
EEPROM.write(VM_State_OffsetVM_State); 
    
// Пересчитаем контрольную сумму в EEPROM
    
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 

    
VM_State SM_Closed_State;
  } else {
    
// Теперь сохраним состояние системы в "хорошем" состоянии
    
VM_State SM_Opening_State;

    
// Сохраним положение монитора в EEPROM
    
EEPROM.write(VM_State_OffsetVM_State); 
    
// Пересчитаем контрольную сумму в EEPROM
    
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 

    
VM_State SM_Opened_State;
  }

  
// Подключим контакт управления серво-приводом вертикального перемещения
  
Vertical_Motor.attach(VM_Pin);

  
delay(25);

 

  
Serial.print("Start_Vertical_Motor(");
  if (
VM_Direction == Servo_Close_Command) {
    
Serial.print("Servo_Close_Command)");
  } else {
    
Serial.print("Servo_Open_Command)");
  }
  
Serial.println();

  
Serial.print("VM_Working_Angle_Position\t  = \t");
  
Serial.print(VM_Working_Angle_PositionDEC);
  
Serial.println();


  
// Проверим в каком направлении нам необходимо двигаться
  
if (VM_Direction == Servo_Close_Command)
  {
    
// Проверка для избежания дерганья сервы
    
if (VM_Working_Angle_Position != ) {

    
// Включим диагностический светодиод
    //digitalWrite(Led_Pin, HIGH);

      
Serial.print("Close_Down!\t  = \t");
      
Serial.print(VM_Working_Angle_PositionDEC);
      
Serial.println();

      for (
StartPos VM_Working_Angle_PositionStartPos 0StartPos -= 3) {
        
Vertical_Motor.write(StartPos);
        
delay(15);

        
Serial.print("CurrentPos\t  = \t");
        
Serial.print(StartPosDEC);
        
Serial.println();

        
// Сохраним угол наклона монитора в EEPROM
        
EEPROM.write(VM_Temp_Angle_OffsetStartPos); 
      }
    }

    
Vertical_Motor.write(0);
    
delay(15);
    
    
// Отключим питание модуля MOSFET управления питанием планшета
        
digitalWrite(Mosfet2LOW);
        
    
// Сохраним угол наклона монитора в EEPROM
    
EEPROM.write(VM_Temp_Angle_Offset0); 

  } else {
    
delay(15);

    
// Проверка для избежания дерганья сервы
    
Serial.print("Open_Up\t  = \t");
    
Serial.print(VM_Working_Angle_PositionDEC);
    
Serial.println();

    if (
VM_Working_Angle_Position != ) {
      for (
StartPos 1StartPos VM_Working_Angle_PositionStartPos += 3) {
        
Vertical_Motor.write(StartPos);
        
delay(15);

        
Serial.print("CurrentPos\t  = \t");
        
Serial.print(StartPosDEC);
        
Serial.println();

        
// Сохраним угол наклона монитора в EEPROM
        
EEPROM.write(VM_Temp_Angle_OffsetStartPos); 
      }
    }

    
Vertical_Motor.write(VM_Working_Angle_Position);
    
delay(15);
  
    
// Сохраним угол наклона монитора в EEPROM
    
EEPROM.write(VM_Temp_Angle_OffsetVM_Working_Angle_Position); 
  }

  
// Отключим контакт управления серво-приводом вертикального перемещения, чтобы не жужжала бестолку
  
Vertical_Motor.detach();



  
// Теперь сохраним состояние системы в "хорошем" состоянии
  // Сохраним положение монитора в EEPROM
  
EEPROM.write(VM_State_OffsetVM_State); 

  
// Пересчитаем контрольную сумму в EEPROM
  
EEPROM.write(Check_Sum_Offset, (HM_State 256) + VM_State); 


На мой взгляд-нормальная программа. Все работает, все шевелится...

skanch 11.10.2015 13:04

Вложений: 13
Вариант крепления планшета для системы перемещения. Возможно кому-нибудь будет интересно.
Требования к конструкции:съемный планшет (в данном случае Samsung Galaxy Tab S2),постоянная подзарядка планшета.
Реализовано с применением комплекта беспроводной подзарядки, чехла для планшета, магнитов от держателя в авто.
Конструкция "подиума" для планшета практически ничем не отличается от описанного выше. За исключением крепления самого планшета.
Вот фото такой конструкции.
В алюминиевой площадке просверлены отверстия под диаметр магнитов, которые приклеены на тыльной стороне пластикового "чехла" для планшета. Сзади к алюминиевой площадке приклеены полоски жести толщиной 0.8мм. К ним и "цепляются" магниты. Все держится хорошо и при надобности планшет вместе с "чехлом" можно легко снять.

skanch 09.12.2015 22:45

Вложений: 16
Еще одна подобная система.

skanch 10.12.2015 21:18

Это ролик https://youtu.be/waMT_I0s6vY

skanch 11.12.2015 02:29

Вложений: 4
Это "пациент".

skanch 08.02.2016 21:43

Делаем из сервы мотор-редуктор.
 
Вложений: 1
При разработке механизма размера 1DIN столкнулся с проблемой подбора моторов для перемещения каретки и подъема монитора. Большинство не подходят по размерам - нужны приводы с габаритами, которые можно "вписать" в окно 34мм шириной. Еще немаловажный момент - усилие, которое развивает такой привод (мотор-редуктор). Если для перемещения по горизонтали достаточно 15 кг/см, то для подъема монитора необходимо уже не менее 30 кг/см и больше. Не так давно попались мне такие сервомоторы для роботов.
http://www.pccar.ru/attachment.php?a...1&d=1454963201
Технические характеристики:
Рабочее напряжение: 6.0~7.4в
Скорость работы: 0.18сек/60° / 0.16сек/60°
Макс. момент: 25.8кгс∙см /32.4кгс∙см
Ход: 0~280°
Размер: 43X32X32.5мм
Вес: 73г
Шлиц: 25T
Подшипник: 2 шарикоподшипника
Редуктор: металл
Длина кабеля: 50см
Отверстия крепления: 2.5x21.5мм
Частота работы: 1520мкс/333Hz, 900~2100мкс

Опробовал их на нескольких механизмах в узлах подъема монитора. Усилие с запасом, угол отрабатывают точно (для подъема нужен в пределах 0-110 градусов), ток при нагрузке и напряжении +/-7в не превышает 2,0А. Размер, вес и крепление - можно сказать идеальные.
Но для перемещения каретки по горизонтали нужен сервомотор с постоянным вращением, не ограниченный углом поворота (у этих 0-280 градусов). Решил немного переделать серву под свои "хотелки".

skanch 08.02.2016 22:14

Вложений: 10
Разбираем мотор.

http://www.pccar.ru/attachment.php?a...1&d=1454963415

Выпаиваем драйвер и потенциометр ограничения угла поворота.Зачищаем место крепления потенциометра

http://www.pccar.ru/attachment.php?a...1&d=1454963443

Для управления мотором буду использовать драйвер TB6612FNG.

http://www.pccar.ru/attachment.php?a...1&d=1454954573

При своем размере имеет очень достойные параметры.

"Модуль драйвер на основании чипа TB6612FNG производства компании Toshiba. В отличие от наиболее распространенных на сегодняшний день драйверов на основе чипа L298N,L293D,LB1836M имеет ряд преимуществ таких как : минимальный размер, максимальный выход на канал до 3А, частота ШИМ 100 кГц, температурный контроль. Все это выделяет данный модуль драйвер TB6612FNG из всех имеющихся на сегодняшний день.

Характеристики:

- входное напряжение для двигателей от 4.5 до 13.5 Вольт DC;

- напряжение логики от 2.7 до 5.5 Вольт DC;

- максимальный ток на канал 3А (при длительном использовании рекомендуется установка радиатора), до 2А без радиатора;

- частота ШИМ 100 кГц ;

- встроенная тепловая схема отключения;

- фильтрующий конденсатор питания;

- защита от обратного тока;

- рабочая температура от (-20) до 80 градусов Цельсия;

Размер:20 x 17 мм.

Вес: до 20 гр."

Впаиваем "гребенку" с пинами.

http://www.pccar.ru/attachment.php?a...1&d=1454954654
http://www.pccar.ru/attachment.php?a...1&d=1455031795
http://www.pccar.ru/attachment.php?a...1&d=1455031795


Примерка в корпусе мотора.

http://www.pccar.ru/attachment.php?a...1&d=1454963694

Это с крышкой.

http://www.pccar.ru/attachment.php?a...1&d=1454963750

Остается припаять нужные провода и подключить к Ардуино. Ну это еще в процессе...

"Питаться" сервы будут от общеизвестных DC-DC преобразователей

http://www.pccar.ru/attachment.php?a...1&d=1454955223

http://www.pccar.ru/attachment.php?a...1&d=1454955252

skanch 08.02.2016 22:54

Вложений: 4
Это предварительная примерка на плате управления.

http://www.pccar.ru/attachment.php?a...1&d=1454963908
http://www.pccar.ru/attachment.php?a...1&d=1454964048
http://www.pccar.ru/attachment.php?a...1&d=1454957725
http://www.pccar.ru/attachment.php?a...1&d=1454957725

skanch 10.02.2016 22:42

Вложений: 5
Заготовка для каретки.

http://www.pccar.ru/attachment.php?a...1&d=1455129611
http://www.pccar.ru/attachment.php?a...1&d=1455129611
http://www.pccar.ru/attachment.php?a...1&d=1455129611
http://www.pccar.ru/attachment.php?a...1&d=1455129668
http://www.pccar.ru/attachment.php?a...1&d=1455129668

skanch 06.03.2016 11:42

Цитата:

Сообщение от Serdj (Сообщение 353781)
неплохо было бы добавить библиотеку irremote...

Я совсем не программист. "Нажал-поехало-открыл" еще смогу написать. Все, что связано с Eeprom, прерываниями и прочим для меня сложно. Но по существу вопроса- есть вот такой скетч в свободном доступе. В шапке ссылка на первоисточник. Возможно это то, что нужно?
Скопировано без изменений.
PHP код:

/*             v.01 Arduino servo IR EEPROM speed ИК пультом  
 ****************************
 урок от Дмитрия Осипова. http://www.youtube.com/user/d36073?feature=watch
 v.01 Arduino servo IR EEPROM speed ИК пультом
 Version 0.1-2013/08/19
 -----------------------------
 изменения; в Version 0.1-2013/
 1. 
 2. 
 ------------------------------
 идеология;
 управление двумя servo любым (ИК) инфракрасным пультом,для управления задействуем 5 кнопок  ИК пульта,
 4 кнопки для плавного поворота вправо или влево, а одну кнопку для регулировки скорости поворота.
 Также задействуем ОЗУ EEPROM (энергонезависимая память): (данные сохраняются при отключении питания). 
 То бишь после включения питания, градус поворота servo, и установленная скорость поворота, будут теми же
 какие были на момент отключения. 
 
 внимание, при первой заливки sketch, Arduino будет читать значение скорости из ячейки №3 ОЗУ.
 ОЗУ скорей всего у вас девственный, поэтому нужно сначала нажать на кнопку ИК пульта управления скоростью,
 чтоб в ячейке №3 появились данные. В следующих заливках sketch это делать не нужно.
 
 Рекомендую использовать конденсаторы для сглаживания электрических колебаний которые создают servo во время работы.
 
 
 Также рекомендую отключать servo от Arduino в момент заливки sketch, USB компьютера может не потянуть нагрузку,
 servo потребляют много тока.
 
 ------------------------------------------ 
 скетч sketch:  v.01 Arduino servo IR EEPROM speed ИК пультом  
 
 ================================ 
 что нам понадобиться. 
 Аппаратное:
 1.servo
 2. любая Arduino
 3. ИК инфракрасный приёмник 
 4. Светодиоды нужны только для визуального контроля за процессом. 
 5. конденсаторы
 --------------------------------
 программное:
 Библиотеки.
 
 1.IRremote, библиотека для работы с ИК сигналом.
 Скачать библиотеку IRremote для ИК пульта
 https://disk.yandex.ru/public/?hash=yNz1au3lm3/yyMHOYtnZ2UGSf19wTvYBZnkxmhW4Xt0%3D
 
 IRremote эта библиотека кажется по новее будет
 http://yadi.sk/d/0jIS1tfw6tbb7
 
 https://github.com/shirriff/Arduino-IRremote
 
 =======================================================
 подробную видео инструкцию выложу здесь
 
 ++++++++++++++++++++++++++++++ 
 Вспомогательные видео обзоры, скетчи.....
 
 скетч arduino чтобы узнать код кнопки ИК пульта
 sketch arduino buttons on the remote to learn the code
 https://disk.yandex.ru/public/?hash=KzLtuC1ljISPaCoXw03D6mbiKea8spktcWL5QKJHGRQ%3D 
 
 4/6 как ? узнать код - кнопки своего ИК пульта
 http://www.youtube.com/watch?v=InZuGntH_wk
 
 
 v.01 Arduino IR Управление с ИК пульта в режиме удержания кнопки
 https://www.youtube.com/watch?v=AjIASUNiWkY
 
 
 Самый дешевый Arduino Uno 5$ Minimal Atmega328 without Arduino Board
 http://www.youtube.com/watch?v=joSc-AT8o5k
 
 v.01 Arduino управление servo любым ИК пультом Control IR + speed
 http://www.youtube.com/watch?v=KYNoWX4yG8s&feature=c4-overview&list=UU7aH7HVqDvwB1xNHfSl-fDw
 
 
 */


#include <EEPROM.h> // подключаем библиотеку EEPROM 
#include <Servo.h> // подключаем библиотеку для Servo
#include <IRremote.h> // подключаем СКАЧЕННУЮ библиотеку IRremote для ИК пульта


int RECV_PIN 2//вход ИК инфракрасного приемника 
IRrecv irrecv(RECV_PIN);
decode_results results;

Servo dimkaservo_1//даём имена servo
Servo dimkaservo_2;

//Pin для светодиодов,светодиоды для визуального контроля за процессом
int ledPin_1 15//PIN 15, на Arduino Uno, Atmega328 (A1)
int ledPin_2 16;
int ledPin_3 17;
int ledPin_4 18;

// 1. для сглаживания пульсирующего ИК сигнала.
// 2. для отключения светодиодов ledPin после пропадания ИК сигнала, без использования delay.
int timer_ledPIN 14//индикация таймера //PIN 14, на Arduino Uno, Atmega328 (A0)

// (спидометр)для визуального контроля яркостью светодиода, за изменением (увеличения или уменьшения) скорости работы servo.
int speed_PWM_ledPin 5;

// переменные для плавного вращения servo,чтоб не использовать delay.
// промежуточная переменная для хранения (увеличенного диапазона от 0 до 30000)значений (увеличения или уменьшения)PWM,
// с последующей конвертации в переменную(val) диапазон градусов поворота доступных для servo.
int a_1;
int a_2;

// переменные для экономии ресурсов ОЗУ EEPROM 
int e_1;
int e_2;

//переменные для конвертации (увеличенного диапазона значений от 0 до 30000) (a_1;),(a_2;),в значения требуемые для поворота servo.
int val_1
int val_2;

//переменная для (увеличения или уменьшения)скорости поворота servo.
int speed_PWM;

//переменная eventTime, для паузы,  вместо delay,будем использовать функцию millis.
unsigned long eventTime=0;

void setup() {              
  
// Serial.begin(9600);
  
irrecv.enableIRIn(); // включить ИК приёмник

  
dimkaservo_1.attach(9); // серво подключён на цифровой вход (pin 9)
  
dimkaservo_2.attach(10); // серво подключён на цифровой вход (pin 10)

  
pinMode(ledPin_1OUTPUT);
  
pinMode(ledPin_2OUTPUT);
  
pinMode(ledPin_3OUTPUT);
  
pinMode(ledPin_4OUTPUT);


  
pinMode(timer_ledPINOUTPUT);

  
pinMode(speed_PWM_ledPinOUTPUT);

  
// после подключения питания или перезагрузки, читаем значение из ячейки №1 ОЗУ 
  // умножаем это значение на *118 и записываем его в переменную a_1
  // делаем это в void setup то бишь только один раз в момент подключения питания 
  
a_1=EEPROM.read(1)*118;
  
a_2=EEPROM.read(2)*118;

  
// также записываем  значение из ячейки №3 ОЗУ, в переменную speed_PWM отвечающую за скорость поворота servo
  
speed_PWM=EEPROM.read(3);
}

void loop() {
  
// По приёму и обработки сигнала от ИК инфракрасного пульта. 
  //Мой опыт работы с ИК пультами выявил разные принципы отправки ИК сигналов кодов у разных производителей техники (пультов) 
  //мне нужно, чтоб система могла работать и в режиме удержания кнопки, для этого нужно постоянно слать ИК код с пульта
  // пока кнопка на пульте нажата.
  //Увы, есть пульты которые шлют код только один раз, в момент нажатия кнопки.  
  // послав 1 код, пульт далее продолжает, слать (в момент удержания кнопки), (назовем его (пустой инфракрасный сигнал).
  // после отпускания кнопки (пустой инфракрасный сигнал) исчезает.
  // Задача такая, после приёма определённого кода кнопки,сразу перехватывать идущий за ним (кодом), (пустой инфракрасный сигнал)
  // и считать его, (пустой инфракрасный сигнал), за код кнопки. 
  //после пропадания (пустого инфракрасного сигнала), будем считать, что код перестал слаться

  // Эта конструкция нужна чтобы. 
  //1.после приёма определённого кода кнопки,перехватывать  (пустой инфракрасный сигнал)
  //2.конвертировать пульсирующий (-) с (ИК) преемника сигнал в постоянный.
  //После появления и пропадания сигнала, состояние сразу не меняется! а ждет  100 миллисекунд.
  //Если 100 миллисекунд не прошло, и поступил еще один ИК сигнал с пульта, тогда таймер заново запускается на 100 миллисекунд.

  //Проще говоря, пока кнопка на ИК пульте нажата timer_ledPIN остается HIGH
  //если кнопка на пульте отпущена, LOW.



  // Читаем состояние ноги у (ИК) преемника. В момент приема данных, у (ИК) 
  //приемника на выходе появляется пульсирующий (-)отрицательный сигнал


  
if (digitalRead(RECV_PIN) == LOW)     
    
eventTime=millis(),digitalWrite(timer_ledPINHIGH);  
  if(
millis()-eventTime>100digitalWrite(timer_ledPINLOW),digitalWrite(ledPin_1LOW),digitalWrite(ledPin_2LOW),
  
digitalWrite(ledPin_3LOW),digitalWrite(ledPin_4LOW);


  
//если ledPin_1) ==, выставляем ограничение для переменной(a_1) до (&& a_1<30000).и Начинаем увеличивать
  // значения переменной(a_1) прибавляем на значение переменной speed_PWM,
  //и также выставляем ограничение при убывании (&& a_1>0)
  
if(digitalRead(ledPin_1) == HIGH && a_1<30000  a_1=a_1+speed_PWM;
  if(
digitalRead(ledPin_2) == HIGH && a_1>0  a_1=a_1-speed_PWM;


  
//читаем значение (a_1) и конвертируем его в значение val_1, то бишь в значение поворота в градусов доступных для servo.
  // правильно было бы конвертировать в, (от 0, до 180) градусов, но мои дешёвые servo доходя до краёв,
  //начинают дребезжать,поэтому я кастрировал их (края) по 10 градусов (10, 170);)
  
val_1 a_1;           
  
val_1 map(val_103000010170);     // scale it to use it with the servo (val_1ue between 10 and 170) 
  
dimkaservo_1.write(val_1);                  // sets the servo position according 

  //делаем тоже самое и для dimkaservo_2
  
if(digitalRead(ledPin_3) == HIGH && a_2<30000  a_2=a_2+speed_PWM;
  if(
digitalRead(ledPin_4) == HIGH && a_2>0  a_2=a_2-speed_PWM;

  
val_2 a_2;           
  
val_2 map(val_203000010170);     
  
dimkaservo_2.write(val_2);  //записываем значения  val_2 в dimkaservo_2     


    // эта конструкция отвечает за запись положения градусов servo в ОЗУ EEPROM. 
  // Можно было бы сделать так if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH)EEPROM.write(1, a_1/118);.
  // В документации на ATMEGA328P-PU указано, количество записи и чтения в ячейку ОЗУ гарантировано не более 100.000 раз,
  // поэтому будем экономить ОЗУ, то бишь записывать не постоянно в (момент движения) изменения градусов servo, 
  //а только тогда, когда servo остановилась.
  //когда кнопка №1 или №2 на ИК пульте нажата if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH)
  // фиксируем это событие в переменную e_1 и записываем в неё =1; (e_1=1;)
  // когда кнопку №1 И №2 отпустили, то бишь servo остановилась //(ledPin_1) == LOW && digitalRead(ledPin_2)== LOW//
  // и && e_1==1 то бишь перед тем как servo остановилась она была включена,
  //записываем в ячейку №1 EEPROM значение переменной a_1.
  // Так как ячейка EEPROM может хранить значения от (0 до 255), а диапазон значений переменной a_1
  //от (1 до 30.000), то перед записью в ячейку №1, делим значение переменной a_1 на 118  //(1, a_1/118)//
  // и меняем значение переменной e_1 на 0 // ,e_1=0;// 

  
if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH)e_1=1;
  if(
digitalRead(ledPin_1) == LOW && digitalRead(ledPin_2)== LOW && e_1==1)EEPROM.write(1a_1/118),e_1=0;

  if(
digitalRead(ledPin_3) == HIGH || digitalRead(ledPin_4)== HIGH)e_2=1;
  if(
digitalRead(ledPin_3) == LOW && digitalRead(ledPin_4)== LOW && e_2==1)EEPROM.write(2a_2/118),e_2=0;

  
//Serial.println(EEPROM.read(1));




  // Эта часть отвечает за приём и обработку ИК кодов
  // здесь считываем коды от ИК пульта



  // У моего пульта при нажатии на одну и ту же кнопку, могут отсылаться два разных (КОДА) сигнала,  чтобы обойти эту проблему
  //я использовал Логический оператор "или" (||) if (results.value == 0x1000809 || results.value == 0xF7283C77
  // Теперь неважно какой код отправлен  с кнопки пульта, первый или второй
  // Если ваша кнопка пульта не страдает раздвоением личности, можете написать так if (results.value == 0x1000809 
  //также мною замечено при использовании разных ИК приемников, частотой 36,или 38, кГц, библиотека IRremote
  // выдает Разные коды.
  //можно сделать 4 "или" (||), чтобы можно было управлять с двух разных ИК пультов

  //ВАЖНО !!! (1000809) это код кнопки №1 - моего (ИК)! (инфракрасного пульта)!, -
  //-у вашего пульта будет другой код, замените на свой!

  
if (irrecv.decode(&results)) {
    if(
digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1000809 || results.value == 0xF7283C77))digitalWrite(ledPin_1HIGH);  
    if(
digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1008889 || results.value == 0x757FB4DF))digitalWrite(ledPin_2HIGH);

    if(
digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1004849 || results.value == 0xB33B4597))digitalWrite(ledPin_3HIGH);  
    if(
digitalRead(timer_ledPIN) == HIGH && (results.value == 0x100C8C9 || results.value == 0x3C03E507))digitalWrite(ledPin_4HIGH);



    
//эта кнопка пульта для (увеличения или уменьшения)скорости поворота servo.
    // начинаем увеличивать скорость на одну позицию speed_PWM++;
    // и ставим ограничение на количество скоростей if (speed_PWM > 51)
    // дойдя до 51 скорости,сбрасываемся на первую скорость > 51)speed_PWM=1;
    // записываем в ячейку №3 EEPROM  значение speed_PWM



    
if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1002829 || results.value == 0xE705551F))
      
speed_PWM=speed_PWM+1,EEPROM.write(3,speed_PWM);
    if (
speed_PWM 51)speed_PWM=1;
    
//Serial.println(EEPROM.read(3));

    //для визуального контроля за состоянием скоростной коробки передач (спидометр),используем светодиод speed_PWM_ledPin
    //(увеличивая или уменьшая)PWM сигнал (analogWrite) "записываем в светодиод" значения от переменной speed_PWM,
    // для контрастности изменений в яркости, умножаем speed_PWM на 5  (speed_PWM*5)

    
analogWrite(speed_PWM_ledPin,speed_PWM*5);
    
//Serial.println(speed_PWM);

    
irrecv.resume(); 
  }


// уникальность этого sketch в том, что не используется ни одного delay();.
// Благодаря этому, значение (плавность поворота servo) высокое. 
// Есть возможность параллельно выполнять в постоянном режиме другие процессы. 


skanch 27.03.2016 21:30

Вложений: 9
Проект получил продолжение - пришли компоненты для планшета ipad mini.
Чехол -ZAGG rugged book.
Беспроводная подзарядка PLESON-C180.
Приемник беспроводной подзарядки.
Комплект магнитов.

Чехол оказался достаточно массивным - толстая мягкая резина, а в середине жесткий пластик.

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

Магниты обычные - тонкие и мощные.

skanch 27.03.2016 21:44

Вложений: 4
В этом механизме управление наклоном планшета в открытом состоянии планирую сделать от потенциометра. Но столкнулся с небольшой проблемой - после выставления угла потенциометром серва некоторое время "дрожит" (у серв это бывает и называется "jitter"). Сначала использовал обычный "переменник", купленный на рынке . С ним "jitter" был очень существенный. Поменял на "импортный" и взял шнурок от USB кабеля с фильтром - "дрожание" есть, но совсем небольшое и по времени пару секунд. Оба "переменника" с угольным напылением резистивного слоя. Решил попробовать кермет. Сегодня приобрел такой, но еще не экспериментировал. Надеюсь это он...

skanch 28.03.2016 22:52

Потенциометр кермет решил проблему- дрожание полностью исчезло.

skanch 03.04.2016 11:40

Вложений: 2
"Слепил" скетч управления сервомашинкой с помощью механического энкодера. Энкодер использовал первый попавшийся- выпаял из платы управления магнитолой. За основу взял скетч с этого ресурса. Алгоритм такой:
1.Нажали кнопку один раз-серва повернулась на максимальный угол (сохраненный в памяти).
1.1.Зашли в режим настройки угла сервы (энкодер).
2.Нажали еще раз-серва вернулась в начальную точку.
Угол сохраняется в памяти (Eeprom) и при следующем включении серва повернется на выставленный угол.
Удивительно, но работает...

PHP код:

#define pinA 3  //Первый PIN Сигнала с энкодера 
#define pinB 4  //Второй PIN Сигнала с энкодера 
#define pinC 10 //PIN кнопки запуска системы
#include <Servo.h>
#include <EEPROM.h>
Servo myservo;   //Название сервомашины 
int servoPin 8//Сервомотор подключен на PIN 8 

int angle//Текущий угол поворота (при запуске программы будет автоматический вставать в указаное положение)
int maxAngle 90//Максимальный угол поворота сервомотора (градусов)
int minAngle 6//Минимальный угол поворота сервомотора (градусов)
int angleStep 2;  //Угол единичного шага (градусов)
int stepSpeed 3//Скорость шага (Время задержки шага)
boolean valA=0//Текущее переменное значение энкодера на выходе энкодера А 
boolean valB=0//Текущее переменное значение энкодера на выходе энкодера В
boolean valC=0//Переменная функции запуска системы
boolean Estate=0//Вспомогательная переменная необходимая для определения направления вращения
boolean pulse 0;  //Импульс шага в любом направлении, не стабилизированный
boolean Dir =0//Переменная направления вращения (Если=1 то влево, если=0 то вправо)
boolean zapret=HIGH//Вспомогательная переменная необходимая для стабилизации импульса шага 
boolean outsig=HIGH//Импульс шага в любом направлении, стабилизированный 
long time;  //Переменная таймера задержки в функции стабилизации
int flag 0// Флаг состояния
int regim 0// Переключалка

void setup()
{
angle EEPROM.read(0);//Считываем из памяти угол поворота сервы
pinMode(pinC,INPUT_PULLUP);  //Цифровой вход С кнопки запуска системы
pinMode(pinA,INPUT_PULLUP);  //Цифровой вход A c энкодера 
pinMode(pinB,INPUT_PULLUP);  //Цифровой вход В c энкодера


void loop()
{
if(
digitalRead(pinC) == LOW && flag == 0)//Если кнопка нажата   
     // и перемення flag равна 0 , то ...  

regim ++;
flag 1;//Это нужно для того что бы с каждым нажатием кнопки 
        //происходило только одно действие 

if(regim 4// Если номер режима превышает требуемого
// то отсчет начинается с 1
regim 1;
}
}
if(
digitalRead(pinC) == HIGH && flag == 1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
{
flag 0;
}

// РЕЖИМ 1: 

if(regim == 1)// Нажали кнопку один раз...
{
   
myservo.attach(servoPin);
 
myservo.write(angle); // Серва повернулась на сохраненный в Eeprom угол
delay(stepSpeed);// Скорость поворота сервы
}
// РЕЖИМ 2: 
if(regim ==)// Нажали кнопку второй раз...
{
  
change_ugol(); // Режим установки наклона с помощью энкодера
 
}
 
// РЕЖИМ 3: 
if(regim == 3)// Нажали кнопку в третий раз...
{
 }
// ничего не происходит...

// РЕЖИМ 4: 
if(regim == 4)// Нажали кнопку в четвертый раз...
{
  
myservo.write(maxAngle); // Серва вернулась в исходное состояние
delay(stepSpeed);// Скорость поворота сервы
 
}
   }

// РЕЖИМ УСТАНОВКИ УГЛА НАКЛОНА С ПОМОЩЬЮ ЭНКОДЕРА
void change_ugol()
{
valA=digitalRead(pinA); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)  
valB=digitalRead(pinB); //Читает и запоминает текущее состояние на выходе энкодера (Выход В)
valC=digitalRead(pinC); //Читает и запоминает текущее состояние кнопки быстрой центровки

//РАСПОЗНАНИЕ ШАГА 
if(valA+valB==HIGH){pulse=1;} //Определяет шаг и дает не стабилизированный импульс шага 
else{pulse=0;}

//СТАБИЛИЗАТОР ИМПУЛЬСА ШАГА
if((pulse==HIGH)&&(zapret==LOW))//Условие работы стабилизатора выходного импульса

time millis();  //Запуск таймера
outsig HIGH//Стабилизированый выходной импульс шага
 

zapret=HIGH;
if(
outsig && (millis() - time) > 1//(2)-Временная длинна выходного импульса
{
  
outsig LOW;//Остановка таймера
  


if(
pulse==LOW)

zapret=LOW//Антидребезг
}
//ОПРЕДЕЛЕНИЕ ВСПОМОГАТЕЛЬНОЙ ПЕРЕМЕННОЙ
//ДЛЯ ОПРЕДЕЛЕНИЯ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
if((valA==LOW)&&(valB==LOW)&&(valA<1)&&(valB<1)) 
{
  
Estate=1;//Вспомогательная переменная для определения направления вращения энкодера на (+) 
  

if((
valA==HIGH)&&(valB==HIGH)&&(valA>0)&&(valB>0))
{
  
Estate=0;//Вспомогательная переменная для определения направления вращения энкодера на (-)
  


//ОПРЕДЕЛЕНИЕ НАПРАВЛЕНИЯ ВРАЩЕНИЯ 
if(((Estate==1)&&(valA==LOW)&&(valB==HIGH))||((Estate==0)&&(valA==HIGH)&&(valB==LOW))) //Условия направления вращения(+)
{
  
Dir=1;//Направление вращения (+)
  
}  
if(((
Estate==1)&&(valA==HIGH)&&(valB==LOW))||((Estate==0)&&(valA==LOW)&&(valB==HIGH))) //Условия направления вращения(-)
{
  
Dir=0;//Направление вращения(-)
  
}  

//ВЫХОДНОЙ СИГНАЛ
if((Dir==1)&&(outsig==HIGH))  //Условие поворота в одну из строн (Направление + стабилизированый сигнал шага)
{
  
angle=angle+angleStep//угол поворота сервомотора меняется по шагово на заданную величину шага 
if (angle maxAngle)
{
  
angle=maxAngle;//Ограничитель угла поворота исполнительного устройства (Рабочий диапозон)
  
}
 }  
if((
Dir==0)&&(outsig==HIGH))  //Все тоже самое как для предидущей функции но с !инверсией
{
  
angle=angle-angleStep//угол поворота сервомотора меняется по шагово на заданную величину шага 
if (angle minAngle)
{
  
angle minAngle//Ограничитель угла поворота исполнительного устройства (Рабочий диапозон) 
  
}
 } 
{
  
myservo.write(angle);  //Входной сигнал на сервомотор
delay(stepSpeed);//Скорость шага (время задержки шага)
}  
EEPROM.write(0angle); //Сохраним в памяти угол поворота



skanch 03.04.2016 19:10

Нашел интересную библиотеку для обработки нажатий кнопок в Ардуино. Попробовал "привязать" к своему энкодеру - получилось не плохо. Можно назначить сколько угодно нажатий (одно нажатие, два, короткие, длинные) кнопки энкодера для запуска чего-либо... Это пример скетча для управления одной сервой (немного подправил).

PHP код:

#define pinA 3  //Первый PIN Сигнала с энкодера 
#define pinB 4  //Второй PIN Сигнала с энкодера 
#include "ClickButton.h"
#include <Servo.h>
#include <EEPROM.h>
Servo myservo;   //Название сервомашины 
int servoPin 8//Сервомотор подключен на PIN 8 
int angle//Текущий угол поворота (при запуске программы будет автоматический вставать в указаное положение)
int maxAngle 90;   //Максимальный угол поворота сервомотора (градусов)
int minAngle =45//Минимальный угол поворота сервомотора (градусов)
int angleStep 2;  //Угол единичного шага (градусов)
int stepSpeed 2//Скорость шага (Время задержки шага)
boolean valA=0//Текущее переменное значение энкодера на выходе энкодера А 
boolean valB=0//Текущее переменное значение энкодера на выходе энкодера В
boolean Estate=0//Вспомогательная переменная необходимая для определения направления вращения
boolean pulse 0;  //Импульс шага в любом направлении, не стабилизированный
boolean Dir =0//Переменная направления вращения (Если=1 то влево, если=0 то вправо)
boolean zapret=HIGH//Вспомогательная переменная необходимая для стабилизации импульса шага 
boolean outsig=HIGH//Импульс шага в любом направлении, стабилизированный 
long time;  //Переменная таймера задержки в функции стабилизации
// Светодиод
const int ledPin 13;
int ledState 0;
// Кнопка
const int buttonPin1 10;
ClickButton button1(buttonPin1LOWCLICKBTN_PULLUP);
// Назначаем функцию переключателя
int LEDfunction 0;

void setup()
{
  
angle EEPROM.read(0);//Считываем из памяти угол поворота сервы
  
pinMode(ledPin,OUTPUT);  
  
button1.maxPresses     9;    // Количество программируемых нажатий для кнопок
  
button1.debounceTime   20;   // Таймер дребезга в мс
  
button1.multiclickTime 350;  // Пауза между нажатиями кнопки
  
button1.heldDownTime   1000// длительность нажатия и удержания кнопки
  
pinMode(pinA,INPUT_PULLUP);  //Цифровой вход A c энкодера 
  
pinMode(pinB,INPUT_PULLUP);  //Цифровой вход В c энкодера
 
}
void loop()
{
 
// Обновлям состояние кнопки
  
button1.Update();
  
  if (
button1.click != 0)
  
  
LEDfunction button1.click;
  if(
button1.click == 1
  
ledState = !ledState;
  
//Два коротких нажатия
  
if(LEDfunction == 2
   {
  
myservo.attach(servoPin);
  
myservo.write(maxAngle); // Серва вернулась в исходное состояние
  
delay(stepSpeed);// Скорость поворота сервы
   
}
  
 
  
// три коротких нажатия
  
if(LEDfunction == 3
  {
  
myservo.attach(servoPin);
  
change_ugol(); // Режим установки наклона с помощью энкодера
  
}
  

  
// длительное однократное нажатие (более 1 секунды)
  
if(LEDfunction == -1)
  {
  
myservo.attach(servoPin);
  
myservo.write(angle); // Серва повернулась на сохраненный в Eeprom угол
  
delay(stepSpeed);// Скорость поворота сервы
  
}
  

  
// одно короткое + одно длительное нажатие (более 1 секунды)
  
if(LEDfunction == -2)
   {}
//можно что-то вставить

   
// два коротких + одно длительное  нажатие (более 1 секунды)
  
if(LEDfunction == -3
  {}
//можно что-то вставить
// update the LED
  
digitalWrite(ledPin,ledState);
  }

  
//*********** РЕЖИМ УСТАНОВКИ УГЛА НАКЛОНА С ПОМОЩЬЮ ЭНКОДЕРА **************//

void change_ugol()
{
valA=digitalRead(pinA); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)  
valB=digitalRead(pinB); //Читает и запоминает текущее состояние на выходе энкодера (Выход В)

//РАСПОЗНАНИЕ ШАГА 
if(valA+valB==HIGH){pulse=1;} //Определяет шаг и дает не стабилизированный импульс шага 
else{pulse=0;}

//СТАБИЛИЗАТОР ИМПУЛЬСА ШАГА
if((pulse==HIGH)&&(zapret==LOW))//Условие работы стабилизатора выходного импульса

time millis();  //Запуск таймера
outsig HIGH//Стабилизированый выходной импульс шага
 

zapret=HIGH;
if(
outsig && (millis() - time) > 1//(2)-Временная длинна выходного импульса
{
  
outsig LOW;//Остановка таймера
  

if(
pulse==LOW)

zapret=LOW//Антидребезг
}
//ОПРЕДЕЛЕНИЕ ВСПОМОГАТЕЛЬНОЙ ПЕРЕМЕННОЙ
//ДЛЯ ОПРЕДЕЛЕНИЯ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
if((valA==LOW)&&(valB==LOW)&&(valA<1)&&(valB<1)) 
{
  
Estate=1;//Вспомогательная переменная для определения направления вращения энкодера на (+) 
  

if((
valA==HIGH)&&(valB==HIGH)&&(valA>0)&&(valB>0))
{
  
Estate=0;//Вспомогательная переменная для определения направления вращения энкодера на (-)
  

//ОПРЕДЕЛЕНИЕ НАПРАВЛЕНИЯ ВРАЩЕНИЯ 
if(((Estate==1)&&(valA==LOW)&&(valB==HIGH))||((Estate==0)&&(valA==HIGH)&&(valB==LOW))) //Условия направления вращения(+)
{
  
Dir=1;//Направление вращения (+)
  
}  
if(((
Estate==1)&&(valA==HIGH)&&(valB==LOW))||((Estate==0)&&(valA==LOW)&&(valB==HIGH))) //Условия направления вращения(-)
{
  
Dir=0;//Направление вращения(-)
  
}  
//ВЫХОДНОЙ СИГНАЛ
if((Dir==1)&&(outsig==HIGH))  //Условие поворота в одну из строн (Направление + стабилизированый сигнал шага)
{
  
angle=angle+angleStep//угол поворота сервомотора меняется по шагово на заданную величину шага 
if (angle maxAngle)
{
  
angle=maxAngle;//Ограничитель угла поворота исполнительного устройства (Рабочий диапозон)
  
}
 }  
if((
Dir==0)&&(outsig==HIGH))  //Все тоже самое как для предидущей функции но с !инверсией
{
  
angle=angle-angleStep//угол поворота сервомотора меняется по шагово на заданную величину шага 
if (angle minAngle)
{
  
angle minAngle//Ограничитель угла поворота исполнительного устройства (Рабочий диапозон) 
  
}
 } 
{
  
myservo.write(angle);  //Входной сигнал на сервомотор
delay(stepSpeed);//Скорость шага (время задержки шага)
}  
EEPROM.write(0angle); //Сохраним в памяти угол поворота



skanch 03.05.2016 13:09

Спрошу в своей теме...
Нужен компактный осевой мотор-редуктор . Диаметр корпуса не должен превышать 10 мм. Редуктор желателен планетарный.
Скорость: 4-10 оборотов в минуту. Усилие на валу: от 1500 г/см. Длинна всего мотора до 100 мм. Нужен для изготовления электропривода декоративной крышки механизма перемещения монитора (принцип, как на видео). Все время пользовался Shayang Ye IG-12GM DC с диаметром корпуса 12 мм. Но сейчас нужен именно не более 10 мм и со схожими параметрами с IG-12GM. Возможно, кто-то из заглянувших в мою тему сможет подсказать - где приобрести такой.

skanch 08.05.2016 23:55

Вложений: 4
Ломаем (модернизируем) дальше сервомотор...
Из-за того, что оси валов пересекаются под углом в 90 градусов я в своих механизмах использую коническую передачу. Коническая шестерня, та что на серве, располагается консольно. При этом, вследствие повышенной деформации консольного вала (один из побочных эффектов конической передачи), увеличивается неравномерность распределения нагрузки по ширине зубчатого венца и как следствие - выход одного подшипника сервомотора из строя - того, что ближе и меньше по размеру на фото. Появляется значительный люфт у "подиума" в открытом состоянии. Подшипник, прямо скажу - слабоват для заявленного усилия в 53кг/см. Подобрать что-то более надежное для замены вряд ли получится. Думаю сделать небольшой промежуточный редуктор с более мощными подшипниками и перенести осевую нагрузку с подшипника сервы.
Позже поделюсь результатом.

skanch 20.05.2016 21:30

Вложений: 5
Вот собственно и редуктор...

skanch 25.05.2016 18:39

Вложений: 2
Нашел миниатюрный мотор с редуктором. Правда не с планетарным... и немного не те размеры, но думаю, что подойдет.
Практически бесшумный. При питании от 5 вольт скорость примерно 6-7 оборотов в минуту и ток при нагрузке в 2 кг./см. - 18-20 мА. Заявленное усилие на валу - 3 кг./см.(похоже на правду). Габариты 12 мм. Х 10 мм. Х 40 мм. Диаметр вала - 3 мм. Ну и до кучи прикупил подшипники... Буду пытаться сделать "управляемую" крышку для корпуса механизма.

skanch 25.05.2016 19:39

Вложений: 2
Сделал новую плату управления под размер нового редуктора. Весь механизм увеличился в ширину - это не критично, место установки позволяет. Главное размер в высоту остается 50 мм.

skanch 25.05.2016 20:12

Вложений: 3
Очередная примерка на заготовке каретки.

skanch 31.05.2016 18:18

Вложений: 4
Купил неплохой, на мой взгляд, мотор с червячным редуктором и с энкодером. Енкодер построен на датчике Холла .
Буду пытаться программно "прикрутить" к своим поделкам.

skanch 26.06.2016 19:58

Вложений: 1
Цитата:

Сообщение от skanch (Сообщение 345990)
Это "пациент".

Так выглядит сейчас.


Часовой пояс GMT +4, время: 05:52.

Работает на vBulletin® версия 3.8.4.
Copyright ©2000 - 2023, Jelsoft Enterprises Ltd.
Перевод: zCarot