Multiple case states

Can an arduino mega run multiple case state switch functions at once? I’m trying to use one mega to sence occupancy in several locations and display the information in each section.

Yes.

Can an arduino mega run multiple case state switch functions at once? I’m trying to use one mega to sence occupancy in several locations and display the information in each section.

why would “nested” switch statements be a concern? why not consider using an array to track the occupancy state for each location?

rkkennedy89: Can an arduino mega run multiple case state switch functions at once?

You need to post an example that illustrates what you are thinking of doing. The devil is in the detail.

...R

below is an example of my code. sorry i did not want to share the whole sketch as it is about 3000 lines long.

in summary I want to enumerate several case states then operate as series of switches to navigate the cases within each state. i want to run all six switch cases at once based on inter dependent inputsfrom my sensors.

gcjr mensioned an “array” as well so i will research that as well.

thanks again.

enum SIGNALSTATESA1
{

//setup for augusta main 1 signal states

ST_GGA1,
ST_GYA1,
ST_GYBA1,
ST_YGA1,
ST_YBGA1,
ST_YYA1,
ST_YBYBA1,
ST_RRA1,
};

enum SIGNALSTATESA2
{

//setup for augusta main 2 signal states

ST_GGA2,
ST_GYA2,
ST_GYBA2,
ST_YGA2,
ST_YBGA2,
ST_YYA2,
ST_YBYBA2,
ST_RRA2,

};

SIGNALSTATESA1 signalStateA1 = ST_GGA1; //Sets default state to Green and Green
SIGNALSTATESA2 signalStateA2 = ST_GGA2;
SIGNALSTATESI1 signalStateI1 = ST_GGI1;
SIGNALSTATESI2 signalStateI2 = ST_GGI2;
SIGNALSTATESK1 signalStateK1 = ST_GGK1;
SIGNALSTATESK2 signalStateK2 = ST_GGK2;

switch(signalStateA1)
{
case ST_GGA1:
signalggA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_GYA1:
signalgyA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_GYBA1:
signalgybA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_YGA1:
signalygA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_YBGA1:
signalybgA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_YYA1:
signalyyA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_YBYBA1:
signalybybA1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
case ST_RRA1:
signalrr1A1(ASM1, AGI1REC, IM1, KM1, ICT1REC, AGIBP1);
break;
//this sets up our different loops within the main loop for our different signal states
}

switch(signalStateA2)
{
case ST_GGA2:
signalggA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_GYA2:
signalgyA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_GYBA2:
signalgybA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_YGA2:
signalygA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_YBGA2:
signalybgA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_YYA2:
signalyyA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_YBYBA2:
signalybybA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
case ST_RRA2:
signalrrA2(ASM2, AGI2REC, IM2, KM2, ICT2REC, AGIBP2);
break;
//this sets up our different loops within the main loop for our different signal states
}

void signalrr1A1(int ASM1, int AGI1REC, int IM1, int KM1, int ICT1REC, int AGIBP1){
digitalWrite(AI1G, HIGH);
digitalWrite(AI1Y, HIGH);
digitalWrite(AI1R, LOW);//Sets AI1R to ON
digitalWrite(AGI1SEND, HIGH); //this will transmit a signal to Block A
delay(500);

if ((ASM1 >500) && (AGI1REC <300) && ( IM1>500 ) && (KM1>500 ) && (ICT1REC<300 ) && (AGIBP1 <300)){
signalStateA1 = ST_GGA1;//block not occupied No adjacent blocks occupied
}
if ((ASM1 >500) && (AGI1REC >500) && ( IM1>500 ) && (KM1>500 )){
signalStateA1 = ST_GYA1;//block not occupied but Block B is
}
if ((ASM1 >500) && (AGI1REC <300) && ( IM1>500 ) && (KM1>500 ) && (ICT1REC<300 ) && (AGIBP1 >500)){
signalStateA1 = ST_GYBA1;//block not occupied but Block B is
}
if ((ASM1 >500) && (AGI1REC <300) && ( IM1<300 ) && (KM1>500 ) && (AGIBP1 <300)){
signalStateA1 = ST_YGA1;//block not occupied but Block A is
}
if ((ASM1 >500) && (AGI1REC <300) && ( IM1>500 ) && (KM1<300 ) && (AGIBP1 <300 )){
signalStateA1 = ST_YBGA1;//block not occupied but Block A is
}
if ((ASM1 >500) && (AGI1REC >500) && ( IM1<300 )){
signalStateA1 = ST_YYA1;//block not occupied but Block B and Block A are
}
if ((ASM1 >500) && (AGI1REC <300) && ( IM1>500 ) && (KM1<300 ) && (AGIBP1 >500)){
signalStateA1 = ST_YBYBA1;//block not occupied but Block B and Block A are
}
}

void signalggA2 (int ASM2, int AGI2REC, int IM2, int KM2, int ICT2REC, int AGIBP2){
digitalWrite(AI2G, LOW); //Sets AI2G to ON
digitalWrite(AI2Y, HIGH);
digitalWrite(AI2R, HIGH);
digitalWrite(AGI2SEND, LOW); //this will not transmit a signal to Block A
delay(500);

if ((ASM2 >500) && (AGI2REC >500) && ( IM2>500 ) && (KM2>500 )){
signalStateA2 = ST_GYA2;//block not occupied but Block B is
}
if ((ASM2 >500) && (AGI2REC <300) && ( IM2>500 ) && (KM2>500 ) && (ICT2REC<300 ) && (AGIBP2 >500)){
signalStateA2 = ST_GYBA2;//block not occupied but Block B is
}
if ((ASM2 >500) && (AGI2REC <300) && ( IM2<300 ) && (KM2>500 ) && (AGIBP2 <300)){
signalStateA2 = ST_YGA2;//block not occupied but Block A is
}
if ((ASM2 >500) && (AGI2REC <300) && ( IM2>500 ) && (KM2<300 ) && (AGIBP2 <300 )){
signalStateA2 = ST_YBGA2;//block not occupied but Block A is
}
if ((ASM2 >500) && (AGI2REC >500) && ( IM2<300 )){
signalStateA2 = ST_YYA2;//block not occupied but Block B and Block A are
}
if ((ASM2 >500) && (AGI2REC <300) && ( IM2>500 ) && (KM2<300 ) && (AGIBP2 >500)){
signalStateA2 = ST_YBYBA2;//block not occupied but Block B and Block A are
}
if ((ASM2 <300) ){
signalStateA2 = ST_RRA2;// block is occupied entered from ASM2
}
}

is this for a model railroad signaling system?

Yes it is. I have found systems for individual blocks with nano boards but I had an extra mega so I wanted to give a multi block system a try. Eventually I want to apply it to an interlocking where each signal stand is it's own case state controller sequence.

i suggest you create a sub-function for controlling a single signal with inputs from adjacent blocks rather than a monolithic approach that doesn't everything.

each invocation thru loop() monitors the occupancy of each block in an array and then sequentially goes through each signal (again arrays) and updates the signals. Each signal description has indices to the blocks affecting it

sub-functions may be helpful

gcjr: i suggest you create a sub-function for controlling a single signal with inputs from adjacent blocks rather than a monolithic approach that does~~n't~~ everything.

I presume my adjustment to the text is appropriate, and if so, I agree even though I cannot figure out what the code in Reply #4 is trying to do.

I have also been writing a program for model railway control and I strongly suspect if the OP were to take a two-week break from her project that he would not understand it either when she returned to it. (I don't know whether the OP is a him or a her).

The most important feature of a program should be the ease with which it can be understood. Without that mistakes are far more likely and far harder to find.

...R

I am developing a railway signalling system. I have been writing a “white paper” system design overview, and have already implemented a working 3-searchligh North American signal controller using AVR and NeoPixels. From my investigations, I found that, at least for ABS operation, it is an efficient use of connections to associate the two signals entering a block, with a single controller that also reads the occupancy of the same block. That part might not be important to you, but it is generally a good idea to drive multiple signals from one controller. However, there are diminishing returns as too many signals become physically distant from the controller. This can result in an “octopus” configuration, with too many wires floating around. In my system, there are an absolute minimum of wires running between blocks - only occupancy and speed/routing selection information.

I’m still trying to reconcile North American and Continental protocol differences, but in NA at least, an interlocking has no exit signals - hence any interlocking (even if it is just a turnout) requires a different kind of controller that does not control any signals of its own. With ABS, the entry signals can be “borrowed” from the spare signals on the dual ABS block controller adjacent to it, since there are no entry signals to that block, from the interlocking direction.

Thus, in my system, there is no place where a single mast controller is required. Instead, dual mast controllers make up the entire system.

I will post more information when it is in a presentable and complete state.

Also, you have posted code without using code tags. The code tags make the code look

like this

when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don’t do it, some of the character sequences in the code can be misinterpred by the forum code as italics or funny emoticons. The “Code: [Select]” feature allows someone to select the entire sketch so it can be easily copied and pasted into the IDE for testing.
If you have already posted without using code tags, open your message and select “modify” from the pull down menu labelled, “More”, at the lower right corner of the message. Highlight your code by selecting it (it turns blue), and then click on the “</>” icon at the upper left hand corner. Click on the “Save” button. Code tags can also be inserted manually in the forum text using the code and /code metatags.

thanks for the edit Robin

hence any interlocking (even if it is just a turnout) requires a different kind of controller that does not control any signals of its own.

i believe all that's needed is an additional input, the turnout position, which if not routed to the route protected by the signal simply causes a Stop indication.

but while Green over Red is indicated when routed to an unoccupied mainline track, Red over Yellow is indicated for restricted speed when the diverging route is selected.

the following is a low-tech signal controller for a mainline and passing track that combines the functions of block detection and turnout position

That works correctly, but does not address all the signals that you need. For example, the signals facing the non-selected exits from a set of points, have to be set to "danger" (stop).

Also, when points are cascaded (exit from a switch leads to another switch), the speed indication can be different. That is because the track speed can depend on the second (far) switch. For this, and other situations, sometimes multiple switch contacts are required. These may not be available on the switch machine itself. This is why I believe an interlocking controller is a simpler solution than electrical switches for all but the most elementary interlockings.

That works correctly, but does not address all the signals that you need. For example, the signals facing the non-selected exits from a set of points, have to be set to "danger" (stop).

the same logic can be applied in the opposite direction, a siding merging into the mainline. A Red signal is displayed when the turnout is not aligned

when there are multiple turnouts involved, DPDT toggle switches can be used on the interior turnouts to either forward the voltage from the preceding turnout or the appropriate voltage for Red.

i agree that a software approach can make things much easier to maintain and as sophisticated as you would like. I came up with the circuit because I'm helping a less-tech savy modeler with his layout. I presented it because is cleanly demonstrates the required logic for many simpler cases.

Yes, actually it's amazing how much you can do with just relays and switches. I'm not sure that the OP has reached the point yet where an interlocking is even something to consider, however the code and use of a Mega does suggest a broad ambition.

It was my intention to show that a multiple mast controller is not just appropriate for multiple blocks, but also for an individual block.

In the system I am designing, a circuit like the one you have shown could be incorporated instead of an interlocking controller - the latter is optional. The important aspect is that each mast controller must be capable of responding to route/speed information as well as occupancy.

I am very ambitious in this undertaking. I'm trying to upgrade an entire section of our club layout to get the signal system out of the way for other projects in the area.

Im quite interested in the sub function and table approach but I'm newish to raw arduino coding. Someone mention posting my whole code but the whole code for 6 blocks with a case state for each and 9 cases within each switch comes out to 2871 lines of code.

I admit this is probably quite inefficient but it was built off a tutorial I saw for a single block system I saw for a nano.

The code I presented was just trying to demonstrate the multiple sub functions I have and how I was trying to run them. My original question was can I run multiple case states like the ones above. They are only relevant excerpts on the different functional elements I have for the entire code.

After this thread and discussion I'm very interested in streamlining the approach with a table and sub functions.

I also want to try to incorporate a "double distant" case where the yellow aspect blinks when the block two blocks away is occupied. I have that sub function worked out I just need to tie everything together with a table.

i’d be surprised if a single mega is sufficient for a club size layout. and from a practical standpoint, all the wiring needs to go back to the mega

this is where C/MRI nodes come in to distribute the processing around the layout where it is needed and allow centralized control using an rs-485 (2-wires)

Yes, C/MRI and/or LCC are excellent choices for a large layout. That's why I'm focusing on distributed, stand alone logic for small layouts.

LOL!

Learn something every day: I noticed the motor labeled “tortoise” and googled thinking it might be some weird translation error.

Nope:

http://www.circuitron.com/index_files/Tortoise.htm

a7

IMHO the expression "sub function" is confusing. In C++ there are only functions.

I have been helping to build the control system for a club layout using two Megas in the control panel and a number of DIY Atmega 328 boards to operate turnouts, uncouplers and signals. The principal Mega communicates with everything else using a serial connection - the distances are not very large. This is not a block-control system but it could be developed that way in the future.

One major issue that arose with this project may also be relevant for the OP's project. Although the Arduino development work was spread over a long period (due to the time taken to build baseboards etc) nobody in the club took any interest in the Arduino development. (Which is probably reasonable, as they are model railway hobbyists, not computer hobbyists). Early this year we ran into a problem with the Arduino system (which has since been solved) and it became very clear that the ability of the layout to operate was totally dependent on me, and my availability and good health. As a result I recommended that the critical business of operating the turnouts and uncouplers should be based on a commercial (Megapoints) system for which they could get advice and assistance from other sources. This recommendation was accepted - but its implementation is now on hold, like everything else. The operation of the signals is less critical and will remain an Arduino project, as will the wireless DC throttle system.

In brief, make sure that at least 3 people - and preferably more - are fully familiar with the development and debugging of any system on which the operation of the layout depends. A lone developer can become incapacitated for many different reasons.

...R

Thanks for the suggestions. The signal system is aesthetic and a couple peoples side project. The main functions of the layout are run from nce comercial products like command stations and switch8 controllers.

Check us out at augustamodelrrclub.org

We are out in augusta ks