Skip to content

Commit

Permalink
rename namespace and animation class
Browse files Browse the repository at this point in the history
  • Loading branch information
timhendriks93 committed Jul 27, 2024
1 parent c3df1ff commit e50f830
Show file tree
Hide file tree
Showing 38 changed files with 411 additions and 512 deletions.
121 changes: 18 additions & 103 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This library helps to control servos based on an exported Blender animation. It

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.

## Quick Start

Take a look at the [StandardServoLib](examples/StandardServoLib) example to get started quickly. It represents the most simple setup and is based on the standard Servo Arduino library with which you might already be familiar.

## Usage

To start using this library, add the following include statement to your script or sketch:
Expand All @@ -16,100 +20,39 @@ To start using this library, add the following include statement to your script
#include <BlenderServoAnimation.h>
```

## Namespace

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:

```ino
// Standard library servo object
Servo(...);

// Blender servo object
BlenderServoAnimation::Servo(...);

// Blender animation object
BlenderServoAnimation::Animation(...);

// Blender show object
BlenderServoAnimation::Show();
```
When not using the standard servo library, you can use the namespace and therefore skip the namespace prefix:
```ino
using namespace BlenderServoAnimation;
// Blender servo object
Servo(...);
// Blender animation object
Animation(...);
// Blender show object
Show();
```
## Defining an Animation

## Defining Servos
The animation object serves as a control instance to play back the servo movement. Just like in Blender, an animation can consist of multiple scenes and can be triggered to play, pause and stop.

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:
Start simply by creating a new animation instance at the outer scope of your sketch (outside of `setup` and `loop`):

```ino
Servo(id, positions, callback);
Servo(id, positions, callback, threshold);
Servo(id, callback);
Servo(id, callback, threshold);
BlenderServoAnimation animation;
```

> Note: servos without positions will only be considered when in live mode.
### Servo Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| id | byte | Unique servo ID as specified via the Add-on |
| positions | const&#160;int[] | Exported positions per frame |
| callback | void&#160;(byte,&#160;int) | Function to trigger when a servo is moved |
| threshold | byte | Max allowed position diff (default=0 / no threshold handling) |
### Define the Position Change Callback

> Note: the threshold is also used to define the speed for moving a servo to its neutral position when stopping an animation.
### Callback Function
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`:
To specify what should happen when a servo needs to be moved to a new position, we have to define a callback function. It receives 2 arguments - the servo ID as `byte` and the new position as `int`:

```ino
void myServoCallback(byte servoID, int position) {
// Do something
}
```

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:

```ino
#include "simple.h"
#include <BlenderServoAnimation.h>

using namespace BlenderServoAnimation;

void move(byte servoID, int position) {
// Do something
// Custom logic to move the servo
}

Servo myBlenderServo(0, Bone, move);
```
## Defining an Animation
This allows the implementation of any logic to handle the actual servo control. For example, you can make use of the standard Servo library for simple setups or add logic to control servos via PWM control boards such as the PCA9685.
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:
After defining the callback function, we need to register it via the `onPositionChange` method of the animation instance:
```ino
Animation();
Animation(fps, frames);
animation.onPositionChange(move);
```

> Note: animations without fps and frames will only be able to handle the live mode.
### Adding Scenes and Animation Data

Before we can play back and control an animation, we first have to add at least one scene to our animation. There are 2 ways to do this depending on the type of animation data you want to provide:

### Animation Parameters
1. test

| Parameter | Type | Description |
|-----------|------|-------------|
Expand All @@ -122,34 +65,6 @@ In general, the provided values should align with the Blender animation you woul
Animation myBlenderAnimation(30, 1000);
```
### Registering Servos
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:
```ino
myBlenderAnimation.addServo(myBlenderServo);
```

This is usually done inside the `setup` function after the servo objects have been defined globally (outside of any function like `setup` or `loop`).

Alternatively, we can also create an array of servos and call the `addServos` method instead:

```ino
Animation myBlenderAnimation(30, 1000);

Servo myBlenderServos[] = {
Servo(0, BoneA, move),
Servo(1, BoneB, move),
Servo(2, BoneC, move),
}

void setup() {
myBlenderAnimation.addServos(myBlenderServos, 3);
}
```
> Note: the `addServos` function expects the amount of servos in the array to be passed via the second argument.
### Updating the Animation State
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`:
Expand Down
2 changes: 1 addition & 1 deletion examples/AdafruitPCA9685/AdafruitPCA9685.ino
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void move(byte servoID, int position) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

#define POWER_PIN 19

Expand Down
2 changes: 1 addition & 1 deletion examples/MultiplePCA9685/MultiplePCA9685.ino
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Adafruit_PWMServoDriver pwmA(0x40);
Adafruit_PWMServoDriver pwmB(0x41);

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

// We use a struct to map a servo to a PCA9685 board and channel
struct servoMapping {
Expand Down
8 changes: 3 additions & 5 deletions examples/MultipleScenes/MultipleScenes.ino
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/*
Setting up an animation consisting of 2 scenes.
Note the namespaces which are used to distinguish the positions
of one scene / animation from another. It's even possible to
have different playback rates (fps) and frames per animation.
It's even possible to have different playback rates (fps)
and frames per animation.
*/

#include "scene-a.h"
Expand All @@ -28,7 +26,7 @@ void move(byte servoID, int position) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

void setup() {
// Attach the servo to the defined servo pin
Expand Down
8 changes: 3 additions & 5 deletions examples/MultipleScenesSD/MultipleScenesSD.ino
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/*
Setting up a show consisting of 2 animations.
Note the namespaces which are used to distinguish the positions
of one scene / animation from another. It's even possible to
have different playback rates (fps) and frames per animation.
It's even possible to have different playback rates (fps)
and frames per animation.
*/

#include <BlenderServoAnimation.h>
Expand Down Expand Up @@ -61,7 +59,7 @@ void changeSceneFile(byte prevSceneIndex, byte nextSceneIndex) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

void setup() {
Serial.begin(9600);
Expand Down
2 changes: 1 addition & 1 deletion examples/SDAnimation/SDAnimation.ino
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void resetFile(byte prevSceneIndex, byte nextSceneIndex) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

void setup() {
Serial.begin(9600);
Expand Down
2 changes: 1 addition & 1 deletion examples/SerialLiveMode/SerialLiveMode.ino
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void move(byte servoID, int position) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

void setup() {
// Initialize serial communication
Expand Down
2 changes: 1 addition & 1 deletion examples/StandardServoLib/StandardServoLib.ino
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void move(byte servoID, int position) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

void setup() {
// Attach the servo to the defined servo pin
Expand Down
20 changes: 10 additions & 10 deletions examples/SwitchModeButton/SwitchModeButton.ino
Original file line number Diff line number Diff line change
Expand Up @@ -46,37 +46,37 @@ void move(byte servoID, int position) {
// Callback function which is called whenever the animation mode changes
void modeChanged(byte prevMode, byte newMode) {
switch (newMode) {
case BlenderServoAnimation::Animation::MODE_PLAY:
if (prevMode == BlenderServoAnimation::Animation::MODE_PAUSE) {
case BlenderServoAnimation::MODE_PLAY:
if (prevMode == BlenderServoAnimation::MODE_PAUSE) {
// E.g. resume audio
} else {
// E.g. start audio
}
break;
case BlenderServoAnimation::Animation::MODE_PAUSE:
case BlenderServoAnimation::MODE_PAUSE:
// E.g. pause audio
break;
case BlenderServoAnimation::Animation::MODE_STOP:
case BlenderServoAnimation::MODE_STOP:
// E.g. stop audio
break;
}
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

// Callback to be triggered on a short button press
void onPressed() {
// Get the current mode, act accordingly and trigger another mode
switch (animation.getMode()) {
// On short press in default or pause mode, we want to start or resume the
// animation
case BlenderServoAnimation::Animation::MODE_DEFAULT:
case BlenderServoAnimation::Animation::MODE_PAUSE:
case BlenderServoAnimation::MODE_DEFAULT:
case BlenderServoAnimation::MODE_PAUSE:
animation.play();
break;
// On short press in play mode, we want to pause the animation
case BlenderServoAnimation::Animation::MODE_PLAY:
case BlenderServoAnimation::MODE_PLAY:
animation.pause();
break;
}
Expand All @@ -87,8 +87,8 @@ void onLongPressed() {
// Get the current mode, act accordingly and trigger another mode
switch (animation.getMode()) {
// On long press in play, pause or live mode, we want to stop the animation
case BlenderServoAnimation::Animation::MODE_PLAY:
case BlenderServoAnimation::Animation::MODE_PAUSE:
case BlenderServoAnimation::MODE_PLAY:
case BlenderServoAnimation::MODE_PAUSE:
animation.stop();
break;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/WebSocketLiveMode/WebSocketLiveMode.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void move(byte servoID, int position) {
}

// Animation object to control the animation
BlenderServoAnimation::Animation animation;
BlenderServoAnimation animation;

// Callback function writing live stream data to the animation
void onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
Expand Down
2 changes: 1 addition & 1 deletion src/internal/AnimationData.cpp → src/AnimationData.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "AnimationData.h"
#include <Arduino.h>

using BlenderServoAnimation::AnimationData;
using BlenderServoAnimationLibrary::AnimationData;

AnimationData::AnimationData() {
}
Expand Down
8 changes: 4 additions & 4 deletions src/internal/AnimationData.h → src/AnimationData.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <Arduino.h>

#ifndef BlenderServoAnimation_AnimationData_H
#define BlenderServoAnimation_AnimationData_H
#ifndef BlenderServoAnimationLibrary_AnimationData_H
#define BlenderServoAnimationLibrary_AnimationData_H

namespace BlenderServoAnimation {
namespace BlenderServoAnimationLibrary {

class AnimationData {

Expand Down Expand Up @@ -39,6 +39,6 @@ class AnimationData {
byte readBuffer();
};

} // namespace BlenderServoAnimation
} // namespace BlenderServoAnimationLibrary

#endif
Loading

0 comments on commit e50f830

Please sign in to comment.