wsular / EasyFlux-DL-CR3000

CR3000 datalogger program for Campbell open-path eddy-covariance systems, by @campbell-scientific
https://www.campbellsci.com/easyflux-dl
3 stars 5 forks source link

Profile sensors out-of-range #15

Closed patricktokeeffe closed 4 months ago

patricktokeeffe commented 5 months ago

Changing default profile sensor address from 3 to 4 revealed a subtle firmware error in CR3000 o/s: within For...Next loops the end counter has an off-by-one error.

Consider this program:

Public I, J                  'Declare variables.

BeginProg
  Scan (10,Sec,0,0)
    For I = 1 To 5
      J += 1
      Delay(0,1,Sec)
    Next

  J = 0
  NextScan
EndProg

According to the CRBasic Editor help text, the "final value of the counter" would be 5 ....

image

But when run, in reality, the counter terminates at 6:

image


The subtle part is, if you use variable assignment to store the loop value in a separate variable, the error seemingly disappears (presumably because despite the loop counter being incremented the loop statement block wasn't actually run an so the final assignment is never reached and therefore the index is not incremented out of bounds)

Consider this program instead:

Public I, J                  'Declare variables.

BeginProg
  Scan (10,Sec,0,0)
    For I = 1 To 5
      J = I
      Delay(0,1,Sec)
    Next

  NextScan
EndProg

Which results in different terminal values for the loop index (I) versus variable-assigned-based-on-loop-index (J):

image image

patricktokeeffe commented 5 months ago

OK nvm ... reviewed all the for loop index references and determined the post incremented indices observed above do not get used and are therefore not the source of index-out-of-range errors

The actual cause is accessing the same index variable from multiple scans. E.g try this program and watch how I jumps all over the place {0, 1, 2, 3, 4, 6, 7, 8, 9, 2, 4, 6, 8, 9, 6, 7, 8, 9, 0, 1, 2, 3, 4, 7, 8, 9, ...}

Public I, J, K                  'Declare variables.

BeginProg
  Scan (5,Sec,0,0)
    If TimeIntoInterval(5,10,Sec) Then
      For I = 6 To 8
        Delay(0,1,Sec)
      Next I
    EndIf
  NextScan

  SlowSequence
  Scan (15,Sec,0,0)
    K = 0
    For I = 0 To 5
      J = I
      Delay(0,1,Sec)
    Next
    K = I
  NextScan
EndProg
patricktokeeffe commented 4 months ago

Rolling back SLOWERSEQ makes this error irrelevant