Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #15 on: February 14, 2012, 03:26:36 pm » |
My project I'd like to do has two speakers, that will each play a line of music. (One bass, and another treble) Is it possible for the arduino to have both playing at the same time?
I suppose it depends how this music is going to be generated. But certainly the Arduino can do multiple things at the same time, in this sense ... Say you want to have two lights on "at the same time". You can do this: - Turn on light 1
- Turn on light 2 (a millisecond later)
To people watching both lights seemed to come on at once, and they are now both on together. It took an action to turn them on, it doesn't take an action to keep them on. In the same way that, in your house, you have lots of lights on at once, once you initially go around turning them on, one by one. Now for the music, the Arduino with only 2 Kb of RAM doesn't have a lot to hold sampled music, so you aren't going to get too far with that, unless you have external peripherals. It has 3 timers capable of generating tones, so you could get Timer 1 to start a tone on one speaker, and Timer 2 to do a tone on the other speaker. Then when it was time to change notes you change the appropriate tones.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA
Offline
Full Member
Karma: 1
Posts: 225
|
 |
« Reply #16 on: February 14, 2012, 09:27:38 pm » |
WOAH. did not expect to see 15 replies today. thank you to everyone for the quick replies! A little more detail on the use of this, I want to put a RGB led in an arcade style button, I have some code to make it fade between colors. I want to run this (looping) while also reading the button and doing other stuff from the resulting state of the button. How do any of you suggest going about this? Button(im going to replace the white led with a RGB one): http://www.paradisearcadeshop.com/en/234-led-convex-arcade-pushbuttonwhite-led-convex-arcade-pushbutton.htmlFading Code: #define GREEN 3 #define BLUE 5 #define RED 6 #define delayTime 20
void setup() {
pinMode(GREEN, OUTPUT); pinMode(BLUE, OUTPUT); pinMode(RED, OUTPUT); digitalWrite(GREEN, HIGH); digitalWrite(BLUE, HIGH); digitalWrite(RED, HIGH); }
int redVal; int blueVal; int greenVal; void loop() { int redVal = 255; int blueVal = 0; int greenVal = 0; for( int i = 0 ; i < 255 ; i += 1 ){ greenVal += 1; redVal -= 1; analogWrite( GREEN, 255 - greenVal ); analogWrite( RED, 255 - redVal );
delay( delayTime ); } redVal = 0; blueVal = 0; greenVal = 255; for( int i = 0 ; i < 255 ; i += 1 ){ blueVal += 1; greenVal -= 1; analogWrite( BLUE, 255 - blueVal ); analogWrite( GREEN, 255 - greenVal );
delay( delayTime ); } redVal = 0; blueVal = 255; greenVal = 0; for( int i = 0 ; i < 255 ; i += 1 ){ redVal += 1; blueVal -= 1; analogWrite( RED, 255 - redVal ); analogWrite( BLUE, 255 - blueVal );
delay( delayTime ); } }
|
|
|
|
|
Logged
|
"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #17 on: February 14, 2012, 10:04:38 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
West Des Moines, Iowa USA
Offline
Sr. Member
Karma: 2
Posts: 429
|
 |
« Reply #18 on: February 14, 2012, 10:48:23 pm » |
(I'm curious - where is UKF?) I couldn't resist the urge to play with your code and ended up withis this (untested): #define GREEN 3 #define BLUE 5 #define RED 6
void (*execute)(); unsigned long runTime,delayTime = 20; int index,redVal,blueVal,greenVal;
void cycle1_head(void) { redVal = 255; index = blueVal = greenVal = 0; execute = cycle1_body; } void cycle1_body(void) { if (index++ < 255) { analogWrite(GREEN,255 - ++greenVal); analogWrite(RED,255 - --redVal); runTime += delayTime; } else execute = cycle2_head; } void cycle2_head(void) { greenVal = 255; index = redVal = blueVal = 0; execute = cycle2_body; } void cycle2_body(void) { if (index++ < 255) { analogWrite(BLUE,255 - ++blueVal); analogWrite(GREEN,255 - --greenVal); runTime += delayTime; } else execute = cycle3_head; } void cycle3_head(void) { blueVal = 255; index = redVal = greenVal = 0; execute = cycle3_body; } void cycle3_body(void) { if (index++ < 255) { analogWrite(RED,255 - ++redVal); analogWrite(BLUE,255 - --blueVal); runTime += delayTime; } else execute = cycle1_head; } void setup(void) { pinMode(GREEN,OUTPUT); pinMode(BLUE,OUTPUT); pinMode(RED,OUTPUT); digitalWrite(GREEN,HIGH); digitalWrite(BLUE,HIGH); digitalWrite(RED,HIGH); runTime = millis(); execute = cycle1_head; } void loop(void) { while (millis() >= runTime) execute();
/* Whatever else you want to do in loop() */ } If you do try it with a multi-color LED, I'd like to know how well it works.  Edited for compactness and clarity
|
|
|
|
« Last Edit: February 15, 2012, 12:50:47 pm by Morris Dovey »
|
Logged
|
There's always a better way!
|
|
|
|
Seattle, WA
Offline
Full Member
Karma: 1
Posts: 225
|
 |
« Reply #19 on: February 14, 2012, 11:40:45 pm » |
Awesome. It did exactly the same thing as when it was running on the old code, nice job. Frome. But as to the original question, there isnt a way to do a simple loop1 and loop2? you HAVE to mess around so there is no delay?
|
|
|
|
|
Logged
|
"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #20 on: February 14, 2012, 11:51:02 pm » |
You tell it to delay and it delays. This chip is not sophisticated enough to do pre-emptive multi-tasking. And even it it was, you would have to learn how to do that. So you substitute one lot of learning for another one. Back to my earlier example. Say you want to turn on two lights for an hour (at the same time). No reasonable person would do this: - Turn on the first light.
- Wait for an hour to elapse.
- Turn off the first light.
- Turn on the second light.
- Wait for an hour to elapse.
- Turn off the second light.
You wouldn't do that, right? It's hardly "messing around" to turn on light 1, then light 2, and then wait an hour, is it?
|
|
|
|
|
Logged
|
|
|
|
|
West Des Moines, Iowa USA
Offline
Sr. Member
Karma: 2
Posts: 429
|
 |
« Reply #21 on: February 15, 2012, 01:04:07 am » |
@Paranemertes... There are ways, but the cost/benefit ratio would be probably be out of proportion for the Arduino market. For its intended market, the Arduino is inexpensive and remarkably capable. It's human nature to always want more than what's provided - and so folks busily tinker away to implement the missing capabilities they (as individuals working on different projects) want - to work around the limitations. From a programmer's perspective, the hard limits are memory space ("M") and processor cycles ("V"), and the challenge is to use both efficiently. The delay() function, by design, throws away some (usually large) number of cycles and so reduces the machine's capacity to do work. The short answer is you probably will have to mess around in order to have several different (asynchronous) things going on concurrently.
|
|
|
|
|
Logged
|
There's always a better way!
|
|
|
|
Seattle, WA
Offline
Full Member
Karma: 1
Posts: 225
|
 |
« Reply #22 on: February 15, 2012, 01:24:50 am » |
cool beans, thanks a bunch everyone. And thanks for the awesome code Morris! If you dont mind i think i will use it...
|
|
|
|
|
Logged
|
"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."
|
|
|
|
the land of sun+snow
Offline
Edison Member
Karma: 81
Posts: 2137
|
 |
« Reply #23 on: February 16, 2012, 02:59:45 pm » |
Interesting thread, and I like all of the solutions tendered. However, might I suggest that the loop1,2 sketch be written in a more structured and readable format. I've included a scheme that I've used in the past, which is a variation on the BlinkWithoutDelay sketch. It uses separate tasks that each keep track of their own trigger times and internal states, and are written as simple state-machines using a switch{} construct (could be if-then-else too). You simply pass the global time variable to each task. With this scheme, it's easy to add extra tasks, using the previous ones as template, and also to add additional states to any one task. Each state increments its internal state variable to the next state. Also, it works best to keep the amount of code in each task to a minimum, in order to keep overall timing accurate, since this scheme, like the others, does not use preemptive multitasking. Any round-robin tasking scheme has to be set up for short task execution and frequent breaks. /* file: timed_tasks (revised: 16.02.2012).
Turns on and off LED using millisec() timing function, and runs multiple timed tasks.
Based upon "File > Examples > 2.Digital > BlinkWithoutDelay". **************************************************************/
const int ledPin = 13;
/**** Variables ****/ long interval = 1000UL; // blink interval, in msec.
/************************************************/ void setup() { pinMode(ledPin, OUTPUT); }
/************************************************/ void loop() { unsigned long currtime = millis(); task1_led(interval, currtime); task2_x(currtime); task3_y(currtime); }
/* interval = blink interval, in msec. currtime = current time from millisecond counter. ***************************************************************/ void task1_led(unsigned long interval, unsigned long currtime) { static long prevtime = 0; static int state = 0; if( (currtime - prevtime) > interval ) { prevtime = currtime; // save the last time Led blinked.
// if the LED is off, turn it on and vice-versa (written // so you don't have to keep track of the Led state). switch( state ) { case 0: digitalWrite(ledPin, HIGH); // set the LED. state=1; break; case 1: digitalWrite(ledPin, LOW); // set the LED. //state=2; //optional instead of state=0; state=0; break; // add more states (optional). // case 2: //do something. // state=3; // break; // case 3: //do something. // state=0; // break; default: break; } } }
/************************************************/ void task2_x(unsigned long currtime) { // similar to task1. }
/************************************************/ void task3_y(unsigned long currtime) { // similar to task1. }
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Offline
Full Member
Karma: 0
Posts: 122
I make my own electricity.
|
 |
« Reply #24 on: February 16, 2012, 03:28:49 pm » |
Yeah, but what about some nice pre-emptive round-robin scheduling?  Who's responsible for stacking and restoring ALU flags during an interrupt?
|
|
|
|
|
Logged
|
|
|
|
|
the land of sun+snow
Offline
Edison Member
Karma: 81
Posts: 2137
|
 |
« Reply #25 on: February 16, 2012, 04:19:58 pm » |
Can you point to some nice "easy to use" multitasker that is fairly standard in the Arduino community, and won't take a month to wring out learning how to use?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Dallas
Offline
Shannon Member
Karma: 120
Posts: 10183
|
 |
« Reply #26 on: February 16, 2012, 04:50:59 pm » |
Who's responsible for stacking and restoring ALU flags during an interrupt? Interrupt service routine. The hardware only handles the return address and the Global Interrupt Enable flag.
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Offline
Full Member
Karma: 0
Posts: 122
I make my own electricity.
|
 |
« Reply #27 on: February 16, 2012, 05:11:08 pm » |
Who's responsible for stacking and restoring ALU flags during an interrupt? Interrupt service routine. The hardware only handles the return address and the Global Interrupt Enable flag. Cool! So, in my ISR I save the flags and PC in a task state structure, the load the previous saved flags from a different task state structure, stack the PC, and RETI? Time to port Linux to an ATmega 2560! 
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 596
Arduino rocks
|
 |
« Reply #28 on: February 16, 2012, 05:28:48 pm » |
Keywords (recently mentioned in this forum)
ChiboOS
FreeRTOS
DuinoOS
I'm sure there are others.
Also, the timing section of the Playground is a nice starting point.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #29 on: February 16, 2012, 05:29:47 pm » |
Cool! So, in my ISR I save the flags and PC in a task state structure, the load the previous saved flags from a different task state structure, stack the PC, and RETI?
Just remind me of how you are going to handle stack-based variables.
|
|
|
|
|
Logged
|
|
|
|
|
|