Search Microcontrollers

Showing posts with label Rover. Show all posts
Showing posts with label Rover. Show all posts

Monday, June 16, 2014

Arduino Robot - "Zeroing" Stepper motors

Hello, this is yet another post related to the series dedicated to the Arduino Rover project.
These posts, although eventually enjoyable by any kind of maker, are targeted to young and non particularly expert geeks.
Not long ago I was toying around with hall effect sensors, the reason I was is related to today's posts.

The rover will have three ultrasound sensors (yup, 3!!! they are cheap :) ) in the front side.
Two of them will point slightly on the side (one per each side, symmetrically) and the central one normally will point straight ahead.
This one will be mounted on a stepper motor which will allow the rover to scan the area in front of it (and eventually map it, sending back sonar data via the NRF24L01+ radio).
To avoid ultrasonic interference the three modules will be triggered separately (the two side ones will be on the same trigger, sensors have a 15 degree angle sensitivity, they will be pointing in directions that are way more than that angle apart).

Stepper motors, particularly the one I chose (a cheap 28bjy-48, with gearbox reduction), can have a very fine resolution, so they can provide a very precise scanning, way more than the 15deg sensitivity angle of the ultrasound sensor... gotta do something about that, probably via software.

Despite the fact they can rotate an extremely precise amount of degrees, unfortunately they cannot remember their position, it is normally up to the software to keep track of it.
But what happens if you reset the MCU running such piece of software while the motor is in a given position X?
It happens that whatever variable you were using -if not stored in some flash memory or similar solution- it will be re-initialized at boot time after the reset.

Sure, saving this variable in a non volatile storage might help... but still might fall short of other issues, such as a motor "missing" a few steps.
Actually you instruct the motor to move X steps, but you have no feedback if it actually moved that precise number of steps.
It normally does, unless it gets stuck against something.

So a good solution is to detect a zero position and reset your position variable on that at each boot or even from time to time during normal operation.

Then the question becomes :how to?
As we said, a stepper motor provides no feedback, so we need to ADD something that does.
A typical solution is to use a magnetic or optical device, basically something static that can detect a moving part without touching it.

I went for the magnetic solution, using a hall effect sensor and  neodymium magnets.


The one in the picture is just a test setup, as you can see the small hall effect sensor is taped down while the final solution will hopefully be a bit more stable.
The stepper motor is physically on the opposite side, below the wooden surface, and  a 2mm thick piece of plastic is connected to its shaft, coming this side of the chassis.



I am using some tiny round neodymium magnets (got 200 of those, also really cheap on ebay), they are 3mm in diameter and 1 mm thick, so I was able to embed 2 of them in the 2mm thick plastic.
I simply drilled a 2.8mm hole with my dremel, they are slightly forced in, no need for glue or anything else, they just stay there nicely.

I connected motor and sensor to the arduino, using a mega for this test,  a Uno or pro mini would do the same, I just had this one available at the moment and did not want to disconnect the others I am using for other purposes.

Then using the Stepper Library demo code (configured to run with the mega pins)
I managed to have the motor turn clockwise for a few steps and counter-clockwise for the same number of steps, continuously.
The LED is turned on if the digital pin connected to the sensor is LOW (sensor is active LOW).



The key thing is that I move the motor 1 step at a time and at each step I poll the sensor (you could theoretically use interrupts for this, but I will need two interrupts for the speed encoders and arduino does not have any spare int available :( ).

Now that we saw it works, we need to consider that, even if those magnets are really small -and you might find smaller ones, but they become more difficult to handle- they still cover an area that is represented by a finite number of steps.
Arguably this area might change a bit depending on the distance (the radius) at which you place them from the shaft.

The idea is to consider as ZERO the position of the stepper motor that corresponds to the center of the magnet being over the center of the sensor.
We then need to calculate, when the magnet hits the sensor, how many steps it needs to clear it again.

My simple code is here :

#include <Stepper.h>
int input_pin = 52;
int sensor_vcc =50;
int led_pin = 13;
int cnt=0;
int dir =-1;
int lastSensor = LOW;


// initialize the stepper library 
// I am using a MEGA!!
Stepper myStepper(stepsPerRevolution, 30,26,28,24);  

void setup()
{
 Serial.begin(9600);
 pinMode(led_pin,OUTPUT);
 pinMode(input_pin,INPUT_PULLUP);
 pinMode(sensor_vcc,OUTPUT);
 digitalWrite(sensor_vcc,HIGH); 
 digitalWrite(led_pin,LOW); 
 myStepper.setSpeed(40);
}

void loop()
{
   if (digitalRead(input_pin)==LOW)
   {
      //detecting magnet
      if (lastSensor==LOW)
      {
        cnt=0;
        lastSensor=HIGH;
      }
      cnt++;
   } else 
    if (lastSensor==HIGH) 
    {
      Serial.println(cnt);
      lastSensor= LOW;
    }
   myStepper.step(dir);   
}

Turns out that the readings are quite consistent and it usually takes 36 steps with that sensor, placed in that position, with those magnets etc... you need to run your own measurements if you try to replicate this experiment.



You probably noticed that the numbers tend to increase after few passes, that happened because the tape started to warp a bit when heated by the lamp and the sensor raised a bit getting closer to the magnet.
As I pressed it down again it temporarily went back to 37, this will not happen when the sensor is securely placed on the rover.
As a general rule, when you zero your motor at boot or anytime you may need it, you should also check again this number of steps and get half the value as the zero position.

Tuesday, May 20, 2014

Arduino Robot - Moving around and steering

It is true the Rover we are planning will have to do many things, but the most basic thing it has to do is to stroll around, to put it simpler : move.

It is a Two Wheel Drive rover, meaning it will have a small electric motor on each of its two traction wheels and it will have a third traction-less wheel on the back, just to balance it out.

It will be able to steer like tanks do, by changing the speed of each motor accordingly.
The simple way to look at this is by considering some basic combination of speeds :
1) The two wheels are turning in the same direction (forward) and with the same speed -> the  rover will drive on a straight line, moving forward
2) The wheels are turning with opposite directions, but the same speed -> the rover will turn on itself, around the middle point between the two wheels

3) One wheel is turning, the other one is still -> The rover will rotate and the center of rotation will be the still wheel.


We can generalize the concept and find the center of rotation for any combination of wheel rotation velocity.
It is easier to do that using vector match which is quite intuitive, I am saying this because the target audience of this article includes very young makers that eventually did not study it yet... don't  get scared :)

If we represent the velocity as an arrow starting from the center of the wheel and pointing to the direction in which the rover is moving, we can use some basic geometry to figure stuff out.


As you can see in the example above the right wheel is rotating roughly twice as fast as the left one, this is why the V2 arrow is about twice as long as the V1 one.
This means that in the same amount of time the right wheel will travel twice as the distance traveled by the left one.
Now, if we connect the base of the arrows and extend the line, then we connect the top of the arrows and we also extend that line, we discover they eventually touch themselves in a point.
That point (the red triangle) is the center of rotation, in fact if V1 = V2 those lines will never touch which means that the center of rotation does not exist... and that is  because there is no rotation at all.
If V1 = V2 the rover would drive in a straight line.

The same concept works for about any combination of velocities.


In this second example V1 and V2 have different direction and modulus (modulus just means how "long" a vector is), can we compute the position of the center of rotation?
Indeed we can, as previously said, basic geometry comes in help.


We want to find X, it is the distance between the left wheel and the center of rotation, you can easily see that we can then relate it to any point we consider the center of the rover, like the middle point between the two wheels.

The green and red triangles are similar, so we can state that :

X : V1 = (D + X) : V2

Note that we use (D + X) or (D - X) depending on which way the X arrow is pointing.
Resolving : 

X = V1/V2 * (D + X)
X = V1/V2 * D + V1/V2 * X
X (1-V1/V2)) = V1/V2 * D


  V1/V2 * D
X =   ------------------    
 1-V1/V2

Now say we want to relate everything to the middle point of the axis connecting the two wheels :

  V1/V2 * D
X =       ----------------    + D/2

 1-V1/V2

Let's assume D = 10 cm,  V1 = -50 rpm ,  V2 = 100 rpm.

X = -50/100 * 10 / (1 +50/100) + 10/2 = -5 / 1.5 + 5 = 2.66 cm  

The coordinate system we are using has the center in the middle point of the axis connecting the wheels and positive X facing left.

Knowing the center of rotation is key to be able to plot maneuvers, i.e. if we need to drive around an obstacle, but it is also important to calculate the position of the robot at any time.

In fact we might try to drive the two motors with a predictable velocity, eventually equal, but for various reasons one might turn a bit faster than the other forcing our rover into a undesired shallow turn and by consequence missing the predicted trajectory.
That's  not really a huge issue provided we can timely apply corrective actions, and this becomes possible if we also measure the real velocity of the wheels.

A typical way to measure the rotation speed of something is to attach an encoder, a small and simple device that sends an impulse every known number of degrees of rotation.
This is typically achieved using a small plastic wheel with a number of holes in it


The U shaped thingy visible in the bottom right is an opto-coupler, on one side of the U there is an LED and on the other side a photo-transistor.
When light generated by the LED hits the transistor, current is allowed to flow through it and that can be detected as a logic 1 on the pins of a MCU.
If the plastic wheel is placed in the U, when it turns it will generate a 0 level each time there is no hole between the LED and the transistor and a 1 each time a hole is between the two.

Finally, if we know how many holes (N) are in the wheel , we can easily compute how many degrees there are between each hole.

deg = 360 / N

And if we count how many times a 0-1 pulse happens on the selected pin of the MCU , we can also compute how many revolution the traction wheel performed:

rev = pulses * 360 / N


The schematics to connect the encoder to the Arduino are pretty simple :
the green triangle represents the LED, the red / white crossed circle represents the transistor.
There is a specific reason why we selected pin 2 on the Arduino, but we will dig into that detail later.

At this point we ASSUME we can activate the two electric motors and we know how we can use a "feedback loop" to measure how much they really moved.
Next step will be to see the details on how to activate the motors.

Monday, May 19, 2014

Arduino Robot

I played a bit with Arduino some time ago and I think it is a great idea to get started with MCUs.
I believe it can support you even when you try to do more complicated stuff, but I stopped playing with it for a while since I preferred to get into a more " hardcore " scenario with MCUs.

That said, a couple of years ago, I gifted an Arduino Uno to a young kid (he is the 11yo son of my cousin) who got totally hooked on this thing.

So, to help him advance, now, I proposed to do a sort of Arduino Bootcamp this summer and to build some kind of robot rover together, in about 1 week.

For this reason I am preparing some material and thought that maybe I could document here my experiments so they could be useful to others.
It will be basic stuff, but still enjoyable I guess, to be fair I am not yet sure what the end result will be as I will try to adapt to things he can understand.

The inspiration is the Curiosity Rover that is strolling on Mars... I believe (I am pretty sure actually :) ) we will do something a bit simpler than that, but the idea is to have a rover that can be autonomous (avoiding obstacles, computing directions, speeds etc) and that can receive high level orders via a digital radio connected to a PC on which we will run probably a java client (that I will write).



I guess we will have another arduino as a bridge for the digital radio to the pc.

The rover is based on a 2WD chassis that can be easily found on ebay.


 Rotary encoders will allow us to measure the speed of the robot and calculate its position by integration.
We are planning to use a digital compass to identify the heading, ultrasound modules (most likely 3 of them) to detect obstacles and to scan the area (one of them is going to be mounted on a stepping motor).

I also have some IR emitter/detectors that eventually can be used to implement a "follow the path" functionality, not sure we will be able to stick that one in in time, but maybe we will just add the hardware and later on we will enable the functionality via software.

I am assuming we will use 3 arduinos for the rover itself as we need a lot of i/o (maybe a mega would be enough tho) and this is an option for me to illustrate some serial protocol concepts (we will use uart/spi and I2C, I am leaning towards I2C to allow the communications between the 3 mcus).

If all this sounds interesting to you, then stay tuned, I will document my experiments and tests while I get ready to explain those concepts and ideas to my young colleague!
Plus, hopefully, I will document the construction and tests of the robot which should happen this summer (in a week).

If you have ideas or suggestions, send them in before this summer!

Meanwhile I will probably put on hold my other experiments (I already have a second part on NRF24L01 ready, but not publishing yet until I finish the full series) and focus on this Arduino project.
I simply don' t have enough time for both, sorry.