The OpenMoco Time-Lapse Engine (OMTLE) is designed to run on an Arduino microcontroller with the Atmega328P Chipset. It is provided as a C++ sketch to be uploaded via the Arduino IDE. It can be easily ported to other microcontroller platforms as well.
The OpenMoco engines are the heart of the OpenMoco system, providing direct camera and motor control and are used as a building block for a system that is personalized around your specific needs. The time-lapse engine provides a control set that is specifically designed for motion control in time-lapse photography using a dSLR camera, in a standard shoot-move-shoot style of execution. That is, motor movements are taken between each exposure cycle, to prevent any possibility of movement or blurring of output video frames. Up to four stepper motor axes can be driven with the OMTLE, when using drivers that utilize pulse logic for step and direction. This includes many common drivers such as the Easydriver, Gecko drives, and many others easily sourced online.
Camera control for dSLRs is driven by a direct connection to the camera using a wired cable remote port. Some cameras can also utilize an infrared LED to emulate a wireless remote with no software changes. In the hardware implementation section below, several options and guidelines for connecting to a camera are discussed.
It is important to note that the time-lapse engine does not come with a human interface, its provides only a programmatic interface that can be utilized by other microcontrollers, personal computers, laptops, and PDAs. New interfaces, varying from software to run on a PC, to stand-alone PDA-like custom designs are being worked on constantly to suit different uses.
The time-lapse engine is completely free of charge, and open-source. All software is released under the GPL v3 or PERL Artistic license (see the individual licenses included with the source code), and all hardware is released under the Creative Commons Attribution Share-Alike license.
A quick glance at the time-lapse engine features:
The time-lapse engine operates under the context of a 'program'. The 'program' is considered to be the collection of your current settings, automating certain activities for you on a schedule. The schedule is determined by the camera intervalometer, controlling how often to fire the camera and therefor when to move motors and check keyframes. You may change any settings during program execution, or even begin executing a program without having entered any settings. (The result of this would be to have the program run timer incrementing for you.)
For example, a program may look like this:
Any program setting may be changed during execution, but some changes may have a deliterious impact on your final output video (such as changing a motor's ramp rate during ramp execution).
The concept of executing within a program is important as certain settings may be discarded or changed during execution, for example, keyframes that have been executed are removed to prevent accidental multiple execution of them, and to allow you to continue to add new keyframes in their place. Additionally, the engine keeps many data elements during program execution, including how far motors have moved, where in ramp cycles motors are, how many shots have been taken, etc.
You may, of course, use the engine without ever starting the program, and instead choosing to manually determine when to fire shots and when to move motors.
There are three basic controls for program execution:
The start control is very simple: it starts the current program wherever it left off, or at the beginning if cleared or in a first run. Once a start command is received, the pogram will begin immediately.
The pause control pauses the execution of the current program. The program run timer is stopped until a start command is received, but any outstanding settings or configuration items are retained.
It is important to note that the pause command will not interfere with anything currently being executed, it will wait until the current tasks being performed are completed. For example, if you pause during an exposure, the exposure will continue, any expected camera keyframe will be executed, the current motor move cycle will run, and any associated motor keyframes and time keyframes will execute if pending, and then the program will be paused.
All information regarding the current execution will be retained when restarted from a pause state.
The clear control both stops program execution, and removes most settings such as actions and keyframes, and also resets all information about the running program.
It is not possible to recover from a clear control and resume your program where it left off.
The clear control should be used before sending a new program, even if paused, to make sure that settings that haven't been used in your current program don't remain from a previous program.
The time-lapse engine provides the following camera control functions:
Exposure and Interval timers are non-blocking, this means that you may continue to interact with the engine while a timer is engaged (e.g. during an exposure), or even trigger keyframes. This is especially useful when you want to continue to modify your program based on time during the execution of your program. Post-exposure and Pre-focus tap timers are blocking, however, and you may not expect time-based keyframes to execute during these actions.
Exposure time is set in milli-seconds, from 1 to 4,294,967,296. Or, 1/1000th of a second to nearly 50 days. (49.7103 days to be more precise!)
You will need to perform some experimentation to determine what the minimum trigger time for your camera is. Some cameras will detect a trigger on the remote in 10-20 mS, while others may require 70 or even 100mS to detect the remote accurately. Make sure you let your camera run for a while with a single trigger time when testing to make sure that it doesn't miss the occasional trigger. The fastest time that your camera will reliably recognize is the preferred trigger time to use for all camera modes except 'bulb'.
The Exposure timer is non-blocking.
Interval is set in seconds, from 1 to 65,536 (Around 45.5 days.)
The interval time is the amount of time to wait between shots.
The Interval timer is non-blocking.
Post-exposure delay time is set in milli-seconds, from 1 to 65,536. (65.5 seconds.)
The post-exposure delay timer specifies how long after completing a shot to wait before moving any motor. This is used when the Exposure Time Setting is less than the actual exposure value set in the camera. For example, when shooting with the camera in manual mode, if the camera is set to a 1 second exposure, and the Exposure Time Setting is set as 70mS, you would want a post-exposure delay of at least 930mS to prevent the motors from moving while the camera is exposing.
Note: If your combination of exposure time, post-exposure time, and the amount of time it takes to move your motors the required distance exceeds your interval time, the actual interval time between shots will be greater than or equal to the combination of these times. The engine will not execute another shot until all outstanding activities have been completed for the current cycle. It will, however, attempt to execute the next shot at the earliest available opportunity.
The post-exposure delay timer is a blocking timer, and therefore no time-based keyframes will occur while this is running, and the engine will not act upon any serial commands while in post-exposure delay.
Pre-Focus tap time is set in milli-seconds, from 1 to 65,536. (65.5 seconds.)
The pre-focus tap timer allows you to tap the focus line (for cameras and remote setups that support this capability) immediately before a shot is executed (exposure is triggered). This is especially useful for longer interval times where the camera may go to sleep between shots, causing shot cycles to get missed.
The order of operations, when a positive pre-focus tap time is set, is as follows:
Thus, you will have a delay of at least 2x your pre-focus tap time. The cause for the second delay is to prevent certain cameras from ignoring an exposure trigger that comes too soon after the pre-focus tap.
The pre-focus tap timer is a blocking timer, and therefore no time-based keyframes will occur while this is running, and the engine will not act upon any serial commands while in focus is being executed.
For some cameras, especially certain Nikon cameras, the focus line must be engaged whenever the shutter line is triggered using a wired remote. This setting allows one to enable this behavior and control these cameras properly.
Maximum shot count is an integer from 1 to 65,536.
The camera, and camera alone, will be disabled when the maximum shot counter is reached within the current program execution. You may rather choose to disable the camera after a certain number of shots, and re-enable it after a certain amount of time through the use of actions and camera and time keyframes.
Setting the maximum shot count to zero specifies that there should be no maximum shot count, and the camera will fire until the program is stopped, paused, or an action to disable the camera is taken.
A Camera Repeat Cycle allows you to trigger multiple exposures at each interval, using actions in-between to script out complex behaviors. A typical use might be to easily create a gigapanoramic photo sequence by using repeat cycle for the rows, and the normal program execution for the vertical movement changes. One could also use it to shoot several interlaced videos at once, with different output speeds - or even a couple of interlaced videos at once with different subjects in the same visible area.
The Repeat Cycle options are a little more involved than can be discussed in a paragraph, so please see the documentation for this feature specifically.
The Time-lapse Engine provides the ability to craft unique and complex shots using a number of features which can be combined at-will for automating different activities. One of these tools is the Camera Repeat Cycle.
A Repeat Cycle specifies that each time an exposure would be triggered during the normal execution of a program, that shot should be repeated. Most importantly, a repeat cycle is invisible to the normal flow of program execution, so only the initial shot is recorded in 'shots fired' parameter, no motor distances moved for the normal program are updated, no keyframes are executed, and any changes to program parameters can be reset upon completion of an individual cycle.
This means that the repeat cycle can be used for crafting multiple, interleaved time-lapse videos either moving at different video speeds, or shooting entirely different subjects. A repeat cycle could also be used for easily scripting panoramic photos by specifying the start of a row of photos, the total rows to takes, and the vertical distance between rows as part of the normal program execution, and then using the repeat cycle to specify the distance between photos in a given row. Another popular use for a repeat cycle would be for creating HDR timelapse. One could specify that each shot is repeated X times, with each repetition further reducing exposure by 1/2 EV. In this way, it can function as an extended bracketing setting for cameras in bulb mode.
Unless a repeat action modifies camera parameters, all parameters for camera exposures are the same for each repeat exposure, including: exposure time, post-exposure delay, focus pre-tap time, etc.
The following parameters are available for controlling the Camera Repeat Cycle:
The Repeat Count specifies how many times to repeat each exposure. The value for this parameter ranges from 0-255. Setting this to zero disables camera repeat cycling.
Repeat Actions can be called between each repeated shot. This allows one to move motors, change exposure parameters, etc. during the cycle. You can have up to four repeat actions called between each shot in the repeat cycle. For more information on defining actions, and what can be done with them, see the Actions page later in this document.
If any repeat action changes the direction of a motor, the motor will be set back to its normal direction after the action is complete.
The Motors Home after Repeat is a simple on/off option, that specifies that if any motor movement occurred during the repeat cycle (i.e. a repeat action caused a motor to move), that all motors should be returned back to where their position was before any repeat actions were called. This is an essential option for shooting interlaced time-lapse videos, otherwise one would be unable to control the output speed ramping, and it motor position would likely jump far out beyond the intended location.
You may specify up to four actions to be called upon completion of a Camera Repeat Cycle. This function can be used to set parameters back to new values after each Repeat Cycle. In particular, specifying a direction change only action (see Serial Protocol) to be run at the end of a repeat cycle is an excellent way to cover "columns and rows" in your program.
The time-lapse engine supports control of up to four motors. Each motor's settings are independant from the other motors, allowing distinct control of the behavior of each axis.
Note: motor movements are made incrementally to ensure proper performance. That is, any movements needed by motor 0 will be made before motor 1, which will be made before motor 2. This prevents timing issues during motor move execution that may cause jerkiness or un-reliability of a particular axis' movements.
The following controls are provided for each motor:
Additionally, several settings control motor behavior:
With stepper motors, it is essential that speed (delay between each step request) be generally increased and decreased throughout the movement. By coming up to speed from a stopped position, and slowing down as you come back to a stop, you not only excersize the torque band of the motor better, you also prevent missed steps and jerky movements. A stepper motor coming to an abrupt shot may also over-step several steps as the braking torque of the motor is exceeded by the force of the camera or other axes in motion.
For the time-lapse engine, a linear speed ramping during movement is used. The default rate of the ramp is to utilize the first and last 33% of the total steps to be taken to linearly come up to speed, or down from speed. These points in the step cycle are called shelfs - the low shelf for bringing up to speed, and the high shelf for coming down from speed. As the motor's movement approaches the low shelf, the time between steps is decreased linearly until the minimum step delay is reached. As the motor's movement crosses the high shelf, the delay time is increased until the last step taken is the maximum step delay after the previous step.
Delays, or time between steps, are expressed in micro-seconds (uS). Obviously, certain movement combinations can result in ramp rates of less than one microsecond, which would result in no change in motor speed. The engine automatically detects this, and will reduce the shelves by 10% until a delay change rate of at least 1uS is achieved. See the minimum/maximum step delay information below.
The motor enable control allows to turn on or off a given axis during program execution. You may disable a motor at any time during exection. If a motor is disabled during program execution, everything about its status is remembered when re-enabled, such as the steps taken so far, where in the linear output ramp it is, etc. To flush this remembered inormation, you will have to issue a program clear control.
The steps per move control defines how many steps the motor should take between exposures. If an output speed ramp is set, the steps per move setting is the maximum output video speed to be ramped and/or down to.
The time-lapse engine is not aware of the gear ratio, microstepping ratio, or steps per revolution of your motor. If you wish to control movement in degrees of a circle, for example, your calling application would need to distill this information to a specified number of steps.
Valid values for Steps per Move are 1-65,536.
The maximum steps control specifies the maximum distance to move a given motor during the execution of a program. It monitors total steps moved, no matter their direction, and will not allow the given axis to move any further than this - no matter what other settings (such as linear ramping) are used. Maximum steps may be specified from 0 (disabled) to 4,294,967,296.
The linear ramp rate provides control over how the speed of the motor's motion is perceived in the final output video. This control allows the motor to move further between shots until the Steps per Move rate is achieved. For example, you may define that at the beginning of the motors movement, it takes ten exposure cycles to reach the full step rate. This allows for natural, smooth starts and stops in the output video.
The motor ramp control value ranges from 1 to 255, with 1 being no ramp.
If a maximum step movement is defined, the linear ramp up and down are designed such that you are always gauranteed that:
However, you are not gauranteed that you will actually take the maximum step count steps during program execution. The algorithm is designed such that it calculates when the steps should start and stop, such that it gaurantees the ramp takes at least as many cycles as you defined. This results in certain combinations, an single incomplete full-step rate motion. This motion is eliminated to prevent over-stepping or incorrect ramping down and poor motion in the output video.
The Linear Ramp Rate is specified as an integer, in how many shot cycles to take before the full step rate should be achieved. For example, if a linear ramp rate of 10 is defined, it will take ten exposure cycles to reach the defined Steps per Move for the given motor. If no maximum step count is defined, then it will not programmatically determine when to start ramping down to no movement - you will have to trigger this via a running control (see below).
Note: some ramp rates and steps per move combination may result in no change between some exposure cycles, for example - a ramp rate of 100, and a steps per move count of 10, would result in a change of movement of 1 step every 10 exposures. Preference should always be given to make ramp rate a factor of the step amount (or vice-versa), e.g.: if step count is 100, an appropriate ramp rate would be 10, 30, 50 or 1000.
The execute down ramp control is useful when no maximum step count has been defined, but a linear ramp rate for a motor has been used. This control alows you to make a decision about when to start ramping down the step rate for a given axis. This is an especially useful control when executed as an action with a keyframe, for example, I can state that I want the movement for a particular axis to begin slowing down after 500 shots, rather than slowing down to achieve a total amount of movement.
If this control is executed while the motor is currently ramping up to full movement, this may result in a poor output movement. You should generally only use this control while the motor is moving at its full step rate.
Once the down ramp has been completed, the down ramp control for that motor will be disabled, and the motor will be disabled to prevent any further movement.
The direction control determines which direction the motor will move in. It uses a simple boolean value of 1 or 0. Which direction this results in is determined by how you wire your motor, what type of gearing you use, and the physical design of your setup.
The set home control allows you to set the current position of a given axis as the 'home' position. It erases any previously set home position for this axis, and enables you to utilize the go to home control to return to this position at a later time.
The default home position for any axis is the position of the axis at power on. If you do not use the set home control, this will be the position that the axis returns to when the go home control is used.
The go home control forces a given axis to immediately return to its home position. It will do so, without any ramping, at the maximum capable speed. This is primarily designed to return to a given position between program executions.
If this control is executed while a program is running, and the given axis is engaged, it will continue to operate properly according to the given program once it has returned home. For example, if it is halfway through a down ramp, moving left, when this control is called, after returning home, the axis will complete its ramp, moving to the left, no matter which direction was required to go home.
The move steps now control allows you to cause an axis to move a specified number of steps immediately. This is primarily designed for positioning an axis before executing a program. However, it can be called while a program is executing. If called while a program is executing, the axis will continue to move as defined after completing this move -- in the same manner as the go home control.
Unfortunately, many motor gear chains have some backlash. Backlash results in missed steps as the final output drive will not move until the backlash has been consumed when changing directions. This setting allows you to set the amount of backlash to compensate for when changing motor directions, specified in steps. You may specify from 0-255 steps of backlash compensation.
The built-in settings control global aspects of motor movement related to your design and implementation.
For hardware setups that are capable of cutting power to the motors between moves, a single pin is used from the Arduino to connect to all motor drivers' sleep lines. (If your drivers support them.) This setting allows one to control whether the drivers should be put to sleep between each movement of a stepper motor or left running. For hardware with appropriate gearing and design, this can greatly reduce wasted power andreduce motor/driver over-heating. making it an excellent option for long-term timelapse or field use.
The minimum step delay is expressed in micro-seconds. It determines the minimum amount of time between step pulses.
You must configure this amount to a safe amount for your motor/controller combination. Too low of a value, and your motor will miss steps, too high of a value and your movements will take longer than they should.
Valid values are 1uS to 65,536uS.
The maximum step delay is also expressed in micro-seconds, it is the longest delay between step pulses.
The difference between this and the minimum step delay determines the overall velocity when making a series of steps. There should be enough difference between these two to smoothly ramp up to speed. For clean velocity ramps, one should set the maximum step delay to be several times larger than the minimum step delay.
Valid values are 1uS to 65,536uS.
This is the minimum amount of time to delay after motor movements before triggering an exposure. It is defined in milli-seconds. If the combination of all times (alt trigger, post-delay, motor move execution times, any keyframe execution, etc.) exceed the interval cycle time, this timer will be used to prevent the camera from firing immediately after the motor movement executes, allowing a small amount of time for any motion to settle. This setting is not available via the serial protocol and must be controlled via a #define in the sketch.
The OpenMoco Timelapse Engine supports the storage of up to sixteen pre-recorded actions that can be called at motor, camera, or time keyframes or during a camera repeat cycle. These actions provide control over most of the aspects of the currently running program.
There are three core types of actions:
These actions correspond to the controls they make available.
Each action is indexed, starting at zero. The index position allows you to call it from any number of keyframes, delete, or overwrite.
If you add an action at an index position that has already been used, it will overwrite the previously recorded action, allowing you to use more than sixteen by overwriting ones that are no longer needed.
A camera action allows you to execute any of the following controls:
If the camera has been disabled, this control allows you to re-enable it. It also allows you to set a new interval time, in seconds, from 1-65,536
This control disables the camera
This control allows you to set the exposure time for the camera in mS, from 0 to 65,536. (65.5 seconds)
This control allows you to multiply the current exposure time, from .000001x to 65,536x
note: exposure multiplication actions are modified by the global parameter 'exposure action modifier' - this allows you to specify how much to divide the value used for multiply/divide actions. E.g., if set to 10, and you call a multiply action of 1, the current exposure time would be set to ( exposure * (1/10) ), or 1/10th of the current exposure time.
Motor:
A motor action always requires you to define the motor number to operate against.
Direction/Enable:
Every motor action requires you to set the direction of the motor (0, 1, reverse, or unchanged), and enable value (on, off, inverted, unchanged) for the given motor.
The following additional controls are provided in addition to setting direction and enable/disable:
This control allows you to set the number of steps for the given motor, from 0 to 65,536.
This control allows to tell a given motor to move a given number of steps each time this action is called. Steps are 0 to 65,536.
This causes the given motor to immediately begin executing its downward ramp. This is especially useful if you have not defined a maximum number of steps to take for the given motor, and instead use a keyframe to control when the motor will begin its downward ramp.
A program action allows you to execute any of the following controls:
Start a paused/stopped program
Pause the currently running program
Stop/Clear the currently running program
Keyframes allow you to trigger actions at different times, based on the current information about the camera shot cycles completed, the number of steps a given motor has moved, or the amount of time that has elapsed since the program began running.
There are three types of keyframes:
You can store up to sixteen keyframes of each type.
Each keyframe type is indexed, like actions are, from 0-15, allowing you to specify which keyframe position to write to/overwrite.
Each type of keyframe defines when it triggers:
Each keyframe also specifies the action index to execute when the keyframe triggers. You may use multiple keyframes to trigger the same action at different times, but you may only trigger one action per keyframe.
Keyframes are executed when their given trigger is reached or exceeded, therefore you can always trigger immediate execution of a given keyframe by setting its value to one. Multiple keyframes of the same type may be stored with the same trigger value, allowing you to trigger multiple actions at the same time.
Once a keyframe has been executed, it is removed from memory, to prevent it from triggering multiple times. This also means the keyframes may be written to again, allowing you to continue to add keyframes once they've been executed.
All communications with the TimeLapse Engine via a computer or connected device utilize a standard serial protocol that enables parameters and commands to be sent, and provides the ability to read data back from the engine.
For all communications, a command or response byte is sent, followed by a data length byte, and then the specified number of bytes of data. Some commands and responses require no data, so the minimum number of bytes that is considered a valid communication is two (command/response + data length of zero).
Commands flow to the Engine from a connected device, and have the following structure:
| Command Byte | Data Length Byte | Data Byte 1 | Data Byte 2 | ... | Data Byte n |
Please note, that '0' (binary zero, or 0x00) is an invalid command byte value - all valid commands must be a positive value (1-255).
The data length byte's value should always exclude the two bytes used for command and data length, it is used to express how many bytes follow the data length byte.
After a command has been executed, a response is returned by the engine, the response has the following structure:
| Response Value Byte | Data Length Byte | Data Byte 1 | Data Byte 2 | ... | Data Byte n |
By default, the engine always uses a response value of zero (0x00) to indicate that a command failed, or was unknown, and a response value of one (0x01) to indicate the command succeeded.
Whenever the engine returns zero as the response byte value, the data length byte will be zero.
The following table describes common responses:
| Response | Response Value Byte | Data Length Byte | Data Byte 1 | Data Byte 2 |
|---|---|---|---|---|
| error | 0 | 0 | n/a | n/a |
success (no data) | 1 | 0 | n/a | n/a |
| success (one byte of data) | 1 | 1 | byte | n/a |
| success (16-bit response) | 1 | 2 | 16-bit integer MSB | 16-bit integer LSB |
Please note that in the above responses, there is nothing to indicate whether multiple types of data are being sent, or what the sign of the provided data type is. The consuming software is expected to be aware of the responses they anticipate to certain commands, and deal with them appropriately.
Each command has several sub-commands, these sub-commands are sent as the first data byte. Therefore, all valid commands will have a data length of at least one byte.
Please remember, that all values used in the TimeLapse Engine protocol are binary, and should be communicated as the data type specified, not the ASCII representation of that data. The data types used in this documentation should be mapped against the Arduino data types, e.g.: int is a 16-bit value.
All multi-byte values must be sent in Big-Endian format, meaning the most significant byte comes first, and the least significant comes last.
The following table lists the basic commands, click on the command name for documentation:
| Command | Command Byte Value |
|---|---|
| Engine Control | 1 |
| Set Program Information | 2 |
The Engine Control command provides access to commands that control the operation of the engine, or report current status of the engine. Each Engine Control command will use the command byte value of '1'. The following table lists each sub-command:
| Name | Data Length | Sub.Com (DB1) | DB2 | DB3 | DB4 | DB5 | Info | |
|---|---|---|---|---|---|---|---|---|
| noop | 1 | 0 | n/a | Non-operative, always returns true. Used for checking to see if the engine is awake and ready for a command. | ||||
| start | 1 | 1 | n/a | Start the current program,or resume from pause. | ||||
| pause | 1 | 2 | n/a | Pause program execution. | ||||
| stop | 1 | 3 | n/a | Stop the current program, moved steps, time spent, shots fired and other statistics are reset. | ||||
| camera enable | 1 | 4 | n/a | Enable the camera for use | ||||
| camera disable | 1 | 5 | n/a | Disable the camera for use | ||||
| move motor now | 5 | 6 | motor # | direction | steps (unsigned int) | Move the given motor the specified number of steps. (Blocking) | ||
| send motor home | 2 | 7 | motor # | Send the given motor to its home position. (Blocking) | ||||
| fire camera now | 5 | 8 | exposure time - ms (unsigned long) | Expose the camera immediately. (Non-Blocking) | ||||
| motor sleep line | 2 | 9 | on/off | Enable or disable the motor sleep line. This causes the motor sleep pin to be brought low between movements to reduce power consumption. | ||||
| min step delay | 3 | 10 | microseconds (unsigned int) | Set minimum delay between motor steps. | ||||
| max step delay | 3 | 11 | microseconds (unsigned int) | Set maximum delay between motor steps. | ||||
| down ramp now | 12 | motor # | Execute a down ramp on the given motor now (used outside of actions/keyframes) | |||||
| exposure action mod | 3 | 13 | divisor (unsigned int) | Divide the value specified in any exposure multiplication action by this value. This is how you would decrease or increase exposure time in fractions of a whole. | ||||
| current status | varies | 100 | status value | Get value of different operating parameters. See documentation on status values below. | ||||
Send a start command to the engine:
| Command Byte | Data Length Byte | Sub-Com (DB1) |
| 1 | 1 | 1 |
Send motor #2 home:
| Command Byte | Data Length Byte | Sub-Com (DB1) | Data Byte 2 |
| 1 | 2 | 7 | 2 |
The Current Status sub-command allows one to retrieve a number of details about the current state of the engine. Each request must include a parameter which one is requesting the value of. The parameter is a single-byte integer which is sent as the second data byte in the command. All current status requests will respond with at least one byte of data when the request is successful.
The following table lists all parameter values:
| Name | Parameter Value (DB2) | DB3 | Returns | Info |
|---|---|---|---|---|
| api version | 0 | n/a | byte | Returns current API version # |
| running status | 1 | n/a | byte | Returns 0 if engine stopped/paused, or 1 if engine currently running |
| run time | 2 | n/a | unsigned long | Returns current program run time, in ms |
| camera status | 3 | n/a | byte | Returns 0 if camera disabled, 1 if camera enabled |
| shot count | 4 | n/a | unsigned long | Returns count of shots fired in currently running program |
| interval time | 5 | n/a | unsigned int | Returns currently set interval time |
| exposure time | 6 | n/a | unsigned long | Returns currently set exposure time, in ms |
| post time | 7 | n/a | unsigned int | Returns currently set post-exposure delay time, in ms |
| currently exposing | 8 | n/a | byte | Returns 1 if camera is currently exposing, 0 if not |
| motor enabled | 9 | motor # | byte | Returns 1 if given motor is enabled, 0 if not |
| motor dir | 10 | motor # | byte | Returns direction set for given motor |
| motor steps moved | 11 | motor # | unsigned long | Returns # of steps moved by motor in current program |
| motor dist from home | 12 | motor # | signed long | Returns distance from home (negative if in 0 direction, positive if in 1 direction) |
| reserved | 13 | |||
| motor max step | 14 | motor # | unsigned long | Returns max steps setting for the given motor |
| motor ramp | 15 | motor # | byte | Returns motor ramp value for the given motor |
| motor backlash | 16 | motor # | byte | Returns motor backlash comp. amount for given motor |
| motor steps | 17 | motor # | unsigned int | Returns # of steps between shots for the given motor |
| camera keyframe | 18 | keyframe index | unsigned long | Returns keyframe value at given index |
| time keyframe | 19 | keyframe index | unsigned long | Returns keyframe value at given index |
| motor keyframe | 20 | keyframe index | unsigned long | Returns keyframe value at given index |
| action | 21 | action index | unsigned long | Returns action value at given index |
Some status requests are only meaningful if the program is started or paused, such as shots fired and run time.
Ensure that you pay close attention to the response type, and its sign!
Request the current exposure time setting:
| Command Byte | Data Length Byte | Sub-Com (DB1) | Parameter (DB2) |
|---|---|---|---|
| 1 | 2 | 100 | 6 |
Response from Engine:
| Response Value Byte | Data Length Byte | DB1 | DB2 | DB3 | DB4 |
|---|---|---|---|---|---|
| 1 | 4 | exposure time (unsigned long) | |||
The Set Program Information command allows you to control the different parameters that are used during the running of a program. This is essentially how a time-lapse or similar program is created. You set the different parameters controlling how your program will operate, and then start the execution of the program. Every value is read immediately before it is used by the engine, so you are able to modify parameters on the fly, and have them take effect the next time that value would be used.
Each Program Information command will use the command byte value of 2.
The set program information provides a number of sub-commands, grouping parameters by type. The following table lists each sub-command:
| Name | Sub-Command (DB1) | Info |
|---|---|---|
| camera | 1 | Set camera parameters |
| motor | 2 | Set motor parameters |
| action | 3 | Add/Remove actions |
| keyframe | 4 | Add/Remove keyframes |
When specifying a sub-command, you must also specify which parameter you want to modify as a next byte, the sections below detail each sub-command, and the available parameters.
No Set Program Information command returns any data, only a positive response with zero data bytes will be returned for any set program info command.
The Camera sub-command allows you to control all camera parameters. The following parameters are supported:
| Name | Data Length Byte | Sub-Com (DB1) | Param (DB2) | DB3 | DB4 | DB5 | DB6 | Info |
|---|---|---|---|---|---|---|---|---|
| interval | 4 | 1 | 1 | interval (unsigned int) | Sets the interval between camera shots | |||
| exposure time | 6 | 1 | 2 | exposure tm (unsigned long) | Sets exposure time in milliseconds | |||
| pre-focus tap time | 4 | 1 | 3 | tap tm (unsigned int) | Set amount of time to bring focus pin high before firing camera (0 to disable focus tap) | |||
| max shots | 4 | 1 | 4 | shot count (unsigned int) | Set maximum number of exposures to take during program | |||
| post delay time | 4 | 1 | 5 | delay tm (unsigned int) | Set amount of time to delay after completing exposure, and before moving motors | |||
| focus with shutter | 3 | 1 | 6 | on/off (1 or 0) | Set whether to always bring focus pin high with shutter pin -- 0 to disable, 1 to enable. | |||
| camera cycle repeat count | 3 | 1 | 7 | count | Set repeat cycle (see documentation) count | |||
| camera cycle add repeat action | 4 | 1 | 8 | cycle action index (0-3) | action id (0-15) | Add an action to be called between each repeat shot in a repeat cycle | ||
| camera cycle add complete action | 4 | 1 | 9 | complete action index (0-3) | action id (0-15) | Add an action to be called at the completion of a camera repeat cycle | ||
| camera cycle return motors home upon cycle complete | 3 | 1 | 10 | on/off (1 or 0) | Set whether or not to send all motors back to the point where they were at the beginning of a repeat cycle. | |||
For more information on the camera repeat cycle functions, see the Cycle Repeat documentation.
Example:
Set intervalometer:
| Command Byte | Data Length Byte | Sub-Com (DB1) | Parameter (DB2) | DB3 | DB4 |
|---|---|---|---|---|---|
| 2 | 4 | 1 | 1 | interval sec. (unsigned int) | |
The Motor sub-command allows you to control all motor parameters.
Each parameter requires a motor number to apply the parameter to. Valid motor numbers are 0-3. You may change any parameter while a program is running, e.g. you could set up each axis initially, and only turn them on as needed during the course of executing your program.
The following parameters are supported:
| Name | Data Length Byte | Sub-Com (DB1) | Param (DB2) | DB3 | DB4 | DB5 | DB6 | DB7 | Info |
|---|---|---|---|---|---|---|---|---|---|
| steps | 4 | 2 | 1 | motor # | steps (unsigned int) | Set # of steps between camera shots for the given motor | |||
| ramp rate | 4 | 2 | 2 | motor # | ramp rate | Set # of exposures to ramp up to full speed/down to stop for the given motor | |||
| direction | 4 | 2 | 3 | motor # | dir (0 or 1) | Set the direction of travel for the given motor | |||
| max steps | 7 | 2 | 4 | motor # | steps (unsigned long) | Set the maximum number of steps to travel in the program for the given motor | |||
| enable | 3 | 2 | 5 | motor # | Enable the given motor | ||||
| disable | 3 | 2 | 6 | motor # | Disable the given motor | ||||
| set home | 3 | 2 | 7 | motor # | Set current position as 'home' for the given motor | ||||
| backlash comp | 4 | 2 | 8 | motor # | steps | Set the number of steps of backlash to compensate for, for the given motor | |||
Example:
Set ramp rate for motor #0:
| Command Byte | Data Length Byte | Sub-Com (DB1) | Parameter (DB2) | DB3 |
|---|---|---|---|---|
| 1 | 2 | 100 | 2 | ramp rate (byte) |
The Action sub-command allows you to create and remove actions for use by keyframes or in a repeat shot cycle. Up to sixteen total actions may be stored, each specified by an index value (0-15). You may, at any time, over-write any existing action, or remove it to prevent it from being called again in the future.
Actions can change parameters, or control program execution. There are four basic action controls:
| Name | Control (DB2) | Info |
|---|---|---|
| camera | 1 | Changes parameters related to camera control |
| motor | 2 | Changes parameters related to motor control |
| program | 3 | Changes program execution |
| delete | 4 | Deletes an action from memory |
Each action control will be followed by a single byte, specifying the action index to write to/delete. The legal values for an action index are 0-15.
Each action request should begin with the following 5-byte sequence:
| Command Byte | Data Length Byte | Sub-Com (DB1) | Control (DB2) | Action Index (DB3) |
| 2 | length | 3 | control | index |
length, control, and index will vary with each action command.
When creating a camera control action, you can choose which camera setting you want to change. The setting to change is defined by the 'type' parameter, that is specified in the 4th data byte. The following table details which controls are available, and the data to send from the data length byte:
| Name | DLB | Sub-Com (DB1) | Cntrl (DB2) | IDX (DB3) | Type (DB4) | DB5 | DB6 | Info |
|---|---|---|---|---|---|---|---|---|
| enable | 6 | 3 | 1 | index | 1 | interval (unsigned int) | Enables the camera and sets the interval time. (Interval time is optional, if 0 the interval is unchanged) | |
| disable | 4 | 3 | 1 | index | 2 | Disables the camera | ||
| exposure tm | 6 | 3 | 1 | index | 3 | exp tm (unsigned int) | Sets exposure time to given amount of milliseconds | |
| exposure mult. | 6 | 3 | 1 | index | 4 | multiplier (unsigned int) | Multiplies exposure time by multiplier | |
Example:
Set Action Index #0 to set exposure time for camera
| Command Byte | Data Length Byte | Sub-Com (DB1) | Control (DB2) | Action Index (DB3) | Type (DB4) | DB5 | DB6 |
| 2 | 6 | 3 | 1 | 0 | 3 | exposure tm (unsigned int) | |
Motor control actions all require a motor number, enable/disable flag, direction, and command. This means that you may, in a single action, enable a motor, set direction, and change an operating parameter for a motor. The following table lists each command and its arguments:
note: DB1-DB3 (sub-com through index) are omitted for brevity
| Name | DLB | Motor (DB4) | Enable (DB5) | Dir (DB6) | Command (DB7) | DB8 | DB9 | Info |
|---|---|---|---|---|---|---|---|---|
| set steps | 9 | motor # | 0-3 | 0-3 | 1 | steps (unsigned int) | Sets steps between shots for the given motor | |
| ramp down | 7 | motor # | 0-3 | 0-3 | 2 | Execute a downramp for given motor, starting with the next movement | ||
| move now | 9 | motor # | 0-3 | 0-3 | 3 | steps (unsigned int) | Execute a move now with given motor | |
| enable/dir change only | 7 | motor # | 0-3 | 0-3 | 4 | Change only direction/enable parameter for motor | ||
The Enable Flag allows you to specify how to modify the Enable parameter for the given motor via this action:
| Enable Value | Info |
|---|---|
| 0 | Set motor enable to 'disabled' |
| 1 | Set motor enable to 'enabled' |
| 2 | Set motor enable to the opposite of its current value (invert) |
| 3 | Leave motor enable unchanged |
The Direction Flag allows you to specify how to modify the Direction of the given motor via this action:
| Direction Value | Info |
|---|---|
| 0 | Set motor direction to '0' |
| 1 | Set motor direction to '1' |
| 2 | Set motor direction to the opposite of its current value (invert) |
| 3 | Leave motor direction unchanged |
Program control actions control execution of the currently running program. Start is included for completeness, but as keyframes cannot run when the program is not running, it would be difficult to call. The following table lists each available command for this action type, from the Data Length Byte:
| Name | DLB | Sub-Com (DB1) | Cntrl (DB2) | IDX (DB3) | Type (DB4) | Info |
|---|---|---|---|---|---|---|
| stop | 4 | 3 | 3 | index | 1 | stop program execution |
| start | 4 | 3 | 3 | index | 2 | start program execution |
| pause | 4 | 3 | 3 | index | 3 | pause program execution |
The Delete Action control allows you to remove an action that you had previously stored.
| Name | DLB | Sub-Com (DB1) | Cntrl (DB2) | IDX (DB3) | Info |
|---|---|---|---|---|---|
| delete | 3 | 3 | 4 | index | delete action at the given index |
The Keyframe sub-command allows you to place a keyframe at a specified point in the program. Each keyframe can trigger an action you have defined with the Action sub-command. Keyframes can be set for motor positions, exposures, or points in time. That is, if you created an action that modified the time interval between exposures, you could call it when a motor has moved 10,000 steps, or when you've taken 50 exposures, or even when the program has been running for two hours.
There are three primary types of keyframes: motor, camera, and time. Each type can hold up to sixteen keyframes, and are identified by a keyframe index ranging from 0-15. Once a keyframe has been activated, it is removed from memory so that you may re-use its position if needed, and so that it does not trigger again. All keyframes require an action index for the action to call, and motor keyframes require you to specify the motor # for the distance measurement.
The following table lists each type of keyframe:
| Name | DLB | Sub-Com (DB1) | Type(DB2) | IDX (DB3) | Value (DB4) | Motor (DB5) | Action IDX (DB6) | Info |
|---|---|---|---|---|---|---|---|---|
| camera | 6 | 4 | 1 | index | 1 | 0 | action index | call action at exposure value |
| motor | 6 | 4 | 2 | index | 2 | motor # | action index | call action at motor dist. moved |
| time | 6 | 4 | 3 | index | 3 | 0 | action index | call action at given run length |
The OpenMoco Time-lapse engine is designed a minimal amount of hardware, using an easy circuit design that can be readily bread-boarded, or soldered to perf-board.
The following schematic shows the basic layout of the circuit, with the arduino in the center, and the default pin connections to motors, camera, alt, etc.
Click on the thumbnail for a full-size image.
To build the above circuit, you will need the following parts:
The following connections must be made to the arduino:
M0_STEP, M1_STEP, M2_STEP
The arduino pins marked for connection to Mx_STEP connect to the "STEP" pin of your stepper motor's controller.
Each connection should include a diode in-line, allowing the flow of current from the arduino to the stepper controller. These diodes will prevent the stepper driver from feeding back electricity and damaging the arduino. If your stepper drivers provide protection diodes, you may still wish to use your own to prevent the possibility of reverse voltage should you experience a short elsewhere.
Note: this circuit is only designed to work with stepper motor drivers that operate using a single input for step, and a single input for direction.
M0_DIR, M1_DIR, M2_DIR
The arduino pins marked for connection to Mx_DIR connect to the "DIRECTION" pin of your stepper motor's controller.
Each connection should include a diode in-line, allowing the flow of current from the arduino to the stepper controller. These diodes will prevent the stepper driver from feeding back electricity and damaging the arduino. If your stepper drivers provide protection diodes, you may still wish to use your own to prevent the possibility of reverse voltage should you experience a short elsewhere.
M0_GND, M1_GND, M2_GND
The arduino pins marked for connection to Mx_GND connect to the GROUND of your stepper motor's controller.
You MUST connect the ground of your controller to the ground of the arduino, otherwise you will not be able to trigger them.
SUART_TX, SUART_RX
The arduino pins 2 and 3 are used to provide a software UART (serial) connection to another microcontroller or computer. This connection is used when a secondary interface is connected.
If you connect the software UART to another device, you must connect its ground (SUART_GND) to the arduino's ground.
CAM_SHUTR, CAM_FOCS, CAM_COM
To control your camera, you must connect, at a minimum, the shutter control line and the common line (The tip and ring on a Pentax remote cable using a 2.5mm stereo plug) through the transistor side of optocoupler OK2.
If you wish to control the auto-focus on your camera, you must connect the focus control line and the common line (sleeve and ring on Pentax remote cable) through the transistor side of the optocoupler OK1.
A 510-ohm resistor should be placed between the arduino pin and the anode of the optocoupler.
| Attachment | Size |
|---|---|
| openmoco-circuit.png | 8.88 KB |