Servo Control — Part Three
This tutorial will focus on controlling a servo with the end goal of creating an autonomous robot. Hopefully you have been following along creating states to control motors and working through advanced motor control. If not make sure you head over to XOD and download the desktop IDE or work in the browser to follow along with the programming steps. XOD is a visual flow-based programming language that you can learn with no prior programming experience.
So far we’ve been able to program a robot to follow simple commands such as move forward, stop, and turn as well as connect states and create loops. We will continue to build on the knowledge we have learned from the previous tutorials and add in some new features as well. The end goal of this tutorial is to create a program that controls a servo which will later hold a range sensor. If we were driving a car we would look around and find objects nearby and react accordingly. We will teach the robot the same process.
For this article we will continue to work with the same hardware as the previous articles but will now focus on control of the servo.
The servo has 3 pins which consist of +5V (Red), Ground (Black), and Data (Yellow). With this particular shield the data pin is connected to pin 9 on the Arduino. This same setup can be used with other shields or connected directly to the controller.
Controlling Servos in XOD
One of the most impressive features of XOD is the ability to write a simple program with only a few nodes. To introduce how the servo works we will write and upload our first program with only one node.
Begin a new project in XOD by selecting File → New Project. Select the xod/core/servo node by dragging it from the project-browser on the right or double clicking and searching for “servo”. In the inspector on the bottom left make the PORT value 9 and the VAL 0.25. One nice feature in XOD is the Helpbar shown on the right. Toggle the Helpbar into view by selecting View-Toggle Helpbar from the top menu. Here you can read about the servo node. Notice the importance of the VAL input which tells the direction the servo is pointing. The value of the servo can be set anywhere from 0 to1. For our robot 0 would be 90 degrees to the right and 1 would be 90 degrees to the left. In order to look 45 degrees to the right we will set the VAL to 0.25. Later in the program we will implement structures to allow the servo to look forward where VAL is set to 0.5 and look left where VAL is set to 0.75.
Program Structure Overview
As we begin to make our project more complex we will begin to add states that the main patch moves through. For this project we will have three states to control the servo: look-left, look-straight, and look-right. Within each state we will create nodes to control the servo. We will also create a feedback loop so that the process repeats again and again.
Each time you begin a new project in XOD you will start with the default main patch. We will use main to create the overall structure of our program and create states to control the servo.
In order to create a new patch select File → New Patch (or Ctrl + N). Create three patches and name them “left-look”, “straight-look”, and “right-look”.
Note: states are named “left-look” instead of “look-left” because it is easier to see the first word in the workspace later.
Now we can begin to structure our main patch. Notice you can search for your newly created patches by double clicking or drag them into the workspace from the Project-Browser.
Go ahead and set up main to have the basic structure above. The goal of our program will be to eventually move between each of these states and then repeat the process. Notice as of right now there is no way to connect our newly created patches; this is because we have not yet created any inputs or outputs within each state. The next step is to configure these state patches.
Designing State Patches
We will begin by designing the left-look patch. Our goal in controlling the servo will be similar to what we created controlling the motors in the previous example. The basic goal of our state is to have some input to begin the patch, control hardware (in this instance a servo) for a set period of time, and then have another output to move on from this state and consequently activate the next state.
As seen in the image above we have a similar structure to most every state in XOD: an input-pulse that we name SET and an output-pulse that we name DONE. In between SET and DONE we design our logic for the state. Again we will use the delay node to do something for a certain period of time. For this instance we will use the servo node that we first introduced at the beginning of the project. I’ve added a few constant-number nodes to show values for T, PORT, and VAL as an additional visual but you can just as easy set those numbers in the inspector and skip the constant-number nodes all together.
All of this looks good so far but there is one part missing. There is currently no connection between the delay node and the servo node. We need to design a way to enable our servo for each state.
Designing a Custom Servo Node
So far we’ve looked at creating custom patches to design states for programs to move through. The next piece of the puzzle is designing a patch to customize hardware control; in this instance a servo. Our goal is to create a third input on the servo that essentially turns the servo on or off. For this we will use the Boolean data type (TRUE or FALSE) to attach and detach the servo.
For this I recommend reading the Hacking Nodes with C++ tutorial. This tutorial guides you through designing a custom enable-servo node that we will use in this project. If you’d prefer to skip the C++ article, you can by installing the gweimer/servo library by selecting File → Add Library and searching for “gweimer/servo”. This will give you access to the servo-enable node prepackaged with that library. Special thanks to gweimer on the forum for creating and publishing this library. You can choose to design your own enable-servo node or use the library’s servo-enable node in the program moving forward. They are literally built the exact same way with the exact same code.
Now that we have the new node lets replace the servo node in our left-look state with the new servo-enable node.
As you can see we have a new input on the servo-enable as compared to the servo node. Make sure that the ACT output of delay is connected to the En of servo-enable. The functionality within the left-look state is now complete.
Copying Structure to Other States
The next step is to use the structure created for the left-look state to populate our straight-look and right-look states. We will use all the same structure and values with the only change being the number attached to the VAL input of servo-enable.
Within the left-look state select the entire patch (Ctrl + a), copy it (Ctrl + c), and paste it (Ctrl + v) into the straight-look and right-look states. Make sure to change the number of the VAL input for servo-enable. Left should be 0.75, straight is 0.5, and right is 0.25. The image above shows how each state should look.
Linking States in Main
Almost done! The last few steps are easy. Go back into main where we created the flow of the program earlier. Notice now after configuring each state there should be a blue (pulse) input and output. Connect the states together and add in a boot patch at the beginning to initiate the process.
Here we can see the structure of our program we designed before. Make sure to connect everything together and initiate with the boot node. Go ahead and test your program by selecting Deploy → Upload to Arduino. You should see the program run once and move through each state. The next step is making the process repeat.
Creating a loop
Using the same process from the motor tutorial we will create a loop using the combination of defer-pulse and any. Defer-pulse sends the program back to the initial state and any allows the first state to be started from boot or defer-pulse.
Insert the any node in between boot and left-look. This allows two inputs to initiate the cycle. Also make sure to add the defer-pulse node after straight-look and then connect it back up to the any node to create the loop.
We can now see the final project in action! Upload to the Arduino and watch the servo look in different directions and scan around the same way we would when driving a car.
After finishing this article you should be able to easily customize and control servos using XOD. If you read the embedded C++ article you can also write code to completely customize hardware control. Previous articles have shown how to control DC Motors and we are well on our way to the final project of having an autonomous robot. We will continue making progress with the next step of incorporating the range sensor.