Storing value in 2d array variable during runtime in c++ - c++

My main code is .ino file for STM32F103C8T6 with STM32 official core. I have also included my library files of .h file and .cpp file.
I want store a values in 2d array called uint32_t Page[15][14]; in .h file of my library
How to store a value in 2d array variable during runtime. I have posted my code below. For me the code below is perfect, but still did not print the value stored in the array by calling the function HatriX_Signal with correct parameters. Kindly let me know what is wrong in my code below.
// .ino file
#include "HATRIX.h"
HATRIX Hatrix;
void setup()
{
Hatrix.HATRIX_INIT(115200);
}
void loop()
{
Hatrix.HatriX_Signal(Temperature_Signal, 0x66, Page[2][0]);
Serial.println(Page[2][0]);
Serial.println((float)Page[2][0] / 100);
}
// .h file
#ifndef HATRIX_H
#define HATRIX_H
#include "Arduino.h"
#include "Thermo_Couple_Input.h"
#define Number_of_Pages 15
#define Number_of_Bytes_Per_Page 64
static Thermo_Couple_Input TC_IN;
static uint32_t Page[Number_of_Pages][(Number_of_Bytes_Per_Page / 4) - 2];
enum Signal { Temperature_Signal,
Pressure_Signal,
Co2_Signal,
Analog_Industrial_Input_Signal,
General_Purpose_Output_Signal,
PWM_Power_Signal,
PWM_Voltage_Signal
};
class HATRIX
{
public:
void HATRIX_INIT(uint32_t bauderate);
void HatriX_Signal(uint8_t Signal, uint8_t I2C_Address, uint32_t Page);
};
#endif
// .cpp file
#include "HATRIX.h"
void HATRIX::HATRIX_INIT(uint32_t bauderate)
{
Serial.begin(bauderate);
}
// \brief Note: The value we get from Thermocouple is float value. So, we multiply the value with 100 and store it in specified static uint32_t Page by user.
// \param enum_Signal choose accordingly from enum signal: { Temperature_Signal ,
// Pressure_Signal ,
// Hatrix.Co2_Signal ,
// Analog_Industrial_Input_Signal ,
// General_Purpose_Output_Signal ,
// PWM_Power_Signal ,
// PWM_Voltage_Signal };
// \param I2C_Address Address of I2C to get the temperature from desired Thermocouple.
// \param Page Give the Page details to store your value. example: Hatrix.Page[4][3]
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
Serial.println("Page");
Page = fThermocoupleTemperature * 100;
Serial.println(Page);
}
}

When calling HATRIX::HatriX_Signal(...), you pass a copy of a uint32_t of the multidimensional array Hatrix.Page to the function.
Inside the HATRIX::HatriX_Signal(...) function, you assign a new value to this variable called Page. But since it's just a copy of the value from the array, the array itself won't be effected by this.
In order to get the value of the function you can either use a pointer to the value in the array or a reference to the value in the array, preferably, return the value directly.
Your function could either look like this using a pointer:
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t* Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
*Page = TC_IN.fThermocoupleTemperature;
Serial.println(*Page);
}
}
and called like:
Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66, &Hatrix.Page[2][0]);
or look like this using a reference:
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t& Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
Page = TC_IN.fThermocoupleTemperature;
Serial.println(Page);
}
}
and called like:
Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66, Hatrix.Page[2][0]);
or alternatively, as I would advice, look like this:
uint32_t HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
uint32_t page = TC_IN.fThermocoupleTemperature;
Serial.println(page);
return page;
}
}
and called like:
Hatrix.Page[2][0] = Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66);

How to fix this program:
Raw data such as this 2D array should be made private, as per the fundamental OO principle of private encapsulation.
Should you wish the user to access this array it should be done through a "setter" function taking (x,y) coordinates.
Provide a similar "getter" function for read/print access.
HatriX_Signal and similar should not pass along a pointer to data in a class member, because that's nonsense. You already have access to that data through the this pointer.
Generally, I'd advise to read a beginner-level book about C++ and OO, or alternatively ditch C++ completely if you have no intention of using OO program design anyhow.

Related

C++ trying to cast address to void* and assign to function pointer (so that my bootloader can jump to actual app)

I am writing a bootloader for an STM32, where I need to jump from bootloader to the real app.
In C this works, because I can cast an address to a void pointer and assign that to a function pointer, and call the function pointer as follows:
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
void (*app_reset_handler)(void) = (void *)reset_handler_add;
SCB->VTOR = address;
uint32_t msp_value = *((volatile uint32_t *)address);
__set_MSP(msp_value);
app_reset_handler();
}
If I use the same implementation in a C++ the gnu compiler will give an error on the cast to void pointer.
include/bootloader.hpp:58:39: error: invalid conversion from 'void*'
to 'void (*)()' [-fpermissive]
After googling I found this SO page, which I tried and came to the following implementation in my class:
void JumpToApp()
{
// Quick test if C style cast does work
//jump_to_firmware(_appStartAddress);
uint32_t mspAdress = *((volatile uint32_t *)_appStartAddress);
uint32_t resetHandlerAddress = *((volatile uint32_t *)(_appStartAddress + sizeof(uint32_t)));
// https://stackoverflow.com/questions/1096341/function-pointers-casting-in-c
typedef void (*functionPointer)();
functionPointer resetHandler = 0;
reinterpret_cast<void*&>(resetHandler) = (void*)resetHandlerAddress;
SCB->VTOR = _appStartAddress;
__set_MSP(mspAdress);
resetHandler();
}
In the C++ implementation:
functionPointer resetHandler is assigned with 0x8035065
SCB->VTOR is assigned with 0x08020000
mspAddress is assigned with `0x20020000
then the function pointer resetHandler is called
In the C implementation:
app_reset_handler is assigned with 0x8035065
SCB->VTOR is assigned with 0x08020000
mspAddress is assigned with `0x20020000
then the function pointer app_reset_handler is called
The C implementation works, it jumps to my app, the app runs without issues.
The C++ implementation ends up nowhere. It hangs/crashes on the following (to me meaningless) address:
I am trying to keep the amount of source files to a minimum, so I would like to keep the logic in the single class definition.
My questions:
Did I misunderstand the linked SO page and can somebody see where I went wrong in the C++ implementation?
Is there a better/easier way to cast an address to a function pointer in C++?
Or is there a technical reason why it simply can't be done in C++?
PS: The bootloader code is the same in both cases. The only difference I made to test either implementation is to comment out the code in Bootloader::JumpToApp and call the C function jump_to_firmware(uint32_t) instead.
PPS: all peripherals are deinitialized properly. Again, it works fine, the problem only appears when I use this C++ implementation.
The same code will compile in C and C++. You simple has to cast to the correct cast (in C++ you cant assign a void * to non void * pointer. It is much more strict than in C.
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
void (*app_reset_handler)(void) = (void (*)(void))reset_handler_add;
/* ... */
}
If you do not like those weird casts you can typedef the function.
typedef void handler(void);
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
handler *app_reset_handler = (handler *)reset_handler_add;
/* ... */
}

Pointer gives abnormal values after deferencing

I am trying to replicate a big C++ library. It has the following structure of code
RobotRunner.h
class RobotRunner
{
public:
VectorNavData* vectorNavData;
};
RobotRunner.cpp
void RobotRunner::run()
{
printf("Quaternion[0]: %f \n", vectorNavData->quat[0]); //Output: 243235653487854 - Abnormal values
}
SimulationBridge.h
class SimulationBridge
{
private:
VectorNavData _vectorNavData; // Actual value of vectornavdata from the robot is stored here
RobotRunner* _robotRunner = nullptr; //Pointer to the RobotRunner Object
}
SimulationBridge.cpp
void SimulationBridge::init()
{
_robotRunner = new RobotRunner();
printf("Quaternion[0]: %f \n", _vectorNavData.quat[0]); // Output: 0.43 - Normal and expected
_robotRunner->vectorNavData = &_vectorNavData;
}
void SimulationBridge::run()
{
_robotRunner->run();
}
//This function runs continuously and updates the _vectorNavData in a separate thread
void SimulationBridge::readIMU()
{
while(true)
{
//_lowState stores the values of different robot parameters at a given time
_vectorNavData.accelerometer[0] = _lowState.imu.accelerometer[0];
_vectorNavData.accelerometer[1] = _lowState.imu.accelerometer[1];
_vectorNavData.accelerometer[2] = _lowState.imu.accelerometer[2];
_vectorNavData.quat[0] = _lowState.imu.quaternion[1];
_vectorNavData.quat[1] = _lowState.imu.quaternion[2];
_vectorNavData.quat[2] = _lowState.imu.quaternion[3];
_vectorNavData.quat[3] = _lowState.imu.quaternion[0];
_vectorNavData.gyro[0] = _lowState.imu.gyroscope[0];
_vectorNavData.gyro[1] = _lowState.imu.gyroscope[1];
_vectorNavData.gyro[2] = _lowState.imu.gyroscope[2];
}
}
VectorNavData is a struct which stores the details about the orientation of the robot. It has the following definition
struct VectorNavData {
Vec3<float> accelerometer;
Vec3<float> gyro;
Quat<float> quat;
};
I have included only the necessary part of the code here for brevity.
Code Explanation:
SimulationBridge class communicates with the robot in the simulation. It takes in vectorNavData and stores it in the member variable _vectorNavData. SimulationBridge also contains the pointer to the RobotRunner class as one of it's member. I am allocating the address of _vectorNavData object to the pointer _robotRunner->vectorNavData (check SimulationBridge.cpp). Inside the RobotRunner class I deference this pointer and use the values in other parts of the code.
Problem:
If I print the vectorNavData inside the SimulationBridge.cpp the values seems to be normal. But after assigning the pointer of the same object to the robot runner, if I print the values there the values seems to be abnormally high. My question is, is this way of using pointers for dynamic allocation recommended? If not what is the best alternative way I can use?
Another important point to note is, I am compiling the code with CMake and "-O3" optimization flag is set to the CMAKE_CXX_FLAGS. If I remove this flag, the code sorta works fine for the above object pointer but I am still getting similar error for another object pointer in another part of the code. I have not included that here because it's pretty complex to describe the code structure and the problem essentially is the same.

Arduino - Enum variable value change by itself

I created an Arduino mega sketch to control LEDs channel to simulate simple sunset and sunrize. In my class LEDChannel declaration, i have an public enum to represent the state of the LED Channel and i have a private instance (CurrentState) of State enum in the class to keep track of this LEDChannel instance.
Everything compile well and is uploaded to my Arduino Mega. The problem is when i debug my code and check the value of CurrentState variable i get a value outside of enum range. Sometime i get value 7579 (actual value in my last test). Another day i can get a value of 612. The value should only be 0 to 4. I verified my code and any place i change the value of this variable, i use the enum. By example :
CurrentState = ManualSunset;
CurrentState variable receive the value NoAction in the default constructor of LEDChannel Class.
The class LEDChannel is part of a bigger project to make an Aquarium controller with other class to represent RTC time module, Bluetooth module, Fan and temperature sensor.
I developed my project with Visual Studio Community 2015 with vMicro plugin for Arduino. If you need the complete project, i will find a way to make it available.
Here is the LEDChannel Declaration/definition and main Arduino program .ino. This is a light version of my code. I removed all unnecessary code. To reproduce the problem, just comment line 13 in main program nNbLEDChannel = 1;. You should then get value ManualSunrise (3) for variable CurrentState. Take not that nNbLEDChannel is only used in main .ino file.
#pragma once
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//#include "DataTypes.h"
typedef byte duration;
class AquariumSimulator;
class LEDChannel
{
public:
typedef enum State
{
AutomaticSunset = 0,
AutomaticSunrise = 1,
ManualSunset = 2,
ManualSunrise = 3,
NoAction = 4
};
private:
byte MaxBrightness;
unsigned long lastTick;
byte CurrentBrightness;
LEDChannel::State CurrentState;
byte DigitalPin;
duration ManualSunsetDuration;// In secondes
duration ManualSunriseDuration;// In secondes
AquariumSimulator* pAquariumSim;
public:
void StartManualSunrise(duration SecDuration);
void PerformSunrise();
LEDChannel();
LEDChannel(byte DigitalPIN, AquariumSimulator* pSim);
private:
void PerformManualSunrise();
void SetCurrentBrightness(byte value);
void IncreaseCurrentBrightness(byte value = 1);
};
Here is the LEDChannel.cpp
#include "LEDChannel.h"
/*
Constuctor
*/
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
LEDChannel();
// Initialize default values
pAquariumSim = pSim;
pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel()
{
CurrentState = NoAction;
}
void LEDChannel::PerformSunrise()
{
switch (CurrentState)
{
case AutomaticSunrise:
//PerformAutomaticSunrise();
break;
case ManualSunrise:
PerformManualSunrise();
break;
}
}
void LEDChannel::PerformManualSunrise()
{
unsigned long currentTick = millis();
if (currentTick >= (lastTick + ManualSunriseDuration / MaxBrightness))
{
// If current brightness is at max brigthness value, stop sunset
if (CurrentBrightness == MaxBrightness)
{
CurrentState = NoAction;
lastTick = 0;
}
else
{
IncreaseCurrentBrightness();
lastTick = currentTick;
}
}
}
void LEDChannel::SetCurrentBrightness(byte value)
{
if (value > 255)
CurrentBrightness = 255;
else
CurrentBrightness = value;
analogWrite(DigitalPin, CurrentBrightness);
}
void LEDChannel::IncreaseCurrentBrightness(byte value)
{
if ((CurrentBrightness + value) <= 255)
CurrentBrightness += value;
else
CurrentBrightness = 255;
SetCurrentBrightness(CurrentBrightness);
}
// Manual Sunrise for a duration in secondes
void LEDChannel::StartManualSunrise(duration SecDuration)
{
switch (CurrentState)
{
case NoAction:
CurrentState = ManualSunrise;
ManualSunriseDuration = SecDuration;
SetCurrentBrightness(0);
break;
}
}
And main program .ino
#include "LEDChannel.h"
LEDChannel** pLED;
byte nNbLEDChannel;
void setup()
{
pLED = new LEDChannel*[1];
pLED[0] = new LEDChannel(44, NULL);
/* If i put the next line as comment CurrentState get a valid value.
If i assigne a value to nNbLEDChannel I get invalid value for CurrentState*/
nNbLEDChannel = 1;
pLED[0]->StartManualSunrise(10);
}
void loop()
{
pLED[0]->PerformSunrise();
}
I didn't get out my Arduino UNO board, but I am pretty sure your main problem is the fact that you are trying to call the default constructor from within another constructor. Edit: The call to LEDChannel() you did actually constructed a new instance of the class which then never gets used or assigned. The version of the C++ standard being used by default by Arduino doesn't support that feature, see the following answer for more information (It also demonstraits the correct syntax for calling a constructor from another constructor if you are using a version of the standard which supports it). This means that the CurrentState variable is uninitialized and will be some random value as you are observing. Uncommenting out the line:
nNbLEDChannel = 1;
really doesn't have anything to do with the error and just rearranges the memory which apparently happens to put the CurrentState variable to a valid value.
Similar functionality, having common code within a constructor, can be achieved by moving your common initialization code out of the default constructor and into another function like this, which is then called by both constructors (don't forget to initialize all of the member variables of the class in this function to a default value and then do any other "special" initialization after it):
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
// Initialize default values
commonInitFunction();
//Do other "special" initialization
pAquariumSim = pSim;
//pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel()
{
// Initialize default values
commonInitFunction();
//Do other "special" initialization
}
void LEDChannel::commonInitFunction()
{
CurrentState = NoAction;
//make sure all other member variables have been initialized to something either in here or
//in your constructors to keep from having unexpected behavior
}
Although it is a good idea to initialize variables in an initializer list, as stated here, which would then change your constructors to be the following (Note: I just picked some random default values):
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim):
MaxBrightness(255),
lastTick(0),
CurrentBrightness(0),
CurrentState(NoAction),
DigitalPin(DigitalPIN),
ManualSunsetDuration(60),
ManualSunriseDuration(60),
pAquariumSim(pSim)
{
//pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel():
MaxBrightness(255),
lastTick(0),
CurrentBrightness(0),
CurrentState(NoAction),
DigitalPin(0),
ManualSunsetDuration(60),
ManualSunriseDuration(60),
pAquariumSim(NULL)
{
CurrentState = NoAction;
}
This ensures all values are initialized (including in the proper order) for the instantiation of the class.
On a side note, I did notice a few other items in the code you provided which might cause you some unexpected behavior.
Since CurrentBrightness is a byte (i.e. uint8_t), in your void LEDChannel::IncreaseCurrentBrightness(byte value) method, your check to see if the CurrentBrightness + value is <= 255. This will only ever be false if the sum is equal to 255 because of overflow. Basically, if the CurrentBrightness is 250 and I add the value of 10 to it then I will get a value of 4 if I am not mistaken. This is probably not the desired behavior of this check.
The second is that the typedef keyword for your enum is not doing anything since you didn't specify a type. In C++, you don't need the typedef for an enumeration or struct if you only want to refer to it by the original name you gave it, like you did here. See some of the answers here, even though none of them were accepted the first few are
Have you guaranteed that loop() cannot be called before setup() ?
It is suspicious that setting a value immediately after your pointer array is the "source" of the problem. This leads me to suspect that either the pLED value is getting changed or you have some other indexing problem that is causing the memory where nNbLEDChannel resides to be interpreted as a LEDChannel object.

Accessing members in a typedef map struct?

My question should be simple and I've spent that last few hours trying to get an answer to it by figuring it out on my own (and google-ing) answers and getting nowhere.
I've got the following in my header file:
Window.hpp
typedef struct {
SDL_Window* window = 0;
const char* title = 0;
int width;
int height;
int flags;
} m_windowStruct;
typedef std::map<std::string, m_windowStruct> m_windowMap;
m_windowMap windowMap; /* <-- Made this accessible */
and in my source file I've the following code:
Window.cpp
bool Window::createWindow(std::string id, const char* title, int width, int height, int flags) {
m_windowMap* windowMap;
m_windowStruct windowData;
windowData.window = SDL_CreateWindow("insert window creation info here");
if (!windowData.window) {
windowData.title = title;
windowData.width = width;
windowData.height = height;
windowData.flags = flags;
windowMap->insert(m_windowMap::value_type(id, &windowData));
SDL_LogInfo(INFO, "Window creation successful");
return true;
}
else {
return false;
}
};
Which works all fine and dandy... The problem I'm having is accessing the mapped struct members after.
For example if I want the instance of the primary window I'd want the following function:
/* Returns the window instance from the mapped struct */
SDL_Window* Window::getWindow(std::string id) {
m_windowMap::const_iterator keyValuePair = windowMap.find(id); /* <-- New error: Error: expression must have a class type */
if (keyValuePair == windowMap.end()) { /* <-- same error as just above */
return 0;
}
return keyValuePair->second.window; /* <-- Same error as just above */
};
I cannot for the life of me figure out how to access the second window member so that I can then give it to my renderer!
Any ideas?
I guess you want the windowMap being a global variable which is accessible across multiple source files (i.e., .cpp). Here are the changes you need to make,
In header file, replace the last line with extern m_windowMap* windowMap;. This makes variable accessible to all source files that include the header.
In your main function (or anywhere appropriate), add this line to initialize the map windowMap = new m_windowMap();
Remove m_windowMap* windowMap; in the Window::createWindow function, otherwise the re-declaration creates a new local m_windowMap and the rest of the function makes no effect to the global windowMap.
Lastly, since the global windowMap is a pointer, change .find() and .end() to ->find() and ->end() in the getWindow function.
If the windowMap is indeed a class member of Window, it is actually easier and cleaner.
From the code you originally posted, remove m_windowMap* windowMap; in the Window::createWindow function. Otherwise the insert goes to this newly created local map. Also, change ->insert to .insert as you did not declare windowMap as an pointer in the header.

Multiple definition errors in Arduino library

I am trying to compile the lightRobot.ino Arduino sketch from https://github.com/janisHD/LightRobot in Arduino 1.0.5, but I'm getting multiple definition errors for the functions in the lightRobot library.
I'm using OS X 10.8.5 but had the same problem in Windows 8.
Here are example .h and .cpp files:
BlueToothEvent.h
/*! \file BlueToothEvent.h checks periodically if new data over BT has been received.
*/
#include <Arduino.h>
#include <OrangutanLCD.h>
#include "TimeEvent.h"
#ifndef BLUETOOTH_EVENT_H
#define BLUETOOTH_EVENT_H
#define DATA_WORD_LENGTH 4
/*! \class BlueToothEvent
retrieves and stores the received BT data. The data should come over the serialport, it must be started in "setup".
The struct DataPacket publishes the parsed data for the Statemanager.
*/
class BlueToothEvent : public TimeEvent
{
public:
struct DataPacket {
char speed;
char direction;
int color[4]; // [3]==blue [2]==green [1]==red [0]==brightness
int mode[2]; // [1]==color mode (0000->remote, 0001->blink, 0010->random, 0011->random&blink) [0]==drive mode (0000->remote, 0001->random)
};
BlueToothEvent();
~BlueToothEvent(){};
/*! Callback which is executed periodically*/
virtual void onTimeEvent();
/*! Returns an internal state.*/
virtual unsigned char getInternalState();
/*! Sets an internal state.*/
virtual void setInternalState(unsigned char state, bool update=false);
/*! Executes a more complex (and time consuming) action.*/
virtual void executeAction();
/*! To get the received data in the DataPacket struct
\return The most recent data received via Serial connection
*/
DataPacket getDataPacket();
bool m_new_data_present;
private:
/*! Processes the array with a 4 byte data word and saves the information in the DataPacket field.
\param data the array (must have the length of 4 bytes)
*/
void processData(unsigned char* data);
private:
enum Data{
velocity=0,//desired velocity
direction,//direction to drive
color,//desired color of the LEDs
mode,//the different modes: remote, random, blink
};
unsigned char m_data[DATA_WORD_LENGTH];
struct DataPacket m_data_packet;
};
#endif
BlueToothEvent.cpp
#include "BlueToothEvent.h"
BlueToothEvent::BlueToothEvent():
TimeEvent(),
m_new_data_present(false)
{
//init data array
m_data[velocity] = 0;
m_data[direction] = 0;
m_data[color] = 0;
m_data[mode] = 0;
processData(m_data);
//Serial connection
}
void BlueToothEvent::onTimeEvent()
{
//Code to receive a single data word and store it in m_data field
//Word consists of 4 chars (see the docu for further explanations):
//[0] -> direction to drive [0-254]
//[1] -> velocity to drive [0-254]
//[2] -> desired color for the Light [0-254] in 2 bit packets -> b0[0,3]->Brightnes | [0,3]->Red| [0,3]->Green | [0,3]->Blue
//[3] -> internal mode (see responsible class)[0-254]
if(Serial.available() >= DATA_WORD_LENGTH)
{//minimum number of bytes must be available in the buffer
while(Serial.available() > DATA_WORD_LENGTH)
Serial.read();//clear buffer except the last 4 bits
m_data[velocity] = (char)Serial.read();
m_data[direction] = (char)Serial.read();
m_data[color] = (char)Serial.read();
m_data[mode] = (char)Serial.read();
processData(m_data);
m_new_data_present = true;
}
}
void BlueToothEvent::processData(unsigned char* data)
{
m_data_packet.speed = data[velocity];
m_data_packet.direction = data[direction];
m_data_packet.color[0] = data[color] & 0b00000011;
m_data_packet.color[1] = (data[color] & 0b00001100)>>2;
m_data_packet.color[2] = (data[color] & 0b00110000)>>4;
m_data_packet.color[3] = (data[color] & 0b11000000)>>6;
m_data_packet.mode[0] = data[mode] & B00001111;
m_data_packet.mode[1] = (data[mode] & B11110000)>>4;
}
BlueToothEvent::DataPacket BlueToothEvent::getDataPacket()
{
m_new_data_present = false;
return m_data_packet;
}
//unsigned char BlueToothEvent::getData(unsigned char field)
//{
// if(field <= mode)
// return m_data[field];
// else
// return 0;
//}
unsigned char BlueToothEvent::getInternalState()
{
return m_data[mode];
}
void BlueToothEvent::setInternalState(unsigned char state, bool update)
{
//nothing to do here!
}
void BlueToothEvent::executeAction()
{
//nothing to do here!
}
I get the following errors on compilation - I've only shown the errors for the listed pair of .h/.cpp files - there are similar ones for every file in the lightRobot library:
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::processData(unsigned char*)':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:43: multiple definition of `BlueToothEvent::processData(unsigned char*)'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:43: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:4: multiple definition of `BlueToothEvent::BlueToothEvent()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:4: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:4: multiple definition of `BlueToothEvent::BlueToothEvent()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:4: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::getDataPacket()':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:56: multiple definition of `BlueToothEvent::getDataPacket()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:56: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::getInternalState()':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:73: multiple definition of `BlueToothEvent::getInternalState()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:73: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::setInternalState(unsigned char, bool)':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:78: multiple definition of `BlueToothEvent::setInternalState(unsigned char, bool)'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:78: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::executeAction()':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:83: multiple definition of `BlueToothEvent::executeAction()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:83: first defined here
lightRobot/BlueToothEvent.cpp.o: In function `BlueToothEvent::onTimeEvent()':
/Users/lemmy/Documents/Arduino/libraries/lightRobot/BlueToothEvent.cpp:18: multiple definition of `BlueToothEvent::onTimeEvent()'
BlueToothEvent.cpp.o:BlueToothEvent.cpp:18: first defined here
It seems that the errors are occurring in the object file, but I'm not sure why, as the header files have guards on them to prevent multiple definitions.
In case anyone else comes across this question later I was having the same problem and it was fixed by deleting the tabs on the library files in my sketch. It seems to include those files there and again when you have #include "lib.h"
The compilation succeeded when I moved the .ino file out of the lightRobot folder.
I know you already found the answer but, for future searchers, I had this same problem. I fixed it by renaming the main folder, for the .ino, and removing any .h or .cpp files from the folder.
Note: I don't know how this happened to me but it may be an issue for someone else.