Fail Safe for PS4 controller used to control dc motors

357 views Asked by At

I'm working on a project to control an old rc cars dc motors through an arduino uno & L298N. I have the motors working but want to include a failsafe that stops the motors if the bluetooth gets out of range so that it doesn't just keep driving on until it crashes. Code starts below this with my attempt at failsafe at the very bottom.

    //This begins the actual motor stuff 

int forwards = (PS4.getAnalogButton(R2)); // Read R2 Button for forward 
int backwards = (PS4.getAnalogButton(L2)); // Read L2 Button for backwards 
forwards  = map(forwards,  0, 255, 0, 255); //Need to figure out how to add offset to remove buzzing 
//noise from motor. 
backwards = map(backwards, 0, 255, 0, 255);

//This is for Rear motor Forwards
if ((PS4.getAnalogButton( R2 )) > 0 ) {
analogWrite(enA, forwards );
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);}
//This is for Rear motor Backwards 
if  ((PS4.getAnalogButton( L2 )) > 0 ) {
 analogWrite(enA, backwards );
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);} 
//This is so that if neither L2/R2 is pressed the motor does nothing.
if (PS4.getAnalogButton( R2 ) == 0  &&
PS4.getAnalogButton( L2 ) == 0  ){
  analogWrite(enA, 255);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW); }


//This is for front l/r Motor

int steer = (PS4.getAnalogHat(LeftHatX) ); 
steer = map(steer, 0, 255, 255, 255);


//This is for front motor turning left 
//code for analog for l/r 
 if ((PS4.getAnalogHat(LeftHatX)) >135 ){
 analogWrite(enB, steer); 
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);} 
else if ((PS4.getAnalogHat(LeftHatX)) <115 ){
 analogWrite(enB, steer);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH); } 
 else{
  analogWrite(enB, 255);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW); }
//This is code to turn off motor if controller is out of range and disconnect still a wip 
//if (PS4.disconnect())return = true;{      //this comes back as an error "could not convert 
'PS4.PS4BT::<anonymous>.BTHID::disconnect()' from 'void' to 'bool' "
 //analogWrite(enA, 255);
 //digitalWrite(in1, LOW);
 //digitalWrite(in2, LOW);}

 }}
3

There are 3 answers

3
a43nigam On

Your code uses the .disconnect() function, which actually disconnects your device if it is connected, hence why it is a void instead of a bool. Instead, I would use the .connected() method, which returns a bool telling you whether or not your device is connected. In order to implement this, you would do:

if (PS4.connected() == false {
// do whatever you need to do here to turn off your motors
}

I hope that this helped, and in case you need more help with Bluetooth functionality on Arduino, the library from which I got the function .connected() function can be found here: https://www.arduino.cc/en/Reference/CurieBLE

0
ukBaz On

It would have been easier to understand your question if you were unable to detect the controller had disconnected and given a minimal piece of code that would run.

Having said that, as Anubhav Nigam pointed out, .connected() is how you test if the controller is still connected.

https://felis.github.io/USB_Host_Shield_2.0/class_p_s4_b_t.html#a08a857b8533e59f6eb872e4c8f727405

I don't have the hardware to test this, but looking at the example at: https://www.instructables.com/id/Creating-a-DualShock-4-Controlled-Arduino/

I believe this is what a minimal runnable example would look like:

#include <PS4BT.h>
#include <usbhub.h>

USB Usb;

BTD Btd(&Usb);

PS4BT PS4(&Btd, PAIR);

void setup() {
  Serial.begin(19200);
  if (Usb.Init() == -1) {
    Serial.print("OSC did not start");
    while (1); // Halt
  }
  Serial.print("PS4 Bluetooth Library Started");
}
void loop() {
  Usb.Task();

  if (PS4.connected()) {
    if(PS4.getButtonClick(CROSS)){
      Serial.print("cross");
    } 

    if(PS4.getButtonClick(PS)){
      PS4.disconnect();
      Serial.end();
    }
      
  } else {   
    Serial.print("switch off motors");
  }
}
0
David Duronslet On

ended up adding a few things so if the controller was connected and no longer was, thanks to a buddy that helped me out

/*
PS4 Bluetooth Controlled RC Car- developed by David Duronslet, 
Code adapted from example sketch for the PS4 Bluetooth library by Kristian Lauszus
 */
#include <PS4BT.h>
#include <usbhub.h>
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>


////////////GLOBALS DEFINED HERE///////////

bool Paired=false; 
//For motor 1 
#define enA 9
#define in1 4
#define in2 5

//For motor 2 
#define in3 6
#define in4 7
#define enB 10 

//For PS4 Controller inputs on debug menu 
#define ENABLE_UHS_DEBUGGING 1

USB Usb; //use Usb class
BTD Btd(&Usb);
bool printAngle, printTouch;
uint8_t oldL2Value, oldR2Value;

int val = map(PS4.getAnalogButton(R2), 255, 100, 100, 255)   ; //map function for R2 button 

void setup() {
  Serial.begin(115200);//communication baud rate for the Serial port.
  
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); // Permanently Halt
  }
  Serial.print(F("\r\nPS4 Bluetooth Library Started "));

  //Motor Controller Pin Setup
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
}

void loop() {
  Usb.Task();
 if (PS4.connected()) {
  Paired=true; //for the range checker 
//This begins the actual motor stuff 

int forwards = (PS4.getAnalogButton(R2)); // Read R2 Button for forward 
int backwards = (PS4.getAnalogButton(L2)); // Read L2 Button for backwards 
forwards  = map(forwards,  0, 255, 0, 255); //Need to figure out how to add offset to remove buzzing noise from motor. 
backwards = map(backwards, 0, 255, 0, 255);

//This is for Rear motor Forwards
  if ((PS4.getAnalogButton( R2 )) > 0 ) {
    analogWrite(enA, forwards );
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);}
//This is for Rear motor Backwards 
if  ((PS4.getAnalogButton( L2 )) > 0 ) {
     analogWrite(enA, backwards );
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);} 
//This is so that if neither L2/R2 is pressed the motor does nothing.
if (PS4.getAnalogButton( R2 ) == 0  &&
    PS4.getAnalogButton( L2 ) == 0  ){
      analogWrite(enA, 255);
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW); }

    
//This is for front l/r Motor

int steer = (PS4.getAnalogHat(LeftHatX) ); 
steer = map(steer, 0, 255, 255, 255);


//This is for front motor turning left 
//code for analog for l/r 
 if ((PS4.getAnalogHat(LeftHatX)) >135 ){
 analogWrite(enB, steer); 
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);} 
else if ((PS4.getAnalogHat(LeftHatX)) <115 ){
 analogWrite(enB, steer);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW); } 
 else{
      analogWrite(enB, steer);//Change 255 value?
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW); }

 }

//Out of range condition goes here! 
else if(Paired==true){//this means the was Connected in the past but is no longer connected.
  //stop all motors
    analogWrite(enA, 255);
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
}
 }