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

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 ...


7

What is the logic behind Arduino inlining HardwareSerial::_rx_complete_irq() for receiving serial data (but NOT _tx_udr_empty_irq()), and when is it advisable? There's a couple of reasons which end up with this arrangement: The RX interrupt has to be fast as we're reacting to an external stimulus. The TX interrupt doesn't have to be fast as it's only used ...


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 ...


5

As a matter of efficiency, I would favor chrisl’s advise to use the platform's low-level interrupts if at all possible. This, however, comes at the cost of portability: you would need an implementation specialized for each platform you want to support. If you don't want to or cannot maintain all this platform-specific code, attachInterrupt() may be a ...


5

You have probably learnt that objects created with new are stored in the heap, while globals are stored in the .data and .bss sections, and locals on the stack¹. This distinction, however, only exists in the software. At the hardware level, .data, .bss, heap and stack are just arbitrary portions of the RAM. Think of what would happen if the RAM was erased, ...


5

If you put: #define DO_NOTHING(s) (s) DO_NOTHING(R"xyz(Hello World)xyz") you can see g++ choke on preprocessing the raw string literal in the macro invocation with the latest esp8266 board package as of writing (version 2.7.4). This comes with g++ 4.8.2 for xtensa. ~/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-4-...


4

1 << 31 is interpreted by the compiler as (int)1 << (int)32. See the implicit types of integer literals. The rules of usual arithmetic conversions state that no implicit conversion is performed in this case. The result is then computed as an int, and it overflows. Note that this is undefined behavior. The assignment int64_t a = ... converts the (...


4

It returns it to whatever the function is being assigned to. Take the function: int plus(int a, int b) { return a + b; } That function takes two integers, adds them together, and "returns" them as an integer. You can then do: int c = plus(3, 4); and c will be handed the value 7 by the function. Equally you can do: Serial.println(plus(3, 4)); ...


4

This answer covers: Which Arduinos support ATOMIC_BLOCK? And how can I duplicate this concept in C with __attribute__((__cleanup__(func_to_call_when_x_exits_scope))) and in C++ with class constructors and destructors?. Which Arduino's support the ATOMIC_BLOCK macros? Which Arduinos support ATOMIC_BLOCK? Only AVR (ATmel AVR architecture) microcontrollers ...


4

The if statements (plural) you posted on GitHub are a lot different to the one you posted above. They contain a lot of of print commands to the LCD, so I think this is what is slowing your code down. It's a fair effort at nicely formatting the output on the display, but is rather convoluted. Here is a simplified version which writes to the LCD as little as ...


4

The question is somewhat confused, but I think I got what you mean. Your code suffers from too much repetition. You only showed the handling of two selectors, but you want to handle 6 of them. Repeating all the logic 6 times would make the code unwieldy and hard to maintain. So you want to put the logic in a function and just call that function six times. I ...


4

As hinted by chrisl in a comment, there are various criteria you may want to optimize for: speed, size, readability... Judging from the current state of this sketch, I would say that your first goal at this point should be to optimize for readability. The hardest think to make sense of are most of the plain numbers. When setting registers that are bit fields,...


4

The best way to handle this exception is to identify what's using so much space on the stack and rewrite your code to avoid it. The three most common ways you'd use too much stack space are: large local variables - for instance, declaring a large array as a local variable inside a function, like: #define VERY_LARGE_STRING_LENGTH 8000 void loop() { char ...


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(); ...


4

As @timemage explains in a comment, you cannot pass a capturing lambda to a function that expects a plain pointer to function. There is, however, a way out of this: the Ticker class provides an overload of the attach() method that allows you to provide a parameter of any type to tour callback: template<typename TArg> void attach(float seconds, void (*...


4

Your breadboard is one of those which have the power/GND lines interrupted between columns 31 and 33. I also once fell into this trap. If you look closely, you see that the blue and red lines are interrupted in the middle of the board. Just put wires between these pins to bridge the gap.


4

The following code will pause (Give some delay) when it runs for the first time and also when you press the button. void loop() { static int status = true; if(status){ //Pause delay(15); status=false; return; } if(digitalRead(switch_pin) == LOW){ digitalWrite(led_green_pin,LOW); digitalWrite(led_red_pin,HIGH); ...


4

The problem is, that you are filling up the Serial buffer rather fast, because you try to send ASCII numbers every 10ms at only 9600ms. When the buffer is full, Serial.println() will wait, until there is enough space free in the buffer for the current data. That makes your loop lasting significantly longer. In that case the time, where the time is exactly 10 ...


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

A CPP file isn't an Arduino file. It doesn't know about anything Arduino-esque unless you tell it about it. The simplest way is to just add, at the top of the file: #include <Arduino.h>


3

It seems you got confused by the pointer indirections, which is confounded by the implicit indirections made by the compiler. Here: extern "C" void __attribute__ ((used, noinline)) call(func_ptr *ptr) { (*ptr)(); } The parameter ptr is not a function pointer: it's a pointer to a function pointer. You have to dereference it twice in order to ...


3

This is 3 years way too late, but here's what I did In my own mpu_sensor.h file, I only included #ifndef MPU_SENSOR_H #define MPU_SENSOR_H #include "MPU6050.h" #include "helper_3dmath.h" .... #endif Note that I don't include MPU6050_6Axis_MotionApps20, since most datatypes are declared in MPU6050 and helper_3dmath In my mpu_sensor....


3

To make it generic, you simply divide the sizeof the array by the sizeof the type: for(int i=0; i<sizeof(controls)/sizeof(SwitchControl); i++){ } Then you can later change the items if the array, or the structure and the code will be the same.


3

The AVR implementation of sscanf() does not support parsing floating point numbers, thus you only get zeros out of it. You can't use the %f specifier with it. You need to convert these numbers by yourself with functions like atof() or similar. Splitting a string into parts can be done many ways. You could use sscanf() to split up the string parts and then ...


3

Your code is riddled with typographical and basic syntax errors. Such things as using brackets instead of parentheses, semicolons after an if meaning it will do nothing, etc. Sort out your basic syntax errors (hint: autoformat can help you with the indenting to highlight your problems) and you will see where you have gone wrong. For instance, after ...


3

After color = Serial.readString(); color also contains a newline character. You can remove that by adding the line color.trim();, or even better, avoid the newline altogether by using Serial.readStringUntil('\n'); which discards the terminating newline character. Also, you could, and maybe should, avoid using the String class and use: char color[10]; // char ...


3

The global constructors run right after the initializations performed by the C runtime startup code, and right before main() gets called. In a nutshell, the C runtime initialization code: does some low-level initializations (e.g., setup the memory) calls the global constructors calls main(), which in turn calls init() to do the Arduino-specific ...


3

You can't. Variables and macros are completely different concepts and handled by completely different parts of the compiler toolchain. Instead you will need to build your string up into a char array (or whatever format the _user_gcode_exec() function accepts) with the likes of sprintf.


3

This looks like a rounding problem. If the number you want to print lies within the open interval (9.95, 10), the condition value < 10 is true, as the number is strictly less than 10. Obviously, value != 10 is also true. Yet, lcd.print(x, 1) will round the number to the closest multiple of 0.1, which in this case is 10. I see no better solution than ...


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