Pages: [1]   Go Down
Author Topic: Serial Read, values sent to Serial via Bluetooth  (Read 5250 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm working on building an Android app that will control a camera via Arduino. My app sends a long string of text to my Arduino via Bluetooth:

ExposureTime=5000, FocusTap=500, Interval=4000

I know how to get the Arduino IDE to display the above text in the Serial Window when it is sent over Bluetooth, but I'm, not sure how to take the next step and get the Arduino to read the values and then use them as variables in my loop. Is there an easy way to set up the Serial.Read() to handle it?

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50335
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I know how to get the Arduino IDE to display the above text in the Serial Window when it is sent over Bluetooth
Great. That's 2/3 of the battle. Let's see that code.

Quote
but I'm, not sure how to take the next step and get the Arduino to read the values
You said that you were already reading the data. Did you mean that you want the Arduino to understand/save/parse the data, too?

Quote
and then use them as variables in my loop.
Well, that's going to be hard, since you are sending constants. You can have the Arduino parse the data, and convert the strings to int values, and store those values in variables, for later/other use.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply. I used this code ("bluetooth_LED_example") as a test to get the Arduino to turn on/off the LED when a 0 or 1 was sent via my Android phone.

Quote
/*
simple LED test
*/

char val;         // variable to receive data from the serial port
int ledpin = 2;  // LED connected to pin 2 (on-board LED)

void setup()
{
  pinMode(ledpin = 13, OUTPUT);  // pin 13 (on-board LED) as OUTPUT
 
  Serial.begin(115200);       // start serial communication at 115200bps
 
}
 
void loop() {
  if( Serial.available() )       // if data is available to read
  {;}
    val = Serial.read();         // read it and store it in 'val'
 
  if( val == '0' )               // if '0' was received led 13 is switched off

  {
   digitalWrite(ledpin, LOW);    // turn Off pin 13 off
delay(1000);                  // waits for a second   
Serial.println("13 off");
  }

if( val == '1' )               // if '1' was received led 13 on
 {
    digitalWrite(ledpin = 13, HIGH);  // turn ON pin 13 on
    delay(1000);                  // waits for a second
    Serial.println("13 on");
  }
}


Then I modified the code so that my phone would send over the camera parameters and those would show up in the serial window. So I guess my question is - how do I get the Arduino to read and store those values (the #s - ie the ExposureLength=20000) in the loop? Do I need to declare "ExposureLength" as a char and then somehow get the serial to read it's value (20000) and store it somewhere so the loop can read it?

I am a complete newb with Arduino, and I'm certain this is a fairly common task that people employ...I've read through "Getting Started With Arduino" and "Beginning Arduino" and can't find anything specific. Apologies if I am being unclear. Thanks!
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50335
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if( Serial.available() )       // if data is available to read
  {;}
If there is data available to read, do nothing.

Then, regardless of whether or not there is serial data available:
Code:
    val = Serial.read();         // read it and store it in 'val'
read it.

Quote
Then I modified the code so that my phone would send over the camera parameters and those would show up in the serial window.
Your phone should be sending something like
<ExposureLength=20000, NextParameter=value, AnotherParameter=anotherValue>

Then, you can use code like this to get the serial data into an array:
 
Code:
#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where it says "Process the packet", you can then use strtok() to get the bits from the array. Use "=" as the delimiter to get the ExposureLength name. Then, use "," as the delimiter to get the value as a string ("20000") and atoi() to convert the string to a number, 20000. Then, store the value in a variable - which one depends on the name token (use strcmp() to detect a match).

Quote
I'm certain this is a fairly common task that people employ
It is.

Quote
I've read through "Getting Started With Arduino" and "Beginning Arduino" and can't find anything specific.
It is not a beginner project, though. You can use the code I posted above as a starting point, and google strtok (NOT strtok_r), strcmp, and atoi, to learn how to use them.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Paul! More than enough for me to get lost in for a few days and try to learn some new tricks. I really appreciate your help. If/when i get this all working I will be sure to post the finished code here for the beenfit of anyone else looking to do the same thing.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Paul I have just started to dive into your strtok suggestions and to learn about arrays. Before I got there though I have adopted new code for the Android / Bluetooth / Arduino connection with the SoftwareSerial library that simply reads what my phone is sending via the BlueSmirf and prints it to the Arduino serial window.

All was well until I tried to add an LCD screen and have that also display what is being written to the Arduino. Now, if I send "testing" from the phone, the Arduino serial window prints "tsg" or sometimes "stg" (it is only getting some of the letters).

I know that the issue stems from the multiple instances of the serial communication occurring at the same time, how do I add an interrupt or some other code to create a buffer?

It is worth noting also that peculiarly, the below code does not work unless the BlueSmirf RX/TX are wired to the Arduino 1,0. Despite defining the RX/TX pins as Arduino 7,6 connecting the wires from the BlueSmirf to these pins does not send text from the phone to the Arduino.  I tried defining the Arduino pins 1,0 as RX,TX but then the Serial monitor showed only gibberish characters.

here is the code:

Code:
/*******************************************\
 BlueSMiRF I/O Example
 
 Sends and recieves single-bytes between the
 client-USB connection and the tethered
 Bluetooth device.
 
 Jeremy Bridon
 jgbridon@gmail.com
\********************************************/
 
// Included for serial communication
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 
// Define pins you're using for serial communication
// for the BlueSMiRF connection
#define TXPIN 6
#define RXPIN 7
 
// Create an instance of the software serial object
SoftwareSerial BlueSerial(RXPIN, TXPIN);
 
// Main application entry point
void setup()
{
    // Define the appropriate input/output pins
    pinMode(RXPIN, INPUT);
    pinMode(TXPIN, OUTPUT);
 
    // Begin communicating with the bluetooth interface
    Serial.begin(115200);
    BlueSerial.begin(115200);
 
    // Say we are starting the serial com
    Serial.println("Serial start!");
    BlueSerial.println("Serial start!");
    //turn on the lcd, 20 columns and four rows
    lcd.begin(16, 2);
    // print the name of the code to tjhe LCD
    lcd.print("Program Start!");
    //wait six seconds
    delay(6000);
    //clear the LCD
    lcd.clear();
    
}
 
// Main application loop
void loop()
{
    // Wait for command-line input
    if(Serial.available() > 0)
    {
        // Read off all bytes
        BlueSerial.print( Serial.write(Serial.read()));
        delay(100);
        lcd.write(Serial.read());
    }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50335
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
        BlueSerial.print( Serial.write(Serial.read()));
        delay(100);
        lcd.write(Serial.read());
You have two read()s. Each one is going to get part of the data.

Code:
int val = Serial.read();
BlueSerial.print(val);
lcd.write(val);

The Serial.write() function returns a value - the number of characters written. It is that value that you are trying to send to the BlueSerial port. Why?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I see, so the two read ()s split the data being sent in. How would I put in a buffer or some sort of a delay so that what is read by the first read() is also sent to the lcd?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50335
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How would I put in a buffer or some sort of a delay so that what is read by the first read() is also sent to the lcd?
I showed you how.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, duh! I'm reading this on my phone and I missed the code you posted. Thanks!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK Paul, giving strtok() a go. Apologies in advance for the shallowness of knowledge I am sure to display.

I've modified my Android App so the parameters are sent over in the following format:

FT=500, EXP=20000, INT=5000, EXPDLY=500, MTR=100

I removed the LCD from the code to streamline it a bit and will add that back in later, but I'm still stuck on the strtok() useage. I found some examples in older forum posts where you helped others, but haven't come across a good tutorial that explains the syntax. I tried to insert come code that would be a starting point:

Code:
// Included for serial communication
#include <SoftwareSerial.h>
// Define pins you're using for serial communication
// for the BlueSMiRF connection
#define TXPIN 6
#define RXPIN 7
// Create an instance of the software serial object
SoftwareSerial BlueSerial(RXPIN, TXPIN);
// array definitions
// define SOP (start of packet) and EOP (end of packet)
#define SOP '<'
#define EOP '>'


bool started = false;
bool ended = false;

char inData[80]; // creates an 80 character array called "inData"
byte index; //creates a variable type=byte called "index"
unsigned int FT; //variable for Focus Tap
unsigned int EXP; //variable for Exposure
unsigned int INT; // variable for interval
unsigned int EXPDLY; //variable for Exposure Delay
unsigned int MTR; // variable for Motor Speed

// Main application entry point
void setup()
{
    // Define the appropriate input/output pins
    pinMode(RXPIN, INPUT);
    pinMode(TXPIN, OUTPUT);
 
    // Begin communicating with the bluetooth interface
    Serial.begin(115200);
    BlueSerial.begin(115200);
 
    // Say we are starting the serial com
    BlueSerial.println("Serial start!");
       
}
 
// Main application loop
void loop()
{
    // Wait for command-line input
    if(Serial.available() > 0)
    {
        // Read off all bytes
        int val = Serial.read();
       // BlueSerial.print(val);
        Serial.write(val);
        delay(100); 
    }
  {
 
 
 // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read(); //PaulS - do I need to change "Serial.read()" to "val?" because of the double read() issue you helped me solve before?
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
  /* The end of packet marker arrived. Process the packet
  Where it says "Process the packet", you can then use strtok() to get
  the bits from the array. Use "=" as the delimiter to get the
  ExposureLength name. Then, use "," as the delimiter to get the
  value as a string ("20000") and atoi() to convert the string to
  a number, 20000. Then, store the value in a variable - which one
  depends on the name token (use strcmp() to detect a match).*/
char *token = strtok(inData, ","); // do I need to change "token" to one of my variables (i.e FT, EXP, INT etc. and repeat this codeblock for each one)?
while(token)
{
   int iVal = atoi(token); // not sure what "iVal" needs to be changed to here, or how I would use strcmp()

   token = strtok(NULL, "="); // Is this where I would use the "=" in the parsing with strcmp()?
}


    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}
   
   
}

Thanks for your help Paul!
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 640
Posts: 50335
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you have input like "FT=500, EXP=20000, INT=5000, EXPDLY=500, MTR=100", and you call strtok() with that string, and a delimiter of ",", the first token that you get will be "FT=500".

What I think you want to do is more like this:
Code:
char *name = strtok(inData, "=");
while(name)
{
  char *valToken = strtok(NULL, ",");
  if(valToken)
  {
     int val = atoi(valToken);
     if(strcmp(name, "FT") == 0)
        ftVal = val;
     else if(strcmp(name, "EXP")
        expVal = val;
     // More else if's go here
  }

  name = strtok(NULL, "=");
}
Logged

Pages: [1]   Go Up
Jump to: