Friday, March 27, 2015

Reading PWM

Background
The AimBot rig is to be controlled remotely. To achieve this we are using a standard RC remote of the same type that's normally used with RC cars and planes. The reciever for this unit uses very little power, and is in a very handy size for our rig.

The control and reciever

The reciever puts out a PWM signal, and every joystick and button is designated it's own PWM chanel,
For our rig we will be using 4 chanels:
  1. X-axis joystick
  2. Y-axis joystick
  3. Mode switch
  4. Picture trigger
Every chanel is input to separate digital pins on the Arduino.

Interrupts
In the Arduino program every pin gets set up with a hardware interrupt that runs a interrupt function when the pin state changes. This interrupt is run immediately when the state changes, and interrupts all other code execution. After the interrupt routine is run the code returns to whatever it was doing before it got interrupted.

The code that runs during the interrupt checks the state of the pin that called the interrupt and checks the current time from the internal microseconds counter. The next time the pin state changes the last recorded time is subtracted from the current time, which gives the length of the pulse. The pulse length is then stored in a global variable so it can be accessed by other parts of the program. The image above shows the PWM pulse, where T is one of the pulse lengths we want to measure.

Time and memory
The function code uses micros() to get the current time, this returns a unsigned long (32 bit), that overflows every 70 minutes or so.

Elapsed time is stored in a uint16, this gives us the ability to measure frequencies down to 15 Hz before overflow occurs. The picture below shows the calculation regarding this:


The lowest possible frequency for the PWM signal is around 50 Hz, giving us good margins before overflow.

The counter value is also declared volatile to remove the write-protection, allowing the value to be updated from the interrupt without interfering with the rest of the program.

Advantages over other methods
The Arduino has a ready made library for reading pulse-width modulated signals. The function sigin() can be used for this purpose. We considered using this function, but upon closer examination we decided not to. The reason is that the sigin() function hangs upon call, until the pulse has passed. For a 50 Hz signal this would use about 20 ms per chanel.
Reading the signal using interrupts on the other hand only records the current time of every pass and allows the rest of the program code to continue executing almost immediately.

Monday, March 9, 2015

Battery guard

We are using Li-Po batteries for our rig, and in order to keep them in good condition for a long time it is very important that you dont discharge them too much.
So in order to prevent over-discharge we created a circuit that would let the rig fully disconnect from the battery when the voltage get too low.

We had already made a power management module that lets the Arduino control the power to the other components of the rig. What we now needed was a circuit that would enable the Arduino to switch off it's own power supply.

This turned out to be a bit tricky when designing a transistor based circuit. When the voltage supplied to the Arduino goes too low you loose control over the state of the digital pins. This resulted in the Arduino leaking current to the digital pins, leaving the Arduino in a state of limbo between fully on and fully off.

There are ways of solving this using pull-down resistors and transistors with lower gain, however since it was absolutely imperative that the circuit would not leak any current in the off-state we opted to go with a relay in place of the transistor.


The above picture shows the full circuit for the battery guard.

Some comments to the circuit:
Arduino_A2 - Reads the battery voltage
Arduino_A1 - Reads the state of the ON/OFF button
Arduino_D1 - Outputs 5V, holding the relay and keeping the Arduino alive