In [1]:
from collections import OrderedDict
import sys
import base_node_rpc.node as bn
import motor_control as mc
from nadamq.NadaMq import cPacket, cPacketParser, PACKET_TYPES, PACKET_NAME_BY_TYPE
from serial import Serial
import pandas as pd
import numpy as np
import numpy as np

STEP_SETTINGS = pd.DataFrame([[0, 0, 0], [1, 0, 0], [0, 1, 0],
                              [1, 1, 0], [1, 1, 1]],
                             columns=['ms1', 'ms2', 'ms3'],
                             index=['full', 'half', 'quarter',
                                    'eighth', 'sixteenth']).T
STEP_SETTINGS_BYTECODE = STEP_SETTINGS.apply(np.packbits, axis=0).iloc[0]
STEP_SETTINGS_BYTECODE.name = 'microstep_bytecode'
STEP_SETTINGS_BYTECODE


def dump_message(msg):
    keys = msg.DESCRIPTOR.fields_by_name.keys()
    max_len = max(map(len, keys))
    return '\n'.join([('%' + str(max_len) + 's: %s') %
                      (k, getattr(msg, k)) for k in keys])

Connect to device


In [3]:
import time
# serial_device = Serial('/dev/ttyUSB0', baudrate=115200)
serial_device = Serial('/dev/ttyACM0', baudrate=115200)
proxy = mc.Proxy(serial_device)
time.sleep(2)

print proxy.ram_free(), 'bytes RAM free'
proxy.properties()


255 bytes RAM free
Out[3]:
base_node_software_version                                          0.10.post14
name                                                              motor_control
manufacturer                                                        Wheeler Lab
url                           http://github.com/wheeler-microfluidics/motor-...
software_version                                                      0.2.post2
dtype: object

Dump initial configuration and motor state


In [4]:
config = mc.Config.FromString(proxy.serialize_config().tostring())
state = mc.State.FromString(proxy.serialize_state().tostring())
print dump_message(config)
print ''
print dump_message(state)


max_waveform_frequency: 10000
  max_waveform_voltage: 200
             baud_rate: 115200
min_waveform_frequency: 0
         serial_number: 0
           i2c_address: 0

 motor_direction: False
  motor_delay_us: 1000
  motor_position: 0
motor_continuous: False
   motor_enabled: False
     motor_speed: 0
  motor_pulse_us: 20

Basic interfacing


In [5]:
# Set several motor attributes at once using `update_state` method.
proxy.update_state(motor_delay_us=int(1e3), motor_enabled=True, motor_pulse_us=20)


Out[5]:
1

In [6]:
# Reset current motor position as position 0.
proxy.motor_set_home()

In [7]:
# Query current motor position.
proxy.position()


Out[7]:
0

In [8]:
# Set motor speed (steps per second).
proxy.motor_set_speed(1000)

In [9]:
# Set target position to half turn (assuming 200 steps/revolution motor).
proxy.set_target_position(100)

In [10]:
# Set target position origin.
proxy.set_target_position(0)

In [11]:
# Move steps relative to current position.
# Positive values are clockwise, negative counter-clockwise.
proxy.move(-1)

In [12]:
# If the motor is enabled, start moving the motor at 20 steps per second.
proxy.motor_start(-400)

In [13]:
# Stop the motor (but do not disable it).
proxy.motor_stop()

Interactive control


In [14]:
from IPython.html.widgets import interactive


def update_motor(position=0, speed=1000, enabled=False, microstep_mode='full'):
    if enabled:
        # Change microstep setting (STEP_SETTINGS.(full,half,quarter,eighth,sixteeth)
        proxy.set_MS(*getattr(STEP_SETTINGS, microstep_mode).values)
        # Set motor speed (steps per second).
        proxy.motor_set_speed(speed)
        proxy.update_state(motor_enabled=True)
        proxy.set_target_position(position)
    else:
        proxy.update_state(motor_enabled=False)

    
interactive(update_motor, position=(-400, 400), speed=(200, 1600),
            microstep_mode=('full', 'half', 'quarter', 'eighth', 'sixteenth'))