Wednesday, April 25, 2012

AdaFruit Motor Shield and the DF Robot 4WD

The last test was a good first test in that the robot moved on command and all the sensors appeared to return output (three ultrasonic sensors and the two encoders). Now it is time to deal with the power issues on the motors. First, the motors do not seem to move at all at speeds less than 200 (as specified to the AFMotor library). This implies there is not enough current going to the motors. In searching the data sheets for the motor (see http://www.dfrobot.com/index.php?route=product/product&path=47&product_id=100) they are listed at 6V and 1.2A. In looking at the data sheet for the AdaFruit motor shield (see http://www.adafruit.com/products/81), the shield 0.6A per bridge (and there are two) and up to 25V. Seems that there is just not enough current per bridge. According to their faq (see http://www.ladyada.net/make/mshield/faq.html), they recommend two things. First attach capacitors to the motor to provide better power regulation, and the second is double up on the L293D chips to improve power output. Seems like both are needed as I am seeing both problems.


First, I decided to measure the power draw before doing anything. This means pulling everything apart and attaching the multimeter to one of the motors. I created the simplest sketch I could create. This just runs each of the forward motors at a speed of 100, then turns them off. This repeats indefinitely until powered off.
  1. #include <AFMotor.h>

  2. AF_DCMotor motor1(1);
  3. AF_DCMotor motor2(2);
  4. AF_DCMotor motor3(3);
  5. AF_DCMotor motor4(4);

  6. void setup() 
  7. {
  8.   motor1.setSpeed(100);  
  9.   motor2.setSpeed(100);  
  10.   motor3.setSpeed(100);  
  11.   motor4.setSpeed(100);
  12. }
  13. void loop() 
  14.   motor1.run(FORWARD);  
  15.   motor2.run(FORWARD);  
  16.   motor3.run(FORWARD);  
  17.   motor4.run(FORWARD); 
  18.   ::delay(5000); 
  19.   motor1.run(RELEASE); 
  20.   motor2.run(RELEASE);  
  21.   motor3.run(RELEASE);  
  22.   motor4.run(RELEASE);  
  23.   ::delay(5000);
  24. }
Here is a picture of the connection of the multimeter right to the power terminals on one of the motors.






 Next, I soldered some capacitors over the motor connectors. This will help regulate the voltage. I used .1uf ceramic capacitors as recommended by the ada fruit motor shield faq. Here is a picture of the capacitor and the solder job to mount them on the motors. This took a little bit of work to get the solder iron close to the leads without having to take the motors out. I would recommend soldering these on before you put the motors in the chassis. I then repeated the test with the volt meter and observed the measurements were much more stable (about 1.7 consistently).



The final step was to double up the L293D chips. First I soldered one chip on top (make sure the U shapes are aligned). and then mounted them. I repeated the simple sketch again and now the wheels start moving at about speeds of 60. Definitely better than before.


Next up, put everything back together and try driving around again. I will also output the encoder and wheel information in ros messages so that it will be easier to record data.

Saturday, April 14, 2012

Using ROS (Robot Operating System) Electric with the Arduino





While I wait for parts (extra L293D chips) to improve the current usage on my dfrobot, I thought I would play around with using ROS and the Arduino. ROS provides several tools, mostly on the host side, that will improve visualization of data coming off the robot. Also has some other handy features for messaging so I will not have to do as much serial string parsing. The main web site for ROS is http://www.ros.org/wiki/. I started out following the installation instructions located at http://www.ros.org/wiki/ROS/Installation. Since I already use macports, the specific instructions I followed are at http://www.ros.org/wiki/electric/Installation/OSX/Macports.

The instructions were straight forward so I will not repeat them here. As usual, whenever I update macports it is a several hour process where lots of out of date things are downloaded and installed.  I did have one slight problem in one of the steps. The command:

rosinstall ~/ros "http://packages.ros.org/cgi-bin/gen_rosinstall.py?rosdistro=electric&variant=desktop-full&overlay=no"
Returned an error about tar returning an incorrect version:
ERROR in config: Unable to create vcs client of type tar for ~/ros: "tar --version returned invalid string: 'bsdtar 2.8.3 - libarchive 2.8.3'"
I was able to fix this by changing the link as to which tar was used:
  1. $ sudo rm /usr/bin/tar
  2. $ sudo ln -fsv /usr/bin/gnutar /usr/bin/tar
Then, the rosinstall command hung. For some reason, I had a version of rosinstall in /usr/local/bin. I am not sure how it got there. I used the full path to rosinstall to make sure that it was pulling in the right version. Something to be aware of in the future:

    1. /opt/local/bin/rosinstall ~/ros "http://packages.ros.org/cgi-bin/gen_rosinstall.py?rosdistro=electric&variant=desktop-full&overlay=no"
Several macports project dependencies were needed. A few times I needed to kill the python install and then run the sudo maports install manually. Apparently ros wants gnu tar and macports wants bsdtar. There must be an easier way around what I did. Then restarted the install script. When that was finished, I proceeded to test the installation. First thing I needed to do was add my machine name to /etc/hosts (which now has the line below for my machine name, yoshi, which is now an alias for localhost):
  1. 127.0.0.1 localhost yoshi
I was then able to run a few simple commands to start an ROS session:
  1. roscore > /dev/null &
  2. rosmake turtlesim
  3. rosrun turtlesim turtlesim_node &
  4. rosrun turtlesim turtle_teleop_key 
which let me use the mouse keys to drive a turtle around in a window (see below).



Once ROS was installed, I looked into how to get ROS and the Arduino to communicate. Turns out there is a package called rosserial that is used to send messages back and forth, see the link http://www.ros.org/wiki/rosserial. First I installed the packages:


  1. cd ~/ros
  2. source setup.bash
  3. hg clone https://kforge.ros.org/rosserial/hg rosserial
  4. export ROS_PACKAGE_PATH=~/ros/rosserial:$ROS_PACKAGE_PATH
Note this last step was not provided anywhere and took me a while to figure out. If you do not add the package to the ROS_PACKAGE_PATH then none of the ros commands will work. Next I needed to build rosserial. I do not usually compile aurduino code using macports (I use the Arduino.app) so I needed to install that first:
  1. cd ~/ros
  2. sudo port install avr-gcc 
  3. rosmake rosserial_arduino
  4. rospack profile
  5. roscd rosserial_arduino/libraries
  6. cp -R ros_lib /Applications/Arduino.app/Contents/Resources/Java/libraries
Next, I used one of the rosserial examples that reads out analog pins (see http://ros.org/wiki/rosserial_arduino/Tutorials/Arduino%20Oscilloscope):

  1. #include <ros.h>
  2. #include <rosserial_arduino/Adc.h>

  3. rosserial_arduino::Adc adc_msg;
  4. ros::NodeHandle nh;
  5. ros::Publisher p("adc", &adc_msg);

  6. void setup()
  7.   pinMode(13, OUTPUT);
  8.   nh.initNode();
  9.   nh.advertise(p);
  10. }
  11. void loop()
  12. {
  13.   adc_msg.adc0 = analogRead(0);
  14.   adc_msg.adc1 = analogRead(1);
  15.   adc_msg.adc2 = analogRead(2);
  16.   adc_msg.adc3 = analogRead(3);
  17.   adc_msg.adc4 = analogRead(4);
  18.   adc_msg.adc5 = analogRead(5);
  19.   p.publish(&adc_msg);
  20.   nh.spinOnce();
  21. }
Then I fired up a few ros commands (note the second command was needed to make sure the python serial interface was installed):
  1. roscore &
  2. sudo port install py26-serial
  3. sudo port install py26-matplotlib 
  4. sudo port install py26-wxpython
  5. rosmake rxtools --rosdep-install
  6. rosrun rosserial_python serial_node.py /dev/cu.usbmodem621 &
  7. rostopic list
  8. rxplot adc/adc0
Note that step #4 was simply to make sure the topics was being generated properly. These steps produced the plot shown below.


Turned out setting up ros to work with the Arduino was quite a bit of work. I think it will be worth it down the road though as it opens up a wide range of tools that can be used.

Good Luck!

Friday, April 6, 2012

Driving the DFROBOT around


Now that I have software for the wheel encoders, the range sensor, the motor shield and a simple GUI to control things, it is time to start putting all the pieces together. After trying several things to mount the range sensor on the robot (rubber bands, electrical tape, plexiglass mount), I decided to order a small sensor housing from lynx motion (http://www.lynxmotion.com/p-397-multi-purpose-sensor-housing.aspx). I just had a hard time finding the small screws to properly mount the ultrasonic sensor. The lynx motion mount worked well, although I decided to drill a few holes in the platform to mount three of them at the angles I wanted. Here are a few images of the mounts. This picture shows the range sensor (top left), the mount (top right) and the range sensor on the mount (bottom).


Next, I mounted three of them on the dfrobot. Hopefully, this will give some useful data for robot localization (besides just obstacle avoidance). Here is a picture of the three sensors mounted on the front of the robot.



Next I decided it was time for some re-wiring. I had been just sticking wires together without much organization to get things hooked up. This made it impossible to easily take things apart as the wires were soldered (on the motor) or screwed down (on the motor shield). I ended up soldering some stackable headers on one end of the connection, and header pins on the other to make a cheap connection. This was a little trick recommended in the book http://www.amazon.com/Robot-Builders-Bonanza-4th-Edition/dp/0071750363/ref=sr_1_1?ie=UTF8&qid=1333630892&sr=8-1. Here is a picture of the soldering.


I made sure to label which motor went with which pin. Here is a picture after all the taping and soldering and labeling.


Next up was getting a battery mounted so the Arduino could run without the USB cable running out the back. I searched the web, but did not find much discussion about the best way to do this. I think I have just not hit the right keywords yet. Any suggestions on batteries? 

Seems that LiPo are the way to go. I figured that I would try something simple first and see how long the batteries last before moving onto a better battery solution. I decided to take a trip over to radio shack and found a 9v connector and a barrel jack. I soldered them together and mounted the 9 volt on the robot chassis.


The final change was to mount the Arduino to the chassis. Being paranoid, I was worried that the having the Arduino header pins sitting on the metal chassis would cause cross talk amongst header pin voltages. At radio shack I found some cheap PC mounts. I needed to get out the dremel though as the pins interfered with the mounts (see below). Cutting little slits in the mounts let it sit properly and now everything is rigidly mounted and I am not to worried about shorts.




Then it was putting everything together. Here are a few pictures of the result.



So finally, here is the parts list.
  1. MegaShield: http://store.nkcelectronics.com/megashield-kit.html
  2. Arduino Mega: http://arduino.cc/en/Main/ArduinoBoardMega
  3. Jumper wires
  4. ROB0025: http://www.dfrobot.com/ 
  5. AdaFruit motor drive shield: https://www.adafruit.com/products/81
  6. Wheel encoders: http://www.dfrobot.com/index.php?route=product/product&filter_tag=encoder&product_id=98
  7. Range sensors: http://www.amazon.com/Virtuabotix-Ultrasonic-Rangefinder-Obstacle-Detection/dp/B0066X9V5K
  8. Xbee: http://www.amazon.com/Xbee-Wireless-Kit-Chip-Antenna/dp/B004WLHE1G/ref=sr_1_3?s=electronics&ie=UTF8&qid=1333322544&sr=1-3
At this point little in the code needed to be code to drive the robot using the gui. Basically, just adding a new unit test that had the range sensors and printed all the measurements. Again, the code for this is located on github at
https://github.com/mark-r-stevens/Ardadv/tree/master/device/platform/dfrobot/manual/test04
I added a few command line parameters to the dfrobot UI so that I can specify the device and port to connect. The first drive was moderately successful (see movie below). Seems that not all the motors are moving all the time and the wheels seem to slip a lot. To get the robot to move I need to use the maximum speed. I will need to tackle this next. Possibilities that I have found are adding more battery power, doubling up the L293D chips on the motor shield (get more amps), and using capacitors on the motors (better power regulation). All of these things are possibilities I will start looking at next.


One note about the movie, seems that there is some latency in the video acquisition. I will also look into this for better grabbing of frames that sync up with the robot motion. Lots left to do and experiment!