lba-screenshot-2

The Lightbulb Audit

For the past few months, I’ve been devoting a fair chunk of my “free time” (which is to say, very little time at all… I have a baby and a toddler, neither of whom sleep) to learning a bit of Java. Specifically, Java for Android. This has been… less fulfilling than expected. I’ve learnt a fair bit since the middle of the year, but not as much as I’d hoped. I do a little recreational programming in a few different languages, mostly Visual Basic and C++ derivatives, and while all languages and coding environments have their challenges, none of them compare the the peculiarities of android app development. I won’t wax poetic here, because this post isn’t actually about Java; this post is about results.

Finally, I have got my first Android app ready for public consumption (which is to say, I lowered my standards until they matched where my app was at). I think it’s pretty reasonable, in terms of presentation, but the important thing is that it’s useful. And that pretty much sums up my standards for anything.

The app is a light bulb tracking program, which I affectionately call The Lightbulb Audit. This app is designed to be a list of every light fitting in your house, and every bulb installed in those fittings, which can be carried in your pocket. That way, the next time you see LED lightbulbs on sale, instead of thinking to yourself: “Gee, that seems cheap. I wonder if I actually need more lightbulbs?”, you will check your phone and say “Wow, I actually have three blown lightbulbs that I haven’t replaced yet, no spares, that one dim bulb in the bathroom that really needs to be replaced with something more powerful, and most of my bulbs are ye-olde incandescent lightbulbs. What are we savages? time to upgrade!”… or something very much along those lines.

So, here is a link to my app on the Google Play store (sorry Apple users, after the experience I just had learning to program for Android, it’s unlikely I’ll get to you any time soon. Also, I don’t have an iPhone to test on. Also: *sound of me blowing a raspberry at you*):

https://play.google.com/store/apps/details?id=teslaandi.wordpress.com.lightbulbaudit

(Please see “important” note below!)

I appreciate feedback, comments, suggestions, and bug reports, so please feel free to leave comment on this blog post to let me know what’s on your mind (regarding the app).

But! Because I’m such a nice guy, I’ve also put up a copy of my Lightbulb Audit spreadsheet (which is how this thing originally started life). Not only can non-android users access this, but you can also export a CSV file from the app and paste it into this spreadsheet:

the-lightbulb-audit

Please, feel free to modify the spreadsheet, add colourful graphs, add features, etc. And please share your updated version if you do! Sharing is caring.

IMPORTANT!!!! – Because I’m such a nice guy and put my app up for free, I don’t make money off it just from you downloading and using it. Where I can make a few cents is from you clicking on the ad banner at the bottom of the app (which I’ve tried to make as unobtrusive as possible, because the afore mentioned niceness). So, if you see any ads that are even vaguely interesting: please, click on it. At the time of writing, my revenue is up to about $2.06… sigh… Oh well, I do it because I enjoy it, not to make money. Also because I’m just such a nice guy and want to help you and your lightbulb situation… Which is a mess, right? Be honest.

ALSO IMPORTANT!!!! – Please don’t leave poor reviews. Any comments, questions, queries, or suggestions: Please leave a comment here, and I’ll do my darndest to look after you…

…On account of being such a nice guy.

VR Box 2.0 – QR code and vague review

Before christmas I bought myself a smartphone VR viewer (a la Google Cardboard, just fabricated out of plastic instead of cardboard). I spent ages pondering whether I should buy one or not, since I didn’t actually NEED one, and it would just open up a world of new projects that I don’t have time for. In the end I did it, because the $30 or so that it cost would be offset by not being drawn to eBay and Aliexpress all weekend trying to find the best deal and then talking myself out of it. I bought the VR Box 2.0:

vr box 2.0 image

The reasons I picked this unit were fairly simple:

  • No particularly bad reviews
  • Adjustable lens position for both pupillary distance (distance between the centre of your eyes) and focus (distance from lens to eye)
  • Low cost
  • Moderate specs, enough for my purposes
  • Sliding panel for exposing camera
  • Openings for power and headphones

Overall it functions, and you can get a reasonably good VR experience. Some people will complain about the cheaper VR sets not having an immersive enough experience, but I don’t think that a few degrees extra Field Of Vision will really fix that.

Yes, the headset can get a little heavy on the nose, but that’s nothing that can’t be fixed by adjusting the straps or adding a little extra padding.

This headset doesn’t have the built in magnet switch for interactive with applications, so I made up a little dongle with a small rare earth magnet inside. When I bought the headset, it also came with a miniature bluetooth gamepad, and while many apps don’t accept gamepad inputs (for some bizarre and stupid reason), quite a few do.

In fact, the main issue I had with this purchase was dealing with the seller on Aliexpress. See, when the VR Box 2.0 arrived in the mail, I had a look at the sparse documentation, and it didn’t have a QR code for calibrating the Google Cardboard apps to the headset. There was a shrunk down image of a QR code in the pamphlet (which in itself looked like it had been photocopied onto glossy paper, so the image was blurry), but it wasn’t readable by the phone. Naturally I contacted the seller, asking if they could send me a copy of the QR code required. After a several responses along the lines of “the QR code is in the documentation” (which is wasn’t), and “please see the manufacturer’s website” (which could not be found, nor would the seller give me the URL), I told them that I’d have to leave a negative feedback if they didn’t help. They didn’t, so I did.

In the end, I used the Google Cardboard QR Generator: https://www.google.com/get/cardboard/viewerprofilegenerator/

I use a Samsung Galaxy Note 4 (which has a 145mm screen), and set up the QR code to suit my lens position, so your inputs relating to screen and lens position might be a little different, but the rest should be okay. Here are the values I used:

Primary button type: Magnet

Screen to lens distance: 44 mm

inter-lens distance: 61 mm

Screen vertical alignment: Centre

Distortion coefficients – k1: 0.1

Distortion coefficients – k2: 0.02

Field of View angles: all 50°

Note: if setting up your own QR code for this or another viewer, the fiddliest bit is getting the distortion coefficients set up correctly. These coefficients determine the adjustments for distortion, and need to be set up to ensure that vertical and horizontal lines stay straight, and don’t curve in or out at the edge of the screen. There isn’t a written description of these coefficient, but if you increase/decrease the values significantly you’ll see what they do in the little diagram on the right. k1 I believe sets the distortion for the 2nd power, and k2 sets the distortion coefficient for the 3rd power. For you, this means that if you look at the vertical lines in the VR grid preview (while setting up the QR code parameters), and they are curving in or out, adjust the k1 input until they look pretty straight, particularly in the centre 2/3 of the screen. Then, if the lines are still distorted near the edge of the viewing field, adjust the k2 coefficient in the same direction. If the ends of the lines have distorted too far, just take k2 back the opposite direction instead.

Here’s the QR code that I came up with, and it looks significantly better than the one I used just to test out the headset:

qr_viewer_profile take 2

Overall, I’m happy with it! but… Now I have to figure out how to write a VR app… Yet another project. Sigh.

If you found this blog post useful at all, I encourage you to check out my first android app: The Lightbulb Audit . As I said, it’s my first app, so please leave positive reviews. If you have any criticisms, comments, bugs or suggestions, please leave them as a comment on my corresponding post on this blog: here.

Databullets #2 – A.R.M.S Pistol Mk. 1 – or: Something for Poland

Why something for Poland? My blog doesn’t get that many views, but I noticed a while ago that I was getting fairly regular views from Poland (the Stats page on wordpress tells you the country of origin of all views on your site), and that these views were always to my previous post about using multiple IR receivers… I have NO idea what is going on in Poland, but I figured that if they are interested in IR transmitters/receivers, they may be interested in this new post, which follows on from my previous post about Databullets.

I finally got around to completing the design for my Arduino based laser tagger, designed to work with my nerf gun toting, powerchair based robot. Here is where I posted the tagger design on Thingiverse:  http://www.thingiverse.com/thing:454862

Here’s what I intended it to look like:

concept sketchHere’s how I designed it:

Tagger Modeltagger with beamAnd here’s how it actually turned out:

20140907_20471620140907_20490020140907_21071820140907_204746

Sigh.

Just for the hell of it, here it is in various states of undress:

skeletonskeleton with clip

with circuit board

arduino inside case

with arduino case

with screen

almost complete

Here’s a link to the latest video, showing the laser tagger being used on the robot, as well as links to the older videos:

V4: https://www.youtube.com/watch?v=wnNgmFMYZ2g

V3: https://www.youtube.com/watch?v=wdR3sbx-Y1U

V2: https://www.youtube.com/watch?v=wEyu43JD9hw

V1: https://www.youtube.com/watch?v=C08r5BpwVEs

Performance

Since the system uses infrared, which is also produced by the sun, the performance of the system is pretty bad when the receiver is in direct sunlight, but as soon as the sun is down a little it improves significantly, especially around dusk (probably REALLY good at night).

The laser tagger has a range of about 20m once the sun went down, but I’m sure that could be improved by putting higher current through the IR LED, or aligning the optics a little better.

A laser tag system based on this hardware would probably work quite well in an underground carpark, or in the office on a Friday afternoon once the boss has gone home…

Tagger Optics

tagger with beam - closeIn order for the receiver to pick up the IR signal, the signal needs to be strong enough. You can measure the strength of the beam in W/m². Those units tell us that there are two ways to get long range from your laser tagger:

  1. More power (increased W)
  2. Narrower beam (reduced m²)

Getting more power is easy. The infrared LEDs that I used (TSAL 6100) are rated for 100 mA (200 mA peak). If you want to be safe, you select your current limiting resistor for 100 mA, but since the IR protocols actually use a pulsed carrier signal, you should be able to push it higher, maybe take it to 200 mA. If you really want to get extra range, you can always crank the current right up, and have spare LEDs ready in case you blow it. Since the laser tagger uses an easily modified design, you could print some LED holder plugs so that you can swap it out mid-laser battle.

The problem with increasing power, is that (as the units of measurement suggest) the signal strength is inversely proportional to distance squared. So if you want to double the range, you have to quadruple the power. Which brings us to Narrowing the Beam.

If you think about your infrared remote, it is a bit like a torch. It doesn’t need to shine very far (only from your couch to your TV), but it has a very widely spread beam (you don’t want to have to be a sharp shooter just to change the channel). This is what your LED is like. The TSAL 6100 has an angle of half intensity of 10°. This is essentially the angle, around the centreline of the LED, that describes the cone of light put out by the LED (well, most of the light is inside this cone). See the datasheet extract below:

intensity vs angular displacementFor a laser tagger, you want a fairly narrow, straight beam of light. Not only does this make the game more interesting (taking more skill to hit a target), but it gives you greater range. To achieve this, we can use a basic convex lens. I just used a standard 40mm lens from a small magnifying glass that I got from a $2 shop. By placing the LED at the focal point of the lens, the light emitted will come out the other side of the lens parallel to the centreline of the LED and lens. This means that the beam of light is now a straight, narrow cylinder (almost) instead of a wide cone. See the image below:

Lens OpticsThe best lens for the job is one where the cone of light from your LED reaches the diameter of your lens, when the LED is placed at the focus point of the lens. This way, your lens isn’t larger than necessary (increasing the size of your tagger), and it isn’t smaller than necessary (meaning that light from the LED would miss the lens, around the edges, wasting power).

The optimal diameter of the lens is calculated like this:

D_optimal = 2*tan(angle of half intensity)*focal length

To find the focal length of the lens, just go outside on a nice sunny day. Because the light from the sun has travelled so far, the rays are coming in almost parallel. So just hold the magnifying glass over something that won’t catch fire, and adjust the height until the light is focused into a tiny point (as if you were trying to set fire to the object). Now measure the height from the point of light to the magnifying glass; This is approximately equal to the focal length. I found that the focal length of my lens was about 123mm.

Now, at 123mm, a cone with a 10° half angle will have a base circle of 43mm. This means that I’m losing a little bit of light around the edges, because the lens is only 40mm in diameter. I have a 60mm lens with a focal length of 170mm, which is just about spot on, but I chose to go with the 40mm anyway, as it would make the laser tagger SLIGHTLY less bulky, awkward and ugly.

The next step is to actually fine-tune your optics. I suggest using a tagger design that lets you move your LED in three directions relative to the lens.

Set up your gun, but us a normal red (or any other visible colour) LED, instead of infrared. Stand in a dark hallway, and turn on the LED. Aim the tagger at a nearby wall, You should be able to see a faint circle. Now move the LED in and out, to get the circle sharply focused on the wall (a nice clear, crisp outline, instead of blurred). Also move the LED left/right, up/down, to get the circle bright and well rounded (not distorted). Point the tagger at a far wall to check the focus is still good. Now lock it down. I used a crap load of super glue to fix all three directions. This is important, because you don’t want the optics to shift during play, or when you replace the coloured LED for the IR LED.

Another point to take care of once you have done the above, is to align any laser pointers that you have mounted on your tagger. Since the laser on my design is mounted just below the lens, the laser (if aligned parallel to the LED) would always shine slightly below where the IR blast is shining. To ensure that a direct hit with the laser corresponds to a direct hit with the IR, I angled the laser up slightly. At close range, the laser is in the lower half of the IR circle; at long range, the laser is in the upper half of the circle. The diagram below will (hopefully) describe the arrangement better than I can.

Lens Adjustment

tagger with beam - sideHardware

I printed the tagger on my 3D printer; you can check out the design here: http://www.thingiverse.com/thing:454862

The intention was for the tagger to be easy to modify or enhance, and to use a user friendly mounting arrangement for all parts, so that others can design bigger and better taggers, with more features, such as:

  • Ammo counter
  • Sniper rifles (higher power IR LED, more precise optics arrangement, etc)
  • Shotgun mode (wide angle, short range)
  • Individually programmed favourites buttons
  • Smartphone incorporation (using the smartphone as the controller to select ammunition types, track ammo, etc)
  • IR receiver (to make a fully incorporated laser tagger system to track health, ammunition, kills, etc, for friendly laser skirmishes)

The possibilities are endless. I just wanted to make a cheap system that could be used by others for their own purposes.

Software

The tagger functions fairly simply. It uses an Arduino Uno as the brain of the tagger (minimum. Arduino Mega would allow for greater flexibility).

The Loop code cycles through looking for events such as

  1. The encoder changing position (increment cursor position, or change ammo type if an ammo slot is selected)
  2. Trigger pressed (fire an IR signal containing the series of ammo selected)
  3. Timer elapsed (refresh LCD screen display to show cursor position and update loaded ammo list)
  4. Favourites button pressed (load ammo combination from favourites list)

The main code features that it uses to achieve this are:

  • Quadrature encoder control (checks encoder position A and Position B at each cycle and compares to previous cycle. if different if determines which direction the encoder has turned, and calls an UP or DOWN function).
  • IR library – as discussed in my previous databullets post, I used the library by Ken Shirriff:

http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html

https://github.com/shirriff/Arduino-IRremote

  • LCD library (standard with arduino software) – I still find these LCDs a little to temperamental, but they do the job, as long as your cables aren’t too long (interference can easily cause problems with the screen display)

The best way to figure it out is probably to look at my code, so here it is:

ARDUINO SKETCH FOR TAGGER (paste into Arduino, or rename to .ino):

Copy of tagger_uno_updated

ARDUINO SKETCH FOR ROBOT (paste into Arduino, or rename to .ino):

Copy of _9_1_TAG_BOT

Any questions, feel free to ask.

Electronics

Here’s a copy of the schematic for the circuit board that sits between the Arduino Uno and the various switches / LCD screen / LEDs. It’s drawn up from memory, so let me know if any of it doesn’t seems right… I’m pretty sure that it’s right.

schematic

R1, R2, R3, R4, R5 – 10kOhm (pull down resistors for various switches

R6, R7 – 270 Ohm to limit base current controlling BC337 transistors.

R8 – mini potentiometer, for adjusting LCD contrast. Any rating should be fine. say 1kOhm?

R9 – 56 Ohm (or select as appropriate for your IR LED rating)

R10* – approx 72 Ohm (I had two LEDs wired in series). The reason for the asterisk is that this resistor was actually external to the circuit board, as I had a laser module wired in parallel to the muzzle flash LEDs.

Parts

Here’s a BOM for the tagger electronics, including cost:

  • Arduino Uno – $10 on ebay
  • Prototyping Breadboard (soldered type) – 20 cents on eBay
  • Rotary Encoder – 30 cents
  • Header Strips – 30 cents
  • Microswitch (trigger) – 50 cents
  • 16×4 LCD Screen (Hitachi HD44780 type) – $2.50 on eBay
  • 2x Transistors (BC337) – 20 cents (check out RS components)
  • Resistors – 5x10kOhm, 2×270 Ohm, 1×72 Ohm, 1×56 Ohm – negligible cost, you should already own some.
  • mini potentiometer – 1kOhm? – negligible cost, find whatever you have lying around.
  • LEDs – 1 x red, 1 x yellow – negligible cost, you should already own some.
  • IR LED – TSAL6100 (940nm, 100mA, 10°) – 50 cents (check out RS components)
  • Laser Diode – 50 cents

I scrounged the mini potentiometer and favourites button from an old VCR, I’m sure you can do the same with some of these parts.

The Future

My intention is to post additional parts for the A.R.M.S collection on thingiverse, such as:

  • Alternative battery packs
  • Alternative Arduino cases (i.e. for the Arduino Mega 2560)
  • Alternative handles
  • Accessory mounts compatible with Nerf Rail accessories
  • Improved LCD screen mounts
  • IR diode arrays
  • Add-ons
    • Shotgun (sliding IR led mount to put LED closer to lens, giving shorter range but wider beam)
    • Grenade launcher (under-mounted launcher that fires a ball array over-powered of IR LEDs connected to a wire, wire could be used to re-wind grenade)

And of course, I would use the same five-point screw mounting system for all of these parts, so that people can mix and match.

As it was foretold, the second posting…

It took me a while to post again, mostly because I was trying to iron out a few wrinkles in my robot before I started going on about how great it is. There are still a few bugs, but here it is anyway…

A couple of years ago I bought a Nerf Stampede, inspired by my mate Josh. When my girlfriend, now wife, told me that I was too old to buy nerf guns, I replied “But all the other kids have one”. As this wasn’t the compelling argument that I thought it was, I was forced to disregard her objections and rolling eyes, and get one anyway.

I won’t go into detail regarding the modifications that I did, there are plenty of sites that talk about modding nerf guns, but essentially, I removed the air restrictor, put in a stronger spring, added a relay and connection for an external firing signal, and a connection for an external 12V battery.

Naturally, my next thought was to stick it on a robot that could do my evil bidding.

Here are a couple of pictures of the first iteration (remote controlled over local wifi; nerf stampede cannon; laptop webcam for telecontrol)

ver 1 - side view ver 1 - angled view

So, I wanted the robot to have sufficient power to propel itself, including the modified Nerf Stampede and any associated electronics/control equipment at a quick walking speed (aiming for minimum 7.5km/h), and have enough battery life to have some fun (30 minutes).

I wanted the robot to be controlled over a wireless network.

Originally, the robot was to use geared DC motors, rubber wheels and a custom build frame. I later received a powerchair (Jazzy 1122) which was kindly donated to science.

The Jazzy was quite old and had not been used for years, so the batteries were almost completely dead (enough life left to commission the robot, but not enough for prolonged testing). I was fortunate enough to receive some second-hand 50Ah 12V deep cycle batteries (two of), which are performing admirably. I love scrounged parts, and I’m glad I didn’t have to buy NEW batteries, which are quite expensive.

While I initially tried to use a very rudimentary interface board (Velleman k8055), this caused me to waste more time than necessary, just trying to get the inputs and outputs required. Had I been driving the motors directly using a power mosfet circuit (PWM H-bridge), this board would have been fine, but I later decided that building such a high current board would be a hassle, and decided to hijack the existing powerchair control circuit.

I ended up doing this by using an Arduino Mega 2560 R3. These boards have multiple PWM outputs, and by running the PWM signals through a low pass RC filter, you can convert it to a DC voltage that varies proportionally with PWM duty cycle.

I wish I had discovered Arduino long ago. I love it seriously, the possibilities are endless.

Electronics of Jazzy 1122

Below is a link to the datasheet to the joystick used on THIS PARTICULAR jazzy 1122 works (there are a few variations on the pilot system, but this seems to be a fairly common joystck).

D50800-03[1] – joystick potentiometer info

Here are some photos showing the connection inside the controller. I drilled a hole in the casing for the controller, and ran some network cable through, with a 2.54mm plug on each end, so that I can easily disconnect the chair controller from the robot control box. The white plug is my plug in, the green plug is the original connection from the joystick to the chair controller.

SAMSUNG SAMSUNG

20131005_16320220131005_163152

This controller has two outputs per axis on the joystick. As far as I can tell, each of these outputs must be at 2.5V (centre position), give or take, in order for the controller to not throw up an error when you turn it on. The two outputs on each axis then vary proportional to deflection of the joystick (at FULL position, one goes up to about 3.89V, the other down to about 1.11V). I didn’t do extensive testing, but I think that if these don’t both change at the required rate (i.e. if one were to stay at 2.5v), the chair will not perform properly.

This controller was configured with two speed settings, and both were programmed to be VERY slow. I was lent one of the small computers required to program these settings, and have since re-configured the controller so that Speed 1 is “quick” and Speed 2 is “very [dangerous, do not use inside or near your car] quick”.

Hijacking the controls of the jazzy, by sending fake signals to the joystick pins, I was able to make use of the motor drivers that come with the chair. These fake signals took the form of 2.5V DC voltages, which varied up to 3.89V or down to 1.11V, as described above.

Circuit design

I put in RC filters to convert the 5V PWM from the Arduino into 0-~5V analogue voltages that the chair controller will accept:

schematic extract

R=1000 Ohm

C=100 uF

And I used the following duty cycle set points to convert controller inputs into signals for the chair:

Upper 3 = 202 = 3.89 V

Upper 2 = 177 = 3.43 V

Upper 1 = 151 = 2.96 V

Neutral = 127 = 2.5 V

Lower 1 = 101 = 2.04 V

Lower 2 = 77 = 1.57 V

Lower 3 = 51 = 1.11 V

Note: I’ve just added a Map function to the code, to allow linear conversion of the controller inputs to the wheelchair input signals (instead of using the 3 step system shown above).

NOTE: if you build a similar circuit for a powerchair, you may need to fiddle with the PWM set points to get precisely the right output voltages, depending on the chair controller and your low pass filter design.

So once the electronics were set up, I just needed to send my inputs to the Arduino. Initially I just connected the Arduino to an old laptop via USB, and sent the commands over the serial connection. The laptop was connected to my wifi, and I wrote some software to send commands from a PS2 controller connected to another laptop. Using the webcam on the robot’s laptop meant that I could skype in and see through the robot’s eyes, to drive it remotely. Phew! that’s a bit convoluted. So:

PS2 —(USB)—> laptop –(wifi)—> laptop —(usb)—> arduino —(analogue signals)—>Chair controller.

Here’s a video:   (Remote Control Jazzy 1122 + Modded Nerf Stampede)

UPGRADES:

I decided that that was all a bit too involved. I put an ethernet shield on the arduino, connected it to a wifi router mounted on the robot (for better range and portability).

I also added a 24V-12V converter, so that I could run the Stampede, Wifi router, and arduino all off the powerchair batteries. This saves me having to worry about multiple batteries. The photo below shows the Power Strip on the right, with a (BLUE) Low Power / Continuous Use terminals, to provide power to the arduino (and anything else that I decide to install on the robot) which has low current draw with little in the way of fluctuations. The (ORANGE) High/Intermittent Power strip is for things like the nerf gun, which will draw more power, but may vary greatly. I intend to swap the low power circuit over to 5V by adding a second converter, as I’m currently having some issues with the current power converter.

20131005_163030

The next photo shows an isolation switch (little white one), the 24V-12V converter, a software kill switch (big red one, obviously), an LED to confirm when the isolation switch is on, and a terminal for connecting the electronics box too the powerchair batteries.

20131005_162947

I printed mounting brackets for the breadboard, powerstrip, router, etc, on my 3D printer (I’ll post about this later, see some of my miscelanious designs here):

20131005_162951 20131005_163036

As you can see, my style of electronics is best described as “Frankensteining bits together as I go”.

All of this allowed me to first control the robot using a PS2 controller connected to my laptop, which was connected to the robot’s Wifi router…

Jazzy 1122 wireless robot

… Then I modified the arduino code to accept UDP signals from an app on my phone (using “IPGamepad” on android (see also), but I intend to write my own app, to be better suited to my specific needs). This is cool, because I can now just turn on the switch, and while I’m opening up the app on my phone, the wifi router turns on and the arduino connects, making the robot ready for action.

Smartphone controlled powerchair

That’s all for now. I will post more as I finish the current round of upgrades (I’ve just added an LCD screen which glows a reassuring blue and displays useful information). I’ve posted a copy of the Revision 3 arduino code below, which works with IPGamepad. If anyone wants it, I’ll see if I can put up the software that I used for sending the commands from a PS2 controller connected to a computer.

Key Lessons Learnt:

  1. Kill Switches!!! When I first got the robot running, I had a few little glitches, which meant that on a few rare occasions, it went insane and tried to kill me. This inspired me to install the kill switch. Unfortunately it’s not a batter isolation switch (didn’t want to spend the money), it’s just a software kill switch that just sets the outputs to neutral and stops the robot from accepting new inputs, but it does the job.
  2. Arduino is very powerful for this sort of hobby robotics, and cheap too. There might be other types of boards out there, but I’m not familiar with them. They are cheap enough that there’s no excuse to try to boot-strap other bits of technology together to make your device, just fork out the money for an arduino board and you will save yourself a lot of heartache.
  3. Hot Glue Guns (the type you use for art and craft) are extremely useful for electronics projects. I used one to insulate soldered joins between two wires (to stop them from touching other circuits in the same enclosure). I also used them to hold my breadboard in place, loose alligator clip connections in place, etc. Firm enough to hold parts of a prototype circuit in place, but not so permanent that you can’t peel the glue off at the end of the project.
  4. Electric wheelchair repair companies can be a potential source of second hand parts and batteries. They are often replacing clients’ chairs, and use the old ones for spares.

Reference Info:

Arduino Code (latest fully tested UDP version)

//!!!!! DEFINE NETWORK STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress ip(10, 1, 1, 177);
unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

//!!!!! END DEFINE NETWORK STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//!!!!! DEFINE ROBOT STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//define variables here
int ledPin = 13;
int val = -1;
int vX;
int vY;
int vF;

int Fore_PWM = 4;
int Aft_PWM = 5;
int Left_PWM = 7;
int Right_PWM = 6;
int Fire_OUT = 22;
int Fire_IN = 23;
int Fore_IN = A1;
int Left_IN = A2;
int kill_switch = 24; //interupt pin for kill switch, normally high

//int Manual_IN=28; //switch for manual control. closed circuit for manual

int AnalogLower = 0;
int AnalogUpper = 1023;
int PWMLower = 0;
int PWMUpper = 255;
int VoltsLower = 0;
int VoltsUpper = 500;

int JazzyUpper3   = 202;
int JazzyUpper2   = 177;
int JazzyUpper1   = 151;
int JazzyNeutral = 127;
int JazzyLower1   = 101;
int JazzyLower2   = 77;
int JazzyLower3   = 51;

//int JazzyUpper3   = 212;
//int JazzyUpper2   = 186;
//int JazzyUpper1   = 160;
//int JazzyNeutral = 135;
//int JazzyLower1   = 108;
//int JazzyLower2   = 82;
//int JazzyLower3   = 57;

unsigned long lastTick=millis();
String Temp = “”;

//!!!!! END DEFINE ROBOT STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//!!!!! DEFINE IPGAMEPAD STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

const int PACKET_SIZE = 4; //Size of the joystick data packet
byte joystick_data[PACKET_SIZE]; //Byte array for incoming data – [0] = leftUP, [1] = leftRIGHT, [2] = rightUP, [3] = rightRIGHT

int gamepadUpper3   = 219;
int gamepadUpper2   = 182;
int gamepadUpper1   = 145;
int gamepadLower1   = 111;
int gamepadLower2   = 74;
int gamepadLower3   = 37;

//!!!!! END DEFINE IPGAMEPAD STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

void setup() {
//!!!!! SETUP NETWORK STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  Serial.begin(9600);
 
  Serial.println(Ethernet.localIP());
  Serial.println(localPort);
  Serial.println(“Robot control system initialized.”);
 
  String inData = “”;
//!!!!! END SETUP NETWORK STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//!!!!! SETUP ROBOT STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
pinMode(ledPin,OUTPUT);

pinMode(Fire_OUT, OUTPUT);
digitalWrite(Fire_OUT,LOW);

pinMode(Fire_IN,INPUT);
pinMode(Fore_IN,INPUT);
pinMode(Left_IN,INPUT);
pinMode(kill_switch,INPUT);
//pinMode(Manual_IN,INPUT);

pinMode(Fore_PWM, OUTPUT); // sets the pin as output
analogWrite(Fore_PWM, JazzyNeutral); //sets reference voltage level= 125

pinMode(Aft_PWM, OUTPUT); // sets the pin as output
analogWrite(Aft_PWM, JazzyNeutral); //sets reference voltage level = 125

pinMode(Left_PWM, OUTPUT); // sets the pin as output
analogWrite(Left_PWM, JazzyNeutral); //sets reference voltage level= 125

pinMode(Right_PWM, OUTPUT); // sets the pin as output
analogWrite(Right_PWM, JazzyNeutral); //sets reference voltage level= 125

lastTick = millis();
//!!!!! END SETUP ROBOT STUFF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

}

void loop() {
 
 
//    if (digitalRead(Manual_IN)==HIGH)
//  {
//    analogWrite(Fore_PWM, map(analogRead(Fore_IN), AnalogLower, AnalogUpper, PWMLower, PWMUpper));
//    analogWrite(Aft_PWM, map((256-analogRead(Fore_IN)), AnalogLower, AnalogUpper, PWMLower, PWMUpper));
//    analogWrite(Left_PWM, map(analogRead(Left_IN), AnalogLower, AnalogUpper, PWMLower, PWMUpper));
//    analogWrite(Right_PWM, map((256-analogRead(Left_IN)), AnalogLower, AnalogUpper, PWMLower, PWMUpper));
//
//  }
 
if (millis()-lastTick>100){
   timeout();
}
 
  // if there’s data available, read a packet
 
int packetSize = Udp.parsePacket();
if(packetSize)
{
  Udp.read(joystick_data, PACKET_SIZE); //read data into joystick_data array
//     Serial.println(“Contents:”);
//     Serial.println(“jostick_data[]: “);
//     Serial.println(joystick_data[0]);
//     Serial.println(joystick_data[1]);
//     Serial.println(joystick_data[2]);
//     Serial.println(joystick_data[3]);

    lastTick = millis();

vY=(long)joystick_data[0];
vX=(long)joystick_data[1];
vF=(long)joystick_data[2];

// !!!!!  DATA USE HERE   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

          if (digitalRead(kill_switch)==HIGH)//check for kill switch not hit (normally closed circuit, i.e. high), if not, deactivate robot
          {

          //CODE FOR COMMAND HERE!!!!!

              if (vX>gamepadUpper3)
              {
                //code here
                analogWrite(Right_PWM, JazzyUpper3);
                analogWrite(Left_PWM, JazzyLower3);
                
              }
              else if (vX>gamepadUpper2)
              {
                //code here
                analogWrite(Right_PWM, JazzyUpper2);
                analogWrite(Left_PWM, JazzyLower2);
              }
              else if (vX>gamepadUpper1)
              {
                //code here
                analogWrite(Right_PWM, JazzyUpper1);
                analogWrite(Left_PWM, JazzyLower1);
              }
              else if (vX<gamepadLower3)
              {
                //code here
                analogWrite(Right_PWM, JazzyLower3);
                analogWrite(Left_PWM, JazzyUpper3);
              }
              else if (vX<gamepadLower2)
              {
                //code here
                analogWrite(Right_PWM, (JazzyLower2));
                analogWrite(Left_PWM, (JazzyUpper2));
              }
              else if (vX<gamepadLower1)
              {
                //code here
                analogWrite(Right_PWM, (JazzyLower1));
                analogWrite(Left_PWM, (JazzyUpper1));
              }
              else
              {
                //code here
                analogWrite(Right_PWM, (JazzyNeutral));
                analogWrite(Left_PWM, (JazzyNeutral));
              }
              
              
              
              
              
              
              if (vY>gamepadUpper3)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyUpper3));
                analogWrite(Aft_PWM, (JazzyLower3));
                
              }
              else if (vY>gamepadUpper2)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyUpper2));
                analogWrite(Aft_PWM, (JazzyLower2));
              }
              else if (vY>gamepadUpper1)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyUpper1));
                analogWrite(Aft_PWM, (JazzyLower1));
              }
              else if (vY<gamepadLower3)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyLower3));
                analogWrite(Aft_PWM, (JazzyUpper3));
              }
              else if (vY<gamepadLower2)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyLower2));
                analogWrite(Aft_PWM, (JazzyUpper2));
              }
              else if (vY<gamepadLower1)
              {
                //code here
                analogWrite(Fore_PWM, (JazzyLower1));
                analogWrite(Aft_PWM, (JazzyUpper1));
              }
              else
              {
                //code here
                analogWrite(Fore_PWM, (JazzyNeutral));
                analogWrite(Aft_PWM, (JazzyNeutral));
              }
              
              
              
              if (vF>gamepadUpper3)
              {
                //code here
                digitalWrite(Fire_OUT,HIGH);
              }
              else
              {
                //code here
                digitalWrite(Fire_OUT,LOW);
              }

          }
          else
          {
            kill();
          }
    
            

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  }
  delay(10);
}

void kill(){
Serial.println(“kill switch hit”);
digitalWrite(Fire_OUT,LOW);
analogWrite(Fore_PWM, JazzyNeutral); //sets reference voltage level= 125
analogWrite(Aft_PWM, JazzyNeutral); //sets reference voltage level = 125
analogWrite(Left_PWM, JazzyNeutral); //sets reference voltage level= 125
analogWrite(Right_PWM, JazzyNeutral); //sets reference voltage level= 125
}

void timeout(){
digitalWrite(Fire_OUT,LOW);
analogWrite(Fore_PWM, JazzyNeutral); //sets reference voltage level= 125
analogWrite(Aft_PWM, JazzyNeutral); //sets reference voltage level = 125
analogWrite(Left_PWM, JazzyNeutral); //sets reference voltage level= 125
analogWrite(Right_PWM, JazzyNeutral); //sets reference voltage level= 125

}