Reputation: 175
I am trying to implement the NeopixelAnimator class of this library: https://github.com/Makuna/NeoPixelBus.
I created an animator class that contains an instance of the library's NeoPixelAnimator class. To run animations I have to call: .StartAnimation(uint16_t indexAnimation, uint16_t duration, UpdateCallback animUpdate)
.
My goal is to make a queue of animations that are being animated after one another. The second animation should start when the first has been completed. Since the library itself does not provide a way to do this I created a vector representing the queue, it contains the Animation to be animated and it's colour.
The problem is that the .StartAnimation()
function expects a UpdateCallback
parameter which is a callback function that is fired whenever the .UpdateAnimations()
function is being called.
The animations will be triggered by switches connected to the Arduino Due that call the .add()
function (not in the example code). For now, I want to test if it works by adding one animation in .init()
.
My plan was to create an array of function pointers that are pointing to those callback functions. The problem is that I can't get the data types to match up.
Help would be greatly appreciated. Also, feedback on how to approach these kinds of problems and to build up the code would be greatly appreciated.
I'm using platformIO with the Arduino library on an Arduino Due board.
defines.h:
//Amount of different animations should correspond to the number of callback functions
#define NUMBER_OF_ANIMATIONS 2
//Animation ID's:
#define WIPE_ANIM 0
//Colour ID's:
#define GREEN 0
animator.h:
#include <arduino.h>
#include <NeoPixelAnimator.h>
#include <NeoPixelBrightnessBus.h>
#include <array>
#include <vector>
class Animator
{
public:
private:
//NeoPixel animation time management object
NeoPixelAnimator animations;
//Neopixel strip communication object
NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip1; //NeoPixel strip 1 object
//Array of AnimUpdateCallback function pointers to the animation callback functions
AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS])(const AnimationParam ¶m);
//Vector of arrays to store animations to be animated (animId, colorId)
std::vector<std::array<uint8_t, 2>> _animationQueue;
public:
Animator();
void init();
void run();
void add(uint8_t animId, uint8_t colorId);
private:
void updateQueue();
animator.cpp:
#include <Animator.h>
//Default constructor
Animator::Animator() : strip1(NUMBER_OF_LEDS_1, LED_PIN_1),
_callbackPt{wipeColorAnim, wipeColorAnim}
{
}
//Inititalisation function, inits strips, sets brightness for strips, sets inital color with wipeColorAnim()
void Animator::init()
{
strip1.Begin();
strip1.SetBrightness(100);
add(WIPE_ANIM, GREEN); //wipeColor strip1 with Green
}
//Add aniamtion to the queue
void Animator::add(uint8_t animId, uint8_t colorId)
{
//Create array storing the animation ID and its color
std::array<uint8_t, 2> animation{animId, colorId};
//Add the animation to the end of the queue
_animationQueue.push_back(animation);
}
//Loop this function to update animations
void Animator::run()
{
//if there is an animation running
if (animations.IsAnimating())
{
animations.UpdateAnimations(); //update running animation
strip1.Show();
}
else
{
updateQueue();
}
}
//Checks whether there is an animation in the queue if so it's started
void Animator::updateQueue()
{
//if there is an animation waiting in the queue
if (!_animationQueue.empty())
{
//Start next animation in queue on channel 0 with specified time and animUpdate callback function (channel, time, callback)
animations.StartAnimation(0, _animationQueue[0][1], _callbackPt[_animationQueue[0][0]]);
//Remove the just started animation from the queue
_animationQueue.erase(_animationQueue.begin());
}
}
main.cpp:
Animator animator;
void setup()
{
animator.init();
}
void loop()
{
//Put new animation requests in queue and update animations
animator.run();
}
platformio.ini:
[env:due]
lib_ldf_mode = chain+
platform = atmelsam
board = due
framework = arduino
monitor_speed = 115200
monitor_port = COM16
lib_deps =
NeoPixelBus
calling animations.StartAnimation(0, _animationQueue[0][1], _callbackPt[_animationQueue[0][0]]);
doesn't give any compilation errors. Trying to instatntiate the callback functions in the function pointer array does though:
a value of type "AnimUpdateCallback (Animator::*)(const AnimationParam ¶m)
" cannot be used to initialize an entity of type "AnimUpdateCallback (*)(const AnimationParam ¶m)
"
My main confusion is:
what the datatype of the callback functions in my class should be (void
or AnimUpdateCallback
)?
why (const AnimationParam ¶m)
has to be added at the end of (*_callbackPt[NUMBER_OF_ANIMATIONS])
, otherwise I get an error that the data types are not matching as well
Upvotes: 0
Views: 208
Reputation: 17073
a value of type "
AnimUpdateCallback (Animator::*)(const AnimationParam ¶m)
" cannot be used to initialize an entity of type "AnimUpdateCallback (*)(const AnimationParam ¶m)
"
This is true. I don't see the code that causes this error, but presumably you are using a non-static member function of Animator
to initialize an element of your array. (Is that what wipeColorAnim
is? A member function? It's not declared within the question.) Since non-static member functions have a hidden parameter (the this
pointer), they are not signature-compatible with non-member functions. If your member function does not need the this
parameter, declare it static
. (If it does require this
, you have a bigger design problem.)
what the datatype of the callback functions in my class should be (
void
orAnimUpdateCallback
)?
Well, void
is not a function type, so I suppose that is out, leaving you with only one choice... (Unless you meant the return type, rather than the data type? The data type would be the function signature, encompassing both the return type and the types of the parameters.)
why
(const AnimationParam ¶m)
has to be added at the end of(*_callbackPt[NUMBER_OF_ANIMATIONS])
, otherwise I get an error that the data types are not matching as well
I suppose a good way to explain this is to look at what the declarations would declare.
AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS])(const AnimationParam ¶m);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- an array of pointers
The innermost piece is an array of pointers to something. To see the type they point to, condense the innermost piece to just an asterisk:
AnimUpdateCallback (*)(const AnimationParam ¶m);
This is a pointer to a function that takes a single parameter (of type const AnimationParam &
) and returns a value whose type is AnimUpdateCallback
. The "param
" identifier is superfluous here.
Without the part on the end, you have simply
AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS]);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- an array of pointers
This time the pointed-to type is easier to see: AnimUpdateCallback
.
So in either case, you have a way to get a value of the type AnimUpdateCallback
. In the former case, you would access an element of your array, invoke the function it points to, and look at the returned value, for example: _callbackPt[0](param)
. In the latter case, you would just access an element of your array, for example: _callbackPt[0]
. The correct form depends upon how you intend to use this array. (The declaration of NeoPixelAnimator
is not directly in the question, so I don't know what it expects as parameters to NeoPixelAnimator::StartAnimation()
.)
Upvotes: 1