C++ Static Function/Namespace issue - c++

I am having issues with some code. In the CrossingSensor::loop() function, there is a line with: sonar.ping_timer(readSensor);.
I can call that fine, but in that function I can't access the status variable. What am I missing?
Error: error: 'status' was not declared in this scope status = on;
/*
Name
*/
#ifndef CrossingSensor_h
#define CrossingSensor_h
#include "Arduino.h"
class CrossingSensor
{
enum Status {off, on};
public:
CrossingSensor();
void init();
void loop();
void start();
void stop();
Status status;
private:
unsigned long _startMillis;
};
#endif
/*
NLE
*/
#include "Arduino.h"
#include "CrossingSensor.h"
#include <NewPing.h>
NewPing sonar(2,3,6);//trigger, echo, max distance
unsigned int pingSpeed = 500;// 50ms would be 20 times a second
unsigned long pingTimer;// Holds the next ping time
CrossingSensor::CrossingSensor()
{
Serial.println("CrossingSensor: Init");
//init();
}
void CrossingSensor::init()
{
Serial.println("CrossingSensor: Init/Attach/Reset");
pingTimer = millis();
}
void readSensor()
{
if (sonar.check_timer())
{
int cm = sonar.ping_result / US_ROUNDTRIP_CM;
if(cm > 0 && cm < 10)
{
//status = on;
}
else
{
//status = off;
}
}
}
void CrossingSensor::loop()
{
if (millis() >= pingTimer)
{
pingTimer += pingSpeed;
sonar.ping_timer(readSensor);
}
}
void CrossingSensor::start()
{
if(status == off)
{
Serial.println("CrossingSensor: Turning Sensor On");
status = on;
}
}
void CrossingSensor::stop()
{
if(status == on)
{
Serial.println("CrossingSensor: Turning Sensor Off");
status = off;
}
}

You never declared the function readSensor() as a part of CrossingSensor. Since it isn't a member function, it has no access to status.
All you should have to do is declare the function as a member of CrossingSensor or pass it a CrossingSensor object.
You would also need to change the .cpp file to reflect that change. The declaration for each would look like the following:
class CrossingSensor
{
enum Status {off, on};
public:
CrossingSensor();
void init();
void readSensor();
void loop();
void start();
void stop();
Status status;
private:
unsigned long _startMillis;
};
#endif
This is your method declaration:
void CrossingSensor::readSensor()
{
// your code here
}
This makes readSensor a part of CrossingSensor as well as the other way around.

The readSensor() function isn't part of CrossingSensor so it can't see CrossingSensor's status.
Make it part of Crossingsensor by declaring it there in your header file, and then define it as void CrossingSensor::readSensor(), in your code, and not as void readSensor().
Also, I don't know what sonar.ping_timer() takes as an argument, but I doubt it is readSensor. You will have to find another way of passing status to sonar.ping_timer(), if that is what you intended to do.

Related

Populate and execute callbacks from array class attribute

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;
};

undefined reference to vtable (class)

I am getting this error:
Linking CXX executable muse3.exe
driver/libmuse_driver.a(qttimer.obj):qttimer.cpp:(.rdata$.refptr._ZTVN8MusECore10InnerTimerE[.refptr._ZTVN8MusECore10InnerTimerE]+0x0): undefined reference to `vtable for MusECore::InnerTimer'
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [muse\CMakeFiles\muse.dir\build.make:212: muse/muse3.exe] Error 1
mingw32-make[1]: *** [CMakeFiles/Makefile2:600: muse/CMakeFiles/muse.dir/all] Error 2
mingw32-make: *** [Makefile:151: all] Error 2
I understand that the message is a little unclear and the issue is probably with some method.
Here is my .h file:
#ifndef __QTTIMER_H__
#define __QTTIMER_H__
#include <fcntl.h>
#include <QThread>
#include <QBasicTimer>
#include <QTimerEvent>
#include "timerdev.h"
namespace MusECore {
//---------------------------------------------------------
// QtTimer
//---------------------------------------------------------
class InnerTimer : public QObject {
Q_OBJECT
int writePipe;
long int tickCount;
QBasicTimer timer;
public:
void setupTimer(int fd, int timeoutms);
~InnerTimer();
long int getTick();
bool isRunning() { return timer.isActive(); }
protected:
void timerEvent(QTimerEvent *event);
};
class QtTimer : public Timer, public QThread {
int writePipe;
int readPipe;
bool keepRunning;
InnerTimer *innerTimer;
int timeoutms;
public:
QtTimer();
virtual ~QtTimer();
virtual signed int initTimer(unsigned long init);
virtual long unsigned int setTimerResolution(unsigned long resolution);
virtual long unsigned int getTimerResolution();
virtual long unsigned int setTimerFreq(unsigned long freq);
virtual long unsigned int getTimerFreq();
virtual bool startTimer();
virtual bool stopTimer();
virtual long unsigned int getTimerTicks(bool printTicks=false);
void setFindBestTimer(bool ) { }
private:
virtual void run();
};
} // namespace MusECore
#endif //__QTTIMER_H__
And here is the .cpp file:
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include "qttimer.h"
#ifndef TIMER_DEBUG
#define TIMER_DEBUG 1
#endif
#ifdef _WIN32
#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
#endif
namespace MusECore {
QtTimer::QtTimer()
{
if(TIMER_DEBUG)
fprintf(stderr,"QtTimer::QtTimer(this=%p) called\n",this);
innerTimer = NULL;
timeoutms = 10;
readPipe=-1;
writePipe=-1;
}
QtTimer::~QtTimer()
{
if(TIMER_DEBUG)
fprintf(stderr,"QtTimer::~QtTimer(this=%p) called\n",this);
exit(); // thread exit
}
signed int QtTimer::initTimer(unsigned long)
{
if(TIMER_DEBUG)
printf("QtTimer::initTimer(this=%p)\n",this);
int filedes[2]; // 0 - reading 1 - writing
if (pipe(filedes) == -1) {
perror("QtTimer - creating pipe failed");
exit(-1);
}
#ifndef _WIN32
int rv = fcntl(filedes[1], F_SETFL, O_NONBLOCK);
if (rv == -1)
perror("set pipe O_NONBLOCK");
#endif
if (pipe(filedes) == -1) {
perror("QtTimer - creating pipe1");
exit(-1);
}
writePipe = filedes[1];
readPipe = filedes[0];
return filedes[0];
}
long unsigned int QtTimer::setTimerResolution(unsigned long)
{
return 0;
}
long unsigned int QtTimer::setTimerFreq(unsigned long freq)
{
if (freq > 1000)
freq = 1000;
if (freq < 100)
freq = 100;
timeoutms = 1000/freq;
return 1000/timeoutms;
}
long unsigned int QtTimer::getTimerResolution()
{
return 20;
}
long unsigned int QtTimer::getTimerFreq()
{
return 1000/timeoutms;
}
bool QtTimer::startTimer()
{
QThread::start();
return true;
}
bool QtTimer::stopTimer()
{
QThread::quit();
return true;
}
unsigned long int QtTimer::getTimerTicks(bool /*printTicks*/)
{
if(TIMER_DEBUG)
printf("getTimerTicks()\n");
unsigned long int nn;
if (readPipe==-1) {
fprintf(stderr,"QtTimer::getTimerTicks(): no pipe open to read!\n");
return 0;
}
if (read(readPipe, &nn, sizeof(char)) != sizeof(char)) {
fprintf(stderr,"QtTimer::getTimerTicks(): error reading pipe\n");
return 0;
}
//return nn;
return innerTimer != 0 ? innerTimer->getTick() : 0;
}
void QtTimer::run()
{
//bool keepRunning = true;
innerTimer = new InnerTimer();
innerTimer->setupTimer(writePipe, timeoutms); // make sure it is running in the right thread
exec();
}
void InnerTimer::setupTimer(int fd, int timeoutms)
{
tickCount=0;
writePipe = fd;
timer.start(timeoutms, this);
printf("InnerTimer::setupTimer() started\n");
}
InnerTimer::~InnerTimer()
{
timer.stop();
}
void InnerTimer::timerEvent(QTimerEvent *event)
{
//if (tickCount%1000)
//printf("InnerTimer::timerEvent %ld ++++++++++++++++++++++\n",tickCount);
if (event->timerId() == timer.timerId()) {
tickCount++;
write(writePipe,"t",1);
}
}
long int InnerTimer::getTick()
{
return tickCount;
}
} // namespace MusECore
I have read other posts on this error, and they mostly point to some virtual methods that were not defined. But, to me, it seems that everything is defined properly and I also have the destructor defined.
Can anybody point me out to what is wrong?

Link error (symbol from plugin)*

Its been a while since ive coded in c++/c and im a little confused as to what im doing wrong
I have three files, 2 .h and one .cpp.
The files are as follow
Base Menu
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
#define SSD1306_LCDHEIGHT 64
Adafruit_SSD1306 display(OLED_RESET);
class BaseMenu {
public:
// for moving the menu up and down
void moveDownMenu();
void moveUpMenu();
void selectMenu();
// for changing the text and the positions
void incrementText();
void decrementText();
protected:
//
char menuTitlePos1[20];
char menuTitlePos2[20];
char menuTitlePos3[20];
bool is_menuPos1_selected = true;
bool is_menuPos2_selected = false;
bool is_menuPos3_selected = false;
private:
virtual void AbstractClass() = 0;
};
MainMenu.h
#include "BaseMenu.h"
#include <string.h>
#define ARRAYSIZE 4
class MainMenu : BaseMenu {
private:
// Constructor
MainMenu() {};
public:
static void init();
};
MainMenu.cpp
#include "MainMenu.h"
void MainMenu::init() {
// clearing display
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(WHITE);
for (int i = 0; i < ARRAYSIZE; i++) {
if (i == 1) {
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
//display.println(MainMenuTitles[i]);
}
else {
display.setTextSize(1);
display.setTextColor(WHITE);
//display.println(MainMenuTitles[i]);
}
}
display.display();
}
When ever i go to build the code i get the following error.
MainMenu.cpp.o (symbol from plugin)*: In function display
(.text+0x0)*: multiple definition of display
TestingLibrary.cpp.o (symbol from plugin)*: (.text+0x0): first defined here
collect2.exe*: error: ld returned 1 exit status
Can someone please shed some light as to what i'm doing wrong?

Compiling error in Arduino library

I'm having a strange error compiling a sketch in Arduino, probably due to a mistake in a library I've created.
here's the code:
#include <BlueHartwin.h>
BlueHartwin bH(7,8,115200);
byte incomingByte;
void noOp(void)
{
Serial<<"noOp"<<endl;
};
void leftWindowDown(void)
{
Serial<<"leftWindowDown"<<endl;
};
void setup() {
Serial.begin(115200);
bH.registerCmd(0,&noOp);
bH.registerCmd(1,&leftWindowDown);
}
void loop() {
if(bH.available())
{
incomingByte = bH.read()-48;
Serial<<incomingByte<<endl;
if (incomingByte<nrOfCommands)
bH.runCmd(incomingByte);
}
}
Here are the header of the library:
#ifndef BlueHartwin_H
#define BlueHartwin_H
#include <SoftwareSerial.h>
#include <Streaming.h>;
#include <Arduino.h>
#define nrOfCommands 255
typedef void (* CmdFuncPtr) (); // this is a typedef to command functions
class BlueHartwin {
public:
BlueHartwin(byte bluetoothTx,byte bluetoothRx,long baudRate);
~BlueHartwin();
//void setup(byte bluetoothTx,byte bluetoothRx,long baudRate);
boolean registerCmd(byte id,CmdFuncPtr cmdFuncPtr);
boolean unRegisterCmd(byte id,CmdFuncPtr cmdFuncPtr);
boolean runCmd(byte id);
void setDataLength(byte dataLength);
byte getDataLength();
boolean available();
byte read();
private:
CmdFuncPtr setOfCmds[255];
byte mDataLength;
};
#endif
and source
#include "BlueHartwin.h";
SoftwareSerial bluetooth(7,8);
byte mDataLength;
BlueHartwin::BlueHartwin(byte bluetoothTx,byte bluetoothRx,long baudRate){
bluetooth = SoftwareSerial(bluetoothTx,bluetoothRx);
bluetooth.begin(baudRate);
}
BlueHartwin::~BlueHartwin(){
}
boolean BlueHartwin::registerCmd(byte id,CmdFuncPtr cmdFuncPtr){
if ((id<=nrOfCommands)&&(setOfCmds[id]==0)) {
setOfCmds[id]=cmdFuncPtr;
return true;
} else return false;
}
boolean BlueHartwin::unRegisterCmd(byte id,CmdFuncPtr cmdFuncPtr){
if (id<=nrOfCommands) {
setOfCmds[id]=0;
return true;
} else return false;
}
boolean BlueHartwin::runCmd(byte id){
if ((id<=nrOfCommands)&&(setOfCmds[id]!=0)) {
setOfCmds[id]();
return true;
} else return false;
}
void setDataLength(byte dataLength) {
mDataLength=dataLength;
}
byte getDataLength(){
return mDataLength;
}
boolean available(){
return true;
}
byte read(){
return 0;
}
This is the error I get:
sketch/Test_Bluehartwin00.ino.cpp.o: In function `loop':
/home/paolo/Projects/arduino/sketches/TESTS/Test_Bluehartwin00/Test_Bluehartwin00.ino:25: undefined reference to `BlueHartwin::available()'
/home/paolo/Projects/arduino/sketches/TESTS/Test_Bluehartwin00/Test_Bluehartwin00.ino:27: undefined reference to `BlueHartwin::read()'
collect2: error: ld returned 1 exit status
exit status 1
The strange thing is that I get error only in 2 of the public function of the library class.
I really can't understand what's wrong....
I'm using Arduino UNO and IDE 1.6.8 under Ubuntu 14.04 64 bit. Normally everything runs fine.
Thanks for help in advance.
The problem is in the .cpp file.
The two functions giving you a problem are here:
boolean available(){
return true;
}
byte read(){
return 0;
}
As these are, they are free/global functions. You need to make them part of the class:
boolean BlueHartwin::available(){
return true;
}
byte BlueHartwin::read(){
return 0;
}
Note: you'll also have to modify a few others also:
void BlueHartwin::setDataLength(byte dataLength) {
mDataLength=dataLength;
}
byte BlueHartwin::getDataLength(){
return mDataLength;
}
These can be fixed the same way.

FMOD - Unhandled Exception with no source code avaiable

I'm trying to get my audio track to play using FMOD but I keep getting an unhandled exception and then it says there's no source code available, and shows me disassembly code.
main.cpp
bool AudioProject::initAudio()
{
// Audio code
fmSound = new Sound();
fmSound->initialise();
fmSound->load("Music/Rocky_Theme_Tune.mp3");
fmSound->play();
return true;
}
I put break points in the see where it stopped, which was in the initialise function. It even goes into the initialise function and then just randomly breaks. I think I have every include file for fmod as I used it last year no problem.
I'll post my sound.h/.cpp files too.
.h
#include "stdafx.h"
#pragma once
#include "fmod.hpp"
#include "fmod.h"
class Sound
{
private:
bool on; //is sound on?
bool possible; //is it possible to play sound?
char * currentSound; //currently played sound
//FMOD-specific stuff
FMOD_RESULT result;
FMOD_SYSTEM * fmodsystem;
FMOD_SOUND * sound;
FMOD_CHANNEL * channel;
public:
Sound();
~Sound();
void initialise (void);
void setVolume (float v);
void load (const char * filename);
void unload (void);
void play (bool pause = false);
bool getSound (void);
void setPause (bool pause);
void setSound (bool sound);
void toggleSound (void);
void togglePause (void);
};
.cpp
#include "stdafx.h"
#include "Sound.h"
#include "fmod.h"
#include "fmod.hpp"
Sound::Sound()
{
on = true; //is sound on?
possible = true; //is it possible to play sound?
currentSound=""; //currently played sound
sound=0;
}
Sound::~Sound()
{
}
//initialises sound
void Sound::initialise (void)
{
//create the sound system. If fails, sound is set to impossible
result = FMOD_System_Create(&fmodsystem);
if (result != FMOD_OK)
possible = false;
//if initialise the sound system. If fails, sound is set to impossible
if (possible)
result = FMOD_System_Init(fmodsystem,2, FMOD_INIT_NORMAL, 0);
if (result != FMOD_OK)
possible = false;
//sets initial sound volume (mute)
if (possible)
FMOD_Channel_SetVolume(channel,1.0f);
}
//sets the actual playing sound's volume
void Sound::setVolume (float v)
{
if (possible && on && v >= 0.0f && v <= 1.0f)
{
FMOD_Channel_SetVolume(channel,v);
}
}
//loads a soundfile
void Sound::load (const char * filename)
{
currentSound = (char *)filename;
if (possible && on)
{
result = FMOD_Sound_Release(sound);
result = FMOD_System_CreateStream(fmodsystem,currentSound, FMOD_SOFTWARE, 0, &sound);
if (result != FMOD_OK)
possible = false;
}
}
//frees the sound object
void Sound::unload (void)
{
if (possible)
{
result = FMOD_Sound_Release(sound);
}
}
//plays a sound (no argument to leave pause as dafault)
void Sound::play (bool pause)
{
if (possible && on)
{
result = FMOD_System_PlaySound(fmodsystem,FMOD_CHANNEL_FREE, sound, pause, &channel);
FMOD_Channel_SetMode(channel,FMOD_LOOP_NORMAL);
}
}
//toggles sound on and off
void Sound::toggleSound (void)
{
on = !on;
if (on == true)
{
load(currentSound);
play();
}
if (on == false)
{
unload();
}
}
//pause or unpause the sound
void Sound::setPause (bool pause)
{
FMOD_Channel_SetPaused (channel, pause);
}
//turn sound on or off
void Sound::setSound (bool s)
{
on = s;
}
//toggle pause on and off
void Sound::togglePause (void)
{
FMOD_BOOL p;
FMOD_Channel_GetPaused(channel,&p);
FMOD_Channel_SetPaused (channel,!p);
}
//tells whether the sound is on or off
bool Sound::getSound (void)
{
return on;
}
Hit a brick wall here, anyone have any ideas?
You are calling FMOD_Channel_SetVolume(channel,1.0f) in initialise, but the channel variable isn't hasn't been initialized yet, it gets initialized by the FMOD_System_PlaySound(fmodsystem,FMOD_CHANNEL_FREE, sound, pause, &channel); in Sound::play