|
1 |
| -# blender-servo-animation-arduino |
| 1 | +# Blender Servo Animation Arduino Library |
| 2 | + |
| 3 | +This library helps to control servos based on an exported Blender animation. It is specifically designed to work with the [Blender Servo Animation Add-on](https://github.com/timhendriks93/blender-servo-animation). |
| 4 | + |
| 5 | +## Installation |
| 6 | + |
| 7 | +Please refer to the official [Arduino documentation](https://docs.arduino.cc/software/ide-v1/tutorials/installing-libraries) to see how you can install this library. |
| 8 | + |
| 9 | +## Usage |
| 10 | + |
| 11 | +To start using this library, add the following include statement to your script or sketch: |
| 12 | + |
| 13 | +```ino |
| 14 | +#include <BlenderServoAnimation.h> |
| 15 | +``` |
| 16 | + |
| 17 | +## Namespace |
| 18 | + |
| 19 | +To avoid naming conflicts, the library uses the `BlenderServoAnimation` namespace. For example, this allows to use the standard Arduino Servo library to control the servos while using the `Servo` class of this library to represent the servo within the Blender animation: |
| 20 | + |
| 21 | +```ino |
| 22 | +// Standard library servo object |
| 23 | +Servo(...); |
| 24 | + |
| 25 | +// Blender servo object |
| 26 | +BlenderServoAnimation::Servo(...); |
| 27 | + |
| 28 | +// Blender animation object |
| 29 | +BlenderServoAnimation::Animation(...); |
| 30 | +``` |
| 31 | +
|
| 32 | +When not using the standard servo library, you can use the namespace and therefore skip the namespace prefix: |
| 33 | +
|
| 34 | +```ino |
| 35 | +using namespace BlenderServoAnimation; |
| 36 | +
|
| 37 | +// Blender servo object |
| 38 | +Servo(...); |
| 39 | +
|
| 40 | +// Blender animation object |
| 41 | +Animation(...); |
| 42 | +``` |
| 43 | + |
| 44 | +## Defining Servos |
| 45 | + |
| 46 | +Before we can play back and control an animation, we first have to create and attach representations of the animated servos. There are 4 possible syntaxes to create a new servo object: |
| 47 | + |
| 48 | +```ino |
| 49 | +Servo(id, positions, callback); |
| 50 | +Servo(id, positions, callback, threshold); |
| 51 | +Servo(id, callback); |
| 52 | +Servo(id, callback, threshold); |
| 53 | +``` |
| 54 | +
|
| 55 | +> Note: servos without positions will only be considered when in live mode. |
| 56 | +
|
| 57 | +### Servo Parameters |
| 58 | +
|
| 59 | +| Parameter | Type | Description | |
| 60 | +|-----------|------|-------------| |
| 61 | +| id | byte | Unique servo ID as specified via the Add-on | |
| 62 | +| positions | const int[] | Exported positions per frame | |
| 63 | +| callback | void (byte, int) | Function to trigger when a servo is moved | |
| 64 | +| threshold | byte | Max allowed position diff (default=20) | |
| 65 | +
|
| 66 | +### Callback Function |
| 67 | +
|
| 68 | +The callback function is used to specify what should happen when a servo needs to be moved to a new position. It will be automatically triggered by the animation instance and receives 2 arguments - the servo ID as `byte` and the new position as `int`: |
| 69 | +
|
| 70 | +```ino |
| 71 | +void myServoCallback(byte servoID, int position) { |
| 72 | + // Do something |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +This allows to implement any kind of logic to handle the actual servo control. When using this library outside of the Arduino IDE, it is recommended to define the callback function first before passing it as an argument when creating a servo object: |
| 77 | + |
| 78 | +```ino |
| 79 | +#include "simple.h" |
| 80 | +#include <BlenderServoAnimation.h> |
| 81 | + |
| 82 | +using namespace BlenderServoAnimation; |
| 83 | + |
| 84 | +void move(byte servoID, int position) { |
| 85 | + // Do something |
| 86 | +} |
| 87 | + |
| 88 | +Servo myBlenderServo(0, Bone, move); |
| 89 | +``` |
| 90 | +
|
| 91 | +## Defining an Animation |
| 92 | +
|
| 93 | +The animation object serves as a control instance to play back the servo movement. Just like in Blender, an animation can be played, paused and stopped. To do so, we need to provide information about the speed and length of the animation. To just use control servos via the live mode (serial connection), we can omit this information. Therefore, an animation can be created via the following 2 syntaxes: |
| 94 | +
|
| 95 | +```ino |
| 96 | +Animation(); |
| 97 | +Animation(fps, frames); |
| 98 | +``` |
| 99 | + |
| 100 | +> Note: animations without fps and frames will only be able to handle the live mode. |
| 101 | +
|
| 102 | +### Animation Parameters |
| 103 | + |
| 104 | +| Parameter | Type | Description | |
| 105 | +|-----------|------|-------------| |
| 106 | +| fps | byte | Frames per second as specified in Blender | |
| 107 | +| frames | int | Total amount of frames as specified in Blender | |
| 108 | + |
| 109 | +In general, the provided values should align with the Blender animation you would like to export or work on. Given that the Blender animation consists of 1000 frames and plays back at a rate of 30 frames per second, the animation object should be created as follows: |
| 110 | + |
| 111 | +```ino |
| 112 | +Animation myBlenderAnimation(30, 1000); |
| 113 | +``` |
| 114 | +
|
| 115 | +### Registering Servos |
| 116 | +
|
| 117 | +To actually trigger servo movement, the animation needs to know about the individual servos. After defining the servos as mentioned above, we therefore have to register them to the animation by calling the `addServo` method: |
| 118 | +
|
| 119 | +```ino |
| 120 | +myBlenderAnimation.addServo(myBlenderServo); |
| 121 | +``` |
| 122 | + |
| 123 | +This is usually done inside the `setup` function after the servo objects have been defined globally (outside of any function like `setup` or `loop`). |
| 124 | + |
| 125 | +Alternatively, we can also create an array of servos and call the `addServos` method instead: |
| 126 | + |
| 127 | +```ino |
| 128 | +Servo myBlenderServos[] = { |
| 129 | + Servo(0, BoneA, move), |
| 130 | + Servo(1, BoneB, move), |
| 131 | + Servo(2, BoneC, move), |
| 132 | + ... |
| 133 | +} |
| 134 | + |
| 135 | +Animation myBlenderAnimation(30, 1000); |
| 136 | + |
| 137 | +void setup() { |
| 138 | + myBlenderAnimation.addServos(myBlenderServos); |
| 139 | +} |
| 140 | +``` |
| 141 | +
|
| 142 | +### Updating the Animation State |
| 143 | +
|
| 144 | +The animation needs to be triggered regularly in order to update its state and check if any servos have to be moved. We therefore need to call the `run` method during each `loop`: |
| 145 | +
|
| 146 | +```ino |
| 147 | +void loop() { |
| 148 | + myBlenderAnimation.run(); |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +### Animation Modes |
| 153 | + |
| 154 | +At first, an animation will be in the default mode. In this mode, the animation is simply not playing and waiting until the mode is changed. |
| 155 | + |
| 156 | +| Mode | Description | |
| 157 | +|------|-------------| |
| 158 | +| default | Not playing / waiting | |
| 159 | +| play | Playing back the animation | |
| 160 | +| pause | Pausing the animation at the current frame | |
| 161 | +| stop | Slowly moving the servos to their neutral position | |
| 162 | +| live | Reading serial commands to move the servos in real-time | |
| 163 | + |
| 164 | +The modes can be changed or triggered via the following methods: |
| 165 | + |
| 166 | +```ino |
| 167 | +myBlenderAnimation.play(); |
| 168 | +myBlenderAnimation.pause(); |
| 169 | +myBlenderAnimation.stop(stepDelay); |
| 170 | +myBlenderAnimation.live(stream); |
| 171 | +``` |
| 172 | + |
| 173 | +> Note: the default mode is only handled internally. |
| 174 | +
|
| 175 | +When calling the `stop` method, it is possible to pass a delay in milliseconds. This delay will be used when the servos are moved to their neutral position during the stop mode. To get to the neutral position, the current position will either be increased or decreased by 1. The delay therefore controls how fast or smooth this movement will take place. The default value for this parameter is `20`. |
| 176 | + |
| 177 | +To use the `live` method, we have to pass a stream instance which will be used for reading serial commands. For example, we can pass `Serial` if we want to use the standard USB connection of an Arduino compatible board: |
| 178 | + |
| 179 | +```ino |
| 180 | +void setup() { |
| 181 | + Serial.begin(115200); |
| 182 | + myBlenderAnimation.live(Serial); |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +Make sure to check out the [examples](examples) to get started quickly and learn more about using this library with your Arduino sketches / programs. |
0 commit comments