i am trying to write a class for an arduino projekt, i am using the information in http://paulmurraycbr.github.io/ArduinoTheOOWay.html as a guide.
I want to set up a lighstrip for further use and constantly keep getting the errormessage: error: use of 'this' in a constant expression.
My code looks like this:
#include <FastLED.h>
#define LED_STRIP_PIN 2
#define LED_STRIP_NUM_LEDS 10
//const unsigned char LED_STRIP_PIN = 2;
//const int LED_STRIP_NUM_LEDS = 10;
CRGB leds[LED_STRIP_NUM_LEDS];
class LedStrip {
unsigned char pin;
public:
LedStrip(unsigned char attachTo) :
pin(attachTo)
{
};
void setup() {
FastLED.addLeds<NEOPIXEL, pin>(leds, 10);
};
};
//LedStrip ledstrip(LED_STRIP_PIN, LED_STRIP_NUM_LEDS);
LedStrip ledstrip(LED_STRIP_PIN);
void setup() {
}
void loop() {
}
I have tried reading up on what might cause this error, but frankly i do not understand any of it. As far as i have understood it seems like i cannot use a const there (which i am not, i think) since it might be modified during code execution.
the complete error looks like thissketch_feb03b.ino: In member function 'void LedStrip::setup()':
sketch_feb03b:20:33: error: use of 'this' in a constant expression
FastLED.addLeds<NEOPIXEL, pin>(leds, 10);
^~~
Your issue is that pin is not a compile-time constant, and all template arguments must be compile-time constants.
There might be other options, but the (probably) easiest one is passing pin as template argument itself:
template<int pin> // make sure type of pin is correct, I don't know what addLeds expect
class LedStrip {
public:
LedStrip() //not really needed now
{
};
void setup() {
FastLED.addLeds<NEOPIXEL, pin>(leds, 10);
};
};
Usage:
//if LED_STRIP_PIN is a compile-time constant, i.e. a macro or a const(expr) value
LedStrip<LED_STRIP_PIN> ledstrip;
//if LED_STRIP_PIN is obtained at runtime, you cannot it use it at all.
LedStrip<7> ledstrip;
#include <FastLED.h>
const int NUM_LEDS01 = 49; //Missing one LED from string of 50 LEDS
const int DATA_PIN01 = 2; //White wire to GND, Red wire to 5V, Black Wire is data.
CRGB leds01[NUM_LEDS01]; //First strng of LEDS
const int NUM_LEDS02 = 50;
const int DATA_PIN02 = 3; //White wire to GND, Red wire to 5V, Black Wire is data.
CRGB leds02[NUM_LEDS02]; //Second String of LEDS
//#include "Lstring.h"
template<int dataPin>
class Lstring{
private:
int nleds = 0; //initialise to some number
CRGB *ledS;
public:
Lstring(){}
Lstring(CRGB *lds, int nleds){
this->nleds = nleds;
ledS = lds;
}
void ledOn(int ledNum){
ledS[ledNum] = CRGB::Blue;
FastLED.show();
}
void ledOff(int ledNum){
ledS[ledNum] = CRGB::Black;
FastLED.show();
}
void initialise(){
FastLED.addLeds<WS2811,dataPin>(ledS,nleds);
}
};
//---------------------------------
Lstring<DATA_PIN01> lstring01(leds01, NUM_LEDS01);
Lstring<DATA_PIN02> lstring02(leds02, NUM_LEDS02);
void setup() {
lstring01.initialise();
lstring02.initialise();
}
void loop() {
lstring01.ledOn(8);
delay(200);
lstring01.ledOff(8);
delay(200);
lstring02.ledOn(8);
delay(200);
lstring02.ledOff(8);
delay(200);
}
Related
I have the constructor
class MyFrame : public wxFrame { // defines the options on the top bar of the screen here we have:
public:
MyFrame();
private:
void OnHello(wxCommandEvent& event); // hello option
void OnExit(wxCommandEvent& event); // exit option
void OnAbout(wxCommandEvent& event); // about option
void OnHelp(wxCommandEvent& event); // event option
// void OnCourseTextBoxClicked(wxCommandEvent &event);
void OnOneHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnTwoHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnThreeHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnFourHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnFiveHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnDisplayCgpaButtonClicked(wxCommandEvent &event);
// Common Courses equating their credit load
/* 100 LEVEL FIRST SEMESTER */
int CHM111 = 3;
int CHM113 = 3;
int MTH111 = 3;
int MTH112 = 3;
int PHY111 = 3;
int PHY113 = 3;
int GST111 = 2;
int GST112 = 2;
/* 100 LEVEL SECOND SEMESTER */
int CHM122 = 3;
int CHM124 = 3;
int MTH123 = 3;
int MTH125 = 3;
int PHY109 = 2;
int PHY124 = 4;
int GST121 = 2;
int GST122 = 2;
int GST123 = 2;
int LEVEL_TOTAL_100 = 47;
}
And somewhere else in the code base, some text is entered into a text box. The text box is supposed to contain one of the variables defined in the constructor which evaluate to their respective integers.
When the text box's content is evaluated e.g.:
course_one_text_box->GetValue();
evaluates
CHM111
I want to grab the constructor integer value for the CHM111 which is 3. I want to employ this value in a mathematical formula.
How do I do this?
Is there a particular syntax that grabs the constructor recorded version of the variable instead?
Thanks.
wxTextCtrl works with wxString, not with numbers.
But it's really easy to get a number from a wxString: Use wxString::ToCLong. For example:
long value;
mystring = mytextctrl->GetValue();
if ( ! mystring.ToCLong(&value) )
some message here, conversion failed (not a number)
//Your comparisons:
if ( value == (long)CHM111 )
....
So, if the user enters 3 the 'if' is true because CMH111 is initialized as 3
Notice the (long) cast from an int to avoid compiler warning. Why not use long instead of int for the type of CHMxxx?
What is not possible in C++ is to compare against the name of a variable.
#Alvindera97,
Is your program should restrict the user to enter only those constants? Then you have a wrong tool for the job!
Look at the wxComboBox/wxChoice. This way the user will have the only choice to select from the list and you won't need to keep those constants definitions in the class.
Hope this helps!
Part of my problem in finding a solution here is likely that I don't know the correct terms for what it is I am asking. For that, I beg forgiveness in advance.
For a microcontroller, I have a list of pins I wish to initiate at the same time. Each has it's own ISR, and calls the same member of a class for each instance but with a pin number as an argument.
I am trying to attach each pin in the array to its corresponding ISR but I would like to choose which ISR by the pin's index. This is Mailer Codeā¢ and likely does not compile but I believe it's enough to get the idea:
#define PIN1 4
#define PIN2 9
#define PIN3 10
#define PIN4 8
#define PIN5 12
PinAct *pPinact; // Pointer to Counter class
static ICACHE_RAM_ATTR void HandleInterruptsStatic1(void) {
pPinact->handleInterrupts(1);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic2(void) {
pPinact->handleInterrupts(2);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic3(void) {
pPinact->handleInterrupts(3);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic4(void) {
pPinact->handleInterrupts(4);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic5(void) {
pPinact->handleInterrupts(5);
}
class PinAct {
public:
PinAct() {};
void handleInterrupts(int);
}
void PinAct::PinAct() {
int actPins[] = {PIN1, PIN2, PIN3, PIN4, PIN5};
for (int i = 0; i <= sizeof(actPins); i++) {
pinMode(actPin[i], INPUT)
attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING);
}
}
void PinAct::handleInterrupts(int pin) { // Bubble Interrupt handler
// Do something with pin
}
The goal is to actually make the attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING); work, choosing which ISR by virtue of the index i.
I need to make other decisions about whether or not to assign the ISR, so concatenating the ISR name to be assigned is desirable.
attachInterrupt(/* ... */, HandleInterruptsStatic + i, /* ... */);
// ^^^^^
In order to select the function you want to call at runtime depending on some integer index i you can use an array of function pointers:
typedef void (*FunctionPointer_t)(void);
FunctionPointer_t functions[] = {
HandleInterruptsStatic1,
HandleInterruptsStatic2,
// ...
};
// to use:
functions[i]();
Context
The context of the problem is that I am currently writing a small library for use with the Arduino in order to act as a game controller. The problem I am encountering has more to do with C++ than anything Arduino specific however.
I've included the libraries' header and source code below, followed by the Arduino code. I've truncated it where possible.
Problem
In short, only the last switch / action I define actually gets properly handles.
These actions get defined in the Arduino setup function. For example:
controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
means that pin 10 gets mapped to button 0. When pin 10 is switched closed this is treated as the button being pressed. This works fine for a single action but when I start adding more only the last action actually works. So in the following example only pin 9 is recognized:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
This goes for any arbitrary number of actions:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Doesn't work
controller.addSwitchContinuous(8, 2); // <-- Doesn't work
controller.addSwitchContinuous(7, 3); // <-- Works
Potential causes
I am fairly novice with C++ so this I suspect I'm doing something wrong with pointers. More specifically, something seems wrong with how the Joystick_ instance gets passed around.
I have been fiddling with the constructor and trying to use references instead of pointers but I couldn't get it to work properly.
I can confirm the iteration in JFSF::loop does iterate over all actions, if I modify it with:
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
_joystick->setButton(n, PRESSED); // Debug: Set button pressed, regardless of switch.
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
then buttons 0 through n get pressed as expected. It is possible that loop() isn't properly being called, but I would expect it to fail for the N = 1 case as well in that case. Furthermore the fact the last action always succeeds would suggest the iteration is ok.
Full code
// JFSF.h
#ifndef JFSF_h
#define JFSF_h
// ... include for Arduino.h and Joystick.h; bunch of defines
namespace JFSF_PRIV
{
class AbstractAction
{
public:
virtual void loop();
};
/* A Switch that essentially acts as a push button. */
class SwitchContinuousAction : public AbstractAction
{
public:
SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex);
void loop();
private:
Joystick_ *_joystick;
int _pin;
int _btnIndex;
};
} // namespace JFSF_PRIV
class JFSF
{
public:
JFSF(Joystick_ *joystick, bool doSendState); // doSendState should be true if Joystick_ does not auto send state.
void loop();
void addSwitchContinuous(int inputPin, int btnIndex);
private:
Joystick_ *_joystick;
JFSF_PRIV::AbstractAction *_actions[MAX_ACTIONS];
int _nextActionIndex;
bool _doSendState;
};
#endif
Source file (trimmed):
// JFSF.cpp
#include "Arduino.h"
#include "Joystick.h"
#include "JFSF.h"
#define PRESSED 1
#define RELEASED 0
// Private classes
namespace JFSF_PRIV
{
SwitchContinuousAction::SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex)
{
_joystick = joystick;
_pin = pin;
_btnIndex = btnIndex;
pinMode(_pin, INPUT_PULLUP);
}
void SwitchContinuousAction::loop()
{
int _state = digitalRead(_pin) == LOW ? PRESSED : RELEASED;
_joystick->setButton(_btnIndex, _state);
}
} // namespace JFSF_PRIV
JFSF::JFSF(Joystick_ *joystick, bool doSendState)
{
_joystick = joystick;
_nextActionIndex = 0;
_doSendState = doSendState;
}
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
For completeness sake, this is the code for the Arduino, but it is pretty much just declarations:
#include <JFSF.h>
// ... A bunch of const declarations used below. These are pretty self explanatory.
// See: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api
Joystick_ joystick(HID_REPORT_ID,
JOYSTICK_TYPE_JOYSTICK, // _JOYSTICK, _GAMEPAD or _MULTI_AXIS
BTN_COUNT, HAT_SWITCH_COUNT,
INCLUDE_X_AXIS, INCLUDE_Y_AXIS, INCLUDE_Z_AXIS,
INCLUDE_RX_AXIS, INCLUDE_RY_AXIS, INCLUDE_RZ_AXIS,
INCLUDE_RUDDER, INCLUDE_THROTTLE,
INCLUDE_ACCELERATOR, INCLUDE_BRAKE, INCLUDE_STEERING);
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
}
void loop() {
controller.loop();
}
References
ArduinoJoystickLibrary (Source for Joystick_) can be found here: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api
I dont really understand your code. Please read How to create a Minimal, Complete and Verifiable example. Anyhow, the following is certainly wrong and likely the cause of your problem:
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
Lets rewrite it a bit for clarity:
void foo(){
T bar;
container[index] = &bar;
}
What happens here is that bar gets destroyed when it goes out of scope, hence the pointer you put into the container, points to garbage. Presumably somewhere else in your code you are dereferencing those pointers, which is undefined behaviour (aka anything can happen).
Long story short: It is a common pattern among c++ beginners to overuse pointers. Most likely you should make container a container of objects rather than pointers and make use of automatic memory managment instead of trying to fight it.
Thanks to #user463035818 and #drescherjm for identifiying the actual problem.
So in the end I fixed it by simply moving the Action object creation up to the Arduino code (where it's essentially global) and passing references to those objects to the controller.
In code this translates to:
JFSF.cpp
void JFSF::addAction(JFSF_PRIV::AbstractAction *action){
_actions[_nextActionIndex++] = action;
}
Arduino code (ino)
// See code in original post
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
JFSF_PRIV::SwitchContinuousAction btnOne(&joystick, 10, 0);
JFSF_PRIV::SwitchContinuousAction btnTwo(&joystick, 9, 1);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
// controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
// controller.addSwitchContinuous(9, 1); // Pin 9 ; btn index 1
controller.addAction(&btnOne);
controller.addAction(&btnTwo);
}
// loop() is unchanged
I'm creating this library for the ESP8266-Arduino that makes use of the TimeLib.h library.
In my header I have:
WiFiUDP *_UdpNTP = NULL;
void setupTime();
time_t getNtpTime();
void sendNTPpacket(WiFiUDP *u);
And these are my functions:
void Konnec::setupTime() {
setSyncProvider(getNtpTime);
setSyncInterval(NTP_POL_TIME);
}
time_t Konnec::getNtpTime() {
//WiFiUDP udp;
//udp.begin(localPort);
_UdpNTP = new WiFiUDP();
_UdpNTP->begin(localPort);
while (_UdpNTP->parsePacket() > 0); // discard any previously received packets
for (int i = 0; i < 5; i++) { // 5 retries.
sendNTPpacket(_UdpNTP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1000) {
if (_UdpNTP->parsePacket()) {
Serial.println("");
Serial.println("Receive NTP Response");
_UdpNTP->read(packetBuffer, NTP_PACKET_SIZE);
// Extract seconds portion.
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
unsigned long secSince1900 = highWord << 16 | lowWord;
_UdpNTP->flush();
return secSince1900 - 2208988800UL + TIMEZONE * SECS_PER_HOUR;
}
delay(10);
}
}
Serial.println("");
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
void Konnec::sendNTPpacket(WiFiUDP *u) {
// Zeroise the buffer.
memset(packetBuffer, 0, NTP_PACKET_SIZE);
memcpy(packetBuffer, sendBuffer, 16);
if (u->beginPacket(timeServer, 123)) {
u->write(packetBuffer, NTP_PACKET_SIZE);
u->endPacket();
}
}
And this is the error I get:
konnec.cpp: 991:28: error: cannot convert 'Konnec::getNtpTime' from type 'time_t (Konnec::)() {aka long int (Konnec::)()}' to type 'getExternalTime {aka long int (*)()}
setSyncProvider(getNtpTime)
Error compiling libraries
Any knows what would be the solution?
The problem seems to be that Konnec::getNtpTime is a class method, and yet setSyncProvider expects a function. A function and a method are different things remember, as a method also needs to know the specific class instance it is operating on.
Looking through your code though, it looks like getNtpTime doesn't rely on anything specific to your class, so you could declare it as:
static time_t Konnec::getNtpTime();
which will let it be used as a function, as it effectively is at that point.
So I'm writing this little function for some pot pins. The pot sends a value only when its being turned, at rest, it sends nothing. Which is how I want it to function.
It works fine with one pin.
I've gotten it to a point where it half works with multiple pins. So if I call it twice in the loop with two pins, I get back the right values on both those pins. But I loose the functionality of the if statement. Basically I can't figure out the last half of this. Arrays have been suggested I'm just unsure of how to proceed.
Suggestions? Thank you.
byte pots[2] = {A0, A2};
int lastPotVal = 0;
void setup(){
Serial.begin(9600);
}
void loop(){
// get the pin out of the array
rePot(pots[0]);
rePot(pots[1]);
delay(10);
}
void rePot(const int potPin){
// there is probably an issue around here somewhere...
int potThresh = 2;
int potFinal = 0;
int potVal = 0;
// set and map potVal
potVal = (analogRead(potPin));
potVal = map(potVal, 0, 664, 0, 200);
if(abs(potVal - lastPotVal) >= potThresh){
potFinal = (potVal/2);
Serial.println(potFinal);
lastPotVal = potVal;
} // end of if statement
} // end of rePot
This uses a struct to mange a pot and the data associated with it (the pin it's on, the last reading, threshold, etc). Then, the rePot() function is changed to take one of those structs as input, instead of just the pin number.
struct Pot {
byte pin;
int threshold;
int lastReading;
int currentReading;
};
// defining an array of 2 Pots, one with pin A0 and threshold 2, the
// other with pin A2 and threshold 3. Everything else is automatically
// initialized to 0 (i.e. lastReading, currentReading). The order that
// the fields are entered determines which variable they initialize, so
// {A1, 4, 5} would be pin = A1, threshold = 4 and lastReading = 5
struct Pot pots[] = { {A0, 2}, {A2, 3} };
void rePot(struct Pot * pot) {
int reading = map(analogRead(pot->pin), 0, 664, 0, 200);
if(abs(reading - pot->lastReading) >= pot->threshold) {
pot->currentReading = (reading/2);
Serial.println(pot->currentReading);
pot->lastReading = reading;
}
}
void setup(){
Serial.begin(9600);
}
void loop() {
rePot(&pots[0]);
rePot(&pots[1]);
delay(10);
}
A slightly different take on this is to change rePot() into a function that takes the whole array as input, and then just updates the whole thing. Like this:
void readAllThePots(struct Pot * pot, int potCount) {
for(int i = 0; i < potCount; i++) {
int reading = map(analogRead(pot[i].pin), 0, 664, 0, 200);
if(abs(reading - pot[i].lastReading) >= pot[i].threshold) {
pot[i].currentReading = (reading/2);
Serial.println(pot[i].currentReading);
pot[i].lastReading = reading;
}
}
}
void loop() {
readAllThePots(pots, 2);
delay(10);
}