I've recently started learning C++/Arduino and am working on abstracting some of my Arduino code in order to keep it more manageable. I'm trying to construct a class with 2 arrays as attributes on it, one to store strings that represent commands, and a second one to store pointers to those functions.
The below code works (compiles), but when uploaded to the device both the listen
and execute
functions don't appear to work. I've searched around quite a lot, but can't find where I've gone wrong.
/* main.ino */
// SETUP
#include "SoftwareSerial.h"
SoftwareSerial bt(btRx, btTx);
#include "CMD.h"
const int cmdMax = 6;
ArriCMD cmd;
// COMMANDS
void cmdStatus()
{
Serial.println("OK");
}
// START
void setup()
{
Serial.begin(9600);
bt.begin(9600);
cmd.add("AH+STAT", cmdStatus);
}
void loop()
{
cmd.listen(bt);
}
/* ArriCMD.h */
#ifndef ArriCMD_h
#define ArriCMD_h
#include "Arduino.h"
#include "SoftwareSerial.h"
class ArriCMD
{
public:
ArriCMD();
void add(String cmd, void (*cb)());
void listen(SoftwareSerial serial);
void execute(String cmd);
private:
int _max = 16;
int _amt = 0;
String _cmds[16];
void (*_cbs[16])();
};
/* ArriCMD.cpp */
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "ArriCMD.h"
ArriCMD::ArriCMD()
{
//
}
void ArriCMD::add(String cmd, void (*cb)())
{
if (_amt < _max) {
_cmds[_amt] = cmd;
_cbs[_amt] = *cb;
}
}
void ArriCMD::listen(SoftwareSerial serial)
{
if (serial.available()) {
String cmd = serial.readString();
Serial.print(cmd);
execute(cmd);
}
}
void ArriCMD::execute(String cmd)
{
for (int i = 0; i < _amt; i++) {
if (cmd == _cmds[i]) {
_cbs[i]();
}
}
}
While I've been programming for over a decade, C++ and microcontrollers are brand new to me, any and all help here would be hugely appreciated.
I do intend to open source these libraries, and the subsequent platforms they're built for, once I'm more comfortable with my code quality.
Looks like you forgot to increment your commands counter _amt
void ArriCMD::add(String cmd, void (*cb)())
{
if (_amt < _max) {
_cmds[_amt] = cmd;
_cbs[_amt] = *cb;
_amt++; // <-- here, don't you need it?
}
}
Apart from that, is there some particular reason for using raw array and raw function pointers in your code? I do not use Arduino, so I am not sure, but maybe this solution is a bit cleaner:
class ArriCMD
{
public:
ArriCMD();
void add(String cmd, std::function<void()> cb);
void listen(SoftwareSerial serial);
void execute(String cmd);
private:
std::map<String, std::function<void()> > _cmdMap;
};