코동(코스트코 동생 망원경 - 최초의 망원경은 반사망원경?)은 가성비의 NEXSTAR 90GT 굴절식 천체 망원경을 가리키는 말입니다. 지금은 중고로밖에 구할 수 없습니다.
왜 전동 포커서를 DIY하게 되었나?
- 보통 추운 날씨에 관측을 하게 됩니다.
- 저는 기관지가 약해서 마스크를 꼭 쓰는데, 안경까지 쓰다보면 김이 서리다보면 초점 맞추기가 어려워집니다.
- 그리고 워낙 배율이 높은 상태로 망원경을 조작하다보면 조금만 건드려도 대상물이 시야에서 사라집니다.
- 초점을 맞추려면 망원경을 건드리지 않을 수가 없겠죠?
- 그래서, 전동포커서가 있으면 좋겠다는 생각을 하게 됩니다.
물론, 항상 선배님들이 존재하고 찾아보면 자작한 분도 있고, 공동구매한 분들도 있는데 지금와서 구하기는 어려워 보였습니다.
[1차 프로토타입]
1) 모터
- 생각보다 10rpm 모터 찾기가 어려웠습니다. 결국 아마존에서 Greartisan 12V 10rpm 모터를 구입했습니다. Aliexpress에서도 하나 샀지만, 설이 끼면서 배송도 너무 느렸고 빠르게 도착한 아마존 모터가 워낙 튼튼하고 강력해서 따로 테스트는 안 했습니다.
- 10rpm을 고른 이유는 선배님들의 가르침으로,,, 참고: https://m.blog.naver.com/taifight/220801984510 위에 링크한 동작 영상을 보시다시피, 10rpm정도면 적당하다는 느낌이 듭니다.
2) 타이밍 벨트
- 모터 찾기만큼 어려웠습니다.
- https://www.aliexpress.com/item/33005589716.html?spm=a2g0o.order_list.0.0.21ef18020OZmtK 에서 6mm-20T, 10mm-40T를 선택했는데, 코동의 초점 휠을 빼낸 후 재보면 8mm가 조금 넘는 정도이지만 10mm로 구입했습니다. 대신 부족한 부분은 뭔가로 메꾸어야겠지요.
3) 아두이노 프로 미니 3.3V
- 아두이노 블루투스 모듈 HC-06과 통신할 때를 위해 3.3V로 사야 편안합니다. 5V로 사면 레벨컨버터나 저항을 달아야 할 거예요.
4) 아두이노 블루투스 모듈 HC-06
- BLE 버전도 있지만, 오래되어도 단순 무식한 것이 간단합니다. Arduino bluetooth controller앱을 Play 스토어에서 받고 나서 조이스틱 버튼마다 명령어 글자를 매핑해 줍니다.
- 좌측: L, 상향: U, 우측: R, 하향: D
- 좌우측 방향은 1초간, 위아래 방향은 4초간 모터를 구동해 보았습니다.
5) L298N 모터 드라이버
- 12V를 넣고 모터 제어 12V와 아두이노 프로 미니 구동용 5V전원을 공급해 줍니다. 구입한 아두이노 프로 미니는 3.3V버전이므로 VCC에 연결하면 안되고, 5V선은 RAW핀에 연결해야겠습니다.
6) USB to 12V 레벨업 컨버터 700mA
- 20000mA짜리 외장 배터리로부터 12V를 공급하면 되겠습니다.
7) 아두이노 모터 구동 테스트 코드
#include <SoftwareSerial.h>
int motor_1 = 10;
int motor_2 = 9;
int motor_latest = 0;
SoftwareSerial BTSerial(2,3);
void setup() {
// put your setup code here, to run once:
pinMode(motor_1, OUTPUT);
pinMode(motor_2, OUTPUT);
Serial.begin(9600);
BTSerial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
byte ch;
if (BTSerial.available()) {
ch = BTSerial.read();
if (ch == 'L' || ch == 'U') {
analogWrite(motor_1, 255);
digitalWrite(motor_2, 0);
motor_latest = 1;
} else if(ch == 'R' || ch == 'D') {
digitalWrite(motor_1, 0);
analogWrite(motor_2, 128);
motor_latest = 2;
}
}
if (motor_latest == 1){
delay(1000);
if (ch == 'U') delay(4000);
analogWrite(motor_1, 0);
motor_latest = 0;
} else if (motor_latest == 2){
delay(1000);
if (ch == 'D') delay(4000);
analogWrite(motor_2, 0);
motor_latest = 0;
}
}
[2차 프로토타입]
종이상자로 쓰기는 곤란하고 3D 프린팅을 하거나 오토캐드로 설계해서 제작해야 하는데,,, 일단 몇 천원으로 막아보았습니다.
- CCTV 각도기 - 높이 50mm짜리인데 사실 49mm정도가 필요하여 나사를 풀고 조금 기울여서 사용합니다.
- 케이블 타이 긴 것 - 경통에 각도기를 고정하는 용도로 사용
- 투명 양면 매직 접착 테이프 - 두께 2mm 정도로 모터와 각도기, 각도기와 망원경 경통 사이에 미끄러지지 않는 용도로 사용, PCB 보드 고정용으로 사용
- 일단 페어링이 되면, 망원경 경통 제어를 위해 L, R, U, D의 4가지 글자를 보내면 되므로, 위 링크에 있는 Python 프로그램을 그대로 이용해도 됩니다.
- 키보드로 대문자 치기 그러니까, 소켓으로 보낼 때 msg.upper()로 바꿔치기 하면 l, r, u, d를 타이핑해도 대문자로 바꾸어져서 나가겠지요.
- 또한, 경통을 많이 줌인/줌아웃하려면 여러 번 보내야 하는데, 이 때에는 LLLLLLL, RRRRRR 과 같이 여러 번 타이핑해서 Enter를 눌러도 됩니다. 다만, 모터가 회전할 때 힘이 세므로 최대 줌인, 줌아웃을 한 경우 코동 가대가 고장날 우려가 있으니 주의해야 됩니다. 현실에서는 원격으로는 미세 조정하는 정도라서 그럴 일은 없겠지만...
[3차 프로토타입]
기존의 전동포커서 장비는
- 아두이노 블루투스 모듈이 시리얼통신으로 값을 넘겨주면 아두이노 보드에서 L298N 모터드라이버를 통해 조절하는 방식이었습니다.
- 스마트폰이나 라즈베리파이에서 블루투스 모듈로 통신하여 제어하는 것인데, 고장나서 잘 작동이 안되었습니다.
이전 버전의 전동 포커서가 작동하는 모습은 다음과 같습니다. 사실 이번에는 적외선 리모콘으로 제어하게 되었고, 연결된 회로만 더 단순화되었을 뿐 작동 메카니즘은 동일합니다.
새로운 전동포커서 장비는
- 라즈베리파이에 적외선 리모콘 수신부를 추가하고,
- 리모콘으로 제어하면 라즈베리파이의 GPIO를 이용하여 L298N 모터 드라이버를 직접 제어하는 것입니다.
- 이로써 아두이노 보드와 아두이노 블루투스 모듈을 없앨 수 있어서 간단해졌고, 별도의 적외선 리모콘으로 편리하게 제어할 수 있게 되었습니다.
작업하면서 참조한 글들은 다음과 같습니다. 1번이 의외로 가장 난관이었습니다. 2번도 어려울 뻔 했지만 digikey.kr에서 정리해 준 글을 보고 바로 작동이 되었습니다.
- 라즈베리파이에서 리모콘을 설정 - 라즈베리파이 LIRC(리모컨 송수신) 설정 #2 – nakwonelec 참조
- 리모콘 키를 돌아가면서 하나씩 입력을 하는데 입력할 때마다 . 이 표시가 됩니다. 이게 너무 길게 눌러도 안되고 너무 짧게 눌러도 안된다는 설명이 있는데 대충 하나~둘~셋 한 후 다음 키를 연달아 누르면 됩니다. 문제는 첫 줄 입력 후 Got Gap이 어쩌구 하면서 오류처럼 보이는데, 여기에 굴하지 말고 영어로 표시되는 메시지를 잘 보면서 또 한번 리모콘 키를 골고루 바꿔가면서 같은 패턴으로 눌러 주다보면, 드디어 키에 이름을 하나씩 지정한 후 입력하게 되는 단계에 이르릅니다.
- 위 링크의 글을 보기 전에 개인적으로는 LIRC: irrecord wont record, (Buster), mode2 works - Raspberry Pi Stack Exchange 라는 글을 보고, Answer에 있는 패치도 (버전이 달라서 수동으로) 파일을 편집해서 해봤지만 별 차이는 없었습니다.
- 또 한가지, 출처는 기록을 안했지만 1번에서 만든 conf파일에 다음 2개의 줄을 추가해 주었습니다.(저의 경우에는 /etc/lirc/lircd.conf.d/yurobot.lircd.conf에 아래 내용을 추가)
- min_repeat 1
- suppress_repeat 2
- Python으로 리모콘 값 읽기 - How to Send and Receive IR Signals with a Raspberry Pi (digikey.kr) 참조
- Python으로 L298N 모터 드라이버 제어하기 - 7. 라즈베리파이 DC 모터 제어하기 1 (tistory.com) 참조
결과적으로 위 2번의 소스를 바탕으로 3번의 소스를 대충 조합하면 원하는 동작을 얻을 수 있었습니다.
# This script is based on the following script: https://github.com/akkana/scripts/blob/master/rpi/pyirw.py
# It opens a socket connection to the lirc daemon and parses the commands that the daemon receives
# It then checks whether a specific command was received and generates output accordingly
import os
import socket
from gpiozero import Motor
import time
import queue
import threading
import serial
from tendo import singleton
me = singleton.SingleInstance()
SOCKPATH = "/var/run/lirc/lircd"
sock = None
motor = Motor(forward=21, backward=20)
port = "/dev/ttyUSB0"
baud = 9600
queueKey = queue.Queue()
# Establish a socket connection to the lirc daemon
def init_irw():
global sock
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(SOCKPATH)
print ("Press 'E' of IrDA remocon or Ctrl-C to exit program.")
print ("Press 'C' for shutdown of RPi, Press 'D' to reboot RPi.")
print ("To adjust rotation rate, use '0'(down to 2) and 'F'(up to 7) key.")
# parse the output from the daemon socket
def getKey():
while True:
data = sock.recv(128)
data = data.strip()
if (len(data) > 0):
words = data.split()
queueKey.put(words)
def readthread(ser):
while True:
if (ser.inWaiting() > 0):
data_str = ser.read(ser.inWaiting()).decode('ascii')
# print(data_str, end='')
def sendslewcommand(ser, azm, positive, rate):
if azm:
if positive:
data = chr(80) + chr(2) + chr(16) + chr(36) + chr(rate) + chr(0) + chr(0) + chr(0)
else:
data = chr(80) + chr(2) + chr(16) + chr(37) + chr(rate) + chr(0) + chr(0) + chr(0)
else:
if positive:
data = chr(80) + chr(2) + chr(17) + chr(36) + chr(rate) + chr(0) + chr(0) + chr(0)
else:
data = chr(80) + chr(2) + chr(17) + chr(37) + chr(rate) + chr(0) + chr(0) + chr(0)
data = bytes(data,'ascii')
ser.write(data)
time.sleep(0.1)
def controlNexstar(event):
rate = 7
last_azm = True
while True:
words = queueKey.get()
key = words[2].decode()
repeat = words[1].decode()
if (key == "KEY_E"):
break
elif (key == "KEY_D"):
os.system('sudo reboot')
elif (key == "KEY_C"):
os.system('sudo shutdown -h now')
elif (key == "KEY_LEFT"):
motor.forward()
event.wait(0.05)
motor.stop()
elif (key == "KEY_RIGHT"):
motor.backward()
event.wait(0.05)
motor.stop()
elif (key == "KEY_UP"):
motor.forward()
elif (key == "KEY_DOWN"):
motor.backward()
elif (key == "KEY_OK"):
motor.stop()
elif (key == "KEY_NUMERIC_4"):
sendslewcommand(ser, True, False, rate)
last_azm = True
elif (key == "KEY_NUMERIC_6"):
sendslewcommand(ser, True, True, rate)
last_azm = True
elif (key == "KEY_NUMERIC_2"):
sendslewcommand(ser, False, True, rate)
last_azm = False
elif (key == "KEY_NUMERIC_8"):
sendslewcommand(ser, False, False, rate)
last_azm = False
elif (key == "KEY_NUMERIC_5"):
if last_azm:
sendslewcommand(ser, True, True, 0)
else:
sendslewcommand(ser, False, True, 0)
rate = 7
elif (key == "KEY_NUMERIC_0"):
rate = rate - 1
if (rate < 2):
rate = 2
elif (key == "KEY_F"):
rate = rate + 1
if (rate > 7):
rate = 7
# Main entry point
# The try/except structures allows the users to exit out of the program
# with Ctrl + C. Doing so will close the socket gracefully.
if __name__ == '__main__':
try:
ser = serial.Serial(port, baud, timeout=1)
event = threading.Event()
init_irw()
t1 = threading.Thread(target=getKey, daemon=True)
t1.start()
t2 = threading.Thread(target=controlNexstar, args=(event,))
t2.start()
t3 = threading.Thread(target=readthread, args=(ser,), daemon=True)
t3.start()
t2.join()
except KeyboardInterrupt:
print ("\nShutting down...")
# Close the socket (if it exists)
if (sock != None):
sock.close()
if (ser != None):
ser.close()
except serial.serialutil.SerialException:
print ("No Nexstar connection found. Electonic focusser will work only.\n")
event = threading.Event()
init_irw()
t1 = threading.Thread(target=getKey, daemon=True)
t1.start()
t2 = threading.Thread(target=controlNexstar, args=(event,))
t2.start()
t2.join()
finally:
print ("pynexstarcontrol.py is done!\n")
E키를 누르면 종료하고, 왼쪽과 우측 키를 누르면 0.05초 동안 모터를 작동시키고, 위 아래 키를 누르면 0.1초 동안 모터를 작동시키게 됩니다. 그리고, 키를 계속 누르고 있으면 연속적으로 경통을 앞 뒤로 움직일 수 있습니다.
사실 망원경을 밖에 두고 차 안이나 텐트 안에서 노트북 컴퓨터나 스마트폰을 통해서 감상하고, 적외선 리모콘으로 초점을 맞추는 것이 최종 그림입니다. 전에는 옥상에 두고도 이론적으로 전동 포커서를 작동시킬 수 있었지만, 사실 그럴 일은 별로 없었습니다. 더구나 경통의 끝을 인식하는 안전 기능이 없으므로 눈으로 보면서 조작해야만 합니다.
'천체관측(코동)' 카테고리의 다른 글
라즈베리파이 + 적외선 리모콘으로 코동 경통 움직이기 (3) | 2022.10.31 |
---|