Электрическая фокусировочная схема для дешевого телескопа TAPOK
- Войдите на сайт для отправки комментариев
1. Идея
Есть у меня значит телескоп, дешевый и достаточно ущербный. При наведении на обожаемое тело (Небесное естественно) и попытке сфокусироваться вручную, при любом касании и приложении силы жутко начинает вибрировать на штативе, и вибрация эта очень раздражает. И пришла мне в голову идея сделать полностью электрически управляемый телескоп. Хотел я купить шаговые двигатели и винтовые направляющие. Изначально хотел сделать на NRF24, чтобы даже провод не мешал столь "нежной" аппаратуре, но узнал что одна из нрфок в кз и от идеи пришлось отказаться. Затем пришла идея сделать приложение и связь по wi-fi с ESP 8266, но после подключения в ней застрял мой видавший всякое ЮСБ кабель и при попытке его вытащить была допущена фатальная ошибка - я коснулся чего-то на плате своими красными и потными от праведного гнева руками. ESP этого не пережила. Да здравствует ESP!
После всех этих неудач я понял:
1. Сейчас у меня нет инструмента для этого, даже банальной дрели для крепления шаговиков не говоря о сварочном аппарате для приваривания того что необходимо приварить.
2. Покупка трёх шаговиков и направляющих со всем необходимым обвесом обойдется минимум в 30-40 Баксов, что является половиной цены такого нового телескопа, при том что сам телескоп в бородатые времена обошелся мне в 15 вечнозеленых, да ещё и доставку ждать под НГ придется до марта.
После этих размышлений решил действовать. Не так масштабно, ведь это мой первый проект доведенный до конца в принципе. Максимальных колхоз, не щадя ничего на своём пути. Поэтому проект и называется TAPOK, ведь он собран в корпусе роутера TP-LINK и дыры под энкодер и светодиод пришлись прямо на символы -LIN. Так и образовалось культовое название этого ужасного и одновременно прекрасного проекта - TPOK (В режиссерской версии - гордый ТАПОК)
2. Реализация
На этом пункте хочется плакать. Нет, я серьезно. Мне пришлось ездить за двумя метрами медной проволоки для полуторасантиметровой тяги сервопривода, так как вырывать её из электрощитка мне запретили родственники. Корпус, как я уже сказал - обломки древнего роутера. Сердце - Arduino Leonardo (хотел micro, pro micro, nano, esp8266, но все они оказались мертвыми, возможно в том месте где их держал соплеклей им не понравилось, а может быть они даже не проработали и 1 дня, хотя не помню чтоб они вообще работали). Мышца - невероятно мощная дребезжащая синяя сервомашинка на пластиковых шестернях - невероятный зверь.
При разработке проекта, сидя с паяльником и полусгоревшим, оставленным судьбой на вырезку пластика жалом, я решил сделать коробку со световой индикацией и тремя режимами (три устройства ввода которые были у меня), а именно:
1. Красные, знакомые всем, сенсорные кнопки
2. Энкодер на круглой плате
3. Ползунковый потенциометр (далее в моей терминологии слайдер)
После вырезки получилось то, что я даже постеснялся сфотографировать.
После мучений с пайкой ножек элементов и моих обрезков проводов, к которым не лип припой я поставил всё на свои места, залил суперклеем и вывел наружу три контакта под сервопривод. Получилось что-то подобное:
Естественно я удлинил провода сервопривода проводом от зарядки с металлическим экранированием для более удобного контроля и размещения пульта. По фото мы не видим, но справа и слева в центре половин расположены сенсорные кнопки, которые, к моему счастью, не фонят ложными срабатываниями и чувствительны лишь при полном осознанном поднесении пальца к поверхности пластика.
3. Схема
Собирать всё в моих кустарных условиях без схемы было невозможно, поэтому набросал вот это
4. Код
С кодом были сложности, так как первый ардуино проект - ответственнее и сложнее чем первый раз с девушкой, но как и во втором случае всё вышло комом. Я не знаю где, но уверен что этот код можно было написать в 10 раз компактнее и производительней, но как сумел так и написал, главное что работает без перебоев. Использовал библиотеку GyverEncoder - не знаю как здесь к ней относятся, но для меня - это золото ацтеков, невероятно удобно использовать, особенно с дабл кликами и быстрым вращением энкодера
#define CLK 4 //(S2) #define DT 5 //(S1) #include "GyverEncoder.h" #include <Servo.h> //рекомендуется использовать другие библиотеки servo, так как эта ломает ШИМ на 9 и 10 пине если вы работаете НЕ на Arduino Mega Servo myservo; Encoder enc1(CLK, DT); int plusButton = 11; //Кнопка увеличения значения переменной a int minusButton = 12; //Кнопка уменьшения значения переменной a int SwitchButt = 13; //Физическая кнопка переключения режимов (В данном коде это кнопка энкодера), можно использовать функции библиотеки GyverEncoder.h и расширить функционал кнопки на ваше усмотрение, такие как isSingle() или isDouble() int ServoPin = 3; //Сервопривод int EncLED = 0; //Светодиод состояния int ColourRP = 8; //Пины подключения анодов RGB-светодиода с общим катодом, при работе с ШИМ НЕ на Arduino Mega и использовании Servo.h 9 и 10 пины использовать не получится int ColourGP = 9; //^ int ColourBP = 10;//| bool plusB = 0; //переменная состояния кнопки + bool minusB = 0; //переменная состояния кнопки - int a = 90; //начальный угол a int Mode = 0; //Переменная режима работы по умолчанию (0-2) 0-сенсорными кнопками, 1-энкодер, 2-Слайдер-потенциометр int ModeLED = 5; //Дополнительная контрольная переменная для предотвращения бессмысленных прокрутов IF в строках 52-69. Указывать любое значение, переменная будет автоматически установлена на необходимое программе значение int slideValue = 500; //Начальное значение инвертированной переменной положения слайдера. Не имеет смысла, но лучше поставить 500 для минимизации рывков сервопривода при включении int ModeCount = 3; //Количество режимов (3 = режимы 0,1,2; 4 = режимы 0,1,2,3; и тд) bool SliderMode = true; //Инвертирование ползункового потенциометра (Слайдера) - false-без инверсии, true-инверсия включена bool EncoderMode = false; //Инвертирование направления вращения энкодера для изменения направления вращения. Также можно поменять значения местами в 1 и 2 строках bool SwitchButtInv = false; //Если кнопка SwitchButt при нажатии выдает сигнал 0-пишем false, если при нажатии выдаёт сигнал 1-пишем true void setup() { ModeCount = ModeCount-1; myservo.attach(ServoPin); Serial.begin(9600); myservo.write(a); pinMode(plusButton, INPUT); //кнопки 4-Плюс, 2-Минус pinMode(minusButton, INPUT); pinMode(SwitchButt, INPUT_PULLUP); //Подтягиваем для избежания дребезга на кнопке. При использовании логических 1/0 сенсорных и тд кнопок можно оставить просто INPUT pinMode(EncLED, OUTPUT); pinMode(ColourRP, OUTPUT); pinMode(ColourGP, OUTPUT); pinMode(ColourBP, OUTPUT); digitalWrite(ColourRP, HIGH); //задаём высокий сигнал на аноды светодиодов для предотвращения беспорядочного включения всевозможных цветов digitalWrite(ColourGP, HIGH); digitalWrite(ColourBP, HIGH); digitalWrite(EncLED, HIGH); enc1.setType(TYPE2); //Тип энкодера. При некорректной работе энкодера поменять TYPE2 на TYPE1 и наоборот } void loop() { digitalRead(SwitchButt); //Считываем значения кнопки переключения режимов, можно добавить и сконфигурировать любое количество режимов if (digitalRead(SwitchButt) == SwitchButtInv && Mode < ModeCount) { //При нажатой кнопке SwitchButt и режиме от 0 до 1 в оригинале или от 0 до (ModeCount-2) повышаем режим на 1 Mode = Mode + 1; delay(200); //время убрать палец с кнопки, не влияет на скорость выполнения программы при отжатой кнопке } else if (digitalRead(SwitchButt) == SwitchButtInv && Mode == ModeCount) { //При нажатой кнопке SwitchButt и максимальном режиме перескакиваем на режим 0 Mode = 0; delay(200); //время убрать палец с кнопки, не влияет на скорость выполнения программы при отжатой кнопке } if (Mode == 0 && ModeLED != Mode) { //Цветовые отображения режимов. Можно использовать analogWrite, на 9 и 10 пинах Леонардо это не сработало. Спасибо нашей любимой Servo.h, рекомендуется использовать другие пины для ШИМ RGB. digitalWrite(ColourRP, LOW); // При использовании RGB светодиода с общим АНОДОМ можно получить необходимый цвет указав только один выход как HIGH, а остальные указать как LOW digitalWrite(ColourGP, HIGH); digitalWrite(ColourBP, HIGH); ModeLED = Mode; } if (Mode == 1 && ModeLED != Mode) { //Алгоритм проверяет значения Mode и ModeLed, и если переменная ModeLED не равна Mode, прогоняет изменение цвета digitalWrite(ColourRP, HIGH); //После изменения цвета и смены ModeLED на необходимый, алгоритм игнорируется полностью до следующего расхождения в значениях Mode и ModeLED т.е до смены режима работы digitalWrite(ColourGP, LOW); digitalWrite(ColourBP, HIGH); ModeLED = Mode; } if (Mode == 2 && ModeLED != Mode) { //Можно добавить множество вариантов светового отображения режимов работы при их количестве > 3 комбинируя цвета или используя analogWrite digitalWrite(ColourRP, HIGH); digitalWrite(ColourGP, HIGH); digitalWrite(ColourBP, LOW); ModeLED = Mode; } Serial.println(Mode); //Дебаг информация для проверки работы режимов if (Mode == 0) { //режим сенсорных кнопок + и - digitalRead(plusButton); if (digitalRead(plusButton) == 1) { //Если Нажата кнопка + и значение угла < 180 добавляем 2 градуса, отправляем на сервомашинку digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); delay(60); if (a < 180) { a = a + 2; } myservo.write(a); } else if (digitalRead(minusButton) == 1) { //Если Нажата кнопка - и значение угла > 0 добавляем 2 градуса, отправляем на сервомашинку digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); delay(60); if (a > 0) { a = a - 2; myservo.write(a); } } } if (Mode == 1) { //Режим управления энкодером. При вращении на 1 шаг переменная увеличивается/уменьшается на 1. Направление вращения настраивается переменной EncoderMode if(EncoderMode == 0){ //Инверсия отключена enc1.tick(); //Опрашиваем энкодер if (enc1.isRight() && a < 180) { //При повороте по часовой стрелке прибавляем +1 к переменной если она не равна 180 a++; myservo.write(a); digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); } else if (enc1.isLeft() && a > 0) { //При повороте против часовой стрелки вычитаем 1 от переменной если она не равна 0 a--; myservo.write(a); digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); } } else if(EncoderMode == 1){ //Инверсия включена enc1.tick(); //Опрашиваем энкодер if (enc1.isRight() && a > 0) { //При повороте по часовой стрелке вычитаем 1 от переменной если она не равна 0 a = a - 1; myservo.write(a); digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); delay(10); } if (enc1.isLeft() && a < 180) { //При повороте против часовой стрелки прибавляем +1 к переменной если она не равна 180 a = a + 1; myservo.write(a); digitalWrite(EncLED, LOW); //Мигаем светодиодом состояния delay(5); digitalWrite(EncLED, HIGH); delay(10); } } } if (Mode == 2) { //Режим слайдера analogRead(A5); //Считываем значение потенциометра if (SliderMode == 1) { //Инверсия включена slideValue = 1023 - analogRead(A5); //Инвертируем значение и записываем в переменную } else if (SliderMode == 0) { //Инверсия выключена slideValue = analogRead(A5); //оставляем значение как есть и записываем в переменную } Serial.println(slideValue); //Выводим дебаг информацию a=map(slideValue,0,1023,0,180); //Преобразуем значения 0-1023 в понятные сервоприводу 0-180 myservo.write(a); } Serial.println(a); }
Удивительно, но добавление любого 10мс delay для стабильности в конец или середину void loop приводит к полной дисфункции энкодера. Возможно кто-то знает с чем связано?
5. Итог
Получилось скомкано, возникали фантомные отвалы энкодера, которые решались перебором кода (сами по себе), ну а никто и не говорил что первый раз будет приятно, пришлось серьезно порвать заднее технологическое отверстие что-бы добиться желаемого результата - бесперебойной работы
Шедеврально.
Отправлено в 00.45, то есть ТС писал это под бой курантов, бросив жену и детей у праздничного стола.
Лучше б шампусика выпил:)
По моему часовому поясу это было 23:45, да и молод я ещё для жены, да и с мелкой сестрой не особо попразднуешь) 10 минут посидели и спать
Спустя несколько попыток использования я сломал клей, крепивший качалку к оси фокусировочного механизма, теперь можно настроить фокус вручную, а сервомашинка всё ещё позволяет делать точную подгонку без вибраций, так мне даже больше нравится, так как ручной "черновой" фокус также важен