Sunday, June 29, 2014

BeagleBone Black and the LV-MaxSonar-EZ2 Range Finder



Now that I have a working robot, I decided that I wanted to make it autonomous.  After thinking about this a bit I decided that the next step would be to give the robot the ability to “sense” obstacles.  After a little research I found the LV-MaxSonar-EZ2 Range finder by Maxbotix.  This is a low cost sonar range finder that will detect obstacles and return the distance up to 254 inches away (this according to the specs).

You can find the datasheet for the LV-MaxSonar-EZ2 RangeFinder here.  The MaxSonar accepts an input voltage range of 2.5V to 5.5V and outputs the range in pulse width, analog voltage or serial digital output.  For the example here we will be providing 3.3V to the MaxSonar from pin 3 of the P9 expansion header and we will be taking the output from the analog voltage out.

The first thing we have to do is to solder some connecting wire to the MaxSonar so we can attach it to a breadboard.  This will allow us to prototype and test the range finder.




Now we need to connect the MaxSonar to the BeagleBone Black.  Here is how we wire everything:

This diagram was made with fritzing.  Now you do not have to look at my bad wiring to see how I connected everything. 

We connect a 1k ohm resistor to the analog voltage output pin on the MaxSonar.  Then connect a 3.3k ohm resistor in series with the 1k ohm resistor.  We then tie the 3.3k ohm resistor to ground.  Finally connect pin 40 of the P9 expansion header in series with the two resistors as shown in the diagram.

Now before we power everything up we need to determine mV per inch so we can calculate how far the obstacles are.   According to the datasheet, with 3.3V in should yield 6.4mV/in and according to this page we should get 4.57mV/in but neither were correct when I tested my MaxSonar.  I actually have two of the MaxSonars sensors and they both yielded the same results.  After determining that I was consistently getting results that were different from both sites, I went about determining what was correct in my test environment.  To determine mV per inch I measured the output from the MaxSonar for certain distances.  The results showed that I was getting 2.148mV/in.

Now lets write some code to test the MaxSonar range finder.  I will be using JavaScript/Bonescript here instead of Python because I really want to try to use Bonescript more to get a good feel for it.  Create a file called maxsonar.js and insert the following code:

var b = require('bonescript');

var sensorPin = "P9_40";

setInterval(read,3000);

function read() {
      b.analogRead(sensorPin,sensorStatus);
}

function sensorStatus(v) {
      var distanceIn;
      analogV = v.value*1.8;
      console.log('v.value = ' + analogV);
      distanceIn = analogV/0.002148;
      console.log("Object at " + parseFloat(distanceIn).toFixed(2) + " inches away");
}

We begin by setting our sensorPin to pin 40 of the P9 expansion header.  We then use the JavaScript function setInterval to call our read function every three seconds.  The read function calls the Bonescript’s analogRead function to read the output from the MaxSonar range finder and sets the callback function to the sensorStatus function.

The sensorStatus function is where we do all of our calculations.  We begin by converting the ADC to voltage by multiplying the value by 1.8.  We then convert that to inches by dividing the calculated voltage by the Volts per inch (notice we convert the 2.148 mV/in to .002148V/in).

We can run this code by running the following command: 

node maxsonar.js

Now every three seconds we should see the how close an object is to the MaxSonar range finder.  I would be interested in hear how what you find the mV per inch to be.  Is it closer to the other sites I mentioned or closer to what I found it to be?  I am much better at the programming and OS then I am with the electronics therefore if you spot anything that I may of done wrong on the electronic side to get the different mV per inch results, please leave a comment below.

The next step will be connecting the MaxSonar Range Finder to our robot and writing a quick test application that will let the robot move around avoid obstacles.  



Wednesday, June 25, 2014

Using Javascript with Bonescript to program the Beaglebone Black

In this blog so far I have used Python for all programming examples however we are not limited to Python.   We can use many different programming languages to program the Beaglebone Black.  The “Offical” language for the Beaglebone Black is Javascript with the BoneScript library.  BoneScript is a Node.js library that is optimized for the BeagleBone and features Arduino function calls.  Since I am more familiar with Javascript than Python, I figured I would give BoneScript a try. 

Whenever we first dive into a new language or environment, we usually show the typical “Hello World” example.  I know I dislike the Hello World example too but it does show the basics of how Node.js, JavaScript and the BeagleBone Black work together.  If you are familiar with Node.js and Javascript, you can skip the Hello World section.

Hello World:

We will begin by connecting to the BeagleBone Black.  You can connect to it using SSH or by connecting a monitor/keyboard/mouse to the BeagleBone Black.  Once you get connected, open up a file called helloworld.js and insert the following line of code:

console.log("Hello, I am trapped inside");

Now run the following command:

node helloworld.js

This should print out the line “Hello, I am trapped inside”.  The console.log function simply prints out the message to the console.  In this case the console is the Linux shell that we are in.  We used the node command, from Node.js, to execute our Javascript code. 

First BoneScript script:

Now that we got the Hello World example out of the way, let create something somewhat useful.  The BeagleBone Black has four onboard user LEDs.  Lets make one of the user LEDs blink.  Here is the code:

var b = require('bonescript');

var ledPin = "USR3";

b.pinMode(ledPin, b.OUTPUT);
var state = b.LOW;
b.digitalWrite(ledPin, state);

setInterval(toggle, 500);

function toggle() {
    if(state == b.LOW)
        state = b.HIGH;
    else
        state = b.LOW;
    b.digitalWrite(ledPin, state);
}

The require function loads Node.js libraries/modules, therefore the first line loads the BoneScript library.  Next we define a variable named ledPin that conatins the string “USR3” which refers to the onboard LED USR3.

We then use the pinMode function to set the ledPin to b.OUTPUT.  This allows us to write to the pin.  Setting a pin to b.INPUT, means we want to read from it.  We now define our state variable to b.LOW and use the digitalWrite function to set the ledPin to low which turns the led off.

Once we have the ledPin configured and turned off, we use the Javascript function setInterval to call the toggle function every half a second.

The toggle function checks to see what the state is (b.LOW or b.HIGH) and reverses it.  The function then uses the BoneScript function digitalWrite to set the ledPin to the new state.

If we run the application using Node.js, the USR3 led will blink on and off until you stop the application with Ctrl-C.

Controlling an LED with the push of a Button

Now that we know how to use the BoneScript library, lets do something that is actually useful.  Let’s connect a LED and a button to our BeagleBone Black and turn the LED on when then button is pressed.

First thing we need to do is to wire up the button and the LED.  Whenever you connect items to your BeagleBone black, it is a very good idea to disconnect the power first.  Using a solder-less breadboard and jumper cables, connect the ground rail of your breadboard to pin 1 of the P9 expansion header.  Then use another jumper to connect the power rail of your breadboard to pin 3 of the P9 expansion header.  This will connect your breadboard to both power and ground.

Now lets add the LED to our breadboard.  Connect the cathode end of the LED (shorter wire) to the ground rail of our breadboard and then connect the anode end of the LED (longer wire) to one of the rows on our breadboard.

Now take the 100 OHM resistor and connect one end to the row on the breadboard that the LED is connected to and the other end of the resistor to another row on the breadboard.  Finally run a jumper from pin 8 of the P8 expansion header to the row that the 100 OHM resistor is connected too.  Now that our LED is connected, lets connect the button.

You will want the button to straddle the middle section as show in the image below.  Using a jumper, connect the power rail of your breadboard to one end of the button.  Next connect the same end of the button to the ground rail of your breadboard using the 10K pulldown resistor.  Finally connect the other end of the button to pin 11 of the P8 expansion header.  The connections should look like this image but hopefully you did a neater job hooking up the wires then I did.



Now lets write our Bonescript code to make the LED turn on with the push of a button.

var b = require('bonescript');

var ledPin = "P8_8";
var buttonPin = "P8_11";

b.pinMode(ledPin, b.OUTPUT);
b.pinMode(buttonPin, b.INPUT);

b.attachInterrupt(buttonPin, true, b.CHANGE, buttonChange);

function buttonChange(button) {
    if(button.value == b.HIGH)
            state = b.HIGH;
        else
           state = b.LOW;
    b.digitalWrite(ledPin, state);
}

We begin by loading the Bonescript library and defining the ledPin and buttonPin variables that define what pins the LED and Button are connected to on the BeagleBone Black.  P8_8 defines that the LED is connected to pin 8 of the P8 header and P8_11 defines that the button is connected to pin 11 of the P8 header.

We use the pinMode function to set the ledPin to b.OUPUT which means we want to write to the pin.  We set the buttonPin to b.INPUT because we want to read the pin.

We then use the attachInterrupt function to define an interrupt whenever the buttonPin changes.  If we used b.RISING or b.FALLING instead of b.CHANGE, the interrupt would be triggered only when the pin went high or low.  The last argument in the attachInterrupt function defines the function to call when the interrupt is triggered; in this case the function to call is the buttonChange function.

The buttonChange function sets the led pin to either b.HIGH or b.LOW depending on the state of the button.


Using Node.js to load external Javascript files

To create really useful applications for the BeagleBone Black, like robots or home automation applications, we will need to use multiple files to organize our code but Javascript is not designed to include one Javascript file in another Javascript file.  Node.js can help us with this problem.   Lets begin by creating a Javascript file called hello.js that includes both a variable and a function that we will use in another Javascript file.

var name = "JON"

function sayHello() {
      console.log("Hello World");
}
module.exports.sayHello = sayHello;
module.exports.name = name;

This file defines the variable name and the function sayHello.  We then use module.exports to expose the internally scoped function and variable. 

Now lets look at how we would use the name variable and the sayHello function.

var hello = require("./hello.js")
console.log(hello.name);
hello.sayHello();

We begin by using the require function to include the hello.js file that we just wrote. We can then use the hello variable to access the name variable and the sayHello function.

Cloud9 IDE

I know the Angstrom distribution comes with a Javascript IDE called Cloud9 preinstalled (not sure about the other distributions).  To use Cloud9, open a web browser and enter the IP address of your BeagleBone Black with port 3000 as the URL.  For example, if the IP address of your BeagleBone Black is 10.0.1.18, the URL would look like this:  10.0.1.18:3000.  The IDE interface looks like this.



Personally, I do not really care for Cloud9 so I have not used it that much but I did want to mention it here in case you wanted to give it a try.

Conclusion


Personally I like Javascript but I do believe that I can do a lot more with Python, like including Bluetooth communication, than with Javascript however for projects that do not need access to external hardware components like Bluetooth adapters or cameras, I might give Javascript/BoneScript a try.

Sunday, June 15, 2014

LightZord - The Father's day robot

For Father’s day, I wanted to make a totally awesome robot but I did not know what a totally awesome robot would look like so I asked my daughters.  This post shows the robot that we came up with.  I also bought a second Beaglebone Black with a 7.0” LCD cape to make a remote controller unit for our totally awesome robot.  We named the new robot LightZord and below is his first video:


Here is another picture of LightZord wearing his Lei:



As you can see, he has a little bit of a weight issue that causes him to wobble a lot when he turns (at least I think that is the problem).  Not really sure how to solve this issue yet but if anyone has a suggestion please leave a comment below.

Here are a couple of pictures of the inside of LightZord:




The insides are wired exactly the same way as my previous robot and this is documented in the following posts:


What really makes LightZord different from my first robot is the remote controller unit.  To build this controller I purchased a second Beaglebone Black Rev C, 4D Systems 7.0”LCD Cape, second BluetoothUSB adapter and a second EasyACC battery charger. 






The new Beaglebone black Rev C comes with Debian preinstalled but I had a lot of issues trying to get the Bluetooth adapter to work with the preinstalled version of Debian so I put Angstrom on it.  Beaglebone.org’s getting started page documents how to install a new OS.

I then attached the Beaglebone Black to the 7.0” touchscreen cape as the documentation shows.  Once I powered up the Beaglebone, with the cape, the only issue I encountered was the touch screen calibration application did not automatically start.  Since the touch screen was unusable without the calibration, I connected the Beaglebone black to my network, SSH’d to the Beaglebone and ran the ts_calibrate command manually.  This did not actually solve the issue since it did not update the calibration so I copied the output of the ts_calibrate command to /etc/pointercal.  This forced the calibration utility to run the next time the Beaglebone started and correctly calibrated the touchscreen.

There is a virtual keyboard under the Universal Access menu option titled Florence Virtual Keyboard application.  This keyboard works really well with the touch screen but I would not recommend configuring your Beaglebone using that small keyboard.  It is a lot easier to connect your Beaglebone to your network and SSH in.

Now that I had my touch screen connected and calibrated, I configured the USB Bluetooth adapter as documented on in this post.  I then paired the controller with the LightZord robot and ran the Rover 5 rfcomm client application whose code is inthis post.  From here I could control LightZord buy typing in the following commands:
u – full speed
j – all stop
i – increase speed
k – decrease speed
o – set direction all forward
i – set direction all reverse
z – spin left
c – spin right

This was a pretty cool Father’s day project with my daughters.  There is still a couple of to-do’s left.  I want to eliminate the wobbling when LightZord turns, I want to add a GUI to the Rover 5 rfcomm client application and finally we still need to paint/decorate LightZord.  After all that is done, we can then add some sensors and create a robot that can move around by himself.