Arduino bluetooth problem.

I am building a Morse Code machine with bluetooth functionality.

It is in the early stages at the moment but I have hit a problem.

My code uses a button to input Morse code which is displayed on an LCD and flashes an LED on pin 5, but also incorporates a bluetooth HC05 which controls an LED on pin 13.

Separately, they work fine but I wanted to merge the two sketches. I have succeeded but for one small problem.

When pressing the LED ‘ON’ button on my android app, the LED only comes on after the Morse code button has been pressed. And it works the same way for the LED ‘OFF’ function on the app. Press it, then press the Morse code button and the LED switches off again. This repeats. I cannot figure out why this button is controlling the Bluetooth LED command signal.

I have changed baud rates of the bluetooth but to no joy.

Here is my code.

#include <Wire.h>
#include "rgb_lcd.h"
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11);
rgb_lcd lcd;

#define DOT false
#define DASH true

#define MAX_CHAR_LENGTH 6

#define BUTTON A0
#define LIGHTSENSOR A1
#define pinLED 5
#define BUZZER 4

#define PULSE_THRESHOLD 250
#define LETTER_SEPARATION 600
#define WORD_SEPARATION 8000

const struct MorseTree *tree = NULL;

int ledPin = 13;
int colorR = 0;
int colorG = 0;
int colorB = 100;

String answerString = String("");
String answer = "Yellow";
String readString;
int answerLength = answer.length();

int value;
int button = 0;
int pulseThreshold = 0;
int letterSeparation = 0;
int wordSeparation = 0;

void initMorse(int lbutton, int lpulseThreshold, int lletterSeparation, int 
lwordSeparation)
{
  tree = generateMorseTree();
  button = lbutton;
  pulseThreshold = lpulseThreshold;
  letterSeparation = lletterSeparation;
  wordSeparation = lwordSeparation;
}

struct MorseTree
{
  // '-' unless this is a leaf node
  char character;
  struct MorseTree *dotChild;
  struct MorseTree *dashChild;
};

struct MorseData
{
  char character;
  bool code[MAX_CHAR_LENGTH];
  byte codeLength;
};

void initMorseTree(struct MorseTree *tree)
{
  tree -> character = '-';
  tree -> dotChild = NULL;
  tree -> dashChild = NULL;
}

struct MorseTree *newMorseTree()
{
  struct MorseTree *tree = (struct MorseTree *) malloc(sizeof(struct 
MorseTree));
  initMorseTree(tree);
  return tree;
}

void addTreeMember(struct MorseTree *tree, struct MorseData &data)
{
  struct MorseTree *current = tree;
  for (byte i = 0; i < data.codeLength; i++)
  {
    boolean currentSymbol = data.code[i];
    if (currentSymbol == DOT)
    {
      if (current -> dotChild == NULL)
        current -> dotChild = newMorseTree();
      current = current -> dotChild;
    }
    else
    {
      if (current -> dashChild == NULL)
        current -> dashChild = newMorseTree();
      current = current -> dashChild;
    }
  }
  // now current must be a leaf node
  current -> character = data.character;
}

void addTreeMembers(struct MorseTree *tree, struct MorseData data[], 
byte dataLength)
{
  for (byte i = 0; i < dataLength; i++)
    addTreeMember(tree, data[i]);
}

void addAlphabet(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'A', {DOT, DASH}, 2},
    {'B', {DASH, DOT, DOT, DOT}, 4},
    {'C', {DASH, DOT, DASH, DOT}, 4},
    {'D', {DASH, DOT, DOT}, 3},
    {'E', {DOT}, 1},
    {'F', {DOT, DOT, DASH, DOT}, 4},
    {'G', {DASH, DASH, DOT}, 3},
    {'H', {DOT, DOT, DOT, DOT}, 4},
    {'I', {DOT, DOT}, 2},
    {'J', {DOT, DASH, DASH, DASH}, 4},
    {'K', {DASH, DOT, DASH}, 3},
    {'L', {DOT, DASH, DOT, DOT}, 4},
    {'M', {DASH, DASH}, 2},
    {'N', {DASH, DOT}, 2},
    {'O', {DASH, DASH, DASH}, 3},
    {'P', {DOT, DASH, DASH, DOT}, 4},
    {'Q', {DASH, DASH, DOT, DASH}, 4},
    {'R', {DOT, DASH, DOT}, 3},
    {'S', {DOT, DOT, DOT}, 3},
    {'T', {DASH}, 1},
    {'U', {DOT, DOT, DASH}, 3},
    {'V', {DOT, DOT, DOT, DASH}, 4},
    {'W', {DOT, DASH, DASH}, 3},
    {'X', {DASH, DOT, DOT, DASH}, 4},
    {'Y', {DASH, DOT, DASH, DASH}, 4},
    {'Z', {DASH, DASH, DOT, DOT}, 4},
  };

  addTreeMembers(tree, data, 26);
}

void addNumbers(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'1', {DOT, DASH, DASH, DASH, DASH}, 5},
    {'2', {DOT, DOT, DASH, DASH, DASH}, 5},
    {'3', {DOT, DOT, DOT, DASH, DASH}, 5},
    {'4', {DOT, DOT, DOT, DOT, DASH}, 5},
    {'5', {DOT, DOT, DOT, DOT, DOT}, 5},
    {'6', {DASH, DOT, DOT, DOT, DOT}, 5},
    {'7', {DASH, DASH, DOT, DOT, DOT}, 5},
    {'8', {DASH, DASH, DASH, DOT, DOT}, 5},
    {'9', {DASH, DASH, DASH, DASH, DOT}, 5},
    {'0', {DASH, DASH, DASH, DASH, DASH}, 5},
  };

  addTreeMembers(tree, data, 10);
}

void addPunctuation(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'.', {DOT, DASH, DOT, DASH, DOT, DASH}, 6},
    {',', {DASH, DASH, DOT, DOT, DASH, DASH}, 6},
    {'?', {DOT, DOT, DASH, DASH, DOT, DOT}, 6},
  };

  addTreeMembers(tree, data, 3);
}

struct MorseTree *generateMorseTree()
{
  struct MorseTree *tree = newMorseTree();
  initMorseTree(tree);

  addAlphabet(tree);
  addNumbers(tree);
  addPunctuation(tree);
  
  return tree;
}


void waitFor(int pin, int state)
{
  do
  {
    // spin until the pin reads the given state
    while (digitalRead(pin) != state) { }
    // delay, to verify the reading
    delay(5);
    // continue if the reading has changed
  } while (digitalRead(pin) != state);
}

boolean getNextSymbol()
{

  waitFor(button, HIGH);
  digitalWrite(pinLED, HIGH);
  digitalWrite(BUZZER, HIGH);
  unsigned long start = millis();

  waitFor(button, LOW);
  digitalWrite(pinLED, LOW);
  digitalWrite(BUZZER, LOW);
  unsigned long end = millis();

  unsigned long pulseLength = end - start;  

  // Serial.println(pulseLength);
  if (pulseLength > pulseThreshold)
    return DASH;
  else
    return DOT;
}

boolean shouldTimeOut()
{
  unsigned long start = millis();
  while (digitalRead(BUTTON) == LOW)
  {
    if (millis() - start > letterSeparation)
      return true;
  }
  return false;
}

boolean shouldBeSpace()
{
  unsigned long start = millis();
  while (digitalRead(BUTTON) == LOW)
  {
    if (millis() - start > wordSeparation)
      return true;
  }
  return false;
}

char getNextChar()
{
  static boolean lastCharWasSpace = false;

  const struct MorseTree *current = tree;

  byte symbolCount = 0;

  if (!lastCharWasSpace && shouldBeSpace())
  {
    lastCharWasSpace = true;
    return ' ';
  }

  lastCharWasSpace = false;

  while (true)
  {
    symbolCount++;
    boolean currentSymbol = getNextSymbol();
    // Serial.println(currentSymbol == DOT ? "DOT" : "DASH");
    if (currentSymbol == DOT)
      current = current -> dotChild;
    else
      current = current -> dashChild;

    if (current == NULL)
      return '-';

    if (shouldTimeOut() || symbolCount >= MAX_CHAR_LENGTH)
      return current -> character;  
  }

  // should never get here
  return '!';
}

void lcdReset()
{
    delay(1000);
    answerString.remove(0, 10);
    lcd.clear();
    startUp();
}

void startUp()
{     
  colorG = 0;
  colorB = 100;
  colorR = 0;  
  lcd.setRGB(colorR, colorG, colorB);
  lcd.print("Yellow");
  lcd.setCursor(0, 1);  
}

void setup()
{
  pinMode(BUTTON, INPUT);
  pinMode(LIGHTSENSOR, INPUT);
  pinMode(pinLED, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(9, OUTPUT);  // this pin will pull the HC-05 pin 34 (key pin) HIGH to switch module to AT mode
  digitalWrite(9, HIGH);
  value = analogRead(LIGHTSENSOR);

  initMorse(BUTTON, PULSE_THRESHOLD, LETTER_SEPARATION, WORD_SEPARATION);

  mySerial.begin(115200);
  Serial.begin(9600);  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
  lcd.begin(16, 2); 
  startUp();  
}

void loop()
{  while ( mySerial.available() )
  {    // While there is data in the buffer
    delay( 3 ); 
    char cc = mySerial.read();
    readString += cc;         // build the string - “on” or “off”
  }
  if ( readString.length() >0 )
    {
      mySerial.println( readString );
      if ( readString == "on" )
        {
          digitalWrite( ledPin, HIGH) ;
        }
      if ( readString == "off" )
        {
          digitalWrite( ledPin, LOW );
        }
      readString="";
    }
  
value = analogRead(LIGHTSENSOR);
char c = getNextChar();
  
    

if(value<1)
  {
    lcd.clear();
    answerString.remove(0, 10); 
    startUp();
  }
  else
  {   
    answerString.concat(c);
    Serial.print(answerString);
    lcd.print(c);       
  }    

  if(answerString == answer)
  {
    delay(1000);
    lcd.clear();
    colorG = 100;
    colorB = 0;
    colorR = 0;
    lcd.setRGB(colorR, colorG, colorB);
    lcd.print("Correct!");
    delay(1000);
    answerString.remove(0, 10);
    lcdReset();    
  }
  else if(answerString.length() > answerLength)
  {
    delay(1000);
    lcd.clear();
    colorR = 100;
    colorB = 0;
    colorG = 0;
    lcd.setRGB(colorR, colorG, colorB);
    lcd.print("Incorrect!");
    lcdReset();
  }
 
}

Can anyone help me solve this problem?!?

You have spin-loops waiting for the button press. Once in that part of the code you are stuck until the button is pressed and the code exits. Instead to look to see if a button has been pressed. If so, handle it. Otherwise go check for stuff to do on the Bluetooth.

  • Chip

I do not work for SparkFun.

Ok, I kind of understand what you mean. At the risk of pushing my luck, do you have a hint as to where I could start with fixing this?

Am I right in thinking it is the getNextCharacter function that is causing this issue?

If so, I have tried changing it but only succeeded in breaking the code.

If not, where should I look?

It is waitFor() that has the spin loops, but dealing with them will probably impact getNextSymbol() and/or getNextCharacter() as well.