Home AMX User Forum NetLinx Studio

Different behaviors of an IF-statement

Hi!

Could anybody tell me the difference between these two lines of code?
IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) <-- runs incorrect
IF ((TIME = ALARM_TIME) AND (COFFEE_ACTIVE = 1)) <-- runs correct
I've got an Axcent2;. A part of my program should start my coffee maker at a user setable time (ALARM_TIME), it also should print an info on my TP.
I can activate/deactivate the coffee function from TP.

This is my code (it's now running properly):
DEFINE_START
COFFEE_ACTIVE = 0

PUSH[TP,217]   (* "COFFEE_YES/NO" *)
    {
    COFFEE_ACTIVE = NOT(COFFEE_ACTIVE)
    }

[b]IF ((TIME = ALARM_TIME) AND (COFFEE_ACTIVE = 1))[/b]
    {
	ON [RELAY,12]
	SEND_COMMAND TP,'WAKE'
	SEND_COMMAND TP,'PAGE-INFORMATIONS'
	SEND_COMMAND TP,'BEEP'
	SEND_COMMAND TP,"'!T',152,ALARM_TIME,$0D,'COFFEE MAKER STARTED...'"
	COFFEE_ACTIVE = 0
    }

In my first version, the IF-statemant was this:
IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME))
In this version, the IF became true when (TIME = ALARM_TIME) became true, regardless of the state of COFFEE_ACTIVE.
The program did pass the IF several times (I had about seven beeps on the TP) - ignoring the the state of COFFEE_ACTIVE.

After changing the expression after the IF, the code following the IF will only be executed if BOTH conditions are true. (Only one beep on TP)

The program takes one byte more in the working version (compiled file size) than in the non-working version.

I did checked this several times, because I couldn't believe it.
I also checked the state on COFFEE_ACTIVE by directing the state to an unused relay.

I'd like to understand what's wrong in order to avoid further problems by using code like this.

Any explanation appreciated.

Many Thanks
BlackLabel
«1

Comments

  • jjamesjjames Posts: 2,908
    I don't have an answer - but what kind of coffee maker is it? Sounds pretty slick! I want one right beside my Beyond scanable microwave (soon to get!)
  • Hi Jeremiah,

    I'm sorry, it's nothing special.
    I'm just using an RF controlled AC outlet in my kitchen where the coffee maker is connected to.
    The RF transmitter (4 channels) for the outlet is attached to four relays on my Axcent2.
    The transmitter is sending the command for ON if the corresponding relay becomes closed and sends the OFF command if the relay opens.

    If I like to get a automatic brewed coffee in the morning, I have to prepare the maker in the evening.

    It's like a RF-X10 (also 1-way), but much more reliable.
    The other three channels are used for controlling the lights.
  • mpullinmpullin Posts: 949
    I'm curious about this problem. Try IF ((COFFEE_ACTIVE == 1) && (TIME == ALARM_TIME))

    Having a traditional programming background I can't stand for seeing = used as an equals test. Also, AND should be the same thing as &&, but I've always used the latter. Those are the only things I can think of.
  • Hi Matt,

    if I change the code from single = into ==, I get an syntax error.
    && instead of AND is working, but the strange behavior still remains.

    All my knowledge in AMX programming is self educated, so I'm happy that I found out how to make my code running.

    Maybe it's a problem of my NetLinx.
    I'm using
    NetLinx Studio 2, Build 2.2.0.83
    NetLinx Compiler Build 2.2.0.108
    Axcess Compiler Build 2.0.0.143

    My Axcent2 firmware is 3.600
  • mpullinmpullin Posts: 949
    There is no way you should get a syntax error using == to test if variables are equal. This is NetLinx right? If so you should uninstall and reinstall your compiler, because there's a problem with it.
  • Yes I'm using NetLinx Studio, but I compile for Axcess (because I've got an Axcent?).
    I guess, the double equal operator (==) is allowed for the NetLinx language only.
  • mpullinmpullin Posts: 949
    BlackLabel wrote:
    Yes I?m using NetLinx Studio, but I compile for Axcess (because I?ve got an Axcent?).
    I guess, the double equal operator (==) is allowed for the NetLinx language only.
    Actually the double equal operator is used in all modern languages but I get what you're saying. Still not sure why having the clauses being in a different order would cause the program to compile differently, that is very strange. Does AMX still support Axcess in the sense that you could call tech support, describe this case, and have someone get back to you?
  • yuriyuri Posts: 861
    mpullin wrote:
    Actually the double equal operator is used in all modern languages but I get what you're saying. Still not sure why having the clauses being in a different order would cause the program to compile differently, that is very strange. Does AMX still support Axcess in the sense that you could call tech support, describe this case, and have someone get back to you?

    true, == can only be used in Netlinx code.
    btw, as far as i know, = is the same as == in Netlinx, it's just more fashionable to use == when testing a var against another...
  • GSLogicGSLogic Posts: 562
    yuri wrote:
    true, == can only be used in Netlinx code.
    Netlinx does treats == and = the same, but it is a good habit to get it to.
  • DHawthorneDHawthorne Posts: 4,584
    GSLogic wrote:
    Netlinx does treats == and = the same, but it is a good habit to get it to.

    Not quite. When it sees a single =, it figures out by context whether its an assignment or comparison. When it sees ==, it's always a comparison ... so there is the possibility of ambiguity if you just use the = for comparisons. Having said that, it would be very rare for that mistaken interpretation to happen, but it could.

    But ... back to the original post ...

    I think the problem has something to do with the internal precedence levels Axcess uses to process complex comparisons. I never did work it out completely - I generally just bowed to expediency and re-structured my code. In the case of the example, instead of fighting to make ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) work in a single line, I would just next one if inside the other, like this
    IF(COFFEE_ACTIVE)
    {
       IF(TIME = ALARM_TIME)
          (* DO WHATEVER *)
    }
    

    But that doesn't answer the why of it, just makes it work.
  • GSLogicGSLogic Posts: 562
    Not quite. When it sees a single =, it figures out by context whether its an assignment or comparison.
    You are correct! The brain was in another world, thinking about a different language syntax.
  • Very interesting issue
    DHawthorne wrote:
    But ... back to the original post ...

    I think the problem has something to do with the internal precedence levels Axcess uses to process complex comparisons. I never did work it out completely - I generally just bowed to expediency and re-structured my code. In the case of the example, instead of fighting to make ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) work in a single line, I would just next one if inside the other, like this
    IF(COFFEE_ACTIVE)
    {
       IF(TIME = ALARM_TIME)
          (* DO WHATEVER *)
    }
    

    But that doesn't answer the why of it, just makes it work.

    I have been watching this thread with interest and agree with Dave. The keyword TIME is dynamic and does not play well in compound comparisons.

    Consider this method as well:
    DEFINE_PROGRAM
    
    cTemp_Time = TIME
    
    IF ((COFFEE_ACTIVE == 1) AND (cTemp_Time == ALARM_TIME))  // Okay
    {
      // Code Here
    }
    
    IF ((cTemp_Time == ALARM_TIME) AND (COFFEE_ACTIVE == 1))  // Also okay
    {
      // Code Here
    }
    
    I usually assign TIME to a variable array before doing any complex comparisons.

    BlackLabel, What happens when you swap the position of TIME in your original comparison?
    IF ((COFFEE_ACTIVE == 1) AND ([color=red]ALARM_TIME == TIME[/color]))
     Instead of
    IF ((COFFEE_ACTIVE == 1) AND (TIME == ALARM_TIME))
    
  • Hi,

    Brian, I'll try out your suggestions later. I'll also check the TEMP_TIME.

    Until now, I thought, the program is proceeding an AND statement step by step until the first parameter equals FALSE and ignores the rest of the statement because the the AND can't become true.

    In my wrong working IF, the first parameter is false until I set in to 1 by pressing [TP,217], but it seems, the program doesn't care about the COFFEE_ACTIVE = 0 and goes thru the code following the IF.
    BUT if the program follows the code, COFFEE_ACTIVE must become FALSE after the first passing, but I can hear about seven BEEPS instead of one BEEP, so I guess, the program passes the code because of an missinterpreted IF (COFFEE_ACTIVE)...
    IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME))
        {
    	ON [RELAY,12]
    	SEND_COMMAND TP,'WAKE'
    	SEND_COMMAND TP,'PAGE-INFORMATIONS'
    	SEND_COMMAND TP,'BEEP'
    	SEND_COMMAND TP,"'!T',152,ALARM_TIME,$0D,'COFFEE MAKER STARTED...'"
    	COFFEE_ACTIVE = 0
        }
    
  • Spire_JeffSpire_Jeff Posts: 1,917
    I'm not sure how much stuff you are doing with the processor, but you might want to check out Ebay. I just looked and there are Axcent3 processors going for $15 - $150. I'm not positive, but there is a chance that some of the processing problems you are dealing with were addressed in the Axcent3 processor.

    Jeff
  • DHawthorneDHawthorne Posts: 4,584
    I wouldn't count on it evaluating left to right either. A lot of evaluations go the other way. I always put far more parentheses in than is absolutely necessary so it won't matter in those cases when I am not certain ... besides which, explicit groupings like that make it easier for me to read later, in case I have to deal with it on a caffeine shortage or something ...
  • I reduced my code to the suspicious part only (my IR files are still on the processor) and tried out the suggested option of TEMP_TIME = TIME.

    This is the only code, I uploaded to my processor:
    DEFINE_DEVICE
    RELAY		=    5
    TP		=  128
    
    DEFINE_VARIABLE
    ALARM_TIME[8]
    COFFEE_ACTIVE
    TEMP_TIME[8]
    
    DEFINE_START
    COFFEE_ACTIVE = 0
    ALARM_TIME = '22:20:00'
    
    DEFINE_PROGRAM
    TEMP_TIME = TIME
    SEND_COMMAND TP,"'!T',151,TEMP_TIME" (* for checking the time *)
    IF ((COFFEE_ACTIVE = 1) AND (TEMP_TIME = ALARM_TIME))
        {
    	ON [RELAY,12]
    	[TP,14] = [RELAY,12]
    	SEND_COMMAND TP,'WAKE'
    	SEND_COMMAND TP,'PAGE-INFORMATIONS'
    	SEND_COMMAND TP,'BEEP'
    	SEND_COMMAND TP,"'!T',152,ALARM_TIME,$0D,'COFFEE MAKER STARTED...'"
    	COFFEE_ACTIVE = 0
        }
    
    --> Relay 12 closes if TEMP_TIME equals TIME regardless the state of COFFEE_ACTIVE
    There is no possibility that COFFEE_ACTIVE could become TRUE in this code!


    I also checked the nesting of IF (COFFEE_ACTIVE = 1) and IF (TIME = ALARM_TIME):
    DEFINE_DEVICE
    RELAY		=    5
    TP		=  128
    
    DEFINE_VARIABLE
    ALARM_TIME[8]
    COFFEE_ACTIVE
    
    DEFINE_START
    COFFEE_ACTIVE = 0
    ALARM_TIME = '22:30:00'
    
    DEFINE_PROGRAM
    SEND_COMMAND TP,"'!T',151,TIME" (* for checking the time *)
    IF (COFFEE_ACTIVE = 1)
    	{
    	IF (TIME = ALARM_TIME))
    		{
    		ON [RELAY,12]
    		[TP,14] = [RELAY,12]
    		SEND_COMMAND TP,'WAKE'
    		SEND_COMMAND TP,'PAGE-INFORMATIONS'
    		SEND_COMMAND TP,'BEEP'
    		SEND_COMMAND TP,"'!T',152,ALARM_TIME,$0D,'COFFEE MAKER STARTED...'"
    		COFFEE_ACTIVE = 0
    		}
    	}
    
    --> This code is running properly.


    Either it's an issue of my processor or I have found a compiler bug.
  • DarksideDarkside Posts: 345
    BlackLabel wrote:
    Hi,

    Brian, I?ll try out your suggestions later. I?ll also check the TEMP_TIME.

    Until now, I thought, the program is proceeding an AND statement step by step until the first parameter equals FALSE and ignores the rest of the statement because the the AND can?t become true.

    In my wrong working IF, the first parameter is false until I set in to 1 by pressing [TP,217], but it seems, the program doesn?t care about the COFFEE_ACTIVE = 0 and goes thru the code following the IF.
    BUT if the program follows the code, COFFEE_ACTIVE must become FALSE after the first passing, but I can hear about seven BEEPS instead of one BEEP, so I guess, the program passes the code because of an missinterpreted IF (COFFEE_ACTIVE)...
    IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME))
        {
    	ON [RELAY,12]
    	SEND_COMMAND TP,'WAKE'
    	SEND_COMMAND TP,'PAGE-INFORMATIONS'
    	SEND_COMMAND TP,'BEEP'
    	SEND_COMMAND TP,"'!T',152,ALARM_TIME,$0D,'COFFEE MAKER STARTED...'"
    	COFFEE_ACTIVE = 0
        }
    
    Aside from the fact that this routine is misbehaving, the reason it beeps seven times is probably because your 'lockout' flag is at the end of the routine.

    Move your COFFEE_ACTIVE =0 above your on[relay,12] and see if it stops your beeping.
  • But if COFFEE_ACTIVE is FALSE, the code following the IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) must not be executed.
  • DHawthorneDHawthorne Posts: 4,584
    I don't know; it looks more to me like in the compound conditional , (COFFEE_ACTIVE = 1) is being treated as an assignment. The context is ambiguous to the compiler. The fact that it works as two nested IF's bears this out. Try making the compound read IF(COFFEE_ACTIVE AND (TIME = ALARM_TIME)). If that works, I would say it's certain it's assigning COFFEE_ACTIVE to 1 in the original.
  • Hi Dave,

    your suggestion sounds very interesting.
    Unfortunately I'm not at home till Sunday evening, so I'll check this on Sunday or Monday and give a feedback.

    Many thanks!
    Have a nice weekend.
  • JeffJeff Posts: 374
    Also try debugging to see if COFFEE_ACTIVE is becoming 1 instead of staying at 0
  • mpullinmpullin Posts: 949
    DHawthorne wrote:
    I don't know; it looks more to me like in the compound conditional , (COFFEE_ACTIVE = 1) is being treated as an assignment.
    An argument in favor of ==

    :)
  • Axcess compiler bug?

    We have an Axcent2 as the hardware, correct? This means we are compiling in Axcess. What's the version of Studio? I know there were reported Axcess compiler bugs for older versions of Studio. The current version should be fine.
  • So, now I checked several combinations:

    IF ((TIME = ALARM_TIME) AND (COFFEE_ACTIVE = 1)) (* <-- whole program compiled 10538 bytes - runs properly *)
    IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) (* <-- whole program compiled 10537 bytes - doesn't run properly *)
    IF ((TIME = ALARM_TIME) AND (COFFEE_ACTIVE)) (* <-- whole program compiled 10535 bytes - runs properly *)
    IF ((COFFEE_ACTIVE) AND (TIME = ALARM_TIME)) (* <-- whole program compiled 10534 bytes - doesn't run properly *)

    "runs properly" means, the program starts my coffee maker at destinated time when COFFEE_ACTIVE is set to TRUE only.
    "doesn't run properly" means, the program starts my coffee maker at destinated time regardless of the state of COFFEE_ACTIVE.

    I checked the state of COFFEE_ACTIVE by TP feedback and by assigning to an unused relay.


    Brian,

    I'm using
    NetLinx Studio 2, Build 2.2.0.83
    NetLinx Compiler Build 2.2.0.108
    Axcess Compiler Build 2.0.0.143

    My Axcent2 firmware is 3.600

    It must be a compiler issue.

    Regards
    BlackLabel
  • a_riot42a_riot42 Posts: 1,624
    Very weird. I would second the notion about using == rather than =, as if you switch to C or some other language doing this
    if (x=3)
    
    will kill you every time so its a bad habit to have.

    I can see how this has been a time consuming problem to debug since you only get to test it once a day and then have to wait 24 hours to try it again.
  • Using the double equals doesn't work, because I'm compiling the code in Axcess for my old Axcent2 processor.
    A double equal to (==) will bring a syntax error.

    There is no problem with the debugging, because I'm using a routine for setting the ALARM_TIME from the touch panel,
    so I can set the ALARM_TIME to current system time + 1 minute and see, what happens.

    As I wrote, the problem itself is solved, because I found out, that I have to avoid to set the part "(COFFEE_ACTIVE = 1)" on the first position of the AND statement.

    I just want to understand, what's going wrong if I change the two parts of the AND statement.
    AND means, that both conditions must be TRUE, but the wrong working code shows an behavior like an OR.

    In my code, I prefer to set the "(COFFEE_ACTIVE = 1)" at first position, in order to improve the readability of the code, because it's the more important part for me.
  • BlackLabel wrote:
    So, now I checked several combinations:

    IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) (* <-- whole program compiled 10537 bytes - doesn?t run properly *)
    BlackLabel

    Did you get a chance to try swaping the position of TIME and ALARM_TIME?
    IF ((COFFEE_ACTIVE = 1) AND (ALARM_TIME = TIME))
    
    BlackLabel wrote:
    Brian, I?m using Axcess Compiler Build 2.0.0.143
    BlackLabel
    This is the current version.
  • DarksideDarkside Posts: 345
    BlackLabel wrote:
    But if COFFEE_ACTIVE is FALSE, the code following the IF ((COFFEE_ACTIVE = 1) AND (TIME = ALARM_TIME)) must not be executed.
    Correct, but when coffee_active is true, it will enter, and whilst it is true it will continue to execute until coffee_active is switched off.

    This is an axcent - not a rocket ship, so by the time all the send_commands are done and then you switch off coffee_active, it may well have re-entered the routine. Remember this routine is in mainline..

    I haven't got a box to test for you, but, I would always 'lock out' the routine as the first thing before anthing else.
  • DarksideDarkside Posts: 345
    DHawthorne wrote:
    I wouldn't count on it evaluating left to right either. A lot of evaluations go the other way.
    I agree with Dave.

    With feedback,

    [touch,1] = coffee_active

    is not the same as

    coffee_active = [touch,1]

    Therefore, the time statement (TIME = ALARM_TIME), in my opinion is the wrong way around.

    Having said that, my eyes are dim, and I'll need a cup of your coffee_active in a minute...what time is it meant to go off?!

    :-)
  • Hi Stephen
    Correct, but when coffee_active is true, it will enter, and whilst it is true it will continue to execute until coffee_active is switched off.
    You're right, but my problem is that my processor is executing the code after the IF when COFFEE_ACTIVE is FALSE and the ALARM_TIME (set by the user) equals the system time (TIME).
    The bad code passes the IF routine regardless the state of COFFEE_ACTIVE until TIME becomes different to ALARM_TIME (in the next second).

    In the corrct running version of the code, all parameters are same except the positions of the two conditions of the IF ((condition1) AND (condition2)) are swapped.
    If COFFEE_ACTIVE is condition1, the code fails, if COFFEE_ACTIVE is condition2 everything is fine.

    The coffee maker becomes switched off either by pressing a button on TP or two hours after it's started (should be enough time to get up and have breakfast).
Sign In or Register to comment.