Wednesday, September 25, 2013

Combine 2 bytes into int on an Arduino

Recently I have been involved in a project using an iRobot Create. While writing programs for it, I reached an irritating roadblock. The incoming sensor values are transmitted over serial one byte at a time, but the values that actually had meaning were the int values that resulted when the two bytes were combined. Let me clarify.

I receive 2 values, 1 and 213. Now these two numbers are actually stored as 8 binary bits. The values of those bits are 00000001 and 11010101 respectively (HERE is a convenient calculator). The value I want is the 16 bit int variable that results when these two are added together. ie I want the number represented by 0000000111010101; that would be 469. Sounds like I need to do some Arduino data type conversion.

I Googled around and asked one of my computer science friends, but there doesn't appear to be a ready made solution for this. I should point out that if you are reading the value directly from a serial port, you can just use parseInt(). My problem is that I am using an external library to get the sensor data and then need to combine the bytes afterward.

After some deliberation I acquired a list of ways I thought I could combine two 8-bit bytes into one 16- bit int (or short) variable. Some of these ways I have not pursued, but a few I have. I have tested them, and clocked the processing times for a few values on an Arduino Mega2560 r3.

Combination using bitRead(): 108 microseconds
This is the first method I thought of. It reads each bit in the byte and then copies it over to the int. This is not very efficient, but it does get the job done. It does take quite a bit more clock time than the other methods, but it is a rather intuitive approach.

int BitReadCombine( unsigned int x_high, unsigned int x_low)
{
  int x;
  for( int t = 7; t >= 0; t--)
  {
    bitWrite(x, t,  bitRead(x_low, t));
  }
  for( int t = 7; t >= 0; t--)
  {
    bitWrite(x, t + 8,  bitRead(x_high, t));
  }
  return x;
}
Combination using bit shifting: 4 microseconds
In this method, a bit shift operator is applied to move the high byte into the correct position in the final int. This, to me, is the most elegant solution. I don't know that you will find anything much faster. Note that the micros() function has a resolution of 4, so measuring something like this directly is a little difficult. Code modified from HERE.
int BitShiftCombine( unsigned char x_high, unsigned char x_low)
{
  int combined;
  combined = x_high;              //send x_high to rightmost 8 bits
  combined = combined<<8;         //shift x_high over to leftmost 8 bits
  combined |= x_low;                 //logical OR keeps x_high intact in combined and fills in                                                             //rightmost 8 bits
  return combined;
}
Combination using multiplication: 4 microseconds
This method is basically identical to the one above. I read conflicting arguments for whether it would be any slower or not. If it is, it is pretty negligible. Basically, instead of shifting the bits using a bit shift, I  just multiply by 256. This is like if I wanted to shift the "1" in 10 to the 1000th place. I would multiply by 100 (10^2). In binary I want to shift it 8 places, so I multiply the variable by 2^8 or 256.

int MultiplicationCombine(unsigned int x_high, unsigned int x_low)
{
  int combined;
  combined = x_high;
  combined = combined*256;
  combined |= x_low;
  return combined;
}
Other possibilities
It was suggested to me that I should use strings. This seems like a rather roundabout way of getting there, but I would think it would work. You need to combine each byte into a binary string and then concatenate them by adding them together. Then you can convert them back to an int and you're good to go. This could be accomplished several ways with one being the itoa and atoi functions.

Edit: Thanks to Nigel Parker for adding another method and elaborating calculating the speed of each more precisely. In his comment he details how to use the union constructor to combine bytes into different data types. I have saved his code in a sketch available HERE. He notes that this method can be faster than any of the previous methods mentioned when used correctly.

Conclusion
There are probably other methods of combing bytes into an int that I have not looked at. If so, post a link in the comments. That will only broaden the scope of this post. All of the methods here could be adapted to match a 32 bit long if necessary and could be put into an unsigned variable just as easily as a signed one. With that in mind, I will probably use the bit shift method from now on. It seems like the most elegant and efficient solution.

I hope this post helped someone out. If you want my script to check the clock times for yourself, find it HERE. It also might help if you're a little fuzzy on exactly what is going on. If something doesn't work for you, comment below, and I'll do my best to help you.

-Matthew

Friday, September 13, 2013

Arduino Inverse Kinematics for 2 DoF Robot Arm

In this post I will discuss inverse kinematics. Before I do, I should begin with a disclaimer. I will be using high school trig in this post. I am not a mathematician, and I have never been taught anything about inverse kinematics. Everything here is very simple, and should not be taken as cutting edge science.

So what is inverse kinematics? If you have found this, I suspect you already know. If you don't know, go HERE and read all about it. Basically, if you were normally controlling this arm, you would turn some knobs and change the angles. That would give you the position of the end of the arm. Controlling the arm using inverse kinematics in this case means that you tell the end of the arm where you want it to be, and the joints calculate their angles and move there based on that.

Now this can lead to problems. As every good trigonometry student knows, the trig functions are cyclical. This means you can get multiple answers for given equations. Determining which one is the right one is the trick. How do you do that? I have no idea! (Ok, I have a general idea, but not something I am willing to post on the internet). My arm is simple enough that it avoids the whole problem.

My arm is a simple 2 degree of freedom arm made from 9 gram servos. If you have not seen it, you should check it out HERE. It has 2 joints and that is about it. I am using my custom hackduino to control it. You may be able to get away with an Arduino Uno or Mega and a sensor shield, but I would be wary of maxing out the regulator on it. If you have issues, try an external 5V supply.

Anyway, HERE is the code for the basic inverse kinematics. It just moves the arm to the what ever point you enter. The rest is up to you. I have commented it pretty fully, so you shouldn't have too many problems using it, but I will go into a few things.

First, there will be values your arm can't reach. I would say a safe bet is to just make sure all your x,y values are positive. You probably remember from high school that arccos and arcsin have certain domains. Outside of those domains, they are undefined.

Now if I had done my due diligence I would be able to tell you what values will cause these errors. The problem is, I did all my trig in a hurry one night and threw away the sheet. I now have neither the time nor the interest to go back and figure out where it will error. If you figure it out, let me know. The important thing is that those values should be outside what your arm can physically reach anyway.

Second, the coordinates of the point are in centimeters. I did this so I could use decimals easier. There are also a number of correction factors built in. There is one angle correction for each joint plus one for each axis so you can translate the origin to a convenient point. Theta is also a correction factor but it is a variable calculated automatically based on your inputs. Also note that the arm section lengths are measured from joint to joint. The pivots are the corner of the triangle.

Now the fun stuff. We are going to draw a circle with the arm! HERE is the code. Basically, it is the exact same as the other code except the (x,y) points are determined based on the parametric equation of a circle!

It did take a few tries for me to get the center of the circle in a spot where my arm would physically reach it. A more carefully constructed arm would have less problems with that. When I did get it draw a circle the results were this video! Look at that circle. Just tape a sharpie to it and go to town. I will note that the circle is a little rough. Several factors play into this. The base is shaky. The tape holding the pen on is shaky. The servos lack resolution and are slightly under powered, and the pen is not in the correct location. The tip of it needs to be on the corner of the triangle




Of course, you could draw about anything with it if you had the time. I briefly looked into getting some old code from a plotter and adapting it, so I could write words with it. I never got there, but maybe you will!

So there it is. This post has been done many times by many different people, but I hope mine was useful to you. Both the sketches from this post are HERE. If you do create something cool using code or ideas from here, post a link in the comments.

-Matthew

Tuesday, September 3, 2013

Receiving Serial Data with an Arduino

In this post I will demonstrate a few ways to receive data via serial on an Arduino from a computer. I received a question about this on one of my other posts and decided to make a post on this topic.

First off, read the official Arduino documentation on this HERE. You may very well not need this after you do.

Second, there are some official Arduino examples that come with the IDE. I won't replicate something that is already there.

Third, if this is not what you are looking for (perhaps you were looking for serial between 2 Arduinos). Check my labels. There is one called communication that might interest you. Now let's get to it.

I'm going to assume you already know how to send data to your computer. It isn't hard to get pretty things to pop up on the Serial Monitor. If not, check out the serial examples under basics in the IDE.

To send data from the Serial Monitor you need only type something into it and hit enter. Most terminal emulators probably work the same way.

Get my Serial Test sketches HERE. I will just comment on the methods from the Flash_the_LED sketch. It was made for a previous post but will work just fine for this. You send it a number from the Serial Monitor and it flashes the LED that many times.

while (Serial.available())
This is the first important part of the sketch. This is a pretty typical scenario. You only want to check for new values when there is something in the Serial buffer. If there is nothing, Serial.available() will return 0 and the statement will be false. Remember 0 is false. Anything else is true.

val = Serial.parseInt();
This part receives 2 bytes from the serial buffer and converts them back from ascii to the number you want. If you are using a terminal emulator and are having problems, this might be it. I believe the Serial Monitor puts it through an ascii conversion, but other programs might not.

An int value is made up of 2 bytes in ascii format. That is why you need the parseInt(). If you are just receiving one byte, just use Serial.read(). That receives one byte. You can also piece bytes together yourself and do individual bits in a byte, but that is another post. That should about cover it for this topic.

Serial communication can get complicated, but the basics are simple on an Arduino. Play around with it. Look over the Arduino examples and MINE. Hang out on the Arduino playground and forum. You will soon be an Arduino communication master.

Matthew

Monday, September 2, 2013

Simple Arduino Robot Arm from 9 gram servos

Greetings once again. I just wanted to take the opportunity to introduce you to my new robot arm. It doesn't have a name, but it is made from house insulation foam and 9 gram servos. I won't do a full tutorial on this because frankly it isn't required. There are tons of this sort of thing out there. Use mine as a starting point for your own design based on what you have sitting around. This is just one example of something that works.


For this project you will need a few things.

The first is an Arduino or other microcontroller. I suppose you could use an RC receiver or some other sort of signal generator, but I will be using an Arduino Mega2560 r3.

Next you will need two HXT900 9gram servos (or similar). These can be purchased  from hobbyking.com (what I recommend), or you can search for 9 gram servos on Ebay. They are common and cheap. I will say that the one's from HobbyKing are pretty decent quality (for a $3 servo). They aren't without fault, but you could do much worse.

For the arm's physical construction I will be using half inch house insulation foam. It is also cheap, but you will probably need to buy a full 4x8 sheet of it. You might be able to use styrofoam or foam board as well. Just make sure it is light. These servos aren't very big.

Last you will need some sort of hinge bracket. I use a part off some old plastic blinds for the base and then just a plain screw for the elbow.

First, cut two lengths of foam about 6.5" x 1". This is about the maximum length that I would use. Beyond that the servos start to get overtaxed when fully extended. Next cut the center cross beam. It is about 1.25" x 1". Basically, make it big enough that your servo and hinge will fit in between the first two pieces.

Next we are going to glue it together. Make sure your servo horn is pointed in the right direction, and hot glue it in place as shown. I use the servo itself along with the plastic blinds bracket as the joint. Again, if you are using a bracket completely dissimilar to mine, you may need to modify this. The spirit of this arm is use what you have.


Next we are going to make the other arm segment. This is about 5" x 1". I cut two of them and then glued them together to make one solid arm.

Next I screwed a screw into the center of the arm about a half inch from the end. This works as my other hinge. The metal on foam is actually pretty fluid.



Next we need to mount the elbow servo in the 1st arm segment. I cut a nice slot in the arm and slid it in. A little hot glue, and it was secured. This is a good time to go ahead and make sure your elbow servo horn is in the correct position. This is important. It will be hard to change later. Place the horn to achieve the desired range of motion.



Now cut a hole in the 1st segment opposite of the servo to create the other side of the hinge. Insert the screw of the 2nd segment and glue the horn in place once you get it straight. You should now have a completed arm without a base.

Go ahead and cut a base. I used a 5" x 5" slab of the same foam. Now just hot glue the servo of the first joint to the base, and you are good to go. Your arm is now done!

The keen eyed observer may not that this arm can't really do much. It can't rotate or pick up things. About the only useful thing I have done with it is tape a sharpie to the end. That is not the point. The point was to build a tool with which I could explore inverse kinematics. That goal is achieved.

Inverse Kinematics is another post; however, you can test your arm with either the sweep or knob example programs. Note that if you have problems, try powering the servos from an external power supply. It is entirely possible that your Arduino just isn't providing enough current.


Maybe this post inspired you. Maybe it didn't. If not, wait around for inverse kinematics(now HERE). That will be more interesting.
-Matthew