Skip to content

Instantly share code, notes, and snippets.

@qhwa
Created March 18, 2014 15:28
Show Gist options
  • Select an option

  • Save qhwa/9622337 to your computer and use it in GitHub Desktop.

Select an option

Save qhwa/9622337 to your computer and use it in GitHub Desktop.
ruby script that grab pictures from LinkSprite TTL JPEG camera
require 'serialport'
require 'colored'
require 'ruby-progressbar'
class Y201Grab
def self.a2s(*arr)
arr.pack 'c*'
end
LK_RESET = a2s(0x56, 0x00, 0x26, 0x00)
LK_RESET_RE = a2s(0x76, 0x00, 0x26, 0x00, 0x00)
LK_PICTURE = a2s(0x56, 0x00, 0x36, 0x01, 0x00)
LK_PICTURE_RE = a2s(0x76, 0x00, 0x36, 0x00, 0x00)
LK_JPEGSIZE = a2s(0x56, 0x00, 0x34, 0x01, 0x00)
LK_JPEGSIZE_RE = a2s(0x76, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00) # then XH XL
LK_STOP = a2s(0x56, 0x00, 0x36, 0x01, 0x03)
LK_STOP_RE = a2s(0x76, 0x00, 0x36, 0x00, 0x00)
LK_READPICTURE = a2s(0x56, 0x00, 0x32, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) #then KH KL
LK_PICTURE_TIME = a2s(0x00, 0x0A) # .1 ms
LK_READPICTURE_RE = a2s(0x76, 0x00, 0x32, 0x00, 0x00)
JPEG_START = a2s(0xFF, 0xD8)
JPEG_END = a2s(0xFF, 0xD9)
LK_PIC_SIZE_640 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x00)
LK_PIC_SIZE_320 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x11)
LK_PIC_SIZE_160 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x22)
LK_PIC_SIZE_RE = a2s(0x76, 0x00, 0x31, 0x00, 0x00)
LK_BAUD_RATE = a2s(0x56, 0x00, 0x24, 0x03, 0x01)
LK_BAUD_RATE_RE = a2s(0x76, 0x00, 0x24, 0x00, 0x00)
attr_reader :serial
def grab_pic
SerialPort.open("/dev/ttyACM0", 38400, 8, 1, SerialPort::NONE) do |ser|
@serial = ser
ser.read_timeout = 100 #ms
info "reseting"
reset
sleep 2
info "picture"
take_picture
info "size"
check_size do |size|
fetch_data( size ) do |data|
File.open( 'output.jpg', 'w' ) do |f|
info "write into #{f.path}"
f << data
debug "done"
end
end
end
end
end
def reset
serial.flush_input
serial.write LK_RESET
sleep 0.1
check_response_with! LK_RESET_RE
end
def stop
serial.flush_input
serial.write LK_STOP
sleep 0.1
check_response_with! LK_STOP_RE
end
def check_response_with! expect
serial.read( expect.size ).tap do |res|
if res != expect
debug "fail, got: #{res.inspect}"
debug " expect: #{expect.inspect}"
raise "failed"
else
debug "done"
end
end
end
def set_size( size )
serial.flush_input
serial.write LK_PIC_SIZE_640
sleep 0.1
check_response_with! LK_PIC_SIZE_RE
end
def take_picture
serial.flush_input
serial.write LK_PICTURE
sleep 0.5
check_response_with! LK_PICTURE_RE
end
def check_size
serial.flush_input
serial.write LK_JPEGSIZE
sleep 0.5
check_response_with! LK_JPEGSIZE_RE
xh = serial.read(1).unpack('C*').first
xl = serial.read(1).unpack('C*').first
(xh * 256 + xl).tap do |size|
yield size if block_given?
end
end
def fetch_data size
info "fetch JPEG data (#{size}byte)"
kh = (size >> 8) & 0xFF
kl = size & 0xFF
serial.flush_input
serial.write LK_READPICTURE + self.class.a2s(kh, kl) + LK_PICTURE_TIME
sleep 0.05
debug "check ready signal"
check_response_with! LK_READPICTURE_RE
debug "begin reading JPEG"
progress_bar = ProgressBar.create(
:format => '%a %bᗧ%i %p%% %t',
:progress_mark => ' ',
:remainder_mark => '・'
)
picture = ""
read_size = 0
while true do
chunk = serial.read(2)
read_size += chunk.size
picture += chunk
progress_bar.progress = read_size.to_f / size * 100
break if chunk == JPEG_END
end
progress_bar.clear
debug "#{read_size} of #{size} read"
debug "data size: #{picture.size}"
picture.tap do
debug "done reading"
yield picture if block_given?
end
end
private
def info msg
puts section << msg
end
def section
"---> "
end
def debug msg
puts indent << msg.black
end
def indent
" " * 5
end
end
Y201Grab.new.grab_pic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment