At first my BB-8 (v2) wobbled back and forth quite a bit whenever it stopped and so to fix this I added an inertial measurement unit (IMU), the BNO0355 from Adafruit. This is connected to the Arduino and tells the Arduino the orientation of the IMU board, and hence the orientation of the BB-8 drive system that it's mounted on. The Arduino uses that information to turn on the motors in the direction needed to counter the wobble.
You can see it in action in the video below.
As shown below, the board comes with these two parts, the BNO055 board itself and a bunch of male pin headers (you can buy male and female pin headers from Adafruit. First I solder pins to the board. I do that by putting the pins in a breadboard and sitting the board on top of the pins. That way the breadboard acts as a heatsink to reduce the chance of overheating the board. My soldering iron is on the 40 watts setting. I touch the iron's tip to the pin and board's metal ring for only around 2 seconds and then briefly touch it with the solder. Be careful not to put too much solder and connect more than one pin together. Very little solder is needed.
As you can see above, there is no place to connect the wires from the Arduino to the board or the pins without soldering. I prefer to plug in my wires. So, as shown below, I cut up some perboard and drill holes in it for mounting on BB-8's drive system. I then plug some female pin headers into the boards pins. That way they're lined up nicely while I hot glue those female headers to the perfboard.
I also hot glue on a separate seven pin female header which is where I'll be plugging in the wires going to the Arduino. I then solder wires from pin headers that the board will be plugging into, to the seven pin headers. I do the soldering without the board plugged in so as to not damage the board from heat.
Below is how the wiring is done as well as the pinouts for connecting. Notice that I've provided two Vins holes. Why I did that is explained below. Note that I'm not going to use the board's reset or interrupt pins but I make them available on the seven pin header in case I want to later.
Since the wires are short, I remove the Arduino's battery case and put some lightweight nylon nuts, bolts and washers for mounting the board. I then put the board in place.
Below you can see the board in place and wired up, and the new position of the battery case beside it (angled a bit so that it won't collide with the inside of BB-8's ball.) Below you can also see the wires labelled before they were tie strapped together.
Notice that the Arduino has only one 5 volt pin hole. But I need one for the BNO055 IMU board and another for the RC controller board that's installed below the Arduino. That's why I put two Vin holes in the seven pin header. One goes to the Arduino's 5 volt pin and the other goes to the RC controller board to give it power.
The wobble I want to fix is the back and forth wobble that happens immediately after the motors are turned off. The BNO055 IMU board tells me all sorts of information, including the tilt angles in the X, Y and Z orientations. At first I don't know which one is useful since I just arbitrarly mounted the board. So as part of the BNO055 installation information on Adafruit's website, they also give a sample program that displays all three angles to the serial board. I simply install it on the Arduino and manually tilt the BB-8's drive system in the back and forth direction. That shows me that it's the Y-axis angle that's changing.
With that sample code as a basis I add pieces to my BB-8 program and fine tune it until I have something that works well. The code is given below.
The main part is in the loop() function. The first part is the usual checking for commands from the remote control to turn on and off motors. I then added a new section to handle the wobble whenever at least one of the motors was previously on but has just been turned off. If that's the case then I put the loop in a state that I call STATE_IMU_LEVELING. Whenever the loop() function is called and I'm in that state then I keep checking the Y-axis angle and turning on and off motors to get it to less than LEVELLED_ANGLE degrees and no longer changing.
LEVELLED_ANGLE is defined near the top of the code. Check the code for the value I settled on though I tried 3 degrees, and then 5 and then 7. Basically I kept adjusting it by trying to minimize the amount of activity the motors had to do while having it end up standing fairly straight up.
Note that if at any time the remote control sends a signal to turn on a motor (i.e. the operator decides to get the BB-8 moving again) then the code abandons all levelling activity and goes back to normal. That's done simply by having the remote control code be above the levelling code in the loop() function and setting the state to STATE_NORMAL.
/* BB-8 (v2) Arduino code August 10, 2016 - Added BNO055 Inertial Measurement Unit (IMU) to run motors to cancel any wobble after the motors are remotely stopped. July 6, 2016 - Switched pins 5 and 6 to 3 and 11 to use the lower PWM frequency (Arduino UNO). This is because I'm using brushed motors, and unlike with brushless motors, the higher the frequency, the worse it is for brushed motors. Full details about this BB-8 droid can be found at: http://rimstar.org/science_electronics_projects/bb-8_star_wars_droid_v2.htm Drive motor circuits -------------------- The two motors are driven independently and so there are two Radio Controls (RC), one for each motor. Each one can turn in two directions. The RC controls are just on/off switches so there is no speed control from that end and none is done in software either other than PWM, but it never changes. A circuit exists between the RC receiver and the Arduino to give the Arduino the following inputs: rc1FwdPin - a digital pin indicating that motor 1 should be turned on in the _forward_ direction (HIGH) or off (LOW) rc1RvsPin - a digital pin indicating that motor 1 should be turned on in the _reverse_ direction (HIGH) or off (LOW) rc2FwdPin - an analog pin indicating that motor 2 should be turned on in the _forward_ direction (value > 0) or off (0) rc2RvsPin - a digital pin indicating that motor 2 should be turned on in the _reverse_ direction (HIGH) or off (LOW) Note that one of the pins above (rc2FwdPin) is an analog pin simply to save on the cost of one more relay. The relays were needed as using analog for all of them meant problems with common ground in the RC receiver. The two motors are then controlled using two H bridge circuits. Controlling each H bridge circuit is done by the Arduino by turning on and off transistors using digital pins. There are two transistors for each H bridge, one for each direction the motor can turn. The motors each can turn counterclockwise (CCW) or clockwise (CW) depending on which transistor is turned on. Just which direction is called foward and which is reverse is chosen arbitratily since the BB-8 doesn't really have a forward or reverse direction. A piece of masking tape on the drive plate has "FWD" written on it to select one direction as forward. Pulse Width Modulation (PWM) is done to the above mentioned pins for speed control. The variables bridge1PWMduty, for motor 1, and bridge2PWMduty, for motor 2, have the PWM values. 0 turns the transistor/motor off. The pins are: bridge1CWPin - digital pin for motor 1 clockwise bridge1CCWPin - digital pin for motor 1 counter clockwise bridge2CWPin - digital pin for motor 2 clockwise bridge2CCWPin - digital pin for motor 2 counter clockwise Note that since it's a tank drive, to go forward one motor must turn clockwise while the other motor turns counterclockwise. */ /*- stuff for the IMU ----------------------------------------*/ #include
Video - Making BB-8 (v2) - Adding Gyro/BNO055 IMU - Part 4
Here's my video showing how I added the IMU and showing it in action.