Bluetooth Servo Commands

Hello,

I am having trouble controlling my servo motor over bluetooth from an IOS device. I have established communication between the NRF8001 BLE module and Iphone. I am able to send commands from the Blue Remote Free app which show up in my serial monitor as;

Left* 6 bytes available from BTLE Center* 5 bytes available from BTLE Right* 4 bytes available from BTLE Down* 4 bytes available from BTLE

Does anyone know how I can incorporate these commands into my code, so when one of the four commands above are sent my servo motor will turn left or right.

Thanks.

Nick

Does anyone know how I can incorporate these commands into my code

Without seeing your code? No.

#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);
//
/*!
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 Print echo demo”));

// BTLEserial.setDeviceName(“NEWNAME”); /* 7 characters max! */

BTLEserial.begin();
}

//
/*!
Constantly checks for new events on the nRF8001
*/
/
/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

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
while (BTLEserial.available()) {
char c = BTLEserial.read();
Serial.print(c);
}

// 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);
}
}
}

    // OK while we still have something to read, get a character and print it out
    while (BTLEserial.available()) {
      char c = BTLEserial.read();
      Serial.print(c);
    }

Saving the data is going to be essential for comparing to what you expect, so you can take the correct action.

Left* 6 bytes available from BTLE
Center* 5 bytes available from BTLE
Right* 4 bytes available from BTLE
Down* 4 bytes available from BTLE

How do you get 6 bytes for Left, 5 for Center, 4 for Right, and 4 for Down?

Through the Blue Remote Free app, when either the left, center, right and down is pressed it will show the corresponding commands in the serial monitor. I am able to type commands into the serial monitor through bluetooth as well and would be willing to control my servo through typed commands like "L" for left "R" for right. Im just lost on the code to use.

nben16: Left* 6 bytes available from BTLE Center* 5 bytes available from BTLE Right* 4 bytes available from BTLE Down* 4 bytes available from BTLE

Does this mean that you are sending "Left*" and "Centre*" etc?

If so all you really need is to check the first character - if it is 'L' do the left stuff etc.

The mechanism for receiving data in that code is not very robust. You might look at the 2nd example in Serial Input Basics. You will also see that it saves the received data for further use.

...R

Simple serial capture code that uses a comma end of data marker (which you can change to \n, or |r, or even E and should work). Once the String is captured, you can look for substrings like "Left" and do the required actions if it is present.

//zoomkat 3-5-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//send on, or off, from the serial monitor to operate LED

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial LED on/off test with , delimiter"); // so I can keep track
}

void loop() {

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      Serial.println(readString); //prints string to serial port out
      //do stuff with the captured readString
      if(readString.indexOf("on") >=0)
      {
        digitalWrite(ledPin, HIGH);
        Serial.println("LED ON");
      }
      if(readString.indexOf("off") >=0)
      {
        digitalWrite(ledPin, LOW);
        Serial.println("LED OFF");
      }       
      readString=""; //clears variable for new input
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Hi Zoomcat,

I have taken the code provided above and integrated it into my bluetooth code (echodemo). I am able to send letters and codes through the UART app for Iphone. In your code the “,” should activate the LED when present in the serial monitor if I am not mistaken. I have sent “,” through my iphone and it shows in the serial monitor but the LED does not change state. Are you able to look at my code and see if there are any clear errors?

#include <SPI.h>
#include “Adafruit_BLE_UART.h”

int ledPin = 4;
String readString;

// 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);
//
/*!
Configure the Arduino and start advertising with the radio
*/
/
/
void setup(void)
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Serial.println(“serial LED on/off test with , delimiter”);

// BTLEserial.setDeviceName(“NEWNAME”); /* 7 characters max! */

BTLEserial.begin();
}

//
/*!
Constantly checks for new events on the nRF8001
*/
/
/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

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"));
}
while (BTLEserial.available()) {
char c = BTLEserial.read();
Serial.print(c);
}
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ‘,’) {
Serial.println(readString); //prints string to serial port out
//do stuff with the captured readString
if(readString.indexOf(“on”) >=0)
{
digitalWrite(ledPin, HIGH);
Serial.println(“LED ON”);
}
if(readString.indexOf(“off”) >=0)
{
digitalWrite(ledPin, LOW);
Serial.println(“LED OFF”);
}
readString=""; //clears variable for new input
}
else {
readString += c; //makes the string readString
}
}
}

I have sent "," through my iphone and it shows in the serial monitor but the LED does not change state.

The data from the phone ONLY gets sent to the serial port. The data that controls the LED comes from the serial port.

Have you tried sending something like "on," and "off," from your Iphone?

Yes I have, no luck. I have my LED between pin 4 and ground.

Do you get "LED OFF" or "LED ON" or anything returned to the serial monitor?

No nothing returned either

Zoomcat,

I tried a new code and it seems to be working better. The Serial Port has this incoming messages every second;

  • Sending ->""
    Writing out to BTLE:
    LED is on
    LED is off

My led is still not on, even when i send in the commands “n” for on and "f’ for off. Getting closer. Here is my code:

// This version uses the internal data queing so you can treat it like Serial (kinda)!

#include <SPI.h>
#include “Adafruit_BLE_UART.h”

char blueToothVal;
char lastValue;

// 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);
//
/*!
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 Print echo demo”));
pinMode(8,OUTPUT);

// BTLEserial.setDeviceName(“NEWNAME”); /* 7 characters max! */

BTLEserial.begin();

}

//
/*!
Constantly checks for new events on the nRF8001
*/
/
/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

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")); //Naming Conventions
}
if (status == ACI_EVT_CONNECTED) {
Serial.println(F("* Connected!")); //Naming Conventions
}
if (status == ACI_EVT_DISCONNECTED) {
Serial.println(F("* Disconnected or advertising timed out")); //naming conventions
}
// 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
while (BTLEserial.available()) {
char c = BTLEserial.read();
Serial.print(c);
}

// 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);

//LED ON OFF**
if(Serial.available())
//if there is data being recieved
blueToothVal=Serial.read(); //read it

if (blueToothVal==‘n’)
//if value from bluetooth serial is n
digitalWrite(8,HIGH); //switch on LED
if (lastValue!=‘n’)
Serial.println(F(“LED is on”)); //print LED is on
lastValue=blueToothVal;
}

else if (blueToothVal==‘f’)
//if value from bluetooth serial is n
digitalWrite(8,LOW); //turn off LED
if (lastValue!=‘f’)
Serial.println(F(“LED is off”)); //print LED is on
lastValue=blueToothVal;

delay(1000);

}
}

You might try the below. Note I’ve commented out the old reading of the serial port as that may empty the serial port before the capture code starts.

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

int ledPin = 4;
String readString;

// 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);
/**************************************************************************/
/*!
    Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  Serial.println("serial LED on/off test with , delimiter");

  // BTLEserial.setDeviceName("NEWNAME"); /* 7 characters max! */

  BTLEserial.begin();
}

/**************************************************************************/
/*!
    Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

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"));
    }
   

 
//while (BTLEserial.available()) {
      //char c = BTLEserial.read();
      //Serial.print(c);
    //}



      if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      Serial.println(readString); //prints string to serial port out
      //do stuff with the captured readString
      if(readString.indexOf("on") >=0)
      {
        digitalWrite(ledPin, HIGH);
        Serial.println("LED ON");
      }
      if(readString.indexOf("off") >=0)
      {
        digitalWrite(ledPin, LOW);
        Serial.println("LED OFF");
      }       
      readString=""; //clears variable for new input
    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}

@nben16, please use the code button </> so your code looks like this and is easy to copy to a text editor. This is clearly explained in the How to use the Forum and you have seen other people doing it in this Thread

…R

Zoomcat,

Tried the program. In the serial monitor after *connected i sent "on" from my ios device, 2 Bytes Available from BTLE appears and keeps listing below. When I send "off" it just switches up to 5 Bytes Available from BTLE. No LED light yet. I tested the voltage to ground of pin 4, no Volts so it is not the LED.

no Volts so it is not the LED.

That doesn’t make much sense. You should try the original code I posted using the serial monitor to see if you can turn the LED on and off. Also you really need to go #7 below and learn how to post your code using code tags:

http://forum.arduino.cc/index.php/topic,148850.0.html

Zoomcat,

I just uploaded the original code posted. Opened the serial monitor on the Arduino Program and see "serial LED on/off test with , delimiter". I typed in "on" and LED did not turn on. When I typed in "on" and sent it, i did not see "on" present in the serial monitor. Is there some settings to change in my serial monitor.

And yes, from now on I will post my code in the proper format.

I found a code that works in the serial monitor (no bluetooth) to turn on and off the LED. See code below. Now I just have to figure out how to incorporate that code into my BTLE device. I wonder why the other codes did not work.

const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Serial.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    if (incomingByte == 'H') {
      digitalWrite(ledPin, HIGH);
    }
    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByte == 'L') {
      digitalWrite(ledPin, LOW);
    }
  }
}