-
Notifications
You must be signed in to change notification settings - Fork 0
The Driver
- Introduction
- Reaching the driver
- Why it is a separate include
- What you can do with it
- Playing nicely with the framework
Underneath every facade and every module sits the raw OttoDIYLib driver -- a C++ object of class Otto. OttoFlow does not wall it off. The driver is the official escape hatch: if OttoDIYLib can do something OttoFlow has not wrapped yet, you can still reach it, in a documented and supported way.
A framework that hides its lower layer loses its advanced users. OttoFlow's promise is no locked doors -- and this is the door.
The escape hatch lives in its own header, not in <OttoFlow.h>. Include both:
#include <OttoFlow.h>
#include <OttoFlowDriver.h>
void setup() {
OttoFlow::start();
Otto& raw = OttoFlow::driver();
raw.oscillateServos(/* ... */); // anything OttoDIYLib can do
}OttoFlow::driver() returns a reference to the one driver instance the framework itself uses. It is valid after OttoFlow::start(). Changes you make through it are visible to the framework, and vice versa -- there is only ever one robot.
<OttoFlowDriver.h> pulls in all of OttoDIYLib's headers, and those define lowercase macros for the mouth shapes: heart, smile, happyOpen, and so on. In a beginner's sketch those macros would collide with ordinary variable names and produce baffling errors.
Keeping the driver in an opt-in header means the plain <OttoFlow.h> include stays clean, and you only take on the macros when you deliberately ask for the driver. This is the same reasoning that gives the framework its OttoFlow:: namespace -- see Architecture.
Everything OttoDIYLib exposes, including things OttoFlow deliberately leaves raw:
Otto& raw = OttoFlow::driver();
raw.putMouth(heart); // raw mouth macro
raw._moveServos(500, positions); // low-level 4-servo keyframe
raw.getRestState(); // driver's internal rest flag
raw.enableServoLimit(255); // OttoDIYLib features with no wrapper yetConsult the OttoDIYLib source and examples for the full surface. If you find yourself using a driver call often, that is a good sign it should become a module or facade -- see Extending OttoFlow, and consider contributing it back.
The framework and the driver share one instance, so a few habits keep them in agreement:
-
Respect the guards yourself. Calls made straight on the driver bypass
Legs::disable()andVoice::mute(). If you drive servos throughraw, the robot moves even when the framework thinks movement is off. CheckLegs::isEnabled()first if that matters. -
Trims still apply to the driver's own movement calls (
walk,turn,_moveServos), because trims live inside the driver. They do not apply to arm servos, which are separate. -
Let
start()do the setup. The driver has already been initialised with your configuration by the timedriver()returns. Do not callinit()again unless you mean to reconfigure from scratch. -
Prefer the higher layer when one exists. The driver is for what is not wrapped. Mixing
Mouth::show()andraw.putMouth()in the same sketch works, but the facade reads better and survives future refactors.
OttoFlow is licensed under GPL-3.0 and wraps OttoDIYLib. Buy the kits at ottodiy.com.
Prologue
Getting Started
The Basics
Digging Deeper
- Bench Testing
- Serial Console
- Calibration
- Bluetooth and the Otto App
- Modules
- The Driver
- Extending OttoFlow
Reference