Hot answers tagged

16

Most Arduinos (like the Uno or Nano) have very few RAM, thus you first need to make sure that you never allocate too much memory. Dynamically allocating memory can also lead to heap fragmentation (heap being the part of memory where dynamic allocation happens). In most cases you would want to allocate memory of different sizes (for example arrays of ...


7

Have a look at the code for attachInterrupt() and detachInterrupt() in /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/WInterrupts.c (well, that's where they are on a Mac, anyway. Arduino file structure on other OSes' probably looks similar in the lower levels of the path). It appears that attachInterrupt() assumes that the ...


7

Well, this question has been wisely answered in an answer to Stack Overflow question C: differences between char pointer and array. Basically, what you're declaring as PROGMEM with, const prog_char testStringD[] PROGMEM = "JKL"; is both the array and the memory it points to, that is, the elements of the array, both in current's scope stack. Whereas ...


7

void fcn1(int *variable) { fcn2(*variable); } This function takes a pointer to an integer as parameter, and then passes the value of the integer to the second function. To do it by reference, use an ampersand (&, not to be confused with the address-of operator). void fcn1(int &variable) { // Do something to variable } For example: void ...


7

Dynamic allocation is generally discouraged in embedded applications because you cannot guarantee that you do not exceed (attempt to allocate more than) the available memory. Static allocation will generally have this guarantee although out-of-memory bugs may still be possible. Additionally, far fewer services or tools are available to automatically manage ...


6

I don't know the user's function parameters, A common way for dealing with this issue is to pass a generic pointer to arbitrary data. See below. return type It makes little sense to allow for arbitrary return types, as your library would have no way of knowing what to do with the returned value. and number of functions that will be added. Either you ...


6

This all gets very much trickier than just an array of function pointers. Your functions are methods in unknown objects. As such you can't have one single type that stores pointers to the functions in different objects. The simple reason is that C++ changes the function prototype for you. For instance, it changes: class MyClass { public: int ...


6

This is not a direct answer to your question, as I have no such answer, and I believe the answer you are seeking would be of no use to you. The problem with your question is that your method of testing memory usage is heavily flawed. By removing the switch statement, you most likely have allowed the linker to remove lots of methods referenced by it, leading ...


5

String is not a simple type like an int or a char. It is a class with many member functions and, more importantly, operators. When you create the object it allocates room for that object either on the stack (for a local variable) or in the global data area if it's a global variable. However that object doesn't contain the memory used to store the actual ...


5

The StaticJsonDocument is a template class. The template value in <> is here only the size of the internal buffer, but every size used generates a different class. (memory usage!) To have the parameter of the function take an StaticJsonDocument version instance, it must be the same version or a common base class. In this case the base class is ...


5

Here is a full example that shows you all thing things you have been asking over the past few days: int colors[][3] = { {255, 0, 0}, {0, 255, 0}, {0, 0, 255} }; #define NCOLOR (sizeof(colors) / sizeof(colors[0])) int *EXCLUSIVE_COLOR = NULL; void setup() { Serial.begin(115200); Serial.print("You have "); Serial.print(NCOLOR); ...


5

For starters, fix your library As noted by @crasic, dynamic memory allocation is generally not recommended for embedded systems. It may be acceptable for embedded devices which have a larger amount of free memory - embedded Linux is commonly used, for example, and all Linux apps/services will tend to use dynamic memory allocation - but on small devices such ...


4

Problem is local shadow variable b1 in setup() function declared as Beta b1 = Beta();. In loop() is considered uninitialized global variable b1.


4

It is quite right, using that kind of syntax is not allowed. It's a bit of a pain, but it's ok since there is an alternative method - kind of a "trick" if you will. That trick is to use a string, not an array. After all, a string is just an array, it's just handled slightly differently by the compiler. Instead of using {...} use "..." and use the ...


4

I'm not sure if it will not blow your memory limit as every pointer takes up 16 bits. But in C you usually do it this way: void func1() { puts("Hello"); } void func2() { puts("World!"); } void func3() { puts("Array of Size 4"); } void func4() { puts("with Pointer"); } void func5() { puts("to a Function with no arguments"); } void ...


4

Derived derivedObj; is a local variable. It's deleted when the function exits. You have saved a pointer to it, but with that object now gone your pointer points to nothing of any interest - so doing anything with it is doomed to failure. Instead you need to create a new object on the heap, which will already be a pointer: Derived *derivedObj = new Derived(); ...


3

You can't call arbitrary functions (with random return types, and any number of arguments) but you can specify a callback function that takes a certain number of specific arguments, and returns a certain thing (or nothing). See http://www.gammon.com.au/callbacks Example code: typedef void (*GeneralMessageFunction) (); void sayHello () { Serial....


3

Dave X is absolutely right. I never assigned the senRoll pointer to an object. Then when I tried to dereference it, it went to some random address. I guess there are very few memory protections, so rather than causing a seg fault it just caused erratic behavior. Thanks for the help.


3

In your situation, your best bet is probably to use the standard C function strcpy: payload_t payload; char* source = "abcdef"; strcpy(payload.sensorid, source); Note that source string does not have to be declared as char source[20] and can be declared as the rather standard C string char*. Also, since you are limiting the size of the string to be passed ...


3

What this line: const prog_char *testStringC PROGMEM = "GHI"; does is to write prologue code to copy the characters in the string to SRAM, and then initializes the pointer stored in flash to this SRAM location. You must load the pointer via normal means, and then dereference the pointer as usual. const char *str = pgm_read_word(&testStringC); Serial....


3

You're printing the address of the pointer, not the contents of the pointer. Say you have the memory map of: 100 20 test1 low byte 101 0 test1 high byte 102 100 ptr1 low byte 103 0 ptr1 high byte test is located at address 100 and takes two bytes. ptr1 is located at 102 and takes two bytes. ptr1 contains the address of test (100) ...


3

const byte* const message[] PROGMEM = to use an item, load it in RAM strcpy_P(buffer, (byte*)pgm_read_word(&(message[i]))); source Arduino reference - PROGMEM


3

typedef void (*MessageHandler)(void); // def messagehandler as pointer to func struct AvcInMessage { MessageHandler msgHandler; byte dataSize; byte data[8]; char description[20]; } InMessage[] = { { function1, <datasize>, {<byte0>, <byte1>, ..., }, "DescriptionHere" }, // etc, for ...


3

You may try something like this: const char* topicArry[2] = {NULL, groupTopic}; const char** const pDeviceTopic = &topicArry[0]; #define deviceTopic (*pDeviceTopic) Arguably not very elegant, but now when you assign, e.g. deviceTopic = msgTopic; you are actually writing into topicArry[0].


3

As Majenko mentioned in the comment, you created new local arrays in the constructor, but never put anything in the member arrays of the classes. They have the same name, but are not the same variable. Responsible for creating the new variable is the keyword int. However, you cannot simply assign array values by just omitting the int. Therer are multiple ...


3

BUZZER_NOTE notes[]; //-- Funny how the same declaration tried below DOES work if it's inside a class It doesn't really. C++ language prohibits that. It is just a non-standard quirk of GCC compiler used by Arduino IDE, which happens to support C-style flexible array members in C++ code. // BUZZER_NOTE notes[]; //-- Compilation error: Of course. You ...


3

Just as a complement to Delta_G's answer: The names TIMSK0, OCIE0A, etc. are already preprocessor macros so, for consistency, it makes sense to define your own preprocessor macros for them. I tend to be lazy and use one of the already defined names, like #ifdef TIMSK0 // support both ATtiny{25,45,85} and ATmega328P # define TIMSK TIMSK0 #endif A const ...


3

I'm adding this not so much to add to the answer as to add some real world implications for those that may be down this particular rabbit hole. It's nice to talk about what could happen theoretically, but a new programmer may still be tempted to think that he can out-think these limitation and still do something useful. Here is some real world talk about ...


3

Your code with sendBinary is probably fine, as long as on the other side you also use a function that expects to receive exactly 32 bits of binary data (in little-endian format). Trying to print (char*)&some_32bit_int on the other hand will not do anything useful. The short version is this: if you want to send (or receive) binary data, use functions ...


3

Not sure if or why you want to convert char* to int, but if you need to, there are atoi(), atol(), strtol(), strtoul() to consider, or rolling your own function. Pros and cons are discussed here. Main thing to note is that atoi() and atol() have no error handling, but if the char* you feed them is completely under control and predictable, that need not be a ...


Only top voted, non community-wiki answers of a minimum length are eligible