Offline
Newbie
Karma: 0
Posts: 42
|
 |
« on: February 13, 2012, 12:38:17 am » |
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
Brattain Member
Karma: 334
Posts: 36433
Seattle, WA USA
|
 |
« Reply #1 on: February 13, 2012, 07:43:38 am » |
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. 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? 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
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #2 on: February 13, 2012, 06:07:17 pm » |
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. /* 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
Brattain Member
Karma: 334
Posts: 36433
Seattle, WA USA
|
 |
« Reply #3 on: February 13, 2012, 07:54:27 pm » |
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: val = Serial.read(); // read it and store it in 'val' read it. 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: #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). I'm certain this is a fairly common task that people employ It is. 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
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #4 on: February 13, 2012, 09:17:44 pm » |
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
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #5 on: February 19, 2012, 02:24:41 pm » |
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: /*******************************************\ 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
Brattain Member
Karma: 334
Posts: 36433
Seattle, WA USA
|
 |
« Reply #6 on: February 19, 2012, 03:46:33 pm » |
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. 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
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #7 on: February 19, 2012, 04:14:05 pm » |
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
Brattain Member
Karma: 334
Posts: 36433
Seattle, WA USA
|
 |
« Reply #8 on: February 19, 2012, 04:56:00 pm » |
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
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #9 on: February 19, 2012, 05:08:00 pm » |
Oh, duh! I'm reading this on my phone and I missed the code you posted. Thanks!
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 42
|
 |
« Reply #10 on: February 19, 2012, 10:25:48 pm » |
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: // 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
Brattain Member
Karma: 334
Posts: 36433
Seattle, WA USA
|
 |
« Reply #11 on: February 20, 2012, 07:03:00 am » |
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: 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
|
|
|
|
|
|