I am not an expert in Arduino and I am currently learning programming and electronics. I am using an Arduino Nano and I was doing a big project for my car that consisted of reading the speed, fuel consumption of my car and perform other tasks (just for the purpose learning). I did this by attaching the speed sensor and the injector signal in the interrupts ports of the Arduino Nano. Therefore Arduino will count the interrupts and convert them into km/h and liters/100km. In the program, I also implement a "cruise control feature" that based on the speed it will output a voltage to control the throttle. Finally, the Arduino will communicate to a Nextion Touch Display in order to receive data from users and data such as speed, fuel consumption, average fuel consumption, etc. Everything seems to work fine when I tested each function separately.
I know Arduino runs on 16 MHz and my question is: is Arduino fast enough to perform all this takes quickly?
What is the limit of Arduino in terms of "running speed"? In other words, what is an example of code/situation that Arduino will struggle due to the low speed?
The Nano is pretty fast, so it should be able to do a bunch of data input and calcs and display.
However, there are plenty of things that can be done, in your own code and in the libraries you use that can destroy the Nano's ability to keep up.
Blocking code, slow serial comms, use of long delays, display library functions that send more data than you anticipated - it's a long list.
You could post your code to see whether anyone can spot immediate problems.
More generally though, it's usually best to combine these things slowly - did you get some of your functions working together before trying the whole thing?
The principal issue is the lack of floating-point hardware. This means that if you use floating point calculations you take a big penalty, that 16MHz starts to feel more like 16kHz...
Traditionally this can be countered by using fixed point calculations where needed to, but this is more fiddly and error-prone.
Generally if you only want to process a few pieces data every few ms you've got a reasonable amount of grunt in 16MHz processor.
Updating that display is perhaps the most time-consuming operation.
That's okey.
However, don't try to get any best theory for this project.
Execution times are hard, and very time consuming, to calculate.
I once made a prototype sketch for the space industry but got no hardware for testing. Handing over the project to the guy taking over the responsibility I advised him to check just execution times. He did that and some details needed updating.
Do some testing for the subsystems being intended. As already told, know that updating the display should be done using the brain. Don't try to update the display thousands of times per second. It's useless. No human eye will pick up info updates more than a handfull times per second, and execution will slow down. Don't overdo things.
I want to know how you are reading all that data from the car. CANbus?
Personally, I like the Wemos D1 Mini- which has a clock speed of 80mHz.
For floating point math, there is the ESP32 which has two processors and each has an FPU. (I've never used the ESP32 myself)
Frankly you aren't doing that much and what you are doing can be done slowly (relative to the speed of the microcontroller. Putting the important stuff (measuring the sensor inputs) in interrupt routines is a good first move because missing those signals will give you wrong results. Everything else can be done as time permits. Some suggestions:
Don't use floating point. All your values have very small needed dynamic range, 255:1, or a single byte, is sufficient for most measurements, and certainly you wont need more tha 16 bit integers for calculations. This is called scaled integer arithmetic and has been done for decades with microcontrollers and early microprocessors. See https://en.wikipedia.org/wiki/Scale_factor_(computer_science)
Low priority tasks, such as communicating with the display and calculating fuel consumption, etc, can ben done one to ten times a second without concern of being too slow. So integrate those injector and distance ticks over a second if need be. These can all be done within or from subroutine calls within loop().
Use millis() to know the time since the last integration or display update. Don't use delay() since that will gobble up time that could be used for other things.
In the late 1980s GM used a variant of the 2MHz 68HC11 to run their P4 engine control computers. Their earlier C3, still a fully-fledged engine controller ran at something like 1.25MHz. These computers had a few hundred bytes of RAM and 4K EPROM (C3) and up to 32K in the P4. Note that these EPROMs contained both program code and extensive calibration data.
The accomplished this with tight programming and proper use of hardware resources like timers. The ATMega328P has 32K flash, 2K of RAM, 8x the clock rate of the P4 and a suite of timer input captures, output compares, PWM etc. It's definitely up to the task.