need to loop through random group addresses

Discussion in 'Pascal Logic Code Examples' started by Trevor, Oct 11, 2024.

  1. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Hi all,
    I have updated this a bit since last post so best to start again.

    The code below when run gets the 10 values entered into system logic user io input fields and assigns those values to buttons and allocates a group address for each of them, and also to indicator lights on the screen.

    What i need to do now is loop through those group addresses and turn each of them on/off as selected later.
    I just can't seem to get them into any sort of place i can do this. I used to write a lot of visual basic for Excel, Access and Outlook and if it was in one of those i wouldn't have a problem, but the limited syntax is killing me is here.

    to simplify, i have 10 randomly selected group addresses that can be changed/selected as required, after the user has selected them, start a loop and turn on and off each one for amount of times selected in another system user io

    Hope you can help, or even point me in the right direction please.
    regards
    Trevor
    Code below works OK.

    Code:
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
    //Initialise all 10 group addresses
    begin
    SetCompintegerProp("Random Selection", "Gate_Status_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "Gate_Status_2", "C-Bus Group",  GetIntSystemIO(2));
    SetCompintegerProp("Random Selection", "Gate_Status_3", "C-Bus Group",  GetIntSystemIO(3));
    SetCompintegerProp("Random Selection", "Gate_Status_4", "C-Bus Group",  GetIntSystemIO(4));
    SetCompintegerProp("Random Selection", "Gate_Status_5", "C-Bus Group",  GetIntSystemIO(5));
    SetCompintegerProp("Random Selection", "Gate_Status_6", "C-Bus Group",  GetIntSystemIO(6));
    SetCompintegerProp("Random Selection", "Gate_Status_7", "C-Bus Group",  GetIntSystemIO(7));
    SetCompintegerProp("Random Selection", "Gate_Status_8", "C-Bus Group",  GetIntSystemIO(8));
    SetCompintegerProp("Random Selection", "Gate_Status_9", "C-Bus Group",  GetIntSystemIO(9));
    SetCompintegerProp("Random Selection", "Gate_Status_10","C-Bus Group",  GetIntSystemIO(10));
    
    SetCompintegerProp("Random Selection", "gate_indicator_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "gate_indicator_2", "C-Bus Group",  GetIntSystemIO(2));
    SetCompintegerProp("Random Selection", "gate_indicator_3", "C-Bus Group",  GetIntSystemIO(3));
    SetCompintegerProp("Random Selection", "gate_indicator_4", "C-Bus Group",  GetIntSystemIO(4));
    SetCompintegerProp("Random Selection", "gate_indicator_5", "C-Bus Group",  GetIntSystemIO(5));
    SetCompintegerProp("Random Selection", "gate_indicator_6", "C-Bus Group",  GetIntSystemIO(6));
    SetCompintegerProp("Random Selection", "gate_indicator_7", "C-Bus Group",  GetIntSystemIO(7));
    SetCompintegerProp("Random Selection", "gate_indicator_8", "C-Bus Group",  GetIntSystemIO(8));
    SetCompintegerProp("Random Selection", "gate_indicator_9", "C-Bus Group",  GetIntSystemIO(9));
    SetCompintegerProp("Random Selection", "gate_indicator_10", "C-Bus Group",  GetIntSystemIO(10));
    
     end;
     
    Trevor, Oct 11, 2024
    #1
  2. Trevor

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,546
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Use an array and a for loop


    Code:
    // Global variables section
    ga: array[1..10] of integer;   // Array to hold ga's
    i: integer;
    
    // Your Module (compressed a bit)
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
    //Initialise all 10 group addresses
      for i := 1 to 10 do ga[i] :=  GetIntSystemIO(1); // Save ga's in array
      SetCompintegerProp("Random Selection", "Gate_Status_1", "C-Bus Group",  ga[1]);
      SetCompintegerProp("Random Selection", "Gate_Status_2", "C-Bus Group",  ga[2]);
    ...etc
      SetCompintegerProp("Random Selection", "gate_indicator_1", "C-Bus Group",  ga[1]);
      SetCompintegerProp("Random Selection", "gate_indicator_2", "C-Bus Group",  ga[2]);
    ...etc
      end;
    
    // To loop through ga's
    for i := 1 to 10 do
    begin
       SetLightingLevel(ga[i], 0%, "0s"); // For example, turn off all groups
    end
    
    If you need different levels for each ga, just define another array and put the target values in it, and
    access them the same as above.

    You can also loop through setting each component property rather than individually setting them , but that's another story.
     
    Ashley, Oct 11, 2024
    #2
  3. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Thanks Ash,
    Looks like you've fonebit again. Ill have all of that put in nect week...hetting very close now.
     
    Trevor, Oct 11, 2024
    #3
  4. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Hi Ashley,
    I've been playing around with this new code...
    for i := 1 to 10 do ga := GetIntSystemIO(1); // Save ga's in array

    Should this "GetIntSystemIO(1)" have the i variable in place of the 1 so it increments as well to get all the different group addresses saved in the 10 system variables

    And then once i have all the group addresses in the array how do i loop through them.

    See the sample file, random tests are under group tests then Custom...
     

    Attached Files:

    Trevor, Oct 14, 2024
    #4
  5. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Almost there now,
    I did need to change that 1 to an i so it followed the ga as it changed, then the last bit of code you supplied works to turn the selected group addresses on/off as required. Now im just going to add some more code to let the user select the number of loops or continuous, and what action to take eg... On,Off,Ramp,toggle.
    I will also limit to the group addresses that have been selected. ie they need to be greater than 0.
    I'll post the project again with these included.
    Thanks for your help Ashley, much appreciated.
     
    Trevor, Oct 14, 2024
    #5
  6. Trevor

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,546
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Yes, sorry, typo :)
     
    Ashley, Oct 14, 2024
    #6
  7. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    The code below sort of works ok now, it says messages are being sent on every scan. the error line is indicated as the last line before final end statement, i cant seem to get my if and once commands
    correct.

    Code:
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
         setlightingstate(250, OFF);
    //Initialise all 10 group addresses
    begin
    SetCompintegerProp("Random Selection", "Gate_Status_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "Gate_Status_2", "C-Bus Group",  GetIntSystemIO(2));
    //...up to 10
    SetCompintegerProp("Random Selection", "gate_indicator_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "gate_indicator_2", "C-Bus Group",  GetIntSystemIO(2));
    //...up to 10
    end;
    // Set group addresses as per user selections
    for i := 1 to 10 do ga[i] :=  GetIntSystemIO(i); // Save ga's in array
    
    //loop through ga's
    for i := 1 to 10 do
    begin
       SetLightingLevel(ga[i], 100%, "0s"); // For example, turn off all groups
    end     
     
    Trevor, Oct 14, 2024
    #7
  8. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    After fixing my begin end statements it is all ok now.
    Just going to add some parameters for the user to select... run time/count group address actions...On/Off/ ramp.
    hope to be done by late in the week
     
    Trevor, Oct 14, 2024
    #8
  9. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    The code below sort of works ok now, it says messages are being sent on every scan. the error line is indicated as the last line before final end statement, i cant seem to get my if and once commands
    correct.

    Code:
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
         setlightingstate(250, OFF);
    //Initialise all 10 group addresses
    begin
    SetCompintegerProp("Random Selection", "Gate_Status_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "Gate_Status_2", "C-Bus Group",  GetIntSystemIO(2));
    //...up to 10
    SetCompintegerProp("Random Selection", "gate_indicator_1", "C-Bus Group",  GetIntSystemIO(1));
    SetCompintegerProp("Random Selection", "gate_indicator_2", "C-Bus Group",  GetIntSystemIO(2));
    //...up to 10
    end;
    // Set group addresses as per user selections
    for i := 1 to 10 do ga[i] :=  GetIntSystemIO(i); // Save ga's in array
    
    //loop through ga's
    for i := 1 to 10 do
    begin
       SetLightingLevel(ga[i], 100%, "0s"); // For example, turn off all groups
    end     
     
    Trevor, Oct 16, 2024
    #9
  10. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    OK, i had this all working yesterday. NOW it seems that it wants to use the system io numbers as if they are based on 0 starting number, yesterday it was all working when they were based on 1 as starting digit... WTF
     
    Trevor, Oct 16, 2024
    #10
  11. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    ok,
    My numbers didn't change so 1 =1 still works but i had to add a sys io and move it to the number 1 position. it works now
     
    Trevor, Oct 16, 2024
    #11
  12. Trevor

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,546
    Likes Received:
    178
    Location:
    Adelaide, Australia
    I just noticed my original post lost a" begin" when I typed it in. It wouldn't hav compiled as it was. It should have been:

    Code:
    // Global variables section
    ga: array[1..10] of integer;   // Array to hold ga's
    i: integer;
    
    // Your Module (compressed a bit)
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
    begin  // ***** begine here
    //Initialise all 10 group addresses
      for i := 1 to 10 do ga[i] :=  GetIntSystemIO(1); // Save ga's in array
      SetCompintegerProp("Random Selection", "Gate_Status_1", "C-Bus Group",  ga[1]);
      SetCompintegerProp("Random Selection", "Gate_Status_2", "C-Bus Group",  ga[2]);
    ...etc
      SetCompintegerProp("Random Selection", "gate_indicator_1", "C-Bus Group",  ga[1]);
      SetCompintegerProp("Random Selection", "gate_indicator_2", "C-Bus Group",  ga[2]);
    ...etc
      end;
    
    // To loop through ga's
    for i := 1 to 10 do
    begin
       SetLightingLevel(ga[i], 0%, "0s"); // For example, turn off all groups
    end
    In pascal, a semicolon is a statement seperator. i.e. it finishes a statement. Both FOR and ONCE take a single statement. The begin/end commands produce a compound statement that acts like a single statement.
    So here:
    Code:
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
         setlightingstate(250, OFF);
    The ONCE statement is the statement that is part of the IF. It gets executed if the condition is true. The setLightingState is the statement that gets executed if the ONCE is true.
    After that, the IF and ONCE are done and anything following is executed every scan.
    Having the begin next does nothing because you are just creating a compound statemet that is always executed. You want all the intitializing statements to only be executed when ga 250 is set, so you need

    Code:
    If ShowingPage("Random Selection") then
    once getlightingstate(250) = ON then
    begin // *****Begin here
         setlightingstate(250, OFF);
    //Initialise all 10 group addresses
    
    Also, you only want to set up the array once at the same time, so it has to be inside the begin/end block:

    Code:
    // Set group addresses as per user selections
    for i := 1 to 10 do ga[i] :=  GetIntSystemIO(i); // Save ga's in array
    //
    end; // *****End goes here.

    Also, you don't wanting to be executing the last SetLightingLevel command every scan, so you need to place this inside another ONCE block either using the same trigger ga, or perhaps another one since you will probably be issuing these commands multiple time between changing the group addresses.
    I suggest you put the initialization of the group addresses and display in a seperate module so you can keep them distinct. If you do this, you can also just enable the module to get it to run and them let it disable itself at the end. To trigger the module you could have a button that enables the module so it will then run and disable itself. Then you don't need a seperate group address (I'm assuming here you had a button that set ga250 on to trigger the initialization).

    As for the systemIO numbers, if you open the edit systemIO dialog it will show you the assigned numbers. These are assigned sequentially from number one in the order you have the systemIO's. If you delete or move one they will all be renumbered. You need to remember this. There are ways to get around this but it's a bit more involved.

    Hope this helps and there are not too many typos as I wrote it in a hurry and was a bit long winded :)
     
    Ashley, Oct 16, 2024
    #12
  13. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Hi Ashley,
    Appreciate the excellent descriptions here, it will help me and anyone else delving into Pascal logic here.
    I did get things going a bit now, all the initial setting of the GA's via the array work, and i can also turn on the selected 10 GA's.
    I'm now trying to incorporate into this the rest of the options like delays and loops, and to also exclude GA's not selected for test.
    I can see how its a good idea to separate the initialization of the GA's as per selection into a separate module. I have worked with turning them on/off before so this should be ok.

    I can then have 1 module to do all the above, and 1 for setup.

    I'll be back into it next Tuesday.

    :):):):):):):):):):):):):)
     
    Trevor, Oct 16, 2024
    #13
  14. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Hi All,
    Going good so far, all of Ashley's suggestions implemented, just need help now on a couple of small things...

    The code below works except for the Ramp_Rate, it doesn't error out but when i run the logic it just goes to %100 instantly. If i set it to "4s" it works fine, but I'd like to use one of my system io variables to set the ramp rate then use that for the ramp rate in the code below.
    I have Ramp_Rate declared as an integer...
    Any ideas greatly appreciated.

    Code:
    case getlightingstate(5) of
      OFF : for i := 1 to 10 do SetLightingLevel(ga[i], 100%, "0s");
      ON  : for i := 1 to 10 do SetLightingLevel(ga[i], 100%, Ramp_Rate);
      end;
     
    Trevor, Oct 22, 2024
    #14
  15. Trevor

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,546
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Where are you setting the ramp rate value? That's the problem, not the code you posted.
     
    Ashley, Oct 23, 2024
    #15
  16. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Cheers Ashley,
    the Ramp_Rate value is being set as a System user io input variable.
    I did also try lots of variations, as well as just setting it as a variable and assigning it a value.
    Also tried to combine the Ramp_Rate with the s in lots of ways, but to no avail.
     
    Trevor, Oct 23, 2024
    #16
  17. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    This doesn't throw an error but still won't work
    case GetIntSystemIO(Ramp_Rate) of;
    4 : for i := 1 to 10 do SetLightingLevel(ga, 100%, "4s");
    8 : for i := 1 to 10 do SetLightingLevel(ga, 100%, "8s");
    16 : for i := 1 to 10 do SetLightingLevel(ga, 100%, "16s");
    end;
    Even tried to use the system io as a string - "8s" but just goes to 100% instantly
     
    Trevor, Oct 23, 2024
    #17
  18. Trevor

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,546
    Likes Received:
    178
    Location:
    Adelaide, Australia
    I think you are getting confised between systemIO variables, tags, and global variables. I assume you have defined a systemIo variable call ramp_rate as well as a global integer variable also called ramp_rate. These are completely independant things. When you create a systemIO variable, the name you give it becomes a tag for the systemIO variable. A tag is just a constant string that has a predefined integer value. Internally, systemIO's are referenced by a unique number. You can see this in left column when you edit user systemIO's. Thetag is just a shortcut so you don't have to remember the number. It will also get updated automatically is the systemIO number changes if you re-order them. To use a tag, you has to surround it in double quote. At compile time the comiler substitues the tag for its numerical value. However you can also access a systemIO directly by its number if you want to. If you look at the function definition for getIntSystemIO you will see that its parameter is an integer or a tag.
    A global variable is a something you define in the GLOBAL VARIABLES section. These can only be used in logic.
    I assume you have the statment
    Ramp_Rate: integer;
    in this section.

    the statement "GetIntSystemIO(Ramp_Rate)" doesn't read the value of the systemio ramp_rate because you have given it the global variable as the parameter, not the tag. You need the quotes:

    GetIntSystemIO("Ramp_Rate"

    What you have done is telll the system to use the current value of the global variable Ramp_Rate as the interger id of the systemIO.

    As you probably haven't ever set this global varialbe its value will be zero, so in effect you have

    GetIntSystemIO(0) which won't exist.

    In your statement

    ON : for i := 1 to 10 do SetLightingLevel(ga, 100%, Ramp_Rate)

    you are referencing the global variable, not the systemio. I bet you have never set its value
    (i.e. ramp_rate := xxx anywhere in the program, so its value is zero which is instant ramp rate.
    Somewhere you need
    ramp_rate := getIntSystemIO("Ramp_Rate"); to set it's value.

    or just get rid of the global variable and use

    ON : for i := 1 to 10 do SetLightingLevel(ga, 100%, getIntSystemIO("Ramp_Rate"));
     
    Ashley, Oct 24, 2024
    #18
  19. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    WOW,
    As usual, blown away with your help on this. I'm going to re read this on Tuesday. I expect I'll have it working then.
    Thanks Ashley.
     
    Trevor, Oct 24, 2024
    #19
  20. Trevor

    Trevor

    Joined:
    Nov 22, 2018
    Messages:
    363
    Likes Received:
    26
    Location:
    Melbourne Victoria
    Hi Ashley,
    I have this now, works well. got the system io sorted now.
    Just need to work out how to add a delay then turn them off, instant or ramp and do this for as many times selected



    Code:
    If ShowingPage("Random Selection") Then
       Once getlightingstate(250) = ON Then Begin
       For L_Count := 1 To getIntSystemIO("Loop_Count") Do Begin
           Case getlightingstate(5) Of;
           OFF : For i := 1 To 10 Do SetLightingLevel(ga[i], 100%, "0s");
           ON  : For i := 1 To 10 Do SetLightingLevel(ga[i], 100%, getIntSystemIO("Ramp_Rate"));
           End;
       End;
         setlightingstate(250, OFF);
    End
     
    Trevor, Oct 28, 2024 at 10:31 PM
    #20
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.