Matthew Chiang
Created November 20, 2015

HW 07: Bluetooth Controlled Vehicle

Adding wireless control to the RC car with bluetooth low energy

BeginnerShowcase (no instructions)92
HW 07: Bluetooth Controlled Vehicle

Things used in this project

Hardware components

Solderless breadboard
×1
Jumper wires (generic)
Jumper wires (generic)
×6
Adafruit nRF8001 Bluetooth LE Breakout
×1

Story

Read more

Code

callbackEchoModified.ino

Java
Modified callbackEcho code for wireless control only using the arrow buttons on the Adafruit app. Simple forward, turn left/right, and reverse capability.
/*********************************************************************
This is an example for our nRF8001 Bluetooth Low Energy Breakout

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/1697

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Kevin Townsend/KTOWN  for Adafruit Industries.
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in any redistribution
*********************************************************************/

// This version uses call-backs on the event and RX so there's no data handling in the main loop!

#include <SPI.h>
#include "Adafruit_BLE_UART.h"

#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2
#define ADAFRUITBLE_RST 9

Adafruit_BLE_UART uart = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);

boolean messageReceived = false;
uint8_t message[20];

// Added by Matt Chiang

// Motor 1
int IN1 = 7; // IN1 on the L298 is linked to digital pin 7
int IN2 = 6; // pwm

// Motor 2
int IN3 = 8;
int IN4 = 5; // pwm

// button input
char button = '0';

/**************************************************************************/
/*!
    Motor control functions
*/
/**************************************************************************/

void forward() {
  digitalWrite (IN1, HIGH);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, HIGH);
}

void turnLeft() {
  digitalWrite (IN1, LOW); // LOW for stopping
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, HIGH);
}

void turnRight() {
  digitalWrite (IN1, HIGH);
  digitalWrite (IN2, LOW); // this IN2 could not be working. CHECK IF SOLDERED CORRECTLY
  digitalWrite (IN3, LOW); // LOW
  digitalWrite (IN4, LOW);
}

void reverse() {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, HIGH);
  digitalWrite (IN3, HIGH);
  digitalWrite (IN4, LOW);
}

void reverseLeft() {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, HIGH);
  digitalWrite (IN4, LOW);
}

void reverseRight() {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, HIGH);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, LOW);
}

void brake() {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, LOW);
}

/**************************************************************************/
/*!
    This function is called whenever select ACI events happen
*/
/**************************************************************************/
void aciCallback(aci_evt_opcode_t event)
{
  switch(event)
  {
    case ACI_EVT_DEVICE_STARTED:
      Serial.println(F("Advertising started"));
      break;
    case ACI_EVT_CONNECTED:
      Serial.println(F("Connected!"));
      break;
    case ACI_EVT_DISCONNECTED:
      Serial.println(F("Disconnected or advertising timed out"));
      break;
    default:
      break;
  }
}

/**************************************************************************/
/*!
    This function is called whenever data arrives on the RX channel
*/
/**************************************************************************/
void rxCallback(uint8_t *buffer, uint8_t len)
{
  Serial.print(F("Received "));
  Serial.print(len);
  Serial.println(F(" bytes: "));
  for(int i=0; i<len; i++)
   Serial.print((char)buffer[i]); 

  Serial.print(F(" ["));

  for(int i=0; i<len; i++)
  {
    Serial.print(" 0x"); Serial.print((char)buffer[i], HEX); 
  }
  Serial.println(F(" ]"));


  // RC controls basic

   if ((char)buffer[1] == 'B') {
    if((char)buffer[3] == '0') {
      button = '0';    //turn off motors if button is released
    } else {
      button = (char)buffer[2];     //select proper direction, which corresponds to motor output below
    }
  }

  if (button == '0') {
    brake();
  } else if (button == '5') { // up button pressed
    forward();
  } else if (button == '6') { // down button pressed
    reverse();
  } else if (button == '7') { // left button pressed
    turnLeft();
  } else if (button == '8') { // right button pressed
    turnRight();
  }


/*
 * Below are extra controls using the number pads.
 */
//  else if (button == '1') { // button 1 is pressed so turn left
//    turnLeft();
//  } else if (button == '2') { // button 2 is pressed so turn right
//    turnRight();
//  } else if (button == '3') { // button 3 is pressed so reverse left
//    reverseLeft();
//  } else if (button == '4') { // button 4 is pressed so reverse right
//    reverseRight();
//  }

/*

  // RC Controls Alternate (mimics a game controller)
  // 4 is accelerate, 3 is decelerate

  if ((char)buffer[1] == 'B') {
    if((char)buffer[3] == '0') {
      button = '0';    //turn off motors if button is released
    } else {
      button = (char)buffer[2];     //select proper direction, which corresponds to motor output below
    }
  }

  if (button == '0') {
    brake();
  } else if (button == '5') { // up button pressed
    forward();
  } else if (button == '6') { // down button pressed
    reverse();
  } else if (button == '7') { // left button pressed
    turnLeft();
  } else if (button == '8') { // right button pressed
    turnRight();
  }

*/

/* 
 *  Commented out Michael Shiloh's code.
 */

//    switch(buffer[2]) {
//      case 53:
//        Serial.println ( "up");
//        forward();
//        break;
//      case 54:
//        Serial.println ( "down");
//        reverse();
//        break;
//      case 55:
//        Serial.println ( "left");
//        turnLeft();
//        break;
//      case 56:
//        Serial.println ( "right");
//        turnRight();
//        break;
//    }
  
  /* Echo the same data back! */
  uart.write(buffer, len);
}

/**************************************************************************/
/*!
    Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{ 
  Serial.begin(9600);
  while(!Serial); // Leonardo/Micro should wait for serial init
  Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Callback Echo demo"));

  uart.setRXcallback(rxCallback);
  uart.setACIcallback(aciCallback);
  uart.setDeviceName("PHATTY"); /* 7 characters max! */
  uart.begin();

  pinMode(IN1, OUTPUT); // Set the pin IN# to behave as an output
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
}

/**************************************************************************/
/*!
    Constantly checks for new events on the nRF8001
*/
/**************************************************************************/


void loop()
{
  uart.pollACI();
  
}

Credits

Matthew Chiang

Matthew Chiang

16 projects • 9 followers

Comments