Travis you have to be very careful with the coding of custom functions to ensure that they execute very quickly becuase the ladder logic scanning mechanism can not proceed until the function completes.
I didn't like the sample HMI code because of the polling of the keyboard I/O every 0.1s. My version uses ladder logic to detect if a single key is pressed, and then and only then invokes a custom function. Why waste time in a custom function when there is no key pressed, therefore there can't be anything to do.
The the PLC comunicates with the I-7017 over RS-485 and the NETCMD$() function has to wait for the serial mesage to be transmitted to the I-7017, then processed by the I-7017 and then wait for a message to be send by the I-7017. This whole process could easily take 100ms. If you are talking to 3 I-7017s on the same scan your could be tying up the PLC for close to a 1/4 second every second!
I'd suggest that you poll I-7017 at the lowest rate that that makes sense. Do any of your analog inputs change much in 1 second or 10 seconds or 100 seconds? I worked with an 400 gallon aquarium that took about an hour to change 1 degree C with the heaters running full blast. There is no point in checking it's temperature once a second. I checked it once every minute and that was serious overkill.
For sake of arugument, lets say that you could safely poll your I-7017 once every 10 seconds. Poll the first one at 10 seconds, the second one at 11 seconds, the third one at 12 seconds...
The following is the code that I use for a single I-7017. The code is a little more complicated than the example code. This code is much more robust that the example code and provides methods to allow the PLC to continue to function even if the I-7017 dies.
The Simulation RELAY is checked to see if I am running the code in simulation vs. real hardware. The simulator doesn't simulate NETCMD$(). The ADCError is a RELAY that is set if the I-7017 quits responding or has not been successfully initiated. I do not want my PLC to lock up polling dead hardware.
I have a retry mechanism that will wait and resend the NETCMD$(). I found that this improved the reliability of the system tremendously. I kept track of how many retries were required and it was less than 1 every week on my system. The retry was much better than having the system fail once a week.
The for next loop at the end of the code extracts the ADC value for each channel and then scales it to enginerring values that are easier to read. It's easy, even for my old brain, to read 370 and think that means 37.0 C. The scaling components are stored as a set of 3 integer values in DM.
Writing to the LCD was done on the next ladder scan.
' ReadAllADC - function to read, scale and format all 8 analog value from I-7000
'
IF (TestIO(Simulation) = 0) AND (TestIO(ADCError) = 0)
' Read all available ADCs from a I-7000 device
' NETCMD$ is used to send command and wait for response
' using the suffix "~" to suppress the FCS computation
???I = 4???' Retry count
???W$ = NETCMD$(3,"#01"+CHR$(13)+"~")
???WHILE (LEN(W$)= 0) OR (ASC(W$,1)<> 62)
???I = I - 1
???IF (I = 0)
???SetIO ADCError : RETURN???' Still not working
???ENDIF
' Retry command
'
???DELAY 10
???W$ = NETCMD$(3,"#01"+CHR$(13)+"~")
???ENDWHILE
' Extract all numerical digits from the response but omit the
' decimal point. Each data fragment is represented as a percent of
' the A/D fullscale (+100.00 to -100.00). Full scale input is 250mV.
' "+xxx.yy" or "-xxx.yy".
' Extracted integer integer data will be returned in DM[201] to DM[208]
???FOR I = 0 to 7
???T = VAL(MID$(W$,2+I*7,4)+MID$(W$,7+I*7,2)) ' Get the digits w/o the period
' Scale the data to engineering units
'
???T = T * DM[41+I*3]
???IF (DM[42+I*3])
???T = T / DM[42+I*3]
???ENDIF
???T = T + DM[43+I*3]
???DM[201+I] = T???' Store Scaled result for this channel
???NEXT
ENDIF
[/color]
Gary D