r/arduino•
Phriday

Can I do multiple (unrelated) things with my Arduino Uno?

For example, can I regulate and display the temperature in my beer fridge and turn on/off my desk lamp off the same unit?

I made it through about 4 lessons in the starter kit, but I've kind of put my arduino down for a bit because I didn't have any real world problems that needed solving. Now I have 2. The thermostat display went out on my beer fridge and the stock one is rather crummy anyway, and I'd like to use a photosensor to turn my desk lamp on and off. I just have the one board, but the fridge is about 8 feet away from the lamp, so I thought I may be able to kill 2 birds with one Uno.

Am I over- or under-simplifying this? It looks like the Uno is about $25 US, and I would imagine sensors & display would cost at least that much, so should I just build the one, then build the other?

Thanks.

Edit: Thanks for all the responses, folks. They got over my head pretty quickly, though. I guess I have a little more reading and tinkering to do.

Posted Jul 10, 2014, 11:08 AM UTC · edited

1630
frumperinopro mini 3v3•

The short answer is, yes - if you write your program properly.

Design your code so that the two functions that you want your Arduino to perform, each has their own neatly segregated routine that can run side by side without interfering with the other. So they have to be good neighbors. That means they can not use delay() which just makes everything (including the other process) grind to a halt. Define a time regimen for how often each of the two functions are run (once a second? 100 times a second?) and have for your main loop a simple scheduler function looking at millis() and comparing with timestamps to determine when to run each of the two (or more) functions you want to run side by side.

edit: To avoid variable names belonging to each process from "stepping on each other" , you can organize the data that each process type uses, into a struct. Structs are like records or data cards; for example, you could for your thermostat function store the high and low threshold set temperatures in a struct you can call ThermostatSetting. It could also contain a reference to the IO pins that the process uses. Then if for whatever reason you want to add more things to be temperature controlled, you can reuse the thermostat function and just call it with the different structs pertaining to each controlled thermostat. The same goes for lights. And anything else. The 16MHz Atmel CPU is plenty powerful to run basic home automation for a whole house.

13
Simmerlytk•

A professor of mine at Aalborg University wrote a custom arduino kernel for exactly this purpose, called SNOT (Simple NOT) it works as a Semiphore and scheduling kernel, allowing you to designate several schedules to be executed "at the same time" in a very clever way.

Take a look at it and see if it is what you need http://www.control.aau.dk/~jdn/edu/doc/arduino/snot/

7
austin_flowersmega2560, Uno, Leonardo•

The short answer: kinda

The long answer: Unlike a Raspberry Pi (or any other computer) you can't have two totally separate programs running simultaneously on an arduino. To make these two processes run in tandem you would need to write your code cleverly.

One of the main things to do would be to minimise the time that any part of your code "hangs" the loop (i.e. the time it takes for a section of your code to run). The number one culprit for this is delay()! This holds your code for x number of milliseconds meaning that noting else can get done. A better way to do this would be to use millis(). You could store the current millis() and then check everytime your code loops to see if the current time is the stored time + x milliseconds. This means that your code can keep looping unimpeded and therefore be checking stuff related to the second task you wanted to run whilst the first task is waiting.

In your case it should be fairly straightforward as neither of your tasks require high timing precision. Simply have your beer fridge temperature sensor update itself every time the sketch runs (or use a millis() based bit of code to get it to check every so often) and then just below that in the loop update a variable from your photosensor and then turn the lamp on or off depending on it's output.

3†
playaspec•

Unlike a Raspberry Pi (or any other computer) you can't have two totally separate programs running simultaneously on an arduino.

This statement is completely false. The Raspberry Pi has a single computing core just like the AVR and can only execute a single thread of code at any one time. The RPi is no more capable of running two threads simultaneously than the AVR. Scheduling and the elimination of blocking code is the only way to get two processes to run 'simultaneously'.

7
jringstad•

That's technically true, but there is still a huge difference. On the rpi with linux, a preemptively multitasking system, you can run two threads or two processes, and pretend they run simultaneously -- and this will work perfectly fine and maintain your illusion of the two things running simultaneously, unless you need extremely fine-grained timing (at which point using the rpi will probably break down anyway, for various reasons) or expect to gain twice the performance from running two threads. So for most cases where you might use two threads or processes for reasons of encapsulation/separation, or because you want to perform some blocking operation that is not trivially made cooperative, it does pretty much work like running two programs simultaneously.

Also, if we are pedantic, you can run three things on the raspberry pi simultaneously, since it has three cores (one ARM, two VPU cores -- but the latter are less straightforward to utilize.)

2†
playaspec•

On the rpi with linux, a preemptively multitasking system, you can run two threads or two processes, and pretend they run simultaneously

Key word: 'pretend'

Anyone who knows what they are doing can get the exact same effect from an AVR.

Also, if we are pedantic

We're not.

you can run three things on the raspberry pi simultaneously, since it has three cores

Not all three are available from user space, and programming them is WAY beyond the scope of this argument.

4
jringstad•

Anyone who knows what they are doing can get the exact same effect from an AVR.

Completely false. You can get nowhere near the same thing -- not even close.

On the xmega chips, which have an MPU (AFAIR), you can get something that resembles what you get on the rpi a little more -- but you still don't get preemptive multitasking.

On the chips the arduino uno or leonardo have, you can neither get full-blown virtual memory (like the rpi has, because of its MMU), protected memory regions (with an MPU) nor can you get the safety that if one of your "processes" falls into an infinite loop, the other one will be unaffected. Writing a cooperative event dispatcher on e.g. the 32u4 is completely different from what you get on the rpi -- you have nowhere near the same kind of encapsulation you can get from running two separate threads or processes in a linux system. If one tasklet crashes, everything crashes (rather than just being restarted by a supervisor), if one produces a memory access violation, the other one might get the bad effects from it (rather than crashing and then getting restarted by the supervisor), if one overflows the stack, ... you get the idea.

Not all three are available from user space

They are.

programming them is WAY beyond the scope of this argument.

That's a fair enough argument.

3†
austin_flowersmega2560, Uno, Leonardo•

Indeed. It was a significant simplification to help answer the question at hand. Although I'd say that "completely false" was a tad harsh. As you've said, scheduling is a big part of running multiple processes and making it seem like they're running simultaneously. In most computers (certainly the Raspberry Pi) the kernal get's an interrupt 60 times a second at which point it can "pause" the currently running process and switch over to another process for a 60th of a second, then it gets another interupt and can switch back (or to another process). That's why it's really very easy to be using a Raspberry Pi to stream music whilst also using it as a NAS device simultaneously.

The point is that in an arduino you have to be much more careful about how you make two processes play nice with each other than you do on a computer (try writing an arduino sketch that would allow file browsing and audio streaming simultaneously!). The kernal's scheduling makes the job a whole lot easier on a computer provided, as you said, that you've eliminated blocking code from the programs (just as you need to with the arduino).

0
playaspec•

Although I'd say that "completely false" was a tad harsh.

I'd say it's completely accurate.

In most computers (certainly the Raspberry Pi) the kernal get's an interrupt 60 times a second at which point it can "pause" the currently running process and switch over to another process for a 60th of a second, then it gets another interupt and can switch back (or to another process).

All of which can also be done in an AVR, at the same rate.

That's why it's really very easy to be using a Raspberry Pi to stream music whilst also using it as a NAS device simultaneously.

This is no different than reading data off an SD card and blasting it out to a long string of LEDs. The disk IO is a process. The LED player is a process. In an application I developed, I was reading from two different files, each open was it's own thread. There was a real time mixer that layered the two streams and fed it into the display buffer. The player was a fourth thread, to shove the frame buffer down the shift register. Everything had to happen in a timely manner. From the view of the casual observer, it was ALL simultaneous, and it all took place at more than 60fps.

The point is that in an arduino you have to be much more careful about how you make two processes play nice with each othe

No one was ever arguing that. It goes without saying that its a requirement. It does not however exclude it's possibility.

try writing an arduino sketch that would allow file browsing and audio streaming simultaneously!

Not even difficult.

The kernal's scheduling makes the job a whole lot easier on a computer

Again, no one is arguing that. But it's existence doesn't exclude using the SAME techniques being applied to tiny microcontrollers like the AVR.

2
austin_flowersmega2560, Uno, Leonardo•

Although I'd say that "completely false" was a tad harsh.

I'd say it's completely accurate.

I wasn't disputing whether it was accurate or not, I was disputing whether your tone and way of presenting those facts wasn't a bit heavy handed (for want of a better expression).

try writing an arduino sketch that would allow file browsing and audio streaming simultaneously!

Not even difficult.

Entirely depends on your skill level. To you, not a problem, to someone of the assumed experience of OP, to whom this thread is directed, rather tricky.

It goes without saying that its a requirement

No it doesn't. Not to OP. If it did go without saying then they wouldn't have asked the question!

Don't think me an idiot, I too have written sketches that have several processes running simultaneously (although I'd like to know more about how you were able to read from an SD card in under 1/60th of a second as I recognise that you have greater skill than me), nor am I trying to dispute what you're saying (as it is 100% correct) what I was trying to convey is that it is easier on a computer thanks to the kernal than it is on an arduino. I wrote it in a form appropriate for a target audience.

I'll take off my hat and say now that you clearly have a much more in depth knowledge of the subject than I do so for anyone else that's reading this thread, you'd do better to assum that u/playaspec's comments are more accurate and better informed than mine. However, a friendly bit of advice would be to take a step back for a moment, realise that not everyone has 40 years of experience, work out how you should answer the question for the audience and do that rather than getting angry about someone not having the same level of understanding as you.

However, I do appreciate you using your knowledge to clarify my statement.

1
EternityForestuno•

Just as a note: if you really want threads there is a port of freertos to the arduino that works pretty well plus several other RTOSes.

2
radiofragments•

I've written a very simple (~50 line) schedule-driven framework that I'm currently working on filling out and writing up, I'll probably post about it within a week.

It lets you say "Check my position every 100 ms, regulate my speed every 50 ms, check if an infrared shutdown message (the topic of what I posted yesterday) has come in every 25ms" and it does it's best to do all those things.

It's not truly doing those things at the same time, it just tries it's best to run small bits of code on a schedule. Happy to share it with you ahead of schedule if you want.

2
wirbolwabolPro mini 3.3•

This is ideal as these procs are not meant to run multiple threads.

1
playaspec•

Post it! Every solution has something novel worth studying. I almost never use the Arduino libraries. They're to limiting. Instead I study the code and tear out the relevant bits so that it'll cooperate better with the other stuff I'm doing.

1
radiofragments•

Just put it up, I'll make a broader announcement in r/arduino, but since you asked...

http://houseofjeff.com/2014/07/15/a-scheduling-framework-remote-control-sleep-mode-for-arduino/

2
sanels•

this problem arises for every beginner sooner or later and there is something everyone must understand. an MCU can do a million things at once and there are several ways to make it do it. the only limitation is if it has the speed and io pins to do the tasks at hand. The biggest issue comes from the exposure and emphasis on the pause command and the while and do loops. these are called blocking calls and the only one that should exist is the main one which loops the entire program. Every tutorial relies heavily on these but aren't very useful when you want to do more than one thing at once.

To answer your question more specifically, you can do it with either interrupts(timer or io based) or with something called polling. there is no need to use fancy kernels or libraries or any of that fancy nonsense.

In essence you just write a main loop, use if statements to check conditions, and if a condition is met run some output. If anything needs delays or whatnot utilize some kind of timing mechanism(counting a variable, the millis() function and a variable trigger, or use interrupt timers) You do not want to have any pause commands. Essentially every function needs to be broken down into if statements and outputs be instant, then you can do as many things as the mcu is capable of(which is a lot)

2
[deleted]•

You don't need an entire uno board to run a program. The little black chip on your uno is doing all the work. You can buy more chips for about $3.

2
turbov21too many•

Might want to invest in a 16mhz oscillator too which will tack on a whopping $1 to the cost.

I know you don't have to, you can flash the chip to use an internal one, but I have found it easier to use the standard bootloader and an external oscillator.

2
PhridayOP•

As I'm a complete noob, do you have someplace you could point me to learn more about this?

1
[deleted]•

http://arduino.cc/en/Main/Standalone

Note that you don't ne ed the serial thing.

In short, program the chip on the board, remove, add power, then add clock stuff.

1
wirbolwabolPro mini 3.3•

Yes. You are doing three things, updating a display, regulating a thermo and checking the light levels on a lamp. Keep the thought of what you are doing as simple as possible. You don't need threads or anything special, just a good ole loop. Put all of these three things in a loop that can either sleep for x amount of time.

loop{
UpdateDisplay()
CheckThermo()
CheckLighting()// You should be tracking if the light is on already
Sleep()
}

As you don't want all three to be done at the same time, add a counter and set a while loop for each.

const int CheckLight = 3
conts int Checkthermo = 10
const int updatedisplay = 5
counterL = 0
counterT = 0
counterD = 0

loop{

if (counterD == updatedisplay)
{UpdateDisplay()
counterD = 0
}
if (counterT == Checkthermo) 
{CheckThermo()
counterT = 0
}
if (counterL == CheckLight)
{CheckLighting()
counterL =0
}


Sleep(xtime)
counterL++
counterT++
counterD++
}

Yes there are other ways to do it, but this would be a simple way...

1
frumperinopro mini 3v3•

Don't use an exact-value match to determine if the time is right for a process to run. A previously run process might for example go for long enough to push the clock past the exact set millisecond value. Use a greater-than-or-equal comparator instead.

1
wirbolwabolPro mini 3.3•

The example isn't checking for a timer value, just a value that would be incremented at the end of the loop and checked at the beginning. This loop is fairly simple and would catch the exact value as it is not being incremented in any other location and is specific to the function. If the value is being incremented beyond the check value, I would suspect a bug in the code and would want to fix it.

1