ورکشاپ آموزشی - آیسی مدار
رفتن به محتوا

ربات کابلی اسپایدرکم برای عکاسی تایم‌لپس

رباتیک و هوشمندسازی
۰ نظر
۸۶ نفر
کد ۳۰۷۸

عکاسی تایم‌لپس همیشه جذابیت خاصی داره، اما وقتی دوربین در طول زمان حرکت می‌کنه، نتیجه کار فوق‌العاده سینمایی و خیره‌کننده می‌شه. احتمالا تجهیزات حرفه‌ای و گران‌قیمت اسپایدرکم (Spidercam) رو تو مسابقات فوتبال یا رویدادهای بزرگ دیدی؛ دوربین‌هایی که روی کابل حرکت می‌کنن و زوایای بی‌نظیری رو ثبت می‌کنن. امروز در آیسی‌مدار قراره با یک دهم اون هزینه‌ها، نسخه مینیاتوری و شخصی خودمون رو بسازیم!

پروژه SPiDER Cam Robot یک سیستم حرکت‌دهنده دوربینه که روی یک کابل (زیپ‌لاین) نصب می‌شه. این ربات با استفاده از برد قدرتمند Raspberry Pi Pico W و یک موتور استپر با گیربکس سیاره‌ای، می‌تونه وزن سنگین دوربین و گیمبالت رو به نرمی و با دقت میلی‌متری روی طناب جابه‌جا کنه. این گجت به صورت بی‌سیم (از طریق وای‌فای) به گوشیت وصل می‌شه و می‌تونی نقاط شروع، پایان و سرعت حرکتش رو دقیقا تنظیم کنی.

بهترین بخش ماجرا اینجاست که این ربات کاملا با گیمبال و دوربینت سینک می‌شه؛ یعنی با هر بار عکاسی گیمبال، ربات چند میلی‌متر جلو می‌ره تا فریم بعدی ثبت بشه. این پروژه ترکیبی از پرینت سه‌بعدی، لحیم‌کاری مدارهای کنترلی و برنامه‌نویسی میکروپایتونه. پس قطعاتت رو آماده کن تا بریم سراغ ساخت این ربات فیلم‌بردار خفن!

قطعات موردنیاز

  • برد رزبری‌پای پیکو دبلیو (Raspberry Pi Pico W)
  • موتور استپر Nema17 با گیربکس سیاره‌ای 5.1
  • دو عدد باتری سونی NPF یا یک عدد باتری V Mount
  • کابل تبدیل DC به DC
  • سوکت نری 5 پین میکرو USB
  • کابل شاتر مخصوص مدل دوربین خودت
  • دو عدد ماژول اپتوایزولاتور (Optoisolator) برای ایزوله کردن سیگنال‌ها
  • درایور موتور استپر
  • ماژول راه‌انداز استپر موتور
  • آداپتور تبدیل جک 2.5 میلی‌متری به 3.5 میلی‌متری
  • سوکت مادگی 3.5 میلی‌متری
  • قطعات پرینت سه‌بعدی شده (فایل‌ها در ادامه موجود است)
مرحله ۱

پروگرام کردن برد رزبری‌پای پیکو (Pi Pico W)

اول از همه باید سراغ مغز متفکر ربات، یعنی رزبری‌پای پیکو بریم. چون کدهای این پروژه با زبان میکروپایتون (Micropython) نوشته شده، برای آپلود کدها از نرم‌افزار Thonny استفاده می‌کنیم. نصبش خیلی ساده‌ست؛ فقط کافیه دکمه Next رو بزنی تا تموم بشه. بعد از نصب، باید برد پیکو رو تو حالت بوت (Boot Mode) به کامپیوتر وصل کنی.

برای این کار، دکمه Bootsel روی برد رو نگه دار و همون‌طور که دکمه رو فشردی، کابل Micro USB رو به کامپیوتر متصل کن.

حالا وارد نرم‌افزار Thonny شو، روی منوی پایین سمت راست کلیک کن و از بخش تنظیمات، مدل برد رو روی Raspberry Pi Pico W تنظیم کن. چند ثانیه صبر کن تا نرم‌افزار به صورت خودکار فریم‌ور میکروپایتون رو روی برد نصب کنه. وقتی نصب تموم شد، کدهایی که تو لینک پایین هست رو دانلود کن و داخل حافظه رزبری‌پای پیکو کپی کن. برای انتقال فایل‌ها هم باز از همون نرم‌افزار Thonny استفاده می‌کنیم.

پوشه Lib و فایل main.py رو باز کن و روی برد کپی کن. نکته خیلی مهم: قبل از کپی کردن فایل main.py، می‌تونی اسم هات‌اسپات (Hotspot) گوشیت و رمزش رو تو همون خط‌های اول کد وارد کنی تا ربات بعدا بتونه بهش متصل بشه. کار نرم‌افزار تموم شد!

JavaScript
import network
import socket
import uasyncio
import time
import random
from machine import Pin, PWM, time_pulse_us
import stepper
### You need neopixel.py in the same folder
#from neopixel import NeoPixel
### config.py should define something like: password = "mywifi_password"
#import config
##############################################################################
# 0) Configuration
##############################################################################
SSID = "HOME1235"
PASSWORD = "pass1234"
# For controlling the on-board LED
led = Pin("LED", Pin.OUT)
# Create global wlan object
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
##############################################################################
# 1) Wi-Fi Connection Helpers
##############################################################################
def wifi_connect():
"""
Continuously retry Wi-Fi connection until successful.
"""
global wlan
attempt = 0
while True:
attempt += 1
if not wlan.isconnected():
print(f"Attempt {attempt}: Connecting to Wi-Fi...")
wlan.connect(SSID, PASSWORD)
# Wait up to 10 seconds in small increments to see if it connects
max_wait = 10
while max_wait > 0:
if wlan.isconnected():
print("Connected! Network config:", wlan.ifconfig())
return # Exit the function when connected
max_wait -= 1
time.sleep(1)
# If still not connected after 10s, wait a bit before retrying
print("Failed to connect. Retrying in 5 seconds...")
time.sleep(5)
else:
# Already connected
print("Already connected! Network config:", wlan.ifconfig())
return
async def wifi_monitor_task():
"""
Periodically checks if the Wi-Fi is still connected.
If not, it attempts to reconnect.
"""
while True:
if not wlan.isconnected():
print("Wi-Fi dropped; reconnecting...")
try:
wifi_connect()
except RuntimeError as e:
print("Reconnect failed:", e)
await uasyncio.sleep(10)
enm = Pin(0, Pin.OUT)
dirm = Pin(1, Pin.OUT)
stepm = Pin(2, Pin.OUT)
inshot = Pin(3, Pin.IN, Pin.PULL_UP)
outshot = Pin(4, Pin.OUT)
outshot.value(0)
s1 = stepper.Stepper(stepm,dirm,steps_per_rev=800,speed_sps=800)
s1.stop()
s1.overwrite_pos(0)
s1.target(0)
s1.speed(800)
s1.track_target()
current_duty = 0
current_pos = 0
vuelta = 1600
a_pos = 0
b_pos = 0
steps = 0
speed = 800
photos = 20
status = 0
predelay = 1
last_inshot = 1
async def test_status():
global status
global last_inshot
global predelay
while True:
if inshot.value() == 0 and last_inshot == 1 and status == 1:
print("shoot")
last_inshot = 0
#shot()
await uasyncio.sleep(0.1)
outshot.value(1)
await uasyncio.sleep(1)
outshot.value(0)
#await uasyncio.sleep(predelay)
move_step()
last_inshot = 1
await uasyncio.sleep(0.1)
def set_A():
global current_pos
global vuelta
global a_pos
a_pos = current_pos
print ("A_POS:")
print (a_pos)
def go_A():
global current_pos
global vuelta
global a_pos
global s1
s1.target(a_pos)
print ("GO_A:")
print (a_pos)
def go_B():
global current_pos
global vuelta
global b_pos
global s1
s1.target(b_pos)
print ("GO_B:")
print (b_pos)
def set_B():
global current_pos
global vuelta
global b_pos
b_pos = current_pos
print ("B_POS:")
print (b_pos)
calculate_steps()
def minus():
global speed
speed = speed - 100
if speed <= 0:
speed = 0
print ("speed:")
print (speed)
def plus():
global speed
speed = speed + 100
if speed > 6400:
speed = 6400
print ("speed:")
print (speed)
def photo_minus():
global photos
photos = photos - 5
if photos <= 0:
photos = 0
print ("photos:")
print (photos)
def photo_plus():
global photos
photos = photos + 5
if photos > 1000:
photos = 1000
print ("photos:")
print (photos)
def start():
global status
global current_pos
global a_pos
current_pos = a_pos
status = 1
print("start")
def stop():
global status
status = 0
print("stop")
def e_stop():
enm.value(1)
print ("E_Stop")
def shot():
await uasyncio.sleep(0.1)
outshot.value(1)
await uasyncio.sleep(1)
outshot.value(0)
def move_left():
global current_pos
global vuelta
current_pos = current_pos + vuelta
s1.target(current_pos)
print ("Left")
def move_right():
global current_pos
global vuelta
current_pos = current_pos - vuelta
s1.target(current_pos)
print ("Right")
def calculate_steps():
global a_pos
global b_pos
global photos
global steps
steps = abs(int((a_pos - b_pos)/(photos-1)))
if b_pos < a_pos:
steps = -steps
print(steps)
def move_step():
global steps
global current_pos
global s1
global status
global last_inshot
global a_pos
global b_pos
current_pos = current_pos + steps
s1.target(current_pos)
print(current_pos)
if b_pos < a_pos:
if current_pos <= b_pos:
status = 0
print("finish")
elif b_pos > a_pos:
if current_pos >= b_pos:
status = 0
print("finish")
def web_page():
global photos
global steps
global speed
global current_pos
global status
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Zumo Robot Control</title>
</head>
<center><b>
<h1>SPiDER CAM Robot Control</h1>
<table><tr>
<td><form action="./left">
<input type="submit" value="Left" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="Stop" style="height:120px; width:120px" />
</form></td>
<td><form action="./right">
<input type="submit" value="Right" style="height:120px; width:120px" />
</form></td>
</tr></table>
<table><tr>
<td><form action="./photominus">
<input type="submit" value="---" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="{photos}" style="height:120px; width:120px" />
</form></td>
<td><form action="./photoplus">
<input type="submit" value="+++" style="height:120px; width:120px" />
</form></td>
</tr></table>
<table><tr>
<td><form action="./seta">
<input type="submit" value="setA" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="step:{steps}" style="height:120px; width:120px" />
</form></td>
<td><form action="./setb">
<input type="submit" value="setB" style="height:120px; width:120px" />
</form></td>
</tr></table>
<table><tr>
<td><form action="./goa">
<input type="submit" value="Go A" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="a:{current_pos}" style="height:120px; width:120px" />
</form></td>
<td><form action="./gob">
<input type="submit" value="Go B" style="height:120px; width:120px" />
</form></td>
</tr></table>
<table><tr>
<td><form action="./minus">
<input type="submit" value="-spd-" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="spd:{speed}" style="height:120px; width:120px" />
</form></td>
<td><form action="./plus">
<input type="submit" value="+spd+" style="height:120px; width:120px" />
</form></td>
</tr></table>
<table><tr>
<td><form action="./start">
<input type="submit" value="start" style="height:120px; width:120px" />
</form></td>
<td><form action="./stop">
<input type="submit" value="stop" style="height:120px; width:120px" />
</form></td>
<td><form action="./lock">
<input type="submit" value="{status}" style="height:120px; width:120px" />
</form></td>
</tr></table>
<form action="./estop">
<input type="submit" value="E-Stop" style="height:120px; width:120px" />
</form>
</body>
</html>
"""
return str(html)
##############################################################################
# 7) Asynchronous Tasks
##############################################################################
async def handle_client(reader, writer):
"""
Handle one HTTP client request (non-blocking).
"""
global emergency_stop
try:
request = await reader.read(1024)
except Exception as e:
print("Error reading request:", e)
return
request_str = request.decode() if request else ""
# Movement only if no emergency stop
if "GET /favicon.ico" in request:
await writer.aclose()
return
if "/seta?" in request_str:
set_A()
elif "/setb?" in request_str:
set_B()
elif "/goa?" in request_str:
go_A()
elif "/gob?" in request_str:
go_B()
elif "/photominus?" in request_str:
photo_minus()
elif "/photoplus?" in request_str:
photo_plus()
elif "/minus?" in request_str:
minus()
elif "/plus?" in request_str:
plus()
elif "/start?" in request_str:
start()
elif "/stop?" in request_str:
stop()
elif "/left?" in request_str:
move_left()
elif "/right?" in request_str:
move_right()
elif "/estop?" in request_str:
e_stop()
# Send response
resp = web_page()
await writer.awrite("HTTP/1.1 200 OK\r\n")
await writer.awrite("Content-Type: text/html\r\n")
await writer.awrite("Connection: close\r\n\r\n")
await writer.awrite(resp)
await writer.drain()
await writer.wait_closed()
#await writer.aclose()
async def webserver_task():
server = await uasyncio.start_server(handle_client, "0.0.0.0", 80)
print("Web server listening on http://{}:80".format(wlan.ifconfig()[0]))
return server
##############################################################################
# 8) Main Entry Point
##############################################################################
async def main():
# 1) Ensure we are connected to Wi-Fi at startup
wifi_connect()
# 2) Create Wi-Fi monitor task to reconnect if dropped
uasyncio.create_task(wifi_monitor_task())
# 3) Start distance measure task
uasyncio.create_task(test_status())
# 4) Start webserver
server = await webserver_task()
# 5) Simple blink in a loop
while True:
led.value(1)
await uasyncio.sleep(0.1) # Non-blocking
led.value(0)
await uasyncio.sleep(1)
import sys
try:
uasyncio.run(main())
except Exception as e:
# Open (or create) error.log in append mode
with open("error.log", "a") as f:
# Print a full traceback to the file
sys.print_exception(e, f)
print("An error occurred and has been logged to error.log.")
مرحله ۲

مونتاژ برد کنترلر اسپایدرکم

حالا که برد رزبری‌پای پیکو پروگرام شده، می‌تونیم با استفاده از هویه، سیم‌لحیم و روغن لحیم (فلاکس) ساخت مدار رو شروع کنیم. برای اتصال قطعات، حتما با دقت از دیاگرام سیم‌کشی پیروی کن.

اول سراغ ماژول درایور استپر موتور می‌ریم. پایه‌های مثبت و منفی درایور رو به پین‌های 3 ولت و GND روی برد پیکو لحیم کن. بعد پایه‌های Enable، Direction (جهت) و Step رو با توجه به پین‌هایی که تو دیاگرام مشخص شده، به پایه‌های GPIO متصل کن.

در مرحله بعد، باید ماژول اپتوایزولاتور ورودی (Input Optocoupler) رو متصل کنیم. این ماژول وظیفه‌اش اینه که سیگنال شاتر (عکس گرفتن) رو از گیمبال بگیره و بدون این که نویز یا ولتاژ اضافی وارد مدار بشه، اون رو به کنترلر برسونه. پین GND خروجی ماژول رو به پایه GND برد پیکو لحیم کن. بعد پایه OUT ماژول رو طبق دیاگرام به یکی از پایه‌های GPIO متصل کن.

حالا پایه ورودی منفی (Negative Input) ماژول رو به پین 2.5 میلی‌متری کابل شاتر گیمبال لحیم کن. ورودی مثبت ماژول رو هم به پین 3 ولت برد کنترلر بزن. سیم زمین (Sleeve) کابل گیمبال رو هم باید به یکی از پایه‌های گراند (GND) برد اصلی متصل کنی.

سپس ماژول اپتوایزولاتور خروجی رو به مدار اضافه می‌کنیم تا به خود دوربین فرمان عکس گرفتن بده. پایه GPIO پیکو رو به ورودی مثبت ماژول وصل کن و پین GND پیکو رو به ورودی منفی ماژول بزن. حالا برای اتصال به دوربین، خروجی منفی ماژول رو به پایه زمین (Sleeve) سوکت مادگی 3.5 میلی‌متری متصل کن و خروجی مثبت ماژول رو به پایه‌های Ring و Tip سوکت 3.5 میلی‌متری لحیم کن.

در آخر، جک مادگی آداپتور (DC Jack) رو برای تامین برق لحیم می‌کنیم. سیم مثبت جک رو به ورودی مثبت ماژول درایور موتور و منفی رو به منفی متصل کن. بعد از اون، همین جک DC رو به ورودی یک ماژول کاهنده ولتاژ (Buck Converter) بزن تا ولتاژ رو برای برد رزبری‌پای به 5 ولت کاهش بده. خروجی 5 ولت ماژول کاهنده رو هم به پایه‌های VBUS و GND برد پیکو لحیم کن. مدار کامل شد!

مرحله ۳

مونتاژ فیزیکی ربات اسپایدرکم

برای این قسمت، من از چند تا قطعه پرینت سه‌بعدی شده قدیمی که داشتم استفاده کردم، اما می‌تونی قطعات مشابه رو تو ابزارفروشی‌ها پیدا کنی یا فایل‌های مخصوصش رو پرینت بگیری. مهم‌ترین بخش مکانیکی، دو تا چرخ قرقره‌ای (U-wheel) برای حرکت روی طناب و ورق نصب موتور هست که حتما باید تو یک راستا و تراز باشن.

من از دو تا براکت فلزی موتور Nema 17 در دو طرف شاسی استفاده کردم تا به عنوان محور نگهدارنده چرخ‌ها عمل کنن. برای نگه‌داشتن بلبرینگ‌ها و چرخ‌های قرقره‌ای، از شفت (Rod) 8 میلی‌متری و دو تا بست نگه‌دارنده شفت استفاده کردم. تمام این قطعات روی یک پروفیل آلومینیومی شیاردار 2020 با طول 10 اینچ (حدود 25 سانتی‌متر) سوار می‌شن. بعدش براکت موتور رو هم با پیچ به همین پروفیل محکم کردم.

روی شفت موتور استپر، یک پولی تایمینگ (دندانه دار) قرار دادم. من از یک پولی مدل GT2-30 با سوراخ 8 میلی‌متری استفاده کردم که دقیقا با اندازه شفت استپر موتورت باید هم‌خوانی داشته باشه.

در نهایت، گیره نگهدارنده طناب رو با دو تا پیچ M3 روی صفحه موتور بستم. جعبه کنترلر (بردی که تو مرحله قبل ساختیم) و پلیت نگهدارنده باتری رو هم به کناره‌های پروفیل آلومینیومی 2020 پیچ کردم تا شاسی ربات تکمیل بشه.

مرحله ۴

نحوه کار با ربات اسپایدرکم

حالا باید اسم هات‌اسپات (SSID) و رمز عبور گوشیت رو همون‌طوری تنظیم کنی که به عنوان پیش‌فرض تو فایل main.py وارد شده (SSID: ROBOT1234 و Pass: pass1234). اگر تو مرحله اول کد رو با اطلاعات خودت ویرایش کرده بودی، فقط کافیه هات‌اسپات گوشیت رو روشن کنی. بعد از اتصال، برو تو تنظیمات گوشی و آی‌پی آدرس ربات رو پیدا کن. مرورگرت رو باز کن و همون آی‌پی آدرس رو وارد کن.

با این کار، صفحه وب کنترلر ربات (S-Pi-DER Robot Controller) روی گوشیت بالا میاد. تو ردیف اول، دکمه‌هایی داری که می‌تونی باهاشون ربات رو دستی به چپ یا راست حرکت بدی و اگر حس کردی زیاد رفته، دکمه Stop رو بزنی تا متوقف بشه.

ردیف دوم بهت اجازه می‌ده تعداد عکس‌هایی که قراره ثبت بشه رو کم و زیاد کنی. حواست باشه که این عدد باید دقیقا با تعداد عکس‌هایی که گیمبالت قراره به دوربین دستور بده بخونه.

تو ردیف سوم می‌تونی نقطه A (نقطه شروع حرکت) و نقطه B (نقطه پایان حرکت) رو تنظیم کنی. عددی که وسط این ردیف می‌بینی، نشون می‌ده که استپر موتور بین هر عکس، دقیقا چند قدم (Step) باید حرکت کنه تا به نقطه بعدی برسه.

ردیف چهارم دو تا دکمه داره برای این که ربات به صورت خودکار برگرده به نقطه A یا مستقیم بره به نقطه B. عدد وسط این ردیف هم موقعیت فعلی ربات رو بر اساس تعداد قدم‌هاش نشون می‌ده که فقط برای راهنمایی و آمار گرفتنه.

ردیف پنجم مخصوص تنظیم سرعت استپر موتوره. اگر دیدی موتور موقع کشیدن کل تجهیزات (دوربین و گیمبال) داره زور می‌زنه و تق‌تق می‌کنه، سرعت رو کم کن. اگر هم می‌خوای عکس‌ها با فاصله زمانی کمتر گرفته بشن، می‌تونی سرعت رو زیاد کنی.

یادت باشه سرعت حرکت ربات مستقیما به وزن تجهیزاتت ربط داره؛ تجهیزات سنگین‌تر، اینرسی بیشتری ایجاد می‌کنن و موتور برای تکون دادنشون نیاز به سرعت پایین‌تری داره.

با دکمه‌های ردیف ششم، می‌تونی پروسه تایم‌لپس رو استارت بزنی یا متوقف کنی. زدن دکمه Start باعث می‌شه ماژول‌های اپتوایزولاتور فعال بشن و ربات آماده دریافت سیگنال از گیمبال و ارسال فرمان عکس‌برداری به دوربین بشه. تو این ردیف یک قسمت STATUS هم هست؛ اگر عدد 1 باشه یعنی ربات فعاله و آماده به کاره، و اگر 0 باشه یعنی در حالت استراحت قرار داره.

ردیف آخر هم شامل یک دکمه قرمز توقف اضطراریه (Emergency STOP) تا اگر هر اتفاق پیش‌بینی نشده‌ای افتاد، بلافاصله ربات رو درجا متوقف کنی. حالا وقتشه گیمبال و ربات رو با هم ترکیب کنیم تا تایم‌لپس‌های شگفت‌انگیز بسازیم.

مرحله ۵

نصب کابل (زیپ‌لاین) در محیط

اینجا چند تا نکته ایمنی و طلایی برای نصب کابل یا طناب ربات بهت می‌گم. اول از همه، یک جای مناسب و امن رو پیدا کن و حتما اطرافش رو به خوبی بررسی کن.

اگر تو پارکی هستی که مردم رفت‌وآمد می‌کنن، حتما بهشون اطلاع بده که یک طناب بستی تا حواسشون باشه. اگر اون منطقه نگهبان داره، حتما ازش اجازه بگیر تا طنابی که بستی برای کسی دردسر نشه.

کابل رو بین دو تا ستون محکم یا دو تا درخت قطور و قوی ببند. یادت نره که کل تجهیزات تو (ربات، گیمبال و دوربین) حداقل 5 کیلوگرم وزن داره و این وزن قراره وسط یک طناب کشیده‌شده معلق باشه!

و در نهایت، همیشه قبل از این که طناب رو سفت کنی، شاسی ربات رو روی اون سوار کن. هشدار اول: هیچ‌وقت طناب رو جایی که ماشین‌ها یا افراد زیاد تردد می‌کنن نصب نکن، سقوط تجهیزات می‌تونه خسارت جبران‌ناپذیری به بار بیاره. هشدار دوم: موقع بستن طناب در ارتفاع بالا یا نزدیک تیرهای چراغ برق به شدت احتیاط کن تا خطرات جانی تو رو تهدید نکنه.

مرحله ۶

همگام‌سازی گیمبال با ربات اسپایدرکم

برای این مرحله باید کار با اپلیکیشن موبایل گیمبالت رو بلد باشی. من از یک گیمبال قدیمی Zhiyun Weebill S استفاده می‌کنم، اما نگران نباش، منطق کار تو همه گیمبال‌های جدیدتر هم دقیقا شبیه به همینه.

اول دوربین رو طبق دفترچه راهنما روی گیمبال بالانس کن. بعدش گیمبال رو با دقت کامل از پایین به شاسی رباتت متصل کن. تو این مرحله به شدت مراقب باش، چون اصلا دلمون نمی‌خواد تجهیزات چند صد دلاری‌مون سقوط کنن. قبل از این که دستت رو از زیر گیمبال رها کنی، یک بار دیگه سفت بودن همه پیچ و مهره‌ها رو چک کن.

باتری رو به جک تغذیه (DC port) ربات متصل کن. حالا کابل فرمان شاتر گیمبال رو به سوکت "ورودی" ربات بزن و یک کابل شاتر دیگه رو از خروجی ربات به دوربینت متصل کن.

وارد اپلیکیشن گیمبال شو و گزینه Trajectory (حرکت برنامه‌ریزی‌شده) رو انتخاب کن. تو این بخش می‌تونی زاویه اولیه و زاویه نهایی گیمبال، فاصله زمانی بین هر عکس و زمان کل پروسه تایم‌لپس رو تنظیم کنی. اپلیکیشن با این اعداد، تعداد کل عکس‌ها رو محاسبه می‌کنه. این عدد دقیقا همون چیزیه که باید تو صفحه کنترل رباتمون (تو گوشی) وارد کنیم.

هات‌اسپات گوشیت رو روشن کن و وارد صفحه وب ربات اسپایدرکم شو. ربات رو دستی ببر به نقطه‌ای که می‌خوای حرکت از اونجا شروع بشه و دکمه SET A رو بزن. همزمان، زاویه گیمبال رو هم تو اپلیکیشنش برای نقطه شروع تنظیم کن.

ربات رو به سمت نقطه پایان حرکت بده، دکمه SET B رو بزن و کادربندی نهایی گیمبال رو هم ست کن. تعداد کل عکس‌هایی که تو اپلیکیشن گیمبال هست رو تو صفحه ربات هم وارد کن. حالا روی دکمه GO A کلیک کن تا ربات برگرده سر خط و آماده حرکت بشه.

دکمه Start رو روی گوشی (صفحه وب ربات) بزن تا ربات گوش به زنگ دریافت سیگنال از گیمبال بمونه. حالا برو تو اپلیکیشن گیمبال و تایم‌لپس رو استارت بزن. گیمبال اولین سیگنال شاتر رو می‌فرسته، ربات یک قدم جلو می‌ره و دوربین عکس می‌گیره. به همین سادگی! حالا فقط بشین، از منظره لذت ببر و منتظر بمون تا کار ربات و گیمبال تموم بشه.

نکته پایانی: حتما هر چند دقیقه یک بار سفتی طناب و وضعیت درخت‌ها یا ستون‌ها رو چک کن تا ایمنی تجهیزات و افراد اطراف به خطر نیفته.

مرحله ۷

مزایا و معایب این سیستم

مزیت بزرگ این سیستم اینه که یک تایم‌لپس حرفه‌ای با حرکت کامل دوربین تو یک مسیر مشخص بهت می‌ده و نتیجه‌اش جای هیچ بحثی رو باقی نمی‌ذاره. اما خب، چند تا چالش هم داره: کشیدن یک طناب بلند تو فضاهای عمومی، مخصوصا پارک‌ها، می‌تونه برای بقیه مردم مزاحمت ایجاد کنه. پس لطفا با ملاحظه کامل طناب رو نصب کن تا برای بقیه خطری ایجاد نشه.

علاوه بر این، ممکنه هر جایی درخت یا ستون مناسب برای بستن طناب پیدا نکنی. اما اگر دست‌به‌آچار باشی، می‌تونی دو تا پایه فلزی بلند همراهت داشته باشی، اون‌ها رو تو زمین محکم کنی و زیپ‌لاین اختصاصی خودت رو تو هر دشت و طبیعتی راه‌اندازی کنی. با این ترفند، هیچ‌وقت لنگ درخت نمی‌مونی!

فایل‌های پیوست

PY __init__.py

تو میتونی اولین سازنده باشی!

اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر

این آموزش با استانداردهای اختصاصی آیسی‌مدار بازنویسی و بهینه‌سازی شده و تمامی حقوق انتشار آن متعلق به این مجموعه است و در صورت کپی یا بازنشر پیگرد قانونی خواهد داشت.

آموزش‌های مشابه

گفتگو‌های کاربران

هنوز نظری ثبت نشده؛ تو شروع کن!