Pololu Robotics & Electronics
My account Comments or questions? About Pololu Contact Ordering information Distributors

Activating scripts via Nano+wireless PS2 handle


I’m trying to make a wireless hexapod powered by a maestro24 as the servo controller and an Arduino nano and wireless PS2 handle to send commands to activate the scripts. I’ve managed to program my arduino nano to accept the commands from my PS2. At least I think it works it did compile and load after fixing a few syntax errors.

Any way I’m fairly new to coding and only understand a lil of what I’m doing. I’m used to compiling pre-coded .ino files. So I’m still trying to learn. The code for the maestro and arduino to communicate back and fourth has few commands but I don’t really understand how to add it to my PS2 code and script to get it to activate my scripts.

For reference here is my ps2 arduino code

[code] #include <PS2X_lib.h>

PS2X ps2x; //create PS2 Controller Class

int error = 0;
byte type = 0;
byte vibrate = 0;

void setup() {

error = ps2x.config_gamepad(13,11,10,12, true, true); // setup pins and settings

if(error == 0){
Serial.println(“Found Controller, configured successful”);
Serial.println(“Try out all the buttons, X will vibratethe controller; faster as you press harder;”);
Serial.println(“holding L1 or R1 will print out the analog stick values.”);
Serial.println(“go to www.billporter.info for updates and to report bugs.”);

else if(error == 1)
Serial.println(“No controller found,check wiring, see readme.txt to enable debug.”);

else if(error == 2)
Serial.println(“Controller found but not accepting commands. see raedme.txt to enable debug.”);

else if(error == 3)
Serial.println(“Controller refusing to enter pressure mode, may not support it”);

// Serial.print(ps2x.Analog(1),Hex);

type = ps2x.readType();
switch(type) {
case 0:
Serial.println(“Unknown Controller type”);
case 1:
Serial.println(“DualShock Controller Found”);
case 2:
Serial.println(“GuitarHero Controller found”);


void loop() {

if(error == 1) //skip loop if no controller found

if(type == 2){ //Guitar Hero Controller

ps2x.read_gamepad(); //read controller

Serial.println(“Green Fret Pressed”);
Serial.println(“Red Fret Pressed”);
Serial.println(“Yellow Fret Pressed”);
Serial.println(“Blue Fret Pressed”);
Serial.println(“Orange Fret Pressed”);

Serial.println(“Star Power Command”);

if(ps2x.Button(UP_STRUM)) //will be TRUE as long as button is pressed
Serial.println(“Up Strum”);
Serial.println(“DOWN Strum”);

if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed
Serial.println(“Start is being held”);
Serial.println(“Select is being held”);

if(ps2x.Button(ORANGE_FRET)) // print stick value IF TRUE
Serial.print(“Wammy Bar Position:”);
Serial.println(ps2x.Analog(WHAMMY_BAR), DEC);

else { //DualShock Controller

ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at ‘vibrate’ speed

if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed
Serial.println(“Start is being held”);
Serial.println(“Select is being held”);

if(ps2x.Button(PSB_PAD_UP)) { //will be TRUE as long as button is pressed
Serial.print("Up held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
Serial.print("Right held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
Serial.print("LEFT held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
Serial.print("DOWN held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);

vibrate = ps2x.Analog(PSAB_BLUE); //this will set the large motor vibrate speed based on
//how hard you press the blue (X) button

if (ps2x.NewButtonState()) //will be TRUE if any button changes state (on to off, or off to on)

Serial.println(“L3 pressed”);
Serial.println(“R3 pressed”);
Serial.println(“L2 pressed”);
Serial.println(“R2 pressed”);
Serial.println(“Triangle pressed”);


if(ps2x.ButtonPressed(PSB_RED)) //will be TRUE if button was JUST pressed
Serial.println(“Circle just pressed”);

if(ps2x.ButtonReleased(PSB_PINK)) //will be TRUE if button was JUST released
Serial.println(“Square just released”);

if(ps2x.NewButtonState(PSB_BLUE)) //will be TRUE if button was JUST pressed OR released
Serial.println(“X just changed”);

if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) // print stick values if either is TRUE
Serial.print(“Stick Values:”);
Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX
Serial.print(ps2x.Analog(PSS_LX), DEC);
Serial.print(ps2x.Analog(PSS_RY), DEC);
Serial.println(ps2x.Analog(PSS_RX), DEC);





And here is the code I am supposed to add to the script and my arduino nano.

[code] /* This example shows how to control Maestro scripts with an
Arduino. It assumes you have an RC hobby servo connected on
channel 0 of your Maestro, and that you have already used the
Maestro Control Center software to verify that the servo is
powered correctly and moves when you command it to from the
Maestro Control Center software.

Before using this example, you should go to the Serial Settings
tab in the Maestro Control Center and apply these settings:

  • Serial mode: UART, fixed baud rate
  • Baud rate: 9600
  • CRC disabled

Be sure to click “Apply Settings” after making any changes.

It also assumes you have connected your Arduino to your Maestro
appropriately. If you have not done so, please see
https://github.com/pololu/maestro-arduino for more details on how
to make the connection between your Arduino and your Maestro.

Also, the Maestro needs to have the script in the comment
below installed on it. */


Maestro script for Script.ino Arduino library example.

Copy into the Script tab of the Maestro Control Center and

click Apply Settings.

Don’t do anything by default.


Subroutine 0

sub alternate_mid_to_high
6000 0 servo
1000 delay
7000 0 servo
1000 delay

Subroutine 1

Expects the delay time to be on the top of the stack

sub alternate_mid_to_low
6000 0 servo
dup delay
5000 0 servo
dup delay

#include <PololuMaestro.h>

/* On boards with a hardware serial port available for use, use
that port to communicate with the Maestro. For other boards,
create a SoftwareSerial object using pin 10 to receive (RX) and
pin 11 to transmit (TX). */
#define maestroSerial SERIAL_PORT_HARDWARE_OPEN
#include <SoftwareSerial.h>
SoftwareSerial maestroSerial(10, 11);

/* Next, create a Maestro object using the serial port.

Uncomment one of MicroMaestro or MiniMaestro below depending
on which one you have. */
MicroMaestro maestro(maestroSerial);
//MiniMaestro maestro(maestroSerial);

void setup()

void loop()
/* Subroutine numbers can be found by clicking “View Compiled
Code…” on the Maestro Control Center script tab.

Restart script at subroutine 0. Subroutine 0 constantly
alternates the servo position from the neutral position to the
high end of the range. */

// Stop the running script.

/* Restart subroutine 1 with the value 2000 on the stack.

Subroutine 1 constantly alternates the servo position from the
neutral position to the low end of the range. In this case, The
parameter put on to the stack represents how long the delay is
between servo movements.*/
maestro.restartScriptWithParameter(1, 2000);

All right so I want to control multiple scripts using multiple buttons. How would I re-write it and add it to the arduino code in the first code block to activate a certain script when a certain button is pressed?



Since you are new to programming and your project sounds complex, I recommend that you first focus on modifying the Arduino Script example for the Maestro to get the desired behavior between your Maestros and their associated button events. Then you can implement relevant parts of your modified code into your PS2 Arduino code.

You can look at the button tutorial on the Arduino’s website to get a better understanding on how to listen for a button press event and execute the desired behavior (or stop and start the script on a Maestro).

- Amanda


Ok so the byte packet numbers i need to know are the constants in this code library…

* Super amazing PS2 controller Arduino Library v1.8
*	details and example sketch: 
*	http://www.billporter.info/?p=240
* Original code by Shutter on Arduino Forums
* Revamped, made into lib by and supporting continued development:
* Bill Porter
* www.billporter.info
*	Contributers:
*	Eric Wetzel (thewetzel@gmail.com)
*	Kurt Eckhardt
* Lib version history
* 0.1 made into library, added analog stick support. 
* 0.2 fixed config_gamepad miss-spelling
* added new functions:
* NewButtonState();
* NewButtonState(unsigned int);
* ButtonPressed(unsigned int);
* ButtonReleased(unsigned int);
* removed 'PS' from begining of ever function
* 1.0 found and fixed bug that wasn't configuring controller
* added ability to define pins
* added time checking to reconfigure controller if not polled enough
* Analog sticks and pressures all through 'ps2x.Analog()' function
* added:
* enableRumble();
* enablePressures();
* 1.1 
* added some debug stuff for end user. Reports if no controller found
* added auto-increasing sentence delay to see if it helps compatibility.
* 1.2
* found bad math by Shutter for original clock. Was running at 50kHz, not the required 500kHz. 
* fixed some of the debug reporting. 
*	1.3 
*	Changed clock back to 50kHz. CuriousInventor says it's suppose to be 500kHz, but doesn't seem to work for everybody. 
*	1.4
*	Removed redundant functions.
*	Fixed mode check to include two other possible modes the controller could be in.
* Added debug code enabled by compiler directives. See below to enable debug mode.
*	Added button definitions for shapes as well as colors.
*	1.41
*	Some simple bug fixes
*	Added Keywords.txt file
*	1.5
*	Added proper Guitar Hero compatibility
*	Fixed issue with DEBUG mode, had to send serial at once instead of in bits
*	1.6
*	Changed config_gamepad() call to include rumble and pressures options
*	This was to fix controllers that will only go into config mode once
*	Old methods should still work for backwards compatibility 
* 1.7
*	Integrated Kurt's fixes for the interrupts messing with servo signals
*	Reorganized directory so examples show up in Arduino IDE menu
* 1.8
*	Added Arduino 1.0 compatibility. 
*This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

// $$$$$$$$$$$$ DEBUG ENABLE SECTION $$$$$$$$$$$$$$$$
// to debug ps2 controller, uncomment these two lines to print out debug to uart

//#define PS2X_DEBUG
//#define PS2X_COM_DEBUG

#ifndef PS2X_lib_h
#define PS2X_lib_h
#if ARDUINO > 22
#include "Arduino.h"
#include "WProgram.h"

#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>

#define CTRL_CLK 4

//These are our button constants
#define PSB_SELECT 0x0001
#define PSB_L3 0x0002
#define PSB_R3 0x0004
#define PSB_START 0x0008
#define PSB_PAD_UP 0x0010
#define PSB_PAD_RIGHT 0x0020
#define PSB_PAD_DOWN 0x0040
#define PSB_PAD_LEFT 0x0080
#define PSB_L2 0x0100
#define PSB_R2 0x0200
#define PSB_L1 0x0400
#define PSB_R1 0x0800
#define PSB_GREEN 0x1000
#define PSB_RED 0x2000
#define PSB_BLUE 0x4000
#define PSB_PINK 0x8000
#define PSB_TRIANGLE 0x1000
#define PSB_CIRCLE 0x2000
#define PSB_CROSS 0x4000
#define PSB_SQUARE 0x8000

//Guitar button constants
#define GREEN_FRET	0x0200
#define RED_FRET	0x2000
#define YELLOW_FRET	0x1000
#define BLUE_FRET	0x4000
#define ORANGE_FRET	0x8000
#define STAR_POWER	0x0100
#define UP_STRUM	0x0010
#define DOWN_STRUM	0x0040
#define WHAMMY_BAR	8

//These are stick values
#define PSS_RX 5
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8

//These are analog buttons
#define PSAB_PAD_RIGHT 9
#define PSAB_PAD_UP 11
#define PSAB_PAD_DOWN 12
#define PSAB_PAD_LEFT 10
#define PSAB_L2 19
#define PSAB_R2 20
#define PSAB_L1 17
#define PSAB_R1 18
#define PSAB_GREEN 13
#define PSAB_RED 14
#define PSAB_BLUE 15
#define PSAB_PINK 16
#define PSAB_TRIANGLE 13
#define PSAB_CIRCLE 14
#define PSAB_CROSS 15
#define PSAB_SQUARE 16

#define SET(x,y) (x|=(1<<y))
#define CLR(x,y) (x&=(~(1<<y)))
#define CHK(x,y) (x & (1<<y))
#define TOG(x,y) (x^=(1<<y))

class PS2X {
boolean Button(uint16_t);
unsigned int ButtonDataByte();
boolean NewButtonState();
boolean NewButtonState(unsigned int);
boolean ButtonPressed(unsigned int);
boolean ButtonReleased(unsigned int);
void read_gamepad();
void read_gamepad(boolean, byte);
byte readType();
byte config_gamepad(uint8_t, uint8_t, uint8_t, uint8_t);
byte config_gamepad(uint8_t, uint8_t, uint8_t, uint8_t, bool, bool);
void enableRumble();
bool enablePressures();
byte Analog(byte);
unsigned char _gamepad_shiftinout (char);
unsigned char PS2data[21];
void sendCommandString(byte*, byte);
void reconfig_gamepad();
unsigned char i;
unsigned int last_buttons;
unsigned int buttons;
uint8_t maskToBitNum(uint8_t);
uint8_t _clk_mask; 
volatile uint8_t *_clk_oreg;
uint8_t _cmd_mask; 
volatile uint8_t *_cmd_oreg;
uint8_t _att_mask; 
volatile uint8_t *_att_oreg;
uint8_t _dat_mask; 
volatile uint8_t *_dat_ireg;
unsigned long last_read;
byte read_delay;
byte controller_type;
boolean en_Rumble;
boolean en_Pressures;



Now i could use some help turning those byte packets to pololu protocol. Is there some kind of list. Ive been reading the tutorials and cant figure out how to convert them.


Better yet, if the Maestro needs to read this example 0xAA and the arduino puts out this example 0x0000. Do i need to have my arduino print this Format 0xAA or will it still understand the 0x0000


You can find a list of Maestro serial commands along with their description in the “Serial Servo Commands” section of the Maestro User’s Guide. Again, since you are using an Arduino controller and seem new to this, it would be easier for you to use the Arduino library for the Maestro, which can be downloaded here. The source code and comments serve as our documentation for the library. (Please see the example that I linked in my previous post to understand how to use the Arduino library to control your Maestro.)

Every command in the Pololu protocol must start with 0xAA. The value 0x0000 is not the same as 0xAA, so you will need to send the proper command byte 0xAA from your Arduino.

I suggest that you try to follow the steps I recommended in my previous post.

- Amanda