A question about the possible limits of an Arduino Uno
A lot of Arduino code is written either generally inefficiently, or written in completely the wrong way.

For instance, take the LCD code.  Commands have to be sent at the right speed with the proper delays in there for things to happen.  LCDs are actually quite slow devices to communicate with, and as a result the LCD code has a large number of delays in it.

Nothing else can happen while there's a delay() running.

Many other things will introduce their own delays.  Put them all together and you have a slow system.

No, you're not overloading it, you're slowing it down on purpose, and all those small slow-downs add up to one big grind.

There are other ways of doing these things, of course, which are far more friendly to the chip - things that don't require delays of any form.

For a start there is the millis() function which tells you the time.  Using that to know when to do things, instead of sitting waiting for them to happen, allows you to do so much more at once.

It's like boiling an egg.  Do you put the egg in boiling water and sit there staring at it for 3 minutes (or however long you like your egg cooking), or do you set the timer on your oven to alert you in 3 minutes time so you can go and do the ironing while the egg is boiling?

It's the same with Arduino programming.  Note the time, then check that time against the current time to see if the required time has passed.

Of course, with things like the LCD library, changing it to work that way would be quite a lot of effort.

There are also hardware timers.  These allow you to run small snippets of code at regular periods.  Great for managing things like servos or other motors where you only want to be changing the state or speed of them say 10 times per second. Instead of updating them all the time, just set a desired speed / position variable and let the timer interrupt update the actual motor at a lower rate.

There are two key phrases to take away here:


Non-blocking.  That is basically writing routines that never wait for something to complete, but can check to see if it's time for something to happen.
Asynchronous programming.  This is using things like timers to make things happen "outside" your main loop.