------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Control.pde
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ #include <PS2X_lib.h> //for v1.6
#include "EasyTransfer.h"
#include "IOpinsCB.h"
PS2X ps2x; // create PS2 Controller Class
EasyTransfer ET; //Create Transfer Class
struct SEND_DATA_STRUCTURE{
//put your variable definitions here for the data you want to send
//THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
int left;
int right;
int up;
int arm;
int brake;
};
//give a name to the group of data
SEND_DATA_STRUCTURE mydata;
//right now, the library does NOT support hot pluggable controllers, meaning
//you must always either restart your Arduino after you conect the controller,
//or call config_gamepad(pins) again after connecting the controller.
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup(){
delay(100); //Starts the program 100ms late to let the ps2 controller start up
Serial1.begin(9600); //start the Transfer, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
ET.begin(details(mydata), &Serial1);
Serial.begin(57600);
error = ps2x.config_gamepad(37,33,35,31, true, true); //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
if(error == 0){
Serial.println("Found Controller, configured successful");
Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
Serial.println("holding L1 or R1 will print out the analog stick values.");
Serial.println("Speak to Robert Crimmins from the Marine Academy of Science and Technology for updates and to report bugs.");
}
else if(error == 1)
Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
else if(error == 2)
Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
else if(error == 3)
Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
//Serial.print(ps2x.Analog(1), HEX);
type = ps2x.readType();
switch(type) {
case 0:
Serial.println("Unknown Controller type");
break;
case 1:
Serial.println("DualShock Controller Found");
break;
case 2:
Serial.println("GuitarHero Controller Found");
break;
}
}
void loop(){
/* You must Read Gamepad to get new values
Read GamePad and set vibration values
ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
if you don't enable the rumble, use ps2x.read_gamepad(); with no values
you should call this at least once a second
*/
if(error == 1) //skip loop if no controller found
return;
if(type != 2){ //if type is not 2 (GH controller) DualShock Controller
vibrate = ps2x.Analog(PSAB_BLUE); //this will set the large motor vibrate speed based on
//how hard you press the blue (X) button
if (vibrate > 50) mydata.brake = vibrate; //also sets the braking speed to whatever X is, if X is greater than 20% down.
if (ps2x.NewButtonState()) //will be TRUE if any button changes state (on to off, or off to on)
{
if(ps2x.ButtonPressed(PSB_L2)) //will be TRUE if button was JUST pressed
mydata.arm = 2;
if(ps2x.ButtonReleased(PSB_L2)) //will be TRUE if button was JUST released
mydata.arm = 1;
if(ps2x.ButtonPressed(PSB_R2)) //will be TRUE if button was JUST pressed
mydata.arm = 0;
if(ps2x.ButtonReleased(PSB_R2)) //will be TRUE if button was JUST released
mydata.arm = 1;
}
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
mydata.left = ps2x.Analog(PSS_LY) - 127;
Serial.print(",");
Serial.print(ps2x.Analog(PSS_LX), DEC);
mydata.right = ps2x.Analog(PSS_LX) - 127;
Serial.print(",");
Serial.print(ps2x.Analog(PSS_RY), DEC);
mydata.up = ps2x.Analog(PSS_RY) - 127;
Serial.print(",");
Serial.println(ps2x.Analog(PSS_RX), DEC);
}
}
ET.sendData();
delay(50);
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EasyTransfer.cpp
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ #include "EasyTransfer.h"//Captures address and size of struct
void EasyTransfer::begin(uint8_t * ptr, uint8_t length, HardwareSerial *theSerial){
address = ptr;
size = length;
_serial = theSerial;
//dynamic creation of rx parsing buffer in RAM
rx_buffer = (uint8_t*) malloc(size);
}
//Sends out struct in binary, with header, length info and checksum
void EasyTransfer::sendData(){
uint8_t CS = size;
_serial->write(0x06);
_serial->write(0x85);
_serial->write(size);
for(int i = 0; i<size; i++){
CS^=*(address+i);
_serial->write(*(address+i));
}
_serial->write(CS);
}
boolean EasyTransfer::receiveData(){
//start off by looking for the header bytes. If they were already found in a previous call, skip it.
if(rx_len == 0){
//this size check may be redundant due to the size check below, but for now I'll leave it the way it is.
if(_serial->available() >= 3){
//this will block until a 0x06 is found or buffer size becomes less then 3.
while(_serial->read() != 0x06) {
//This will trash any preamble junk in the serial buffer
//but we need to make sure there is enough in the buffer to process while we trash the rest
//if the buffer becomes too empty, we will escape and try again on the next call
if(_serial->available() < 3)
return false;
}
if (_serial->read() == 0x85){
rx_len = _serial->read();
//make sure the binary structs on both Arduinos are the same size.
if(rx_len != size){
rx_len = 0;
return false;
}
}
}
}
//we get here if we already found the header bytes, the struct size matched what we know, and now we are byte aligned.
if(rx_len != 0){
while(_serial->available() && rx_array_inx <= rx_len){
rx_buffer[rx_array_inx++] = _serial->read();
}
if(rx_len == (rx_array_inx-1)){
//seem to have got whole message
//last uint8_t is CS
calc_CS = rx_len;
for (int i = 0; i<rx_len; i++){
calc_CS^=rx_buffer[i];
}
if(calc_CS == rx_buffer[rx_array_inx-1]){//CS good
memcpy(address,rx_buffer,size);
rx_len = 0;
rx_array_inx = 0;
return true;
}
else{
//failed checksum, need to clear this out anyway
rx_len = 0;
rx_array_inx = 0;
return false;
}
}
}
return false;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EasyTransfer.h
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------#ifndef EasyTransfer_h
#define EasyTransfer_h
//make it a little prettier on the front end.
#define details(name) (byte*)&name,sizeof(name)
//Not neccessary, but just in case.
#if ARDUINO > 22
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "HardwareSerial.h"
//#include <NewSoftSerial.h>
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>
class EasyTransfer {
public:
void begin(uint8_t *, uint8_t, HardwareSerial *theSerial);
//void begin(uint8_t *, uint8_t, NewSoftSerial *theSerial);
void sendData();
boolean receiveData();
private:
HardwareSerial *_serial;
//NewSoftSerial *_serial;
uint8_t * address; //address of struct
uint8_t size; //size of struct
uint8_t * rx_buffer; //address for temporary storage and parsing buffer
uint8_t rx_array_inx; //index for RX parsing buffer
uint8_t rx_len; //RX packet length according to the packet
uint8_t calc_CS; //calculated Chacksum
};
#endif
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IOPinsCB.h
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------#define LmotorA 3 // Left motor H bridge, input A
#define LmotorB 11 // Left motor H bridge, input B
#define RmotorA 5 // Right motor H bridge, input A
#define RmotorB 6 // Right motor H bridge, input B
#define UmotorA 5 // Up motor H bridge, input A
#define UmotorB 6 // Up motor H bridge, input B
#define ArmmotorA 5 // Up motor H bridge, input A
#define ARmmotorB 6 // Up motor H bridge, input B