The Task
Read moreFor this stage of the project, we were to add Bluetooth control to our remote control cars.
We were provided a Bluetooth Low Energy receiver and so I used this tutorial made by Adafruit to guide me through wiring the receiver to my two gear motors (shown in previous posts about the project), using an Arduino Uno and an H-bridge.
Here's how the Arduino and the Bluetooth receiver connected.
I was pretty lost at first in developing the code to load onto my Arduino, but with some help from classmates, I was able to integrate my old control system with the Bluetooth code (from the Adafruit tutorial linked earlier). My code is attached to this project.
Once I loaded the code, everything worked pretty seamlessly!
Here's how it went:
#include <SPI.h>
#include "Adafruit_BLE_UART.h"
// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 2 // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9
Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
bool leftButtonDown = false;
bool rightButtonDown = false;
bool forwardButtonDown = false;
bool backwardButtonDown = false;
const int motor1Pin = 7; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 6; // H-bridge leg 2 (pin 7, 2A)
const int motor3Pin = 5; // H-bridge leg 3 (pin 10, 3A)
const int motor4Pin = 4; // H-bridge leg 4 (pin 15, 4A)
/**************************************************************************/
/*!
Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void backward() {
digitalWrite(motor1Pin, HIGH); // set leg 1A of the H-bridge HIGH
digitalWrite(motor2Pin, LOW); // set leg 2A of the H-bridge low
digitalWrite(motor3Pin, HIGH); // set leg 1B of the H-bridge high
digitalWrite(motor4Pin, LOW); // set leg 2B of the H-bridge low
Serial.println("backward");
}
void forward() {
digitalWrite(motor1Pin, LOW); // set leg 1A of the H-bridge LOW
digitalWrite(motor2Pin, HIGH); // set leg 2A of the H-bridge high
digitalWrite(motor3Pin, LOW); // set leg 1B of the H-bridge low
digitalWrite(motor4Pin, HIGH); // set leg 2B of the H-bridge high
Serial.println("forward");
}
void left() {
digitalWrite(motor1Pin, LOW); // set leg 1A of the H-bridge low
digitalWrite(motor2Pin, LOW); // set leg 2A of the H-bridge low
digitalWrite(motor3Pin, HIGH); // set leg 1B of the H-bridge high
digitalWrite(motor4Pin, LOW); // set leg 2B of the H-bridge low
Serial.println("left");
}
void right() {
digitalWrite(motor1Pin, HIGH); // set leg 1A of the H-bridge high
digitalWrite(motor2Pin, LOW); // set leg 2A of the H-bridge low
digitalWrite(motor3Pin, LOW); // set leg 1A of the H-bridge low
digitalWrite(motor4Pin, LOW); // set leg 2A of the H-bridge low
Serial.println("right");
}
void station() {
digitalWrite(motor1Pin, LOW); // set leg 1A of the H-bridge low
digitalWrite(motor2Pin, LOW); // set leg 2A of the H-bridge low
digitalWrite(motor3Pin, LOW); // set leg 1A of the H-bridge low
digitalWrite(motor4Pin, LOW); // set leg 2A of the H-bridge low
Serial.println("station");
}
void setup(void)
{
Serial.begin(9600);
while(!Serial); // Leonardo/Micro should wait for serial init
Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Print echo demo"));
// BTLEserial.setDeviceName("NEWNAME"); /* 7 characters max! */
BTLEserial.begin();
// pinMode(2, INPUT_PULLUP);
// pinMode(9, INPUT_PULLUP);
// pinMode(10, INPUT_PULLUP);
// pinMode(11, INPUT_PULLUP);
// pinMode(12, INPUT_PULLUP);
// pinMode(13, INPUT_PULLUP);
// // set all the other pins you're using as outputs:
//
// pinMode(motor1Pin, OUTPUT);
// pinMode(motor2Pin, OUTPUT);
// pinMode(motor3Pin, OUTPUT);
// pinMode(motor4Pin, OUTPUT);
}
/**************************************************************************/
/*!
Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;
char leftButtonDownSignal[] = { '!', 'B', '7', '1', '4' };
char leftButtonUpSignal[] = { '!', 'B', '7', '0', '5' };
char rightButtonDownSignal[] = { '!', 'B', '8', '1', '3' };
char rightButtonUpSignal[] = { '!', 'B', '8', '0', '4' };
char forwardButtonDownSignal[] = { '!', 'B', '5', '1', '6' };
char forwardButtonUpSignal[] = { '!', 'B', '5', '0', '7' };
char backwardButtonDownSignal[] = { '!', 'B', '6', '1', '5' };
char backwardButtonUpSignal[] = { '!', 'B', '6', '0', '6' };
void readSignal(char signalBytes[]) {
for (int i = 0; i < 5; i++) {
signalBytes[i] = BTLEserial.read();
}
}
bool signalsEqual(char signal1[], char signal2[]) {
for (int i = 0; i < 5; i++) {
if (signal1[i] != signal2[i]) {
return false;
}
}
return true;
}
void loop()
{
// Tell the nRF8001 to do whatever it should be working on.
BTLEserial.pollACI();
// Ask what is our current status
aci_evt_opcode_t status = BTLEserial.getState();
// If the status changed....
if (status != laststatus) {
// print it out!
if (status == ACI_EVT_DEVICE_STARTED) {
Serial.println(F("* Advertising started"));
}
if (status == ACI_EVT_CONNECTED) {
Serial.println(F("* Connected!"));
}
if (status == ACI_EVT_DISCONNECTED) {
Serial.println(F("* Disconnected or advertising timed out"));
}
// OK set the last status change to this one
laststatus = status;
}
if (status == ACI_EVT_CONNECTED) {
// Lets see if there's any data for us!
if (BTLEserial.available()) {
Serial.print("* "); Serial.print(BTLEserial.available()); Serial.println(F(" bytes available from BTLE"));
}
// OK while we still have something to read, get a character and print it out
char signalBytes[5];
if (BTLEserial.available() >= 5) {
readSignal(signalBytes);
for (int i = 0; i < 5; i++) {
Serial.print(signalBytes [i]);
}
if (signalsEqual(signalBytes, leftButtonDownSignal)) {
leftButtonDown = true;
}
if (signalsEqual(signalBytes, rightButtonDownSignal)) {
rightButtonDown = true;
}
if (signalsEqual(signalBytes, forwardButtonDownSignal)) {
forwardButtonDown = true;
}
if (signalsEqual(signalBytes, backwardButtonDownSignal)) {
backwardButtonDown = true;
}
if (signalsEqual(signalBytes, leftButtonUpSignal)) {
leftButtonDown = false;
}
if (signalsEqual(signalBytes, rightButtonUpSignal)) {
rightButtonDown = false;
}
if (signalsEqual(signalBytes, forwardButtonUpSignal)) {
forwardButtonDown = false;
}
if (signalsEqual(signalBytes, backwardButtonUpSignal)) {
backwardButtonDown = false;
}
}
// Next up, see if we have any data to get from the Serial console
if (Serial.available()) {
// Read a line from Serial
Serial.setTimeout(100); // 100 millisecond timeout
String s = Serial.readString();
// We need to convert the line to bytes, no more than 20 at this time
uint8_t sendbuffer[20];
s.getBytes(sendbuffer, 20);
char sendbuffersize = min(20, s.length());
Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");
// write the data
BTLEserial.write(sendbuffer, sendbuffersize);
}
if (forwardButtonDown && !backwardButtonDown) { //forward button are pressed
forward();
}
else if (rightButtonDown && !leftButtonDown) { //right button is pressed
right();
}
else if (leftButtonDown && !rightButtonDown) { //left button is pressed
left();
}
else if (backwardButtonDown && !forwardButtonDown) { //backward switch is pressed
backward();
}
else if (!backwardButtonDown && !forwardButtonDown && !leftButtonDown && !rightButtonDown) { //none are pressed
station();
}
}
}
Comments