The issue I'm having now is that the method checkBluetooth() in my library doesn't work.
What happens is that when this function is called, the program does not return to the Arduino's loop function
I tried commenting out code and re-running multiple times and found out that this happens when I call _bluetooth.available() or _bluetooth.read() in checkBluetooth() function.
Thank you for your help.
MobileBLETest.ino
#include <MobileBLE.h>
// PINS
const int BLUETOOTH_TX = 8;
const int BLUETOOTH_RX = 7;
int throttle, steering;
char button;
MobileBLE phone(BLUETOOTH_TX, BLUETOOTH_RX);
void setup() {
Serial.begin(9600);
Serial.println("setup");
phone.begin();
}
void loop() {
// check for any incoming bluetooth signal
phone.checkBluetooth();
// this button value is the ASCII character you press on the Command page of the app.
//button = phone.getButton();
// TODO: change the range to make it easier
// throttle and steering value goes from 0 to 99.
//throttle = phone.getThrottle();
//steering = phone.getSteering();
int i = 0;
Serial.println("test");
//Serial.println("Throttle: " + throttle);
//Serial.println("Steering: " + steering);
//Serial.println("Button: " + button);
}
MobileBLE.h
#ifndef _MobileBLE_h
#define _MobileBLE_h
class SoftwareSerial;
class MobileBLE
{
public:
MobileBLE(int TX, int RX); // TODO should I use ref?
void begin();
char getButton();
int getThrottle();
int getSteering();
void checkBluetooth();
private:
SoftwareSerial &_bluetooth;
int _signal[10];
int _signalLength = 0;
int _TX;
int _RX;
int _throttle;
int _steering;
char _button;
void push(int elem);
void deleteElements();
};
#endif
MobileBLE.cpp
/*
Name: MobileBLE.cpp
Created: 6/28/2017 11:00:39 AM
Author: jaean
Editor: http://www.visualmicro.com
*/
#include "MobileBLE.h"
#include "Arduino.h"
#include <SoftwareSerial.h>
MobileBLE::MobileBLE(int TX, int RX) {
_TX = TX;
_RX = RX;
_signalLength = 0;
}
void MobileBLE::push(int elem) {
_signal[_signalLength] = elem;
_signalLength++;
}
void MobileBLE::deleteElements() {
for (int i = 0; i < _signalLength; i++) {
_signal[i] = 0;
}
_signalLength = 0;
}
void MobileBLE::begin() {
_bluetooth = SoftwareSerial(_TX, _RX);
_bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void MobileBLE::checkBluetooth() {
// TODO:
// returns 0 - if no transmission found for throttle, steering, or button
// returns 1 - if transmission found for throttle and steering
// returns 2 - if transmission found for button
// returns 3 - if both throttle, steering, and button transmission are found.
for (int i = 0; i < 10; i++) {
if (_bluetooth.available()) {
int input = _bluetooth.read();
push(input);
if (input == 254) {
// end of transmission for orientation
_throttle = _signal[0];
_steering = _signal[1];
deleteElements(); // delete all elements in the singal array
}
else if (input == 255) {
// end of transmission for button click
_button = (char)_signal[0];
deleteElements();
}
}
}
}
char MobileBLE::getButton() {
char btn = _button;
_button = NULL;
return btn;
}
int MobileBLE::getThrottle() {
return _throttle;
}
int MobileBLE::getSteering() {
return _steering;
}
It looks like you have a reference to SoftwareSerial but you never actually create a SoftwareSerial object.
This pattern is used for libraries where you can pass any kind of serial to the library. You might want to run this on a Teensy in the future and you want to put the Bluetooth on hardware Serial3, for example. You would use a Stream reference, since both hardware and software serial are Streams.
MorganS is right, you're library would be much more flexible if you don't integrate serial into the library but just pass it a steam object when you create it.
About this problem, I don't know. SoftSerial is just a bit of a headache which I try to avoid...
It depends on the application indeed. But I think it's a bad thing to make a library that can't be used in an application you want to do more then one thing. Aka, no blocking unless you really really really need it. And I don't find that the case here.
I'm using SoftwareSerial because I need to use serial communication on non RX TX pins of the Arduino.
Is there a easy way to do that using a Stream object?
I'm a newbie, would anyone mind putting up sample code using stream object in a library?
It not that it's easier with the Stream object but the Stream calss is the parent of both HardwareSerial and SoftwareSerial. They share the same functionality although the implementation is different.
The great advantage in designing the library in a way you need to pass a Stream object is that the user may choose to do use Serial or Serial1 etc. You give them a choice All you need to know in your library is that you can call .begin(), print() etc on the object which you can with both HardareSerial and SoftwareSerial because it's part of Stream
So not fixing any other errors you have (except indentation)
.h
#ifndef _MobileBLE_h
#define _MobileBLE_h
#include <Arduio.h>
class MobileBLE
{
public:
MobileBLE(Stream &output);
void begin();
char getButton();
int getThrottle();
int getSteering();
void checkBluetooth();
private:
Stream &_bluetooth;
int _signal[10];
int _signalLength = 0;
int _throttle;
int _steering;
char _button;
void push(int elem);
void deleteElements();
};
#endif
.cpp
/*
Name: MobileBLE.cpp
Created: 6/28/2017 11:00:39 AM
Author: jaean
Editor: http://www.visualmicro.com
*/
#include "MobileBLE.h"
#include "Arduino.h"
MobileBLE::MobileBLE(Stream &output) :
_bluetooth(output),
_signalLength(0)
{
}
void MobileBLE::push(int elem) {
_signal[_signalLength] = elem;
_signalLength++;
}
void MobileBLE::deleteElements() {
for (int i = 0; i < _signalLength; i++) {
_signal[i] = 0;
}
_signalLength = 0;
}
void MobileBLE::begin() {
_bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void MobileBLE::checkBluetooth() {
// TODO:
// returns 0 - if no transmission found for throttle, steering, or button
// returns 1 - if transmission found for throttle and steering
// returns 2 - if transmission found for button
// returns 3 - if both throttle, steering, and button transmission are found.
for (int i = 0; i < 10; i++) {
if (_bluetooth.available()) {
int input = _bluetooth.read();
push(input);
if (input == 254) {
// end of transmission for orientation
_throttle = _signal[0];
_steering = _signal[1];
deleteElements(); // delete all elements in the singal array
}
else if (input == 255) {
// end of transmission for button click
_button = (char)_signal[0];
deleteElements();
}
}
}
}
char MobileBLE::getButton() {
char btn = _button;
_button = NULL;
return btn;
}
int MobileBLE::getThrottle() {
return _throttle;
}
int MobileBLE::getSteering() {
return _steering;
}
And now use SoftSerial in your sketch and pass the SoftSerial object to the constructor of MobileBLE.