Pages: [1]   Go Down
Author Topic: BT serial problems  (Read 425 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Been banging my head against the wall on this forever.  I've got a pile of Arduinos here...some NGs, Duemilanoves, and BTs.  I've built a sketch to serve data up on the serial port in response to requests read in over the serial port.  The NGs and Duemilanoves run it like a charm...  The BTs...well...don't.

Problem is, whenever I try to use the client to connect to the BT boards, I get the following error: Unable to open port : Resource busy.  I can't view data on those serial connections in the serial monitor, either.  The communication fails after a reboot, with Arduino IDE open and closed, and with Serial Monitor open and closed.  I've tried two BT boards.  SOMEtimes, when I change my loop() to the following:

void loop() {
        digitalWrite(13,HIGH);
        Serial.println("Test");
}

I'm really going nuts here, and HAVE to have this running right away.  Can ANYONE point me in the right direction?  By the way, this problem also occurs on any of several computers I've paired the boards to.

My client program--based off of what I found here: http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/--is available for you to see at: http://codepad.org/ANf8iDjO  I'm quite sure my client isn't the problem, though...everything runs like clockwork when I'm not using these !$&@ing BTs.  

Thank you!

///////////////////////
sketch.pde:

/* Arduino BT Serial Server
 * -------------------
 * This sketch sets provides data from analog pins to a client
 * connecting over the serial port.  Data is not streamed
 * continuously, but only provides data when it is requested.
 *
 * version 0.1
 * Copyright 2009 Brennon Bortz <brennon@brennonbortz.com>
 *
 */

#define pins_in_use 2

int incoming_byte, good_byte;      // for incoming serial data

int analog_0 = 0;
int analog_1 = 1;
int analog_2 = 2;
int analog_3 = 3;
int analog_4 = 4;
int analog_5 = 5;
int pin_data[pins_in_use];

void setup() {
  Serial.println("setup()");
  Serial.begin(115200);      // opens serial port, sets data rate to 115200 bps
  int i;
  for (i = 0; i < pins_in_use; ++i) {
    pin_data = 0;
    Serial.print("pin_data[");
    Serial.print(i);    Serial.print("]: ");
    Serial.println(pin_data);
    int testval = 0xFA;
  }
}

typedef enum {
  DSENDANALOG0START = 0,
  DSENDANALOG1START = 1,
  DSENDANALOG2START = 2,
  DSENDANALOG3START = 3,
  DSENDANALOG4START = 4,
  DSENDANALOG5START = 5,
  DSENDANALOG0END = 6,
  DSENDANALOG1END = 7,
  DSENDANALOG2END = 8,
  DSENDANALOG3END = 9,
  DSENDANALOG4END = 10,
  DSENDANALOG5END = 11,
  RXFAIL = 12,
  RXSUCCESS = 13,
  TXFAIL = 14,
  TXSUCCESS = 15,
  TXREQFAIL = 16,
  TXREQSUCCESS = 17,
  DSENDANALOG = 18,
  RAWDATASTART = 19,
  RAWDATAEND = 20
} MESSAGES;
  
void handle_request(int incoming_byte) {
  // parse input
  // if pin data requested refresh data array for pin
  // pass requested value to write_adata_to_serial
  refresh_pin_data(incoming_byte);
  write_data(DSENDANALOG, incoming_byte);
}

void refresh_all_data() {
  // loop through pins for number pins_in_use
  // write reading to data array
  int i;
  for (i = 0; i < pins_in_use; ++i) {
    refresh_pin_data(i);
  }
}

void refresh_pin_data(int incoming_byte) {
  // read pin data and write to data array
  pin_data[incoming_byte] = analogRead(incoming_byte);  
}

bool write_data(int message, int data) {
  Serial.println("write_data()");
  
  if (!write_byte(RAWDATASTART)) {
    return false;
  }
  
  if (message == DSENDANALOG) {
    Serial.println("sending analog data");
    int i;
    int bytes[2];
    bytes[0] = 255;
    bytes[1] = 254;
    for (i = 0; i < 2; ++i) {
      if (!write_byte(bytes)) {
        return false;
      }
    }
    Serial.println("analog data sent");
  }
  
  if (!write_byte(RAWDATASTART)) {
    return false;
  }
}

bool write_byte(int data) {
  Serial.println("write_byte()");
  
  int rxsuccess = 0;
  int data_read;
  while (rxsuccess != 1) {
    if (Serial.available() > 0) {
      Serial.println(data);
      data_read = Serial.read();
      if (data_read == RXSUCCESS)
        rxsuccess = 1;
    }
  }
  if (rxsuccess == 1) {
    return true;
  } else {
    return false;
  }
}

bool check_byte(int incoming_byte) {
  digitalWrite(13, HIGH);
  delay(250);
  digitalWrite(13, LOW);
  // known messages lie between 0-5
  if (incoming_byte >= 0 && incoming_byte <= 5) {
    Serial.print("Got a good message: ");
    Serial.println(incoming_byte, DEC);
    return true;
  } else {
    Serial.print("No match for message: ");
    Serial.println(incoming_byte, DEC);
    return false;
  }
}

void loop() {
        digitalWrite(13,HIGH);
      // send data only when you receive data:
      if (Serial.available() > 0) {
              // read the incoming byte:
            incoming_byte = Serial.read();

                // if byte matches known pattern acknowledge receipt of byte
                good_byte = check_byte(incoming_byte);
                
                if (good_byte == true) {
                  // acknowledge receipt of byte
                  int i = 1;
                  Serial.println(TXREQSUCCESS, BYTE);
                  Serial.println(TXREQSUCCESS, DEC);
                  // handle request
                  handle_request(incoming_byte);
                } else {
                  // send fail message
                  Serial.println(TXREQFAIL, BYTE);
                  Serial.println(TXREQFAIL, DEC);
                }
              Serial.println("Test");
      }
}
« Last Edit: August 26, 2009, 10:48:21 pm by brennon » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 185
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi brennon,

I just do a guess which might not be related to your problem.

In the iWRAP3 user guide of the WT-11 bluetooth chip, you will find a known issue in chapter 10:
"If HW flow control is not used and iWRAP buffers are filled
either in data or command mode, the firmware will hang
and needs a physical reset. This is a bug in the CSR
firmware."

As a possible workaround you can change your code to only send data, when the client software is really connected and listening (use a start command, or the RTS/DTR or CD pin of the WT-11).

 MikeT


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Figured this one out, though I'm not sure why I have to do this...may have something to do with the last post.  Here's my code--everything's explained in the comments:

/**
 *      @file EmotionArduinoServer.pde
 *      @brief Arduino sketch for communication with mobimotion-server.
 *
 *      This sketch provides data from the Arduino's analogue pins to a client
 *      connecting over the serial port.  Data is streamed continuously as quickly
 *      as possible without flooding the serial port.
 *
 *      @author Brennon Bortz
 *      @author brennon@brennonbortz.com
 *      @author http://www.brennonbortz.com
 *      @date Copyright &copy; 2009 Brennon Bortz.  All rights reserved.
 *      @version 1.0
 */

/**
 *      @def      kPinsInUse
 *                  Number of pins to request readings for from the Arduino.
 *      @def      kLedPin
 *                  Pin to which the status LED is connected.
 */
#define kPinsInUse      3
#define kLedPin            13

void handleRequest(int requestedPin);
void activityLed();
void setup();
void loop();

/**
 *      @enum messages Masks used to signal beginning of each data reading being sent to client.
 *      If these values are modified here, make sure the matching modifications are
 *      made in mobimotion-server, as well.
 */
enum messages {
      DSENDANALOGUE0START = 0xFFFFA,
      DSENDANALOGUE1START = 0xFFFFB,
      DSENDANALOGUE2START = 0xFFFFC,
      DSENDANALOGUE3START = 0xFFFFD,
      DSENDANALOGUE4START = 0xFFFFE,
      DSENDANALOGUE5START = 0xFFFFF
};

/**
 *      @brief Sketch initalisation function.
 *
 *      Initializes the sketch by opening the serial port and entering a loop
 *      waiting in a loop for digital pin 2 to be grounded.  Do NOT remove
 *      this loop--it is important.  If the sketch enters the run() function
 *      before the Arduino has established a BT connection, the Arduino will
 *      become unresponsive.
 *
 *      @returns Returns void.
 *      @pre Arduino is powered on.  Digital pin 2 is not grounded.
 *      @post Arduino has been setup and is ready to transmit data readings.
 */
void setup()
{
      // Open serial port.  Arduino BT boards will ONLY work at 115200 bps.
      Serial.begin(115200);            
      
      // Set digital pin 2 as an input and set to HIGH.
      pinMode(2, INPUT);
      digitalWrite(2, HIGH);
      int go = 0;
      go = digitalRead(2);
      
      // As long is pin 2 is not grounded, maintain a holding pattern and show a
      // distinctive flashing pattern on an LED connected to digital pin 13.
      while(go == HIGH) {
            digitalWrite(kLedPin,HIGH);
            delay(50);
            digitalWrite(kLedPin,LOW);
            delay(50);
            digitalWrite(kLedPin,HIGH);
            delay(50);
            digitalWrite(kLedPin,LOW);
            delay(50);
            digitalWrite(kLedPin,HIGH);
            delay(50);
            digitalWrite(kLedPin,LOW);
            delay(700);
            go = digitalRead(2);
      }
}

/**
 *      @brief Sketch run loop.
 *
 *      The main run loop of the sketch.  Simply loops through each pin,
 *      according to kPinsInUse, and requests the data for said pin.  A loop,
 *      like that in setup(), is included so that data transmission can be halted
 *      and the server/client connection can be closed gracefully.  The
 *      connection may hang on either end if this method is not used.
 *
 *      @returns Returns void.
 *      @pre Arduino is powered on and setup() has run.  Digital pin 2 has been grounded.
 *      @post Arduino is executing main run loop.
 */
void loop()
{
      int i;
      
      // Get data reading for each pin.
      for (i = 0; i < kPinsInUse; ++i) {
            handleRequest(i);
      }

      // If digital pin 2 becomes ungrounded, resume loop and wait for pin 2
      // to be grounded before resuming transmission.
      int go = 0;
      go = digitalRead(2);
      while(go == HIGH) {
            digitalWrite(13,HIGH);
            delay(50);
            digitalWrite(13,LOW);
            delay(50);
            digitalWrite(13,HIGH);
            delay(50);
            digitalWrite(13,LOW);
            delay(50);
            digitalWrite(13,HIGH);
            delay(50);
            digitalWrite(13,LOW);
            delay(700);
            go = digitalRead(2);
      }
}

/**
 *      @brief Handler for pin readings.
 *
 *      Called by run() to send data for each pin out serial port.  Data is sent
 *      as a newline-terminated ASCII string containing a decimal value.  Data
 *      ranges between 0-1023 (a 10-bit number).
 *
 *      @param requestedPin Number of analogue pin for reading to be taken.
 *      @returns Returns void.
 *      @pre Arduino is executing main run loop.
 *      @post Reading has been taken for <em>requestedPin</em> and written to serial port.
 */
void handleRequest(int requestedPin)
{
      // Send a message to signal the transmission
      // of data for requestedPin
      Serial.println(DSENDANALOGUE0START + requestedPin, DEC);
      
      // Flash LED
      activityLed();
      
      // Send requested data
      Serial.println(analogRead(requestedPin), DEC);
}

/**
 *      @brief Flashes activity LED.
 *
 *      Just a simple flash of the LED to indicate serial port activity.  The
 *      delay included between the high and low values being sent to kLedPin is
 *      required and also dictates the overall speed at which readings are polled
 *      and data is Here, the minimum value that delay() will accept (1ms) is
 *      used.  Longer delays will make the flashing of the LED more noticeable,
 *      but will cause the sampling rate to deteriorate.  Removing this delay
 *      will flood the serial port and cause communication between the Arduino
 *      and client to fail.
 *
 *      @returns Returns void.
 *      @pre Arduino is powered on and setup() has run.  Digital pin 2 has been grounded.
 *      @post Arduino is executing main run loop.
 */
void activityLed() {
      digitalWrite(kLedPin,HIGH);
      delay(1);
      digitalWrite(kLedPin,LOW);
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I had a similar problem with a bluetooth barcode printer - I forget the make.
The problem was that there was no real closed loop handshaking protocol.
You say you can print OK the 1st time but it fails on the 2nd.
I found out that for me this was because the printer was not ready to have the 2nd print command sent to it but there was no way to tell this from the bluetooth serial port.
I added a Thread.Sleep(1000) between prints, just to give the printer some time to sort itself out and it worked.
Pretty crude but might just work!

Rocky
Logged

Pages: [1]   Go Up
Jump to: