Thursday, May 21, 2015

How to mitigate cogging when driving BLDC motors

When we decided on which motors we were to use for the platform, the main consideration was that they had to provide continous and smooth motion. Smooth motion is a requirement if the rig is to be used for recording video, and it might also be less scary for nearby wildlife.

BLDC motors were chosen, as they seemed to be the best option for smooth motion. However when we started writing our own code for the motorcontroller, we ran into some problems with a previously unknown fenomena, known as cogging.

Cogging is the uneven turning-resistance in electromotors due to different factors, one of which is the magnets passing over the stators, causing periodic peaks in turning resistance.

When running BLDC motors at low RPM's these effects become very pronounced. And the whole rig was continously shivering from torque ripple when turning.

The solution to this problem was implementing a gyroscope and a PID controller. The PID controller compensates for the motors uneven torque response, and the result is smooth rotation.

The first video is the platform without any compensation for cogging:


And this second video is after gyro and PID was introduced:


There are still some fine tuning left to do with the PID parameters.

Monday, May 18, 2015

The next version of the AimBot?

The project is coming to an end, and the last couple of weeks have been spent writing a report on the work we have done. We have also been doing a round of testing, and will be publishing a video on that matter sometime soon.

In the meantime you can check out this rendering of the AimBot with 3 axis:

Wednesday, April 8, 2015

The 3D model is updated

The rig needed a bit more power and so we bought some more appropriately sized motors. And as such the 3D model had to be revised. There have also been a few other adjustments, one being that the arm holding the camera is now hinged on both sides by the addition of a ball bearing oposite of the upper motor.

We couldn't find any premade models of the new motors we bought so we made some sketches ourselves. The result is not incredibly photo-realistic, but at least the measurements are in order.

Here is a quick render and a few images:



Current version of the rig


And a render in exlploded view

And this is how it looks when working with it in SolidWorks

And for comparison this is the actual rig in it's current unpolished state

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

Monday, February 16, 2015

What COM port is my device on?

Sometimes it's ok to let the user manually select the COM port where the device is located, other times you want to select the right device automatically.


The following code snippet loops thru all COM ports in search for a specific device ID. The connected port is the printed to a textbox.

ManagementObjectCollection ManObjReturn;
ManagementObjectSearcher ManObjSearch;
ManObjSearch = new ManagementObjectSearcher("Select * from Win32_SerialPort");
ManObjReturn = ManObjSearch.Get();

foreach (ManagementObject ManObj in ManObjReturn)
{
    string deviID = ManObj["PNPDeviceID"].ToString().Split('\\')[1];
    if(deviID == "VID_2341&PID_0001") // Arduino uno devID
    {
        richTextBox1.AppendText("\nArduino uno is connected on  "
            + ManObj["DeviceID"].ToString());
        break;
    }
}

The devID might be a bit confusing, but we are just splitting a long string to get the relevant info. At the end of the PNPDeviceID it is also appended a counter, starting at 1 and incrementing in case you have many identical devices attached.
The code requires importing a reference to System.Management