ENUM and array declaration using enum to create an array of objects - arrays

I am writing a wrapper for neopixel library. I am adding a full source code of my program:
I have created my own custom function toggle_led_strip which is using a function from the neopixelbus led strip library.
#include "NeoPixelBus.h"
#include <Adafruit_I2CDevice.h>
#define PixelCount 8 // this example assumes 4 pixels, making it smaller will cause a failure
#define PixelPin 27 // make sure to set this to the correct pin, ignored for Esp8266
#define colorSaturation 250
RgbColor blue(0,0,255);
RgbColor black(0);
NeoPixelBus<NeoGrbFeature, NeoEsp32Rmt0800KbpsMethod> strip(PixelCount, PixelPin);
void toggle_led_strip(RgbColor colour){
strip.SetPixelColor(0, colour);
strip.Show();
delay(100);
strip.SetPixelColor(0, black);
strip.Show();
delay(100);
}
void setup() {
strip.Begin();
// put your setup code here, to run once:
}
void loop() {
toggle_led_strip(blue);
// put your main code here, to run repeatedly:
}
Normally, when I want to create a colour variable, I must create it in such way:
RgbColor blue(0,0,255);
RgbColor black(0);
However, I am learning about different ways of creating colour objects and someone has suggested me to use ENUM and array method as such:
enum COLORS
{
blue,black
};
RgbColor a_color[2] = {
[blue] = {0,0,255},
[black] ={0}
};
From what I understand, the code above will set the first variable of enum (blue) to the {0,0,255} and the second variable of enum (black) to {0} so the result should be exactly the same as if I have used
RgbColor blue(0,0,255);
RgbColor black(0);
is that correct understanding?
Then I try to pass the color to the function as following:
//void toggle_led_strip(RgbColor colour) This is function prototype
toggle_led_strip(blue)
But it does not work when using enum and array method and works perfectly with the first method

Those who are interested in the solution:
void toggle_led_strip(COLORS colour){
strip.SetPixelColor(0, a_color[colour]);
strip.Show();
delay(100);
strip.SetPixelColor(0, a_color[black]);
strip.Show();
delay(100);
}
It turned out to be quite simple once you understand that an ENUM is treated as an array index and nothing else. It works as expected now.

Related

Problem with Arduino using arrays in Structure

With an Arduino Uno I'm having a problem that is probably simple to solve for somebody who knows what they're doing. I'm trying to get this code to print out "-30" but all I get is "0" no matter what value I put in "setpt[x]" in the serial.print line in loop().
Thanks in advance, Don
typedef struct
{
byte seg_num[12];
byte ramp_hrs[12];
int setpt[12];
byte ramp_mins[12];
}record_type;
record_type profile[8];
void setup()
{
Serial.begin(9600);
Serial.println("*** START ***");
}
void loop()
{
profile[0] = (record_type) {(1,2,3),(5,7,9),(-40,-30,-25),(2,4,6)};
Serial.println(profile[0].setpt[2]); // fails with setpt[from 0 to 3]
}
Comma operators are used in your expressions like (1,2,3).
(1,2,3) is equivalent to 3 here.
You should use {} instead of () to initialize each arrays.
profile[0] = (record_type) {{1,2,3},{5,7,9},{-40,-30,-25},{2,4,6}};
Then, correct the index to get -30 instead of -25.
Serial.println(profile[0].setpt[1]);

Arduino error: 'I2C_MODE' was not declared in this scope

I'm making a program where a buzzer activates if the accelerometer is tilted a certain number of degrees. I'm getting an error that says "'I2C_MODE' was not declared in this scope." I'm using a Grove Beginner Kit, so all of the parts are automatically connected to each other. I downloaded Seeed_Arduino_LIS3DHTR library from the following link: https://github.com/Seeed-Studio/Seeed_Arduino_LIS3DHTR and used sample code from the Grove Beginner Kit for Arduino Guide that came with the board, so everything should work properly. I'm getting this error and don't want to move further with the project until I figure out what's causing this error.
#include <LIS3DHTR.h>
//Gravity Acceleration
#include "LIS3DHTR.h"
#ifdef SOFTWAREWIRE
#include <SoftwareWire.h>
SoftwareWire myWire(3, 2);
LIS3DHTR<SoftwareWire> LIS(I2C_MODE); //IIC This is what the error
#define WIRE myWire
#else
#include <Wire.h>
LIS3DHTR<TwoWire> LIS(I2C_MODE);//IIC THIS IS WHERE THE ERROR OCCURS
#define WIRE Wire
#endif
void setup() {
Serial.begin(9600);
while (!Serial) {};
LIS.begin(WIRE); //IIC init
delay(100);
LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
}
void loop() {
if (!LIS) {
Serial.println("LIS3DHTR didn't connect.");
while (1);
return;
}
//3 axis
Serial.print("x:"); Serial.print(LIS.getAccelerationX()); Serial.prin
t(" ");
Serial.print("y:"); Serial.print(LIS.getAccelerationY()); Serial.prin
t(" ");
Serial.print("z:"); Serial.println(LIS.getAccelerationZ());
delay(500);
}
The docs you linked have a different instantiation than what you have!
Try passing Wire to the .begin method rather than to LIS (which presumably does exist in Wire.h and likely also exists in SoftwareWire.h)
Plausibly putting LIS.begin() in setup() is needed, though it doesn't seem to matter from their examples
LIS3DHTR<TwoWire> LIS; //IIC
LIS.begin(Wire, 0x19)

How to define the callback for an esp32 arduino ble scan result

The definition to start a BLE scan is:
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false);
The second parameter seems to be the callback when a scan is complete, being somewhat new to this Im unsure how to define it.
fwiw Ive tried this:
void OnScanResults(BLEScanResults scanResults)
{ }
and used it like this:
scanResults = scan->start(60, OnScanResults, true);
but obvious to others, that didnt work.
Please help me decypher that signature
void (*scanCompleteCB)(BLEScanResults)
you need to add & to OnScanResults because:
void (*scanCompleteCB)(BLEScanResults)
is a pointer to a function which takes a BLEScanResults, returns nothing and is called scanCompleteCB
So your call should be:
scanResults = scan->start(60, &OnScanResults, true);
just as a pointer to a int points to the address of a int
int pointedTo;
int* ptr = &pointedTo;

Sound Sensor RGB LED coding

So we connected a sound sensor to our board to light up our LED light when sound is heard, it kinda works but there some hiccups.
We tried messing with the code for a while but no matter what we do the senor will only react to loud even when we put in a threshold. If you see in the picture, it it only displaying "loud" noise to the display and cant seem be able to go to the other condition we set in our threshold. We configure the sensor with our screw driver but nothing seem to work. Our code is below & before we continue on, we wanted to know if there a problem with it that can fix out the issue,thanks you
ALSO the sound sensor is a "ko9A01"
PS: we use "energia" to code this.
#include <msp430.h>
#include <Wire.h>
int soundsensor = 2;
int led = 3;
void setup()
{
Serial.begin(9600);
Serial.println("Begin Test");
pinMode(soundsensor,OUTPUT);
pinMode(led,OUTPUT);
}
void loop()
{
int sensorValue = digitalRead(soundsensor);
Serial.println(sensorValue);
delay(250);
if (sensorValue == 1)
{
Serial.print("LOUD");
digitalWrite(led,HIGH);
}
else
{
Serial.print("QUIET");
digitalWrite(led,LOW);
}
}
EDIT: NOW With the help of Brydon we change the output to input and change it to this we change it to this and now we get this new error voi
void setup()
{
Serial.begin(9600);
Serial.println("Begin Testing");
pinMode(soundsensor,INPUT);
}
and it only show
"begin test":
0 and wont move from there
You have the sound sensor configured as an OUTPUT in the setup.
I assume you want it to be an input? That would be the case if you're reading values from it.
I can't tell what sensor you have - but with more information on the sensor, we can read the documentation and help you configure the inputs appropriately (ie a threshold)

Move object creation to setup() function of arduino

I've created a class that handles sending data to a led matrix (max7219).
This is what I was doing to create an instance of the LedControl class.
LedControl lc=LedControl(11, 13, 12);// data, clock, latch;
void setup()
{
...
}
Now I'm trying to add timer-interrupts to my class. But I found that I can't set the appropriate registries in the initializer (LedControl::LedControl()). If I move this code to setup, it all works perfectly. My guess is that the Arduino bootloader, which uses timer1 for PWM overwrites these registries, just before calling setup() but after my object has been initialized.
So my idea was to just move the object creation to the setup function like so
// FAIL
LedControl lc;
void setup()
{
lc=LedControl(11, 13, 12);// data, clock, latch;
...
}
But then I get the error no matching function for call to 'LedControl::LedControl()'
I tried using pointers (LedControl *lc; lc=&LedControl(11, 13, 12);), but as far as I could tell, this would mean I would have to write (*lc).someFunction() everywhere instead of lc.someFunction(). Even less elegant than moving the registry setting code to setup().
So my question is. How do I create an object in the setup() function, but still have a global variable pointing to it?
Your first error "no matching.. " is because you have no default constructor. You can make that approach function.
Add a no parameter, AKA default constructor, to the class, like this:
class LedControl {
LedControl();
LedControl(uint8_t pin1, uint8_t pin2, uint8_t pin3);
private:
uint8_t pin1;
uint8_t pin2;
uint8_t pin3;
};
LedControl::LedControl() : pin1(0), pin2(0), pin3(0) {
// this constructor leaves the class unusable
}
LedControl::Ledcontrol(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
// this object is ready to use
}
With this class, your approach will work, but is not the optimal method. This line does too much work:
void setup() {
lc = LedControl(11, 13, 12);// data, clock, latch;
}
This line of code involves the compiler creating some code for you:
First another instance of the class is constructed on the stack using the parameters 11,13,12.
Then it applies the = operator copying the data from the stack object to your global object.
When setup() exits, the stack object is flushed.
Because the temporary object is on the stack, your program didn't use too much memory, but your code size is larger because it involves extra operations to construct the temporary then copy from the temporary to the permanent.
Note that the compiler is creating an = operator for you, to fill the function of the line
lc = LedControl(11, 13, 12);
This may or may not work depending on what is in your constructor. The compiler can only presume that you needed a simple = operator. All the basic assignment operator will do is copy all the data members from the instance on the right side of the = to the instance on the left side. The compiler constructed = will not contain any code.
If your constructor does anything significant (other than save the parameters) then the compiler constructed(guessed) assignment operator may not work as you expected. For your case the constructor probably sets the pin modes, something like this:
LedControl::LedControl(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
pinMode(pin1, INPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
return;
}
This happens to function, but only by chance. The pinMode() calls are made when the temporary object is constructed and called from that object, not from the global lc. Because pinMode()'s are global this case will achieve the correct goal, but maybe not in the way expected. For more complex operations such as registering interrupt handlers, you will need to create your own assignment operator:
LedControl& operator= (const LedControl & other);
In that method, you could ensure that the state of the global lc is what you need. An easier/safer approach is to not deal with that at all.
A simple and efficient approach, you may have seen in other libraries is to add a method to the class that assigns the pins:
class LedControl {
void attach(uint8_t pin1, uint8_t pin2, uint8_t pin3);
};
void LedControl::attach(uint8_t pin1, uint8_t pin2, uint8_t pin3) {
this.pin1 = pin1;
this.pin2 = pin2;
this.pin3 = pin3;
// do other setup type operations
return;
}
Now your program, constructs the blank object, and assigns pins during setup():
LedControl lc; // not ready to use until attach pins
void setup() {
lc.attach(11, 13, 12);// data, clock, latch;
...
}
This involves no temporary object construction, and no assignment operator. With respect to design, some people might fairly comment that the user might forget to call attach() and leave the global lc object unusable. For a desktop application, you might add some code to prevent that failure case. For an embedded application, that is a risk you accept which is balanced by the gains in code size or memory savings.
I just stumbled over the same problem. I wanted to create a global debug port object, but I couldn't create it as global instance, as the port won't work after setup() was called. I have the same assumptions that the arduino code does some setup stuff after my constructor (of the global object) and before setup().
I found it the easiest solution, to declare my object as a pointer and init it in setup. In your situation it would be:
LedControl* lc;
void setup()
{
lc = new LedControl(11, 13, 12);// data, clock, latch;
}
void loop()
{
lc->doSomething();
}
So there's no need for additional constructors or operators.
As the object is used until power down, theres is no delete needed in this case.

Resources