BlueSmirf + Arduino inconsistencies

I've been working on this project for a while using the ATMega328p and Arduino Micro, but have not found a solution anywhere. I've tried the BlueSmirf Silver and Gold.

I have a program that reads a one-wire thermometer and transmits the readings over bluetooth to a paired device. While the microcontroller is plugged into a PC, it works as intended - quite well, actually. The hardest part of this phase was parsing the data with the receiving program.

However, in both cases, once the device is removed from the PC, it does not connect to the BlueSmirf. The paired device connects without an issue, but the Arduino does not get or send messages from the BlueSmirf. I can tell both devices are working otherwise, though. I installed an LED on another pin to blink every second and that works as intended.

When removing the device from the PC, the method is different for each of these. With the ATMega, I created a breadboard circuit, provided 9v to a 5v VR and hooked up the necessary peripherals. With the Micro I tried using 9v on the Vin pin (recommended voltage is 7-12v) as well as 5v on the micro USB. All peripherals on the board turn on as expected. The circuit seems to be correct.

On the Micro, there were some differences that may help with troubleshooting and getting past this. Once the micro was plugged into an external power source (Vin or USB) and then plugged back into a PC for troubleshooting, the serial from the BlueSmirf was garbled. The only way to clear it up was to reprogram the board and power cycle it.

Libraries used:
SoftwareSerial
OneWire

Any suggestions? This has got to be something simplistic that I am missing because it happens on multiple platforms. I've not been able to find out what it is so far.

Code:

#include <SoftwareSerial.h>  
#include <OneWire.h>

const int MAX_DEVICES = 4;
const int ONEWIRE_PIN = 9;
const String READ_CMD = "read";

int bluetoothTx = 11;  
int bluetoothRx = 3;  

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);

String cmd = "";
boolean cmdSent = false;
//Thermometer register
byte address[MAX_DEVICES][8];
//Registered devices
int regDevs = 0;

OneWire ds(ONEWIRE_PIN);

void setup()
{
  Serial.begin(9600);  
  pinMode(bluetoothTx, INPUT);
  setupBluetooth();
  setThermDevices();
}

boolean setupBluetooth()
{  
  delay(5000);
  bluetooth.begin(14400);
  bluetooth.print("$");
  bluetooth.print("$");
  bluetooth.print("$");  
  delay(100);
  bluetooth.println("U,9600,N");
  delay(100);
  bluetooth.begin(9600);
  bluetooth.print("$");
  bluetooth.print("$");
  bluetooth.print("$");  
  delay(100);
  bluetooth.println("SA,2");
  delay(100);
  bluetooth.println("SM,0");
  delay(100);
  bluetooth.println("SN,THERM02");  
  delay(100);
  bluetooth.println("S-,THERM02");
  delay(100);
  bluetooth.println("ST,0");
  delay(100);
  bluetooth.println("---");
  delay(100);
  while (bluetooth.available())
    bluetooth.read();  
}

void loop()
{
  if(bluetooth.available())  
  {
    parseInput();
    Serial.print(cmd);
    if (cmdSent)
    {      
      if (cmd == READ_CMD) 
      {        
        readCommand();
      }
      
      cmdSent = false;
      cmd = "";
    }//cmdSent
  }   
}

void parseInput()
{
  while(bluetooth.available())
  {
    char input = (char)bluetooth.read();
    if (input == '\n')
    {
      cmdSent = true;
    }
    else
    {
      cmd += input;
    }
  }
}

void readCommand()
{ 
  for (int i=0; i<regDevs; i++)
  {
    sendTempF(i);
  }
  bluetooth.print(";");
}

float sendTempF(int _index)
{
  byte addr[8];
  byte data[12];
  byte dataRdy = 0;
  int16_t ret;
  byte cfg;
  String btOut = "";
  btOut += (String)_index;
  
  for (int m=0; m<8; m++)
    addr[m] = address[_index][m];

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);    
  
  delay(1000);        
  
  dataRdy = ds.reset();
  ds.select(addr);
  ds.write(0xBE);    //Read the scratch pad (where the temp bits are stored)
  
  for (int m=0; m<9; m++)    //get first 9 bytes of data
    data[m] = ds.read();
    
  ret = (data[1] << 8) | data[0];      
  
  cfg = (data[4] & 0x60);            
  
  if (cfg == 0x00) ret = ret & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) ret = ret & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) ret = ret & ~1; // 11 bit res, 375 ms
  
  float celsius = (float)ret / 16.0;          //Calculate celsius - needed for Fahrenheit
  float fahren = (celsius * 1.8 + 32.0);      //Calculate F
  char buffer[10];                            //Convert the result to string
  dtostrf(fahren, 5,2, buffer);
  String tempOut = buffer;
    
  btOut += "="+tempOut;                              
  bluetooth.println(btOut);
  Serial.println(btOut);

}

void setThermDevices()
{ 
  for (int i=0; i<MAX_DEVICES; i++)
  {
    byte addr[8];    
    
    if (!ds.search(addr))
    {   
      ds.reset_search();
      delay(250);
      regDevs = i;
      return;
    }
    
    if (OneWire::crc8(addr, 7) != addr[7])
    {
      continue;
    }
      
    if (addr[0] != 0x28)
    {
      continue;
    }
    
    registerDevice(addr, i);
  }  
}

void registerDevice(byte _address[8], int _index)
{
  for (int m=0; m<8; m++)
  {
    address[_index][m] = _address[m];
  }
  Serial.println("Device registered...");
}

This kind of stuff drives me nuts. However, I finally figured it out.

The max program size for Arduino Micro is 32kb. My program compiled at 13kb. So I did not see an issue with that at all. I did notice that other programs worked with the BlueSmirf. I created a simple program that would reply whenever a message was received and the paired device received replies. This meant that Arduino was working with the BlueSmirf and something else was up.

So I stripped all intensive calculations out of the program - well, all that I could without rendering it useless. It no longer attempts to store the addresses of the thermometer devices nor does it attempt to perform string operations. String operations are more intensive than most floating point operations. All of them were removed. All local variables were also removed and the code on the paired device was refactored to account for the change.

TL;DR: SRAM overflow, I think. Anyone have a clue? If not, and this post just gets dust and webs, hopefully someone out there will find it and not waste nearly as much time as I did.

dracoaroch:
SRAM overflow, I think.

Quite likely but probably entirely self-inflicted. I think it is all down to the code. You shouldn't need to use strings at all and all data and calcs should be fed directly to whatever without any need for storage. I can't guess at what sensors you are using but, if they actually demand code on this scale, replacing them with something a bit more sensible might help.

Maybe there is something special about BlueSmirfs that demand a lot of code too, but I would assume that they are just another serial device as far as Arduino is concerned and don't actually need any more code than the serial monitor. For starters there appears to be no evidence that you need software serial.

While I would advocate a Mega for this purpose, at the moment you seem to be doing nothing more than collecting some temperatures and passing them on to some device. This is about as simple as you can get and well within the Uno's abilities. The 13k compile confirms that.