Arduino and Wii Nunchuck Laser Turret
I finished my Arduino laser turret. Never did figure out why my bench supply seems to reset the circuit when connected to the veroboard but not the breadboard, but it works fine with 4x AA Eneloops, which at full charge give 5.26v
Bill of materials came to this lot plus a 330ohm resistor and a 2N2222 transistor:
- WiiChuck, £1.40 for two
- Official Nintendo nunchuck (clones didn’t work), £9 for two
- Two SG90 micro servo’s, £2.39
- Servo bracket, £1.11
- Stripboard, £1.68 for two
- Laser diode, £1.45 for ten
- 4xAA battery holder, £1.55 for five
I’ve tried this on a Nano3, Mega2560r3 and SF Pro Micro, but ended up sticking with the Pro Micro as I have a bunch of them and this one has some duff analogue pins that I’m not using. I did try to minimise it to work on an ATtiny85 but as always I couldn’t get TinyWireM to work.
WiiChuck pinout:
- = GND
+ = VCC
d = SDA = a4 on nano, d2 on promicro
c = SCL = a5 on nano, d3 on promicro
Laser/2N2222A transistor pinout:
emitter = GND
base = d5 via 330 ohm resistor
collector = -ve laser
+ve laser to VCC
Here’s a couple of videos of it in action: breadboard and veroboard.
The WiiChuck.h library used was from Arduino Playground with the slight modification of commenting out the following lines to allow it to build on devices without a PORTC3:
57,58c57,58
< #define pwrpin PORTC3
< #define gndpin PORTC2
---
> //#define pwrpin PORTC3
> //#define gndpin PORTC2
The Makefile is quite simple – I used the Leonardo bootloader on the Pro Micro:
BOARD_TAG = leonardo
MONITOR_PORT = /dev/ttyACM0
#BOARD_TAG = nano328
#MONITOR_PORT = /dev/ttyUSB0
#BOARD_TAG = mega2560
#ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS = WiiChuck Wire Servo
include /usr/share/arduino/Arduino.mk
The main INO file is below – note that the JOYX and JOYY values took a bit of tweaking:
#include <Wire.h>
#include <Servo.h>
#include "WiiChuck.h"
#define LASERPIN 5 // Laser module signal pin
#define JOYXLEFT 34 // X Axis - Full left value
#define JOYXCENTER 128 // X Axis - Center value
#define JOYXRIGHT 213 // X Axis - Full right value
#define JOYYDOWN 128 // Y Axis - Full down value
#define JOYYCENTER 224 // Y Axis - Center value
#define JOYYUP 57 // Y Axis - Full up value
#define PANSERVOPIN 7 // Pan servo signal pin
#define PANSERVOLEFT 10 // Pan servo - Full left angle
#define PANSERVOCENTER 90 // Pan servo - Center angle
#define PANSERVORIGHT 180 // Pan servo - Full right angle
#define TILTSERVOPIN 6 // Tilt servo signal pin
#define TILTSERVODOWN 10 // Tilt servo - Full down angle
#define TILTSERVOCENTER 90 // Tilt servo - Center angle
#define TILTSERVOUP 180 // Tilt servo - Full up angle
// create instances
WiiChuck chuck = WiiChuck();
Servo panServo;
Servo tiltServo;
byte joyx, joyy;
void setup()
{
// init wiichuck
chuck.begin();
chuck.update();
chuck.calibrateJoy();
// init servos
panServo.attach(PANSERVOPIN);
panServo.write(PANSERVOCENTER);
tiltServo.attach(TILTSERVOPIN);
tiltServo.write(TILTSERVOCENTER);
// init laser
pinMode(LASERPIN, OUTPUT);
digitalWrite(LASERPIN, LOW);
}
void loop()
{
// take a reading
delay(20);
chuck.update();
joyx = chuck.readJoyX();
joyy = chuck.readJoyY();
// pan servo
if (joyx == JOYXCENTER)
{
panServo.write(PANSERVOCENTER);
}
else if (joyx < JOYXCENTER)
{
byte position = map(joyx, JOYXLEFT, JOYXCENTER, PANSERVOLEFT, PANSERVOCENTER);
panServo.write(position);
}
else
{
byte position = map(joyx, JOYXCENTER, JOYXRIGHT, PANSERVOCENTER, PANSERVORIGHT);
panServo.write(position);
}
// tilt servo
if (joyy == JOYYCENTER)
{
tiltServo.write(TILTSERVOCENTER);
}
else if (joyy < JOYYCENTER)
{
byte position = map(joyy, JOYYDOWN, JOYYCENTER, TILTSERVODOWN, TILTSERVOCENTER);
tiltServo.write(position);
}
else
{
byte position = map(joyy, JOYYCENTER, JOYYUP, TILTSERVOCENTER, TILTSERVOUP);
tiltServo.write(position);
}
// laser
if (chuck.buttonZ || chuck.buttonC)
{
digitalWrite(LASERPIN, HIGH);
}
else
{
digitalWrite(LASERPIN, LOW);
}
}