Usually given answers on Stack Overflow are enough to deal with problems which I come across, but now I'm running into sth. special...
I'm trying to build a custom and modular solution for driving a stepper motor using a shift register. For this I tried to implement a "RegisterWrite" function (just like Arduinos "digitalWrite") to change the states of the registers output pins.
Now it seems that I cannot use values of the member variables of my "register" object in its member functions. I don't know where I screwed up...
I'm trying to compress my codes as much as possible:
main.cpp
#include<Register.h>
Register register1(8, 16, 2, 0);
void motor(){ //this function is called via a html request handle
uint8_t value[8] = {1,0,1,0,1,0,1,0}; //setting values for register outputs
register1.setOutputValues(value); //writing values to member variable
register1.setOutput(); //actually setting the output of the register
}
void setup(){
something something
}
void main(){
something something
}
Register.h
#ifndef REGISTER_H
#define REGISTER_H
#include<Arduino.h>
class Register{
private:
int _NumberOutputs;
public:
uint8_t _OutputValues[];
uint8_t _DataPin;
uint8_t _ClockPin;
uint8_t _ShiftPin;
Register(int NOutputs, uint8_t Data, uint8_t Clock, uint8_t Shift);
Register();
void setOutputValues(uint8_t OValues[]);
void setOutput();
};
#endif
Register.cpp
#include<Register.h>
#include<Arduino.h>
Register::Register(int NOutputs, uint8_t Data, uint8_t Clock, uint8_t Shift){
_NumberOutputs = NOutputs;
_DataPin = Data;
_ClockPin = Clock;
_ShiftPin = Shift;
}
Register::Register(){
}
void Register::setOutputValues(uint8_t OValues[]){
for (int i = 0; i < _NumberOutputs; i++){
_OutputValues[i] = OValues[i];
}
}
void Register::setOutput(){
digitalWrite(_DataPin, 0);
....
....
}
This is, where the value of _DataPin ends up being "1" instead of "16" what screws up the code.
Now in addition, if I go back to main.cpp... Before I call register1.setOutput() the actual value of _DataPin is "16", and then again after calling register1.setOutput(). It seems that only inside of register1.setOutput() _DataPin equals 1. I Have no clue.
Related
I came across a class which sole purpose was to create blinking leds. He used the class for 2 objects which had a different blinking interval. I started thinking in how I could use constants but nothing came to me.
Is it possible to use a const int in combination with the constructor to use different constants for objects?
I am aware that a const int is to be initialized at the same place where it is declared, so I'd guess that the answer is 'no'
If not, are there workarounds to achieve the same thing? That is using different constants (so less memory usage) for different objects of the same type.
The used platform in question is the arduino IDE and an atmega328P.
May it perhaps be that the compiler recognizes that the variables are actually used as constants and treat them as such?
.h
class BlinkingLed
{
private:
int blPin;
short blinkInterval; // <-- the contant
bool blinking;
bool ledOn;
long lastTime;
public:
BlinkingLed(int, int);
void setBlinkInterval(int); // never used, should not exist
int getBlinkInterval(); // never used, should not exist
void setLedOn(bool);
bool getLedOn();
void attachPin();
void heartBeat();
};
.cpp
BlinkingLed::BlinkingLed(int aPin, int aBlinkInterval) // constructor
{
blPin = aPin;
blinking = false;
ledOn = false;
blinkInterval = aBlinkInterval; // <-- the contant
}
The objects are made with this line. The aki class needs 2 BlinkingLed objects.
AKI aki(new BlinkingLed(23,333), new BlinkingLed(22,667), 24); // Red blinks 90/minute, green 45/minute
This is the constructor of aki:
AKI::AKI(BlinkingLed *aRedLight, BlinkingLed *aGreenLight, int aBellPin)
{
redLight = aRedLight;
greenLight = aGreenLight;
bellPin = aBellPin;
}
The 333 and 367 are stored in variables and I want these to become constants to preserve memory space. How do I do that?
To summarize the discussion, and correct some of your wrong assumptions:
class BlinkingLed {
private:
const byte blPin; // This should definitely be const
const unsigned short blinkInterval; // <-- the desired constant (why?)
bool blinking;
bool ledOn;
unsigned long lastTime;
public:
BlinkingLed(byte pin, unsigned short interval)
: blPin(pin), blinkInterval(interval) {}
// void setBlinkInterval(int); // impossible for a const Interval
void init() {pinMode(blPin, OUTPUT);} // should not be done in a c'tor
void run(); // to be called as often as possible for a smooth heartbeat
unsigned short getBlinkInterval() {return blinkInterval;} // why not
void setLed(bool); // stops blinking
bool isLedOn();
void heartBeat(); // start blinking
};
BTW: data type int usually blames you for not thinking about it. :)
I am using a third party library (mavlink) that defines a number of structs that are all tagged with __attribute__((packed)) so they can be efficiently be transmitted across a serial connection (it is written in C and I am using it in a C++ application). When I receive and reconstruct them I would like to add a time stamp field to them. I think the simplest way is to create a new struct that inherits the existing struct. i.e. in the mavlink library this struct is defined:
MAVPACKED(
typedef struct __mavlink_heartbeat_t {
uint32_t custom_mode;
uint8_t type;
uint8_t autopilot;
uint8_t base_mode;
uint8_t system_status;
uint8_t mavlink_version;
}) mavlink_heartbeat_t;
where MAVPACKED is a macro that applies __attribute__((packed)). sizeof(mavlink_heartbeat_t) returns 9. If I define
struct new_heartbeat_t : mavlink_heartbeat_t
{
uint64_t timestamp;
};
sizeof(new_heartbeat_t) returns 24, so it looks like 7 padding bytes are added (I would assume to end of mavlink_heartbeat_t so that timestamp start at byte 16.)
Are there any gotchas or things to be aware of when doing this or is there a better way?
Inheritance is a is a kind of relationship.
Is the local representation of a heartbeat really a kind of wire message? I doubt it.
But it might reasonably contain one.
I would encapsulate it something like this:
#include <cstdint>
#include <cstddef>
typedef struct __attribute__((packed)) __mavlink_heartbeat_t {
uint32_t custom_mode;
uint8_t type;
uint8_t autopilot;
uint8_t base_mode;
uint8_t system_status;
uint8_t mavlink_version;
} mavlink_heartbeat_t;
extern std::uint64_t now();
void sync_fetch_data(mavlink_heartbeat_t&);
void foo(uint8_t);
struct local_heartbeat
{
mavlink_heartbeat_t const& get_io_buffer() const {
return io_buffer_;
}
mavlink_heartbeat_t& prepare_receive() {
request_timestamp_ = now();
return io_buffer_;
}
void complete_receive() {
response_timestamp_ = now();
}
std::uint64_t get_response_timestamp() const {
return response_timestamp_;
}
private:
// stuff in here might have suspect alignment
mavlink_heartbeat_t io_buffer_;
// but these will be aligned for optimal performance
std::uint64_t request_timestamp_;
std::uint64_t response_timestamp_;
};
int main()
{
// create my local representation
local_heartbeat hb;
// prepare it to receive data
auto& buffer = hb.prepare_receive();
// somehow populate the buffer
sync_fetch_data(buffer); // could be async, etc
// notify the object that reception is complete
hb.complete_receive();
// now use the local representation
foo(hb.get_io_buffer().system_status);
}
Below are my codes...
main.cpp
/* header files are included here */
PCI_card card;
int main(void)
{
card.init_card(0);
return 0;
}
pci_card.h
#ifndef __PCI_CARD_H
#define __PCI_CARD_H
/* header files are included here */
typedef struct {
int32_t card_index;
int32_t user_counter;
} card_dev_t;
class PCI_card {
public:
PCI_card() : dev_descriptor(-1) { enlarge_vector(); }
int32_t init_card(int32_t card_num);
private:
int32_t dev_descriptor;
public:
static int32_t enlarge_vector();
private:
static int32_t card_amount;
static std::vector<card_dev_t> cards;
};
#endif
pci_card.cpp
/* header files are included here */
int32_t PCI_card::card_amount = -1;
std::vector<card_dev_t> PCI_card::cards;
int32_t PCI_card::init_card(int32_t card_num)
{
if (card_num >= card_amount || card_num < 0)
return -1;
card_dev_t new_card = {
.card_index = card_num,
.user_counter = 1
};
cards[card_num] = new_card;
dev_descriptor = card_num;
return 0;
}
int32_t PCI_card::enlarge_vector()
{
card_amount = 10;
card_dev_t null_card = {
.card_index = -1,
.user_counter = -1
};
cards.resize(card_amount, null_card);
return card_amount;
}
In main.cpp, card is defined as a global variable, and of course, it should be initialized before invoking main() function, and this can be seen clearly via gdb.
When initializing card, constructor of class PCI_card is invoked, the vector cards in this class is resized according to card_amount member variable. From the gdb, this vector does be initialized properly, it contains 10 elements.
Weird things happened before invoking main() function, the vector is reset. In gdb, the size of vector rolled back to 0, and of course, subsequent operations, such as subscript this vector, cause segment fault error.
I don't know what happen here.... it is too ridiculous...
It looks like you have hit a static initialization order fiasco. It is possible that PCI_card card; initialization will happen before std::vector<card_dev_t> PCI_card::cards. If that happen (and standard allows it) then PCI_card::enlarge_vector() will call resize (here enter UB) on not yet initialized vector. After its execution normal static initialization of PCI_card::cards will get executed - initializing vector to empty one. And this is why you see this behaviour:
In gdb, the size of vector rolled back to 0,
This is Undefined Behaviour so anything that you see in gdb is possible.
The solution is to either make cards non static, or use a static function with static field which will return it:
std::vector<card_dev_t>& getCards() {
static std::vector<card_dev_t> cards;
return cards;
}
this will ensure that cards will get initialized on first use of getCards.
First of all take a look at my struct
typedef struct {
int treeDepth;
unsigned __int8 dmv[19];
unsigned __int8 dv[19];
unsigned __int8 ih;
bool flagLeft = true ;
bool flagRight = true;
}problem_t;
I have a function which works with this struct,
void PMSprune(problem_t &problem)
{
/*
--blocks of code!
--modify properties of "problem"
*/
PMSprune(problem);// I want to call it with problem.treeDepth++, but I
//don't want my original struct to be modified
}
But this function is recursive, and I want to call this function with one of the properties of the struct being modified, does anyone have any idea how can I do this?
UPDATE:
my project is real time, the time is really important for me, and this function is being called inside a loop about a million times
Split the function:
void PMSpruneRec(problem_t &problem, int treeDepth)
{
/*
--blocks of code!
--modify properties of "problem"
*/
PMSpruneRec(problem, treeDepth + 1);
}
void PMSprune(problem_t &problem)
{
PMSpruneRec(problem, problem.treeDepth);
}
Of course, you'll still need some termination condition.
Just copy it before the change:
void PMSprune(problem_t &problem)
{
/*
--blocks of code!
*/
problem_t new_problem = problem
/*
--modify properties of "new_problem"
*/
PMSprune(new_problem);
}
If a treeDepth by some design should be a problem_t member, you could simply reset its value after each recursive call:
void PMSprune(problem_t &problem)
{
/*
--blocks of code!
--modify properties of "problem"
*/
++problem.treeDepth;
PMSprune(problem);// I want to call it with problem.treeDepth++, but I
//don't want my original struct to be modified
--problem.treeDepth;
}
Otherwise Sebastian's approach is better. It is more clear and structured.
Have you considered turning it into a loop? It could even help performance-wise, since it's a nested call inside a tight loop.
void PMSprune(problem_t &problem)
{
for(int treeDepth = problem.treeDepth; someStoppingCondition; ++treeDepth)
{
/*
--blocks of code!
--modify properties of "problem"
*/
}
}
Obviously depends on what code you have there, just wanted to remind you of this possibility.
I have created a class in C++. Each object corresponds with an I/O pin on a microcontroller. I can create an array of the objects and then set each pin to an output with a for loop. I would like to be able to set multiple pins to an output at the exact same time. This can be done with the hardware.
I am trying to create a method that works on an array of objects. You would use it like this:
Pin myPins[] = {0,1,2};
myPins.setOuput();
Basically I want to create a method that works on an array of objects. Is it possible to create a setOuput method like this? If yes, how? Thanks.
Update 1
New non-member method
void setOutput(Pin pins[], int size) {
volatile uint8_t* _DDR = pins[0].getDDR();
uint8_t _offset = 0;
for (int i = 0; i < size; i++) {
_offset |= pins[i].getOffset();
}
DDR_HIGH;
}
I am using the _ in the names so that my existing macro works. Not great but less code.
Nope, you cannot add a method to a classic array the way you intend to. However, you could create a class that inherits from, say, a std::vector<Pin>, and add methods to it, like this:
class Pins : public std::vector<Pin>
{
public:
void setOutput() { /* your code here */ }
};
That way, using C++11's uniform initialization, you could use a similar syntax:
Pins myPins = {0, 1, 2};
myPins.setOutput();
Edit: as per the comments, subclass a STL container is a quick and dirty solution and not the best idea. You could, however, create your own wrapper class very simply:
class Pins
{
std::vector<Pin> mPins;
public:
Pins (std::initializer_list<Pin> pins) : mPins(pins)
{ }
void setOutput()
{
cout << "Pins in this pinset:" << endl;
for (Pin & p : mPins)
{
cout << "\t" << p << endl;
}
}
};
That works exactly the same:
Pins myPins = {0, 1, 2};
myPins.setOutput();
Most probably your setOutput member function is reading some possibly multi byte value, changing a bit depending on the pin, and writing it back.
C++ arrays can't have member functions.
To achieve a similar effect, you should split the work your original setOutput is doing:
Read some hardware config
Do the bit twiddling
Apply the changes
Then you can let multiple pins do their bit twiddling before applying the final output.
Example:
Pin::Config cfg = Pin::read_config();
// the following could also happen in a loop over an array.
cfg = pin1.enableOutput(cfg);
cfg = pin4.enableOutput(cfg);
// or pass by reference and mutate, if you
// want a less functional style
// e.g. pinN.enableOutput(cfg)!
Pin::write_config(cfg);
This way you still have good encapsulation, but better control. Then you can write a free function to operate on arrays, vectors or whatever collection of pins, if needed:
template<typename It>
void setOutputPins(It start, It end) {
Pin::Config cfg = Pin::read_config();
for (; start != end; ++start) {
cfg = (*start).enableOutput(cfg);
}
Pin::write_config(cfg);
};
Using it with C arrays:
Pin array[5]; // or a pointer for dynamic arrays
// ...
setOutputPins(array, array + size);
Don't make everything OO. It'll make your life harder.
[...] a function that returns the offset value for each Pin [...]. Then I bitwise or them all together.
So you don't even need that reading step. And since you bitwise or them, you could even do something like this:
Pin::write_config(pin1.output_mask() | pin4.output_mask());
You can make the function generic, too: Or pass a member function pointer:
template<typename It>
void setPins(It start, It end, Pin::Config (Pin::*fn)(void)) {
Pin::Config cfg = 0; // identity for bitwise or
for (; start != end; ++start) {
cfg |= ((*start).*fn)();
}
Pin::write_config(cfg);
};
And the pass a pointer to the member function you want to invoke:
setPins(array, array + size, &Pin::asInput);
Example here.