Unfortunately electric IMP has servers pretty far from where I live, so latency IS a problem in my case at least.
What you're going to need:
- some electronics knowledge
- a working RF, IR, or wired remote controlled tank, or any kind of vehicle
- a motor controller board + electric imp, or any simple motor controller board, for that matter
- jumper wires
- an ULN board for powering the fifth motor (or stepper)
- a screwdriver
What I had to start with:
- some electronics knowledge
- this RC tank
- a mini-box motor controller board + electric imp
- jumper wires
- this ULN board
- a screwdriver
Step 1: Tearing the Tank Apart, Taking a Look
Be very careful not to break anything thinking, there's no more screws keeping the thing together. I didn't had to find any hidden screws while taking this tank apart, still be patient.
The first thing you need to take off, is the small board in the front with the chaintrack-reserves. This is secured in place with three screws. Even if you get it loose, you'll have to take off the front wheel, and its shaft on the right side, that's blocking it.
I advise anyone doing this to leave the screws in the holes, so they wouldn't lose them.
When you have that done, you can put the wheel back, so you can test the thing later. Carefully put the chaintrack back too. After this, unscrew the six screws on the bottom, and put them away for a while. Now you can lift the top part off to have a look inside.
At first sight, you will see a ~2 x 2 inch board with some transistors, resistors, capacitors on it. That is the RF receiver and the driver section of the motors. In the front you will see the gearbox covered with plastic, holding the gears in place.
In the upper part, you might see a DC motor, some wires, and a white circle shaped thing, that has gears on the outer side. That is the gear that turns the upper hull. Dig deeper, take out the screws holding that white wheel, and pull out the hull.
You won't see much, just the hull, and the shooting mechanism sticking out. There are five screws covering the rest, take them out and take a look on the inside. You can see the LED that lights up when shooting, the rest of the shooting mechanism, the barrel lifting mechanism, and some switches with wires.
The shooting mechanism is pretty complex, and because it's quite fragile too, I had to glue it quite a few times. Regardless of the care you take when you play with it, these kind of thing s break easy. The mechanism has two springs in it, and some gears too, it took em about 15 minutes to reassemble it for the first time. When it broke again, and it needed to be taken apart, I put it back together again in 2-3 minutes.
okay, you got somewhat familiar with the guts of my tank, now I will turn it into something cooler.
Step 2: Start Hacking
Now you got to check out something: look for any capacitors connected straight to the pins of each motor you can see. If there is a cap on one motor, it is very likely for all of them to have one. Those are there to minimize the noise coming from the motors.
However, if you are using a motor controller board, that has current limitation, you need to take the caps off. They act as short-circuits at start-up, when they're in discharged state. You can clip them off, or you can take them off nicely with a soldering iron, it's up to you.
To remove the ones from the track driver motors, you must take the gearbox cover off, take out the motor, snap the caps off, and put everything back. I have to say, putting the motor back in its place wasn't too easy, though it matches the plastic perfectly.
Clipping the remaining caps is easy, you don't have to deal with twisty angles, or weird motor holders.
Okay, caps are off, next thing is to hack in our motor controller with the imp on it.
The board pin headers are marked on the silkscreen layer, the DC motor pins can be easily identified. You will have to connect your DC motors to those, or the equivalent pins on your motor controller board. There are only DC motors in my tank, the wiring wasn't really hard to figure out. I put some resistor legs in the 0.2" header holes, and connected them with a female-to-female cable to the DC outputs.
Since I had five motors in my tank, I had to add an ULN buffer to power the fifth. These are actually made for steppers, but they're just as good for DC motors as well.
The motor that makes the shooting happen is the only one that needs to rotate only in one direction, I chose that to be the one driven by the ULN board. I modified the code of a servo output to give out a constant '1' or '0' whenever the control of the C# app sais so, and connected it to an ULN input. The shooter motor was tied between the coresponding ULN output and the ground.
The buffering is needed, because the servo output can provide currents only up to 20mA, but our DC motor obviously draws more.
The ULN2003 has a rated output current of 500mA each output, that is more than enough for us.
The motor controller board must be powered for this to work. I had a battery of 9.6V in the tank by default, I used that to power my controller board, which had a voltage consraint: Vin must be under 11V.
If you have unclarities about the connections that need to be made, please refer to the image from this step.
Step 3: A Few Words About the Board
What do we need to know about servomotors? Well, they usually have a potentiometer in them for feedback, and a gearbox for higher torque. Small DIY project servos are quite often limited to a certain turn angle, most of the times because of the potentiometer.
Servo motors require a periodic squarewave of 50Hz , with variable pulse width, to change their position. However, if the signal drops out, the servo stays in the position to which it was sent last time.
The pulse width is a variable that differs from servo to servo. I have a servo, that needs a 1 millisecond impulse to turn to the left extremity, and an approximately 2.5 millisecond impulse to turn to the maximum right position. The impulse lengths can be calculated using the law of three.
The 1 millisecond base signal is required, but it doesn't change the position in any way. So we're going to look at this as a 1 ms offset.
Let's say we want to turn the shaft to 75 degrees. We know these:
max turn angle = 180 degrees
impulse width change = 2.5 - 1 = 1.5
180 degrees ................. 1.5 ms (1 ms offset not taken into consideration!)
75 degrees ................... x ms
x = (75 * 1.5) / 180 = 0.625 ms
This is the formula we have to know, when we want to position the shaft to a given angle.
The stepper motors need four amplified servo signals. This is what the ULN board was actually built for. Connect the servo outputs to the ULN inputs, and the Stepper to the ULN outputs. Look at the table to see how the four lines get toggled.
The board supports wave, full-step, and half-step drive modes, basically anything you'll ever need. The IC providing the waveform isn't actually a specialized stepper driver IC, so microstepping isn't supported.
There is no in-built current limit on the stepper controller side.
The simplest of all three, I think. There are four H-bridges on-board, each bridge has an input for direction, and an input for speed. The speed is varied by changing the duty cycle of the signal that goes on the speed pin.
Simple enough, the DC motors have two parameters in our case: speed and direction. Change those to control the motors.
Speed can be changed by giving a modulated signal on their power rail, direction can be toggled by changing the power rail the motor pins go to. Refer to the images to get a more visual example on PWM modulation and direction control.
Each of my bridges can deliver currents up to 1.5 amps before the in-built overcurrent protection kicks in.
Current measurements can be made by developing the firmware for the imp: AD measurements on a shunt connected in series with the low side of the H-bridge can give you an idea on how much current is flowing. Current is directly propotional with torque, so you could get an approximate torque value as well.
Throughout the development, I accidentally reinvented something: Connect the PWM pin to 'high', and PWM modulate the signal that goes to the direction pin. You will get PWM and direction control by controlling a single pin.
Giving a 50% duty cycle signal on direction pin will make the motor stop (it turns to left just as much it does turn to right, so it goes nowhere from a point of view), changing the duty cycle low/high will result in the motor spinning left/right.
The bad thing about this is, that there is consumption even when the motor doesn't move. We also lose one bit from the resolution.
Long story short: this is the board I decided to use for control, the IMP is optional, this can be incorporated into any kind of system, and be controlled via I2C.
I've also had the ebay-type L298 H-bridge board at hand, but that can deal with 2 motors only, and I needed 5. Not to mention the space the ebay bridge eats up :)
If there are any questions about the motor controller board I decided to use, you can ask in a comment!
Let's see how can we control the board via the IMP, and a small C# application!
Step 4: Writing the for the PC Program
First, we need a textbox for the imp http link we're going to get from the imp IDE. This is different for each HTTP IN module, that's why we need to make it a variable.
Next, we need all sort of controls, to have full control on our motors. Different tanks might have different motors in them, so I explain how this board could be used to drive three types.
We need to add input controls to change shaft angle from our C# app. I added a slidebar, a start, end and stop button. The start button takes the servo to 0 degrees, the end to 180 degrees (or servo maximum), the stop button makes the servo output drop to '0', effectively stopping it, whichever position the shaft is in. The slidebar gives the angle we want the servo to turn to. This forms a control string, which is sent to the HTTP link we already have. The imp parses it, and takes action by sending data through serial interface to the servo controller circuit.
To enable a stepper motor, one must select "Stepper A" against "Servo 0->3" down in the Stepper motor groupbox. Then he can select the drive mode from the three possibilities.
Depending on what we chose here, the servo outputs will toggle exactly as the drawing in the board description step depicts. I won't go into details about how the motor shaft gets turned, that would be beyond the scope of this instructable. I tested all three, they all work.
The moment we switch to "Stepper A", the motor will start turning. Changing the two-positioned direction slidebar will change the turn direction.
The angle and steps textboxes aren't dealt with yet, that's something I just realized it could prove useful. To make that work, step angle, and some other parameters would need to be included, too.
Controlling DC motors with the C# app is straightforward. You have a speed slidebar, this changes the duty-cycles from 0 to 100% with a 0.1% resolution. Then, you have a direction slidebar with two positions, left and right. The brake button is there to stop the motor immediately.
After I finished tests with these, I realized, I needed some sort of joystick for better control. I added a "panel" control, and a mouse movement event, to know where I am with the mouse over the panel region. In the middle I put 0, 0 for the two chaintrack-driving outputs, as I move my mouse left-right and front-back, the tank reacts with changes in the speed of each motors.
I also added some textboxes for debugging.
Note, that the point, where the application pops up at start, has effect on the on-screen position of this panel. So, if you decide to use this panel thing to control your tank, you'll have to adjust it to work with your X & Y offsets. Or simply snap it to a corner of your screen, so the panel always has the same on-screen position.
Making such a window is simple, just drag together everything you want from the "Toolbox" bar, align them, and "wire" them together in code. If you want something on a button-press, double click the button. If you want something to happen on a slidebar, or textbox change: add an event handler. It is very-very simple, you can find examples for anything on the web.
The way you communicate your parameters is at your choice. I built up a control string, which has some variables in it. I do something in the C# app, and send the string that reflects that something on the URL I got from the IMP site. On IMP side the string is received on an input port. I parse out the variables, and send data to my I2C devices to execute the commands. very simple. I provided a snip of the code I wrote to send data.
Parameter "data" has the string with the variables in it, the parameter "http" has to be the link from IMP site.
Step 5: Writing the Firmware for the Imp
In the planner press "Add node" and select HTTP IN from the list that appears. After that, copy the link to your version of the C# app.
I got my http post method from the web. I made some slight modifications on it, just to fit my needs better.
When you're done with this part, simply pull an arrow by dragging the plus sign on the right top corner onto your imp node.
Writing the code itself is the part that is the most time-consuming. I took examples from their forum, they proved to be useful. I've also had help from a colleague of mine with great experience in programming.
Low level software isn't required here, the functions provided by the IMP team are more than enough to get this working.
The code I wrote is probably far from optimal, however that wasn't my goal.
I dedicate the following instructables steps to describe the IMP side stuff for each type of motors.
Step 6: Functions That Control My DC Motors
initializes the PCA9635 DC motor signal generator, resets the duty cycle pins to 0%, and puts the direction pin to 0. The two zeros on the H bridge control input pins leave the motor undriven and free spinning.
modifies the output drivers state. There are four modes, the output drivers can work in:
00 - LED driver x is off (default power-up state).
01 - LED driver x is fully on (individual brightness and group dimming/blinking not controlled).
10 - LED driver x individual brightness can be controlled through its PWMx register.
11 - LED driver x individual brightness and group dimming/blinking can be controlled through its PWMx register and the GRPPWM registers.
The mode of each output driver is stored on two bits. Four driver states are grouped into a single register, the register name is the driver_id parameter of the DC_drivers function. The second parameter is driver_mode, the user has to provide an 8 bit value with the wanted output driver mode shifted to its place.
For example, if there is need for a switch from "fully on" to "PWM controlled" mode for output LED1, bits 3:2 of LEDOUT0 has to be changed from 01 to 10. In the default IMP Motor Control board code this is done in the DC_command() function.
Here's an example on this:
temp = I2C_ReadByte(PCA9635, LEDOUT0); // read the registers content
temp = temp & 0xF3; // delete the bits found on bit fields 3:2
temp = temp | 0x08; // set the 3:2 bits to 10
DC_drivers(0, temp); // call DC_drivers() with the two parameters, LEDOUTx -in our case x is 0, and the updated register value
Reading the register previously to the data change it's necessary, because the other bits in the register might have effect on the other outputs we use. To avoid this, I've read it first, changed the used two bits, and wrote it back again.
is the function used to change the speed and direction of the selected DC motor. The first parameter id tells the function, which DC output to modify with the next two parameters: direction and duty_cycle. The last two parameters meaning is straightforward. The duty cycle is limited to 99.6%, any value bigger will result in changing the duty cycle to 100% by changing the output driver state to "fully on" mode.
Different applications will have different load on the motors, to get behind this, a ramp-up algorithm can be used to gradually increase the duty cycle.
Takes advantage of the sleep mode feature of the DRV8835. Since this H-bridge draws very little current from the logic supply(typically 450 µA, maximum 2 mA), it can be powered straight from a PCA9685 pin, which can source a maximum of 10 mA. This is useful when one of the bridges is not used, putting it to sleep mode will minimize the current drawn from the load supply to ~10 nA. The first parameter "bridge" selects one of the two bridges on board, and can take "AB" or "CD" as value. These disable the bridge marked the same way, visible on the board silkscreen. The second parameter is active low, enables or disables sleep mode on the bridge selected by the first function parameter.
Step 7: Functions Controlling the 8 Servo Lines
initializes the PCA9685 servo motor controller on power up. The period register is initialized to a value, that results in an output PWM period of 20 milliseconds. This 20 millisecond period is required, this is the time in which the variable width signal has to repeat itself.
SetServoConstants(turn, start, end)
This function is used to save some values, that can change from servo to servo. Maximum turn angle, shortest impulse, longest impulse. These parameters are required if we want to turn a servo shaft to a desired angle.
function SERVO_command(id, angle);
The function that tells the I2C device to start giving out impulses with given timings. The first parameter is the servo output number, the second is the angle we wish to turn the shaft of the servo on that channel.
These three are the functions I used when it came to control servomotors.
Step 8: Stepper Controlling Function
This function hasn't been finished yet, number of steps can't be given, since we don't know about the number of impulses that were sen't by the PCA9685. However, the mode parameter allows us to control the stepper with three methods mentioned before.
It works in both directions.
When using this step mode to drive the stepper, only a single phase gets activated at a given time. The number of steps is equal as it would be with full step drive mode, but the torque is significantly lower than the rated torque.
Full step drive
This is the most commonly used method, when it comes to drive stepper motors. Two phases are always on, and the motor will have full rated torque.
Half step drive
Half stepping is widely used to increase angular resolution. Since the drive switches between “one phase on” – “two phases on”, it will have less torque at the point, where only a single phase is turned on. Some compensation can be made with increasing the active winding current.
That being said, we know plenty about this controller, now let's see how it works!
Step 9: Final Words
I'm off to clean the workshop :)
Good luck to everyone in the MCU contest!