Monday, November 22, 2010

M-Way

Implementing control systems using micro-controller reduces the overall weight and cost, and improves the response time of the system.


Micro-controllers are small self-contained processing units with memory, processor, and programmable input/output peripherals. They can be utilized in many applications where there is a need for small computations. Unlike computers, they have very limited processing power and memory, and require a very minimalist approach to programming. For segway, we implement the control code in a micro-controller to improve the response time, and also to ensure that the cost remains low.

For those of you, who have no idea of what a micro-controller is, the following tutorial is highly recommended - http://www.societyofrobots.com/microcontroller_tutorial.shtml - It gives a pretty good overview.

In order to evaluate and get a feel of micro-controllers, we started out with experimenting on an Arduino Uno. Although it’s not fast enough to be used in a segway, it has pretty decent features and therefore is a good starting point for further exploration.

Arduino Uno Hardware Details

Quite a bit of information related to arduino and its inner working, including a tutorial introduction to its programming environment, is available online at http://arduino.cc/. This document only covers most of that information very briefly so as to not to repeat whatever has been covered in the best way possible online. If anyone is interested in further exploration on arduino’s, I highly recommend visiting the arduino website. More information related to Arduino Uno can be found at http://arduino.cc/en/Main/ArduinoBoardUno
Interrupts in a micro-controller - In micro-controller, most of the time is spent waiting for reading sensor readings. It can be more efficient for micro-controller to be “informed” whenever a sensor is ready to output an event, rather than the micro-controller to wait for the event, without doing any useful work. This can be accomplished using interrupts. By using interrupts, we setup micro-controller to let us know whenever it reads some signal in an input pin. If the interrupts are handled at the hardware level, they are called hardware interrupts. Otherwise, they are called software interrupts. Arduino supports two hardware interrupts on pin 2 and 3. Further information on interrupts can be obtained from - http://forums.trossenrobotics.com/tutorials/how-to-diy-128/an-introduction-to-interrupts-3248/

Reading optical encoder counts from Arduino

Optical encoders utilizing quadrature encoding usually have two outputs - A and B. Whenever a particular slot A in the encoder is crossed while the motor rotates, a digital pulse is generated. Another slot B, which is 90 deg in phase to the slot A, also works in the similar fashion. By looking at the order at which these two slots generate the pulses, we can identify the direction of rotation of the motor. If A generate pulses before B, the motor is rotating clockwise, otherwise it is rotating anti-clockwise. Usually this information is specific to the motor and encoder that we are using. More information related to quadrature encoders can be found at -
http://forums.trossenrobotics.com/tutorials/introduction-129/introduction-to-encoders-3256/

Based on the resolution of the encoder, it can generate as many as 500 pulses per motor revolution, effectively giving us 360/500 degrees of precision. If the generated signal is not read before another signal overwrites it, we will lose that information. Therefore, instead of reading the pulse from the main loop, we define an interrupt to be generated whenever the sensor outputs a signal.

In arduino, an interrupt handler is just a normal function that can be registered to get called whenever an interrupt is generated. There are only two pins 2 and 3, which support hardware based interrupts. However, the underlying Atmel micro-controller, which is what Arduino is based on, supports interrupts on every pin. The following link provides more information on how to accomplish that -

attachInterrupt(interrupt, function, mode) allows attaching an interrupt. First parameter specifies, which hardware interrupt - whether pin 2 or pin 3. We specify it by passing 0 [for digital pin 2] or 1 [for digital pin 3]. Function refers to the name of the function which needs to be called whenever the interrupt gets generated. Mode refers to the type of interrupt - LOW, CHANGE, RISING, or FALLING.

We can define our interrupt handler as

void count_pulses()
{
++pulse_count;
}

In setup function, we can register the above function as interrupt handler so that it gets called whenever the pulse gets generated.

void setup()
{
// Any initialization code like setting up the pins...

// We assume that the encoder output is connected to digital pin 2.
// As we are interested in counting the number of pulses, counting
// the signal whenever it rises gives us correct count.
attachInterrupt(0, count_pulses, RISING);
}

Once the above two tasks are done, we will be able to read the encoder pulse count by accessing the variable pulse_count wherever we want. However, this only takes care of forward rotation. If the motor rotates in backward direction, we want the pulse count value to be reduced so that we have accurate estimate of the current position of the motor with respect to its original position. From quadrature encoding, we know that we can identify motor rotation by looking at the value of encoder output B with respect to encoder output A. Here, instead of registering another interrupt for B, we can check its relative orientation with respect to A, in A’s interrupt handler. So, the count_pulses interrupt handler, which takes care of encoder output A, can be changed to

// we know that this function gets called whenever A is RISING
// which means whenever A is ON
void count_pulses()
{
// if B is also ON, then motor is rotating in the +ve direction
// otherwise motor is rotating in the -ve direction
// B_pin should be defined to hold pin location where B sensor
// output of encoder is attached
if (digitalRead(B_pin)) ++pulse_count;
else --pulse_count;
}

The above interrupt handler is now capable of dealing with quadrature encoding. If multiple such encoders are there, multiple interrupt handlers need to be attached.

Controlling Servo Motor from Arduino

Controlling servo motor with Arduino is straightforward. We need to connect the reference signal input pin of servo amp to a PWM output pin on arduino. Once we connect that, we can use “analogWrite” function to pass the required voltage. The voltage value varies from 0 to 255. 0 represents 0 volts, while 255 represents 5 volts. If we want to consistently run the motor at 5 V, we simply write -

analogWrite(motor_pin, 255); // where motor_pin represents the pin where motor is connected to

No comments:

Post a Comment