Skip to content

a little refactoring, speed-up, and CPython compatibility #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 21, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 42 additions & 13 deletions adafruit_vc0706.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
* Adafruit CircuitPython firmware for the ESP8622 and M0-based boards:
https://github.com/adafruit/circuitpython/releases
"""
import busio
from micropython import const

__version__ = "0.0.0-auto.0"
Expand Down Expand Up @@ -79,6 +78,11 @@
IMAGE_SIZE_320x240 = const(0x11)
IMAGE_SIZE_160x120 = const(0x22)
# pylint: enable=invalid-name
_BAUDRATE_9600 = const(0xAEC8)
_BAUDRATE_19200 = const(0x56E4)
_BAUDRATE_38400 = const(0x2AF2)
_BAUDRATE_57600 = const(0x1C1C)
_BAUDRATE_115200 = const(0x0DA6)

_MOTIONCONTROL = const(0x0)
_UARTMOTION = const(0x01)
Expand All @@ -93,20 +97,19 @@

class VC0706:
"""Driver for VC0706 serial TTL camera module.

:param ~microcontroller.Pin rx: Receive pin
:param ~microcontroller.Pin tx: Transmit pin
:param int baudrate: Serial connection speed
:param int timeout: Read timeout in seconds
:param int buffer_size: Receive buffer size
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest updating this, not just deleting it. It makes for nicely formatted docs: https://circuitpython.readthedocs.io/projects/vc0706/en/latest/api.html#adafruit_vc0706.VC0706

"""
def __init__(self, rx, tx, *, baudrate=38400, timeout=250, buffer_size=100):
self._uart = busio.UART(tx, rx, baudrate=baudrate, timeout=timeout)
def __init__(self, uart, *, buffer_size=100):
self._uart = uart
self._buffer = bytearray(buffer_size)
self._frame_ptr = 0
self._command_header = bytearray(3)
if not self._run_command(_RESET, bytes([0x00]), 5):
raise RuntimeError('Failed to get response from VC0706, check wiring!')
for _ in range(2): # 2 retries to reset then check resetted baudrate
for baud in (9600, 19200, 38400, 57600, 115200):
self._uart.baudrate = baud
if self._run_command(_RESET, bytes([0x00]), 5):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of bytes([0x00]) do b'\x00'. That way it doesn't need to create a list to convert to bytes.

break
else: # for:else rocks! http://book.pythontips.com/en/latest/for_-_else.html
raise RuntimeError('Failed to get response from VC0706, check wiring!')

@property
def version(self):
Expand All @@ -116,6 +119,32 @@ def version(self):
readlen = self._read_response(self._buffer, len(self._buffer))
return str(self._buffer[:readlen], 'ascii')

@property
def baudrate(self):
"""Return the currently configured baud rate."""
return self._uart.baudrate

@baudrate.setter
def baudrate(self, baud):
"""Set the baudrate to 9600, 19200, 38400, 57600, or 115200. """
divider = None
if baud == 9600:
divider = _BAUDRATE_9600
elif baud == 19200:
divider = _BAUDRATE_19200
elif baud == 38400:
divider = _BAUDRATE_38400
elif baud == 57600:
divider = _BAUDRATE_57600
elif baud == 115200:
divider = _BAUDRATE_115200
else:
raise ValueError("Unsupported baud rate")
args = [0x03, 0x01, (divider>>8) & 0xFF, divider & 0xFF]
self._run_command(_SET_PORT, bytes(args), 7)
print([hex(i) for i in self._buffer[0:10]])
self._uart.baudrate = baud

@property
def image_size(self):
"""Get the current image size, will return a value of IMAGE_SIZE_640x480,
Expand Down Expand Up @@ -172,7 +201,7 @@ def read_picture_into(self, buf):
args = bytes([0x0C, 0x0, 0x0A, 0, 0, (self._frame_ptr >> 8) & 0xFF,
self._frame_ptr & 0xFF, 0, 0, 0, n & 0xFF,
(_CAMERA_DELAY >> 8) & 0xFF, _CAMERA_DELAY & 0xFF])
if not self._run_command(_READ_FBUF, args, 5):
if not self._run_command(_READ_FBUF, args, 5, flush=False):
return 0
if self._read_response(self._buffer, n+5) == 0:
return 0
Expand All @@ -192,7 +221,7 @@ def _run_command(self, cmd, args, resplen, flush=True):
return True

def _read_response(self, result, numbytes):
return self._uart.readinto(result, numbytes)
return self._uart.readinto(memoryview(result)[0:numbytes])

def _verify_response(self, cmd):
return (self._buffer[0] == 0x76 and self._buffer[1] == _SERIAL and
Expand Down
13 changes: 8 additions & 5 deletions examples/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@


# Configuration:
SD_CS_PIN = board.SD_CS # CS for SD card (SD_CS is for Feather Adalogger)
RX_PIN = board.RX # RX pin of board, connected to VC0706 TX
TX_PIN = board.TX # TX pin of board, connected to VC0706 RX
SD_CS_PIN = board.D10 # CS for SD card (SD_CS is for Feather Adalogger)
IMAGE_FILE = '/sd/image.jpg' # Full path to file name to save captured image.
# Will overwrite!

Expand All @@ -33,13 +31,18 @@
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, '/sd')

# Setup VC0706.
vc0706 = adafruit_vc0706.VC0706(RX_PIN, TX_PIN)
# Create a serial connection for the VC0706 connection, speed is auto-detected.
uart = busio.UART(board.TX, board.RX, timeout=250)
# Setup VC0706 camera
vc0706 = adafruit_vc0706.VC0706(uart)

# Print the version string from the camera.
print('VC0706 version:')
print(vc0706.version)

# Set the baud rate to 115200 for fastest transfer (its the max speed)
vc0706.baudrate = 115200

# Set the image size.
vc0706.image_size = adafruit_vc0706.IMAGE_SIZE_640x480 # Or set IMAGE_SIZE_320x240 or
# IMAGE_SIZE_160x120
Expand Down
77 changes: 77 additions & 0 deletions examples/snapshot_computer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# VC0706 image capture to local storage.
# You must wire up the VC0706 to a USB or hardware serial port.
# Primarily for use with Linux/Raspberry Pi but also can work with Mac/Windows

import time
import serial
import adafruit_vc0706

# Configuration:
IMAGE_FILE = 'image.jpg' # Full path to file name to save captured image.
# Will overwrite!

# Create a serial connection for the VC0706 connection, speed is auto-detected.
# Update the serial port name to match the serial connection for the camera!
uart = serial.Serial("/dev/ttyUSB0", timeout=0.25)

# Setup VC0706 camera
vc0706 = adafruit_vc0706.VC0706(uart)

# Print the version string from the camera.
print('VC0706 version:')
print(vc0706.version)

# Set the baud rate to 115200 for fastest transfer (its the max speed)
vc0706.baudrate = 115200

# Set the image size.
vc0706.image_size = adafruit_vc0706.IMAGE_SIZE_640x480 # Or set IMAGE_SIZE_320x240 or
# IMAGE_SIZE_160x120
# Note you can also read the property and compare against those values to
# see the current size:
size = vc0706.image_size
if size == adafruit_vc0706.IMAGE_SIZE_640x480:
print('Using 640x480 size image.')
elif size == adafruit_vc0706.IMAGE_SIZE_320x240:
print('Using 320x240 size image.')
elif size == adafruit_vc0706.IMAGE_SIZE_160x120:
print('Using 160x120 size image.')

# Take a picture.
print('Taking a picture in 3 seconds...')
time.sleep(3)
print('SNAP!')
if not vc0706.take_picture():
raise RuntimeError('Failed to take picture!')

# Print size of picture in bytes.
frame_length = vc0706.frame_length
print('Picture size (bytes): {}'.format(frame_length))

# Open a file for writing (overwriting it if necessary).
# This will write 50 bytes at a time using a small buffer.
# You MUST keep the buffer size under 100!
print('Writing image: {}'.format(IMAGE_FILE), end='', flush=True)
stamp = time.monotonic()
with open(IMAGE_FILE, 'wb') as outfile:
wcount = 0
while frame_length > 0:
t = time.monotonic()
# Compute how much data is left to read as the lesser of remaining bytes
# or the copy buffer size (32 bytes at a time). Buffer size MUST be
# a multiple of 4 and under 100. Stick with 32!
to_read = min(frame_length, 32)
copy_buffer = bytearray(to_read)
# Read picture data into the copy buffer.
if vc0706.read_picture_into(copy_buffer) == 0:
raise RuntimeError('Failed to read picture frame data!')
# Write the data to SD card file and decrement remaining bytes.
outfile.write(copy_buffer)
frame_length -= 32
# Print a dot every 2k bytes to show progress.
wcount += 1
if wcount >= 64:
print('.', end='', flush=True)
wcount = 0
print()
print('Finished in %0.1f seconds!' % (time.monotonic() - stamp))
8 changes: 4 additions & 4 deletions examples/snapshot_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
import adafruit_vc0706

# Configuration:
RX_PIN = board.RX # RX pin of board, connected to VC0706 TX
TX_PIN = board.TX # TX pin of board, connected to VC0706 RX
IMAGE_FILE = '/image.jpg' # Full path to file name to save captured image.
# Will overwrite!

# Setup SPI bus (hardware SPI).
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# Setup VC0706.
vc0706 = adafruit_vc0706.VC0706(RX_PIN, TX_PIN)
# Create a serial connection for the VC0706 connection, speed is auto-detected.
uart = busio.UART(board.TX, board.RX, timeout=250)
# Setup VC0706 camera
vc0706 = adafruit_vc0706.VC0706(uart)

# Print the version string from the camera.
print('VC0706 version:')
Expand Down