Help with program error

TJF1960

Active Member
I thought I was finished with this program...but it has a weird problem that I have not been able to nail down yet. I know it is a long program and troubleshooting someone else's code is a pain. But if you all could just glance at it maybe the problem will be obvious to you.
 
The problem I am seeing is that randomly anywhere between 10 minutes to a couple of hours the AIP bits zero out for some reason. The AIP bits are set in VAR2 until called by the IO section of the code and placed in ram1. Bits 16-24 (0X1FF0000) hold the values for the current AIP readings. I have not been able to find out if var2 is getting set to 0 or if ram1 is getting set to zero.
 
Thanks in advance for any and all help and suggestions.
START
 SET VAR1 0
 SET VAR2 0
 SET VAR3 0
 SET VAR4 0
 SET VAR5 0
 SET VAR6 0
 SET VAR7 0
 SET VAR8 0
 SET RAM1 0
 SET RAM2 0
 SET RAM3 0
 SET RAM4 0
 SET RAM5 0
 SET RAM6 0
 SET RAM7 0
 SET RAM8 0
 SET OP8 1
 DELAY 5000
 SET RAM8 64
 CALLSUB AIP
 DELAY 1000
 CALLSUB TEMP1
 DELAY 1000
 CALLSUB TEMP2
 DELAY 1000
 CALLSUB IO
 CALLSUB HB
 DELAY 1000
 
LOOP:
 TSTLT T5 1119
 CALLSUB FANOFF
 TSTGT T5 1124
 CALLSUB FANON
 TSTEQ OP8[40000] 1
 SET OP8 0
 TSTEQ OP1 1
 CALLSUB MEDIAON
 TSTEQ IP2 1
 CALLSUB MEDIADWN
 TSTEQ RAM5 2
 CALLSUB MEDIAOFF
 TSTEQ OP5[1000] 0
 CALLSUB SMEDIAOFF
 TSTEQ VAR8 1
 GOTO START
 TSTEQ VAR8 2
 GOTO LOOP
 DIV CTS 86400 RAM1
 MUL RAM1 86400 RAM1
 SUB CTS RAM1 RAM1
 TSTEQ RAM1 10800
 SET OP8 1
 TSTEQ RAM1 39600
 SET OP8 1
 TSTEQ RAM1 68400
 SET OP8 1
 
 MOD RAM1 2
 CNZ IOA       
 CZ IO
 
 MOD RAM1 15
 CNZ AIPA       
 CZ AIP
  
 MOD RAM1 30
 CNZ HBA
 CZ HB
  
 MOD RAM1 30
 CNZ TEMP1A
 CZ TEMP1
  
 MOD RAM1 30
 CNZ TEMP2A
 CZ TEMP2
 
 GOTO LOOP
 END
ABORT:
 RET
IOA:
 ANDB RAM8 0XFFFFFFFE RAM8
 RET
AIPA:
 ANDB RAM8 0XFFFFFFFD RAM8
 RET
HBA:
 ANDB RAM8 0XFFFFFFFB RAM8
 RET
TEMP1A:
 ANDB RAM8 0XFFFFFFF7 RAM8
 RET
TEMP2A:
 ANDB RAM8 0XFFFFFFEF RAM8
 RET
 
REFRESHA:
 ANDB RAM8 0XFFFFFFDF RAM8
 RET
 
IO:
 ANDB RAM8 1
 BNZ ABORT
 ORB RAM8 1 RAM8
 
 SET RAM1 0
 TSTEQ IP1 1
 ORB RAM1 1 RAM1
 TSTEQ IP2 1
 ORB RAM1 2 RAM1
 TSTEQ IP3 1
 ORB RAM1 4 RAM1
 TSTEQ IP4 1
 ORB RAM1 8 RAM1
 TSTEQ IP5 1
 ORB RAM1 16 RAM1
 TSTEQ IP6 1
 ORB RAM1 32 RAM1
 TSTEQ IP7 1
 ORB RAM1 64 RAM1
 TSTEQ IP8 1
 ORB RAM1 128 RAM1
 TSTEQ OP1 1
 ORB RAM1 256 RAM1
 TSTEQ OP2 1
 ORB RAM1 512 RAM1
 TSTEQ OP3 1
 ORB RAM1 1024 RAM1
 TSTEQ OP4 1
 ORB RAM1 2048 RAM1
 TSTEQ OP5 1
 ORB RAM1 4096 RAM1
 TSTEQ OP6 1
 ORB RAM1 8192 RAM1
 TSTEQ OP7 1
 ORB RAM1 16384 RAM1
 TSTEQ OP8 1
 ORB RAM1 32768 RAM1
 ORB RAM1 0X40000000 RAM1
 
 ANDB RAM1 0XFE00FFFF RAM1
 ORB RAM1 VAR2 RAM1
 
 TSTEQ VAR1 RAM1
 RET
 WEBSET URL1 RAM1
 SET VAR1 RAM1 
 RET
AIP:
 ANDB RAM8 2
 BNZ ABORT
 ORB RAM8 2 RAM8
 
 SET RAM1 1
 TSTGE AIP1 3
 ADD 1 RAM1 RAM1
 TSTGE AIP1 130
 ADD 1 RAM1 RAM1
 TSTGE AIP1 142
 ADD 1 RAM1 RAM1
 TSTGE AIP1 185
 ADD 1 RAM1 RAM1
 MUL RAM1 0X10000 RAM1
 ANDB VAR2 0XFFF8FFFF VAR2
 ORB VAR2 RAM1 VAR2
 
 SET RAM1 1
 TSTGE AIP3 75
 ADD 1 RAM1 RAM1
 TSTGE AIP3 107
 ADD 1 RAM1 RAM1
 TSTGE AIP3 129
 ADD 1 RAM1 RAM1
 MUL RAM1 0X400000 RAM1
 ANDB VAR2 0XFE3FFFFF VAR2
 ORB VAR2 RAM1 VAR2
  
 TSTEQ OP8 0
 RET 
 SET RAM1 1
 TSTGE AIP2 50
 ADD 1 RAM1 RAM1
 TSTGE AIP2 59
 ADD 1 RAM1 RAM1
 TSTGE AIP2 80
 ADD 1 RAM1 RAM1
 MUL RAM1 0X80000 RAM1
 ANDB VAR2 0XFFC7FFFF VAR2
 ORB VAR2 RAM1 VAR2
 RET
HB:
 ANDB RAM8 4
 BNZ ABORT
 ORB RAM8 4 RAM8
 SET RAM1 0
 DIV RAM8 268435456 RAM1
 TSTEQ RAM1 5
 SET RAM1 6
 TSTEQ RAM1 4
 SET RAM1 5
 TSTEQ RAM1 3
 SET RAM1 4
 TSTEQ RAM1 2
 SET RAM1 3
 TSTEQ RAM1 1
 SET RAM1 2
 TSTEQ RAM1 0
 SET RAM1 1
 TSTEQ RAM1 6
 SET RAM1 2
 WEBSET URL4 RAM1
 MUL RAM1 268435456 RAM1
 ANDB RAM8 0X8FFFFFFF RAM8
 ORB RAM8 RAM1 RAM8
 RET 
TEMP1:
 ANDB RAM8 8
 BNZ ABORT
 ORB RAM8 8 RAM8
 
 SET RAM1 0
 SET RAM3 0
 ADD T1 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X8000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T2 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X10000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 100 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T3 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X20000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 10000 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T4 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X40000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 1000000 RAM1
 ADD RAM1 RAM3 RAM3
 TSTEQ RAM3 VAR3
 RET
 WEBSET URL2 RAM3
 SET VAR3 RAM3 
 RET
TEMP2:
 ANDB RAM8 16
 BNZ ABORT
 ORB RAM8 16 RAM8
 
 SET RAM1 0
 SET RAM3 0
 ADD T5 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X8000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T6 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X10000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 100 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T7 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X20000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 10000 RAM1
 ADD RAM1 RAM3 RAM3
 ADD T8 5 RAM1
 DIV RAM1 10 RAM1
 TSTGE RAM1 100
 ORB RAM3 0X40000000 RAM3
 TSTGE RAM1 100
 SUB RAM1 100 RAM1
 MUL RAM1 1000000 RAM1
 ADD RAM1 RAM3 RAM3
 TSTEQ RAM3 VAR4
 RET
 WEBSET URL3 RAM3
 SET VAR4 RAM3 
 RET
 
MEDIAON:
 TSTEQ IP2 1
 RET
 TSTEQ RAM5 1
 RET
 TSTEQ RAM5 2
 RET
 TSTLE AIP3 105
 SET OP1 0
 TSTEQ OP1[10000] 1
 SET OP2 1
 TSTEQ OP2[2000] 1
 SET RAM5 1
 TSTEQ OP2[2000] 1
 SET OP2 0
 RET
MEDIADWN:
 TSTEQ RAM5 0
 RET
 TSTEQ RAM5 2
 RET
 TSTEQ OP2[8000] 1
 SET RAM5 2
 TSTEQ OP2[8000] 1
 SET OP2 0
 RET
MEDIAOFF:
 TSTEQ IP2[30000] 0
 SET OP1 0
 TSTEQ OP1[5000] 0
 SET RAM5 0
 RET 
SMEDIAOFF:
 TSTEQ OP6 1
 SET OP6 0
 RET
FANOFF:
 TSTEQ OP3 0
 RET
 SET OP3 0
 RET
FANON:
 TSTEQ OP3 1
 RET
 SET OP3 1
 RET
 
 
Not sure what the purpose of these six lines:
TSTEQ RAM1 10800
 SET OP8 1
 TSTEQ RAM1 39600
 SET OP8 1
 TSTEQ RAM1 68400
 SET OP8 1
 
Also, based on az1324's request, rev 17e firmware will change MOD no longer set zero bit.  It seems your code depends on MOD to set zero bit.  Should we change back to let MOD set zero bit?
 
Three preset times a day OP8 is turned on if RAM1 equals either of those three numbers.
 
Well, first I rewrote my code using non-delay and you told me you were possibly going to do away with non-delay. So I rewrote my code again using MOD in it. Now you are telling me this wont work in future updates either.
 
Look, you guys are way ahead of me in coding and understanding what should and what shouldn't be.  So I accept whatever changes you all make.  
 
What I am trying to do is write 1 program which I can use on all my boards and write it so it is future proof (as much as possible). So 2 years from now if I need to replace a board or add another board I can pull out the code and copy it over without much hassle and without having to re-learn how to write this code again. Does that make sense?
 
I know in this latest code I still have an instance or two of non-blocking delay I need to get rid of. And also need to get rid of Mod  Is there anything else I am doing which will not work in the future revs?
 
Thanks,
tim
 
Well really this is not a good way to do it anyway:
 
 MOD RAM1 2
 CNZ IOA       
 CZ IO
 
Because if the first call is made then things happening within IOA change the zero bit meaning the second call could be made unintentionally.  So you should use branches instead.  Or I guess you could make sure to set the zero bit before returning from the first sub.
 
Also
 
TSTEQ RAM1 5
 SET RAM1 6
 TSTEQ RAM1 4
 SET RAM1 5
 TSTEQ RAM1 3
 SET RAM1 4
 TSTEQ RAM1 2
 SET RAM1 3
 TSTEQ RAM1 1
 SET RAM1 2
 TSTEQ RAM1 0
 SET RAM1 1
 TSTEQ RAM1 6
 SET RAM1 2
 
Isn't that the same as
 
ADD RAM1 1 RAM1
TSTEQ RAM1 7
SET RAM1 2
 
As far as your issue, I would just say check all the ANDB VAR2 instructions to make sure you have the right values.
 
TJF1960 said:
Three preset times a day OP8 is turned on if RAM1 equals either of those three numbers.
 
Well, first I rewrote my code using non-delay and you told me you were possibly going to do away with non-delay. So I rewrote my code again using MOD in it. Now you are telling me this wont work in future updates either.
 
Look, you guys are way ahead of me in coding and understanding what should and what shouldn't be.  So I accept whatever changes you all make.  
 
What I am trying to do is write 1 program which I can use on all my boards and write it so it is future proof (as much as possible). So 2 years from now if I need to replace a board or add another board I can pull out the code and copy it over without much hassle and without having to re-learn how to write this code again. Does that make sense?
 
I know in this latest code I still have an instance or two of non-blocking delay I need to get rid of. And also need to get rid of Mod  Is there anything else I am doing which will not work in the future revs?
 
Thanks,
tim
We were just discussing,  since so many people relay on non-blocking delay, we will keep them.
 
az1324 said:
Well really this is not a good way to do it anyway:
 
 MOD RAM1 2
 CNZ IOA       
 CZ IO
 
Because if the first call is made then things happening within IOA change the zero bit meaning the second call could be made unintentionally.  So you should use branches instead.  Or I guess you could make sure to set the zero bit before returning from the first sub.
I will try and work on a different method then.
I have had some difficulty in determining where you end up when using branches, if the branch runs to the end "ret" does the program return to start or return to loop? That is the main difference between branch and callsub, right? If the "ret" sends you back to start from a branch do you then just specify goto loop instead of return?
az1324 said:
Also
 
TSTEQ RAM1 5
 SET RAM1 6
 TSTEQ RAM1 4
 SET RAM1 5
 TSTEQ RAM1 3
 SET RAM1 4
 TSTEQ RAM1 2
 SET RAM1 3
 TSTEQ RAM1 1
 SET RAM1 2
 TSTEQ RAM1 0
 SET RAM1 1
 TSTEQ RAM1 6
 SET RAM1 2
 
Isn't that the same as
 
ADD RAM1 1 RAM1
TSTEQ RAM1 7
SET RAM1 2
Wow! You really nailed it! Thank you!
az1324 said:
As far as your issue, I would just say check all the ANDB VAR2 instructions to make sure you have the right values.
I have checked and rechecked. Near as I can see all my values are correct. I have been thinking that maybe it is a timing issue and may be related to your first comment about the zero bit being reset and unintentionally making a second call. Not sure.
Thanks for your help.
 
CAI_Support,
 
I am glad you decided to keep the non-blocking delay, it is such a slick function and easy to use.
Thanks,
Tim
 
TJF1960 said:
I will try and work on a different method then.
I have had some difficulty in determining where you end up when using branches, if the branch runs to the end "ret" does the program return to start or return to loop? That is the main difference between branch and callsub, right? If the "ret" sends you back to start from a branch do you then just specify goto loop instead of return?
 
Yes branch is like goto.  So just use a goto at the end.  For example replace the RET in IOA with GOTO IOA_RET
 
MOD RAM1 2 RAM2
BNZ RAM2 IOA       
CALLSUB IO
IOA_RET:
 
I have re designed the code for this project and it seems to be working well except for 1 detail. In the code var2 holds data collected only during certain times. The problem is var2 somehow gets set to 0 at ramdom times. I have gone over the code and the only instances of var2 in the code appear to be correct and shouldn't set it to 0. The only thing I can see that makes me wonder is if this bit of code could have an affect on var2:
 
ANDB RAM1 0XFE00FFFF RAM1
ORB RAM1 RAM2 RAM1
ORB RAM1 VAR2 RAM1
 
Thanks,
Tim
 
Tim,
 
Which version firmware and build time do you run on this one? It shows those information in the /api/status.xml
 
3.02.17 was replaced with 3.02.17d with better method to read web server respond.  If you send the board back, we can provide you with latest 3.02.17e update, which has a lot of additional features.  Since end of July, we have shipped boards all with bootloader.  That feature enabled firmware update without shipping back in the future.
 
Thank you for the offer.
 
Is the problem I described likely a problem with the board or something in my code I am not seeing?
 
Thanks,
Tim
 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
edit:
 
Ok, just ran the code on an earlier version board (v3.02.16c) and it does the same thing. Setting VAR2 to 0 randomly. I have pasted all instances of VAR2 in the code. Is there anything here which you can see which would set var2 to 0?
 
 
ANDB RAM1 0XFE00FFFF RAM1             these 3 lines appear just in this order in a sub.
 ORB RAM1 RAM2 RAM1
 ORB RAM1 VAR2 RAM1
 
TSTEQ OP8 0                                            the rest of these lines also are in order in another sub and these lines only run when OP8 is 1 and op1 wasn't 1 when it happened.
 RET 
 SET VAR2 1
 TSTGE AIP2 50
 ADD 1 VAR2 VAR2
 TSTGE AIP2 59
 ADD 1 VAR2 VAR2
 TSTGE AIP2 80
 ADD 1 VAR2 VAR2
 MUL VAR2 0X80000 VAR2
 RET 
 
Thats it, those are the only references to VAR2 in the whole code. I hope someone can tell me what is wrong.
 
Thanks,
tim
 
Tim,
 
I checked firmware, there is nothing in the firmware code causing VAR2 to be set to zero.  There are few people running large PLC code, we did not hear from them any problem like this.
From your code, before MUL, VAR2 max can be 4. then 4 times 0x80000 still fit in the 32bit signed number.   What if you change VAR2 with another VAR, would same problem happen to that VAR?
 
Back
Top