I have a project to "cue" multiple lights (108 in total) sequenced in time to music. This uses a matrixed RF transmission to 3 separate bases. Thanks to this forum I've figured out and tested most of it but Im struggling with the best way to do the actual sequencing and I would rather ask the best approach now rather than code 108 events to find I run out of RAM etc!
This will be in time to music triggered from an MP3 module and the sequence will begin with a button press.
The code for firing one "cue" uses port mapping. PORTD is the address pins of the RF encoder chip and PORTK is the data. I have this bit sorted and working. The delays are arbitrary but to ensure the signal is received (rather than a very brief burst) without crossover:
PORTD = B00000001; // Select base A
PORTK = B00001011; // Select column A
delay(950); // Time to send signal for
PORTD = B00000000; // Off
PORTK = B00000000; // Off
delay(50); // Delay to ensure no crossover
PORTD = B00000001; // Select base A
PORTK = B00000001; // Select cue 1
delay(950); // Time to send signal for
PORTD = B00000000; // Off
PORTK = B00000000; // Off
delay(50); // Delay to ensure no crossover
As this is in time to music and I will be changing this with each show, I would like the timing to be easily modifiable in the future so I believe that using delay( ) to initiate each cue would be a bad idea. I also will not be using each cue in its alphabetical / numerical order.
My current thoughts are to use millis( ) with an if statement at the beginning of each cue that if CurrentMillis minus PreviousMillis (saved at the button press at start of the show) are the intended time after starting then to activate that cue.
My questions are as follows:
Would making a custom library make things easier overall? (i.e. a simpler way of coding to activate each cue)
How long would the Arduino Mega take to cycle through a loop for 108 of the above statements and therefore would my if statement (to begin a cue) need a range of time in case it "missed" the cue due to cycling through the loop?
Is there a limit to number of if statements? (I would have about 110)
Is there any better way to do such sequencing which allows timing to be changed easily in the future?
Is the delay to allow transmission (as above) likely to cause problems (assuming I take 1000ms off the cue time to compensate)?
I can post more code but a lot of it is irrelevant to the questions. Please tell me if more info needed.
Would making a custom library make things easier overall? (i.e. a simpler way of coding to activate each cue)
Joe
You're getting too far ahead with that. A library is an okay idea, but you don't need to go there yet. The main thing you should do now, is contain your control code (as shown above) in functions.
Don't use the port macros. Use digitalWrite() and the actual pin names printed on the Arduino board. Also make up your own names for the pins, describing their function and declare that name at the top of your program. This will be hugely important when you need to change a pin in the future.
const int TriggerPin = 4; //sequence start trigger on digital pin 4
void setup(){
pinMode(TriggerPin, INPUT_PULLUP);
Decide what needs to be programmable in the future. Will the 50ms delay never change? Then you don't need to store that in the re programmable section.
You have several options for where to store this data. The EEPROM memory on the Arduino is good but then you will have to write a lot of code to act as a user interface for programming. The easiest to reprogram is to use an SD card to store the data in a regular file. Then you can pop the SD card out to edit it on your PC.
Thanks for the ideas - really helpful! Ill try having the data on SD card I think.
I have now gotten rid of the 50ms delay as it turned out to be over cautious. The other delays are now 1 second. I have stuck to port macros as the rf transmission encoding chip pt2262 looks at synchronous data bits and I dont want to risk any misinterpretation of data (I realised its a tiny difference in speed between digitalwrite and port macros but still). I also dont intend to change pins as I have built a custom shield for all this.
So do we think an if statement comparing current millis against start time millis would be the best bet for timing?
i just made a Simple playback system to control outputs with in scenes.
you can use it ti scroll thrue scenes(CUE's), at the moment it will automacticly go thrue the steps.
but it would be easy to do it with a button press.
ALSO!!! because i use Micros(); its time sensitive so every delay() will be a disaster for the output value.
also to much digitalWrite(), and other much cycle consuming commands will mess up the timing.
on my Original sketch i also have a lcd attached, and to much Strings will also mass up the timing.
and at the moment i use a Array to store the Sequences , but still thinking if i'm going to use a SDcard or SPIRAM.
but maby progmem will also work in your case.
@spirit - Helpful and I'll have a close look at how you've gone about it! For some reason I can't open your zip file - any chance of attaching the text of the coding?
@Henry_Best - Thank you! Switch/Case looks interesting indeed. I don't see any mention of a maximum number of cases so this may be a very good option to put them all under.
@Robin2 - It would be more helpful if perhaps you can offer an alternative?
What I am trying to do is have a sequence cue'd by a button press. The 108 cues can then be programmed to fire at specific times after the button press in time to music. This would be very easy for a single show but I am wanting it to be easy to reprogram not just the individual timings but also the order of each cue without rewriting the whole code for future shows. I am a complete amateur at any kind of programming and have been reading as many sources as possible and going through all the tutorials to get this far. This is why I am asking for help as this is a decision that will effect everything afterwards.
I've tried looking at the switch/case structure but as you need to specify an integer (rather than a "range") I'm concerned that if that precise millisecond is "missed" as the processor goes through the function, the cue will not fire. What do people think? Am I being stupid / over cautious.
@Robin - If you see my questions I was not asking for troubleshooting of my existing code. I was asking for project guidance and suggestions on the best way to approach the problem which I specified in my post. I am not asking for any code to be written for me but I thought it best to seek guidance on which function may be best suited in the first place rather than trying to troubleshoot what could have been intrinsically flawed coding after writing 108 statements.
@Spirit - Thanks! Really helpful!I am going to borrow some inspiration from yours. Appreciate it.
joeka101: @Robin - If you see my questions I was not asking for troubleshooting of my existing code.
I thought my comment related to Question 3 in your Original Post.
You posted a snippet of code that you seem to want to run several times. I can't figure if it should run 100 times in succession or whether you want one of a 100 variations to run at each occasion. Neither have I any idea what the IF statements might depend on.
It would be a big help if you could provide an english (not code) description of the succession of steps that your program should follow - one step on each line.