I read this forum topic linked below and have my application working pretty well.
https://labjack.com/forums/python/setting-counter-modes
I had some issues with using timer mode 6 (firmware counter with debounce) where it only registered a few counts and then stopped responding to new edges. I'm not exactly able to reproduce the problem but initially I was configuring my U3 using LJControlPanel for the startup defaults, but now I am using software configuration in my program to force it how I want it, and that seems to work better.
My project is a dual Btu meter system where the first meter is 2 temp sensors (supply and return) and a flow meter coming from the boiler to the buffer tank, and then the second Btu meter is 2 sensors and a flow meter from the buffer tank to the greenhouse. The flow meters put out 1 pulse per gallon, design flow is 11 gpm, and the pulse is a reed switch which is wired to ground the timer input when actuated. The negative pulse duration is approximately 1/2 second. I am using the EI-1034 sensors for water temperature which are really great! I appreciate the long sensor tube which is able to get down into the flow stream in the pipes.
Here is the python code:
# dual Btu meter data logger
#
# Peter Oven
# 2017-02-10 first release
# 2017-02-23 new revision
# calibration data
t1Factor = 100
t1Offset = 0
t2Factor = 100
t2Offset = 0
t3Factor = 100
t3Offset = 0
t4Factor = 100
t4Offset = 0
import sys
import time
from time import sleep
import os.path
from datetime import datetime
# flow calculation arrays
times = [datetime.now()]*12
f1Vals = [0]*12
f2Vals = [0]*12
# initialize labjack instance
import u3
d = u3.U3()
def get_data():
# get analog input data
t1 = d.getAIN(0) * t1Factor + t1Offset
t2 = d.getAIN(1) * t2Factor + t2Offset
t3 = d.getAIN(2) * t3Factor + t3Offset
t4 = d.getAIN(3) * t4Factor + t4Offset
# get counter data
f1Result = d.getFeedback( u3.Timer0() )
f1 = f1Result[0]
f2Result = d.getFeedback( u3.Timer1() )
f2 = f2Result[0]
# get internal labjack temperature
ljtemp = ( d.getTemperature() - 273.15 ) * 1.8 + 32 # convert temp from K to F
return [t1,t2,t3,t4,f1,f2,ljtemp]
def store_data(t1,t2,t3,t4,f1,f2,ljtemp):
# get date
date = time.strftime("%Y%m%d")
filename = date + ".csv"
dateAndTime = time.strftime("%m/%d/%Y %H:%M:%S")
# check file contents
if os.path.isfile(filename):
target = open(filename, 'r')
line = target.readline()
target.close()
if line[0:4] == "date":
fileValid = 1
else:
fileValid = 0
else:
fileValid = 0
# write new file with header if necessary
if not fileValid:
target = open(filename, 'w')
target.write("dateandtime,ljtemp,t1,t2,f1,t3,t4,f2")
target.write("\n")
target.close()
# append to file
target = open(filename, 'a')
target.write( dateAndTime + "," + str(ljtemp) + "," + str(t1) + "," + str(t2) + "," + str(f1) + "," + str(t3) + "," + str(t4) + "," + str(f2) )
target.write("\n")
target.close()
def h2o_density( temp ):
# calculate density of water from a straight line approximation
# 120F >> 8.2498 lb/gal
# 160F >> 8.1537 lb/gal
#return (8.2498-8.1537)/(120-160)*(temp-120)+8.2498
# trendline using values from 60 to 200F
# form is ax^2+bx+c
a = -0.000008637907
b = 0.000052557126
c = 8.368228616
return a*temp*temp+b*temp+c
try:
# get config
config = d.configIO()
configTimer = d.configTimerClock()
# check config
if( config['NumberOfTimersEnabled'] != 2 or
config['TimerCounterPinOffset'] != 4 or
config['FIOAnalog'] != 0x0F or
config['TimerCounterConfig'] != 66 or
configTimer['TimerClockBase'] != 2 or
configTimer['TimerClockDivisor'] != 0 ):
print "setting up labjack U3 configuration"
# Set the timer clock
d.configTimerClock( TimerClockBase = 2, TimerClockDivisor = 0)
# Enable 4 analog inputs for FIO0-3 and then 2 counters starting at FIO4
d.configIO( FIOAnalog = 0x0F, NumberOfTimersEnabled = 2, TimerCounterPinOffset = 4 )
# Configure the timer for firmware counter with debounce (mode 6).
d.getFeedback( u3.Timer0Config(TimerMode = 6, Value = 62) )
d.getFeedback( u3.Timer1Config(TimerMode = 6, Value = 62) )
else:
print "skipping configuration"
while(1):
sleep( 0.1 )
now = datetime.now()
sec = now.second
if (0 == sec % 5):
# print time to console
print "\n"
print time.strftime("%m/%d/%Y %H:%M:%S")
# get data from labjack
result = get_data()
t1 = result[0]
t2 = result[1]
t3 = result[2]
t4 = result[3]
f1 = result[4]
f2 = result[5]
ljtemp = result[6]
# calculate gpm
times.insert(0,now)
f1Vals.insert(0,f1)
f2Vals.insert(0,f2)
oldtime = times.pop()
oldf1 = f1Vals.pop()
oldf2 = f2Vals.pop()
delta = now - oldtime
f1GPM = (f1 - oldf1) / delta.total_seconds() * 60
f2GPM = (f2 - oldf2) / delta.total_seconds() * 60
# calculate Btu/hr
boilerBtu = f1GPM * (t1-t2) * 60 * h2o_density( t1 )
districtBtu = f2GPM * (t3-t4) * 60 * h2o_density( t3 )
# print data to console
print "T1:", t1
print "T2:", t2
print "T1-T2:", t1-t2
print "T3:", t3
print "T4:", t4
print "T3-T4:", t3-t4
print "F1 count:", f1
print "F1 GPM:", f1GPM
print "F2 count:", f2
print "F2 GPM:", f2GPM
print "Boiler Btu/hr:", boilerBtu
print "Greenhouse Btu/hr:", districtBtu
print "LabJack Temp:", ljtemp
# log data to file every minute
if ( 0 == sec ):
store_data(t1,t2,t3,t4,f1,f2,ljtemp)
# wait until we are in the next second so we don't trigger this again
sleep( 1.1 )
finally:
d.close()
In the "#check config" section of the program I verify that the U3 is still set up the way I want it, or else I leave it alone (this preserves the counts in the firmware counter). However, I cannot figure out how to verify the configuration for "d.getFeedback( u3.Timer0Config(TimerMode = 6, Value = 62) )"? Is there a way to read this setting in order to check that it has not been changed by someone in LJControlPanel or by some other code?
The U3 does not have a way to read out the current timer modes. The saving grace is that only one application can connect the u3 at a time. So if your application has a open handle to the U3 then other applications cannot connect to that U3.
Thanks for the response. Just to clarify, if I run the code
config = d.configIO()
then checking the value of
config['TimerCounterConfig']
will tell me the modes, if it is 66, then that means mode 6 for both timers, right? But it can't tell me the debounce time (which is 62 in my application)?
The TimerCounterConfig setting is documented here:
https://labjack.com/support/datasheets/u3/low-level-function-reference/c...
With an 8-byte value it will tell you how many timers are enabled, the counters enabled and the pin offset. It will not provide timer mode information. A value of 66 (b01000010) indicates 2 timers are enabled (bxxxxxx10), Counter 0 is disabled (bxxxxx0xx), Counter 1 is disabled (bxxxx0xxx) and TimerCounterPinOffset is 4 (b0100xxxx).
Thanks, that makes sense. I see that the sixes were just a coincidence. I guess I am checking the same the same thing twice, not that it hurts anything, since
config['NumberOfTimersEnabled'] != 2 or
config['TimerCounterPinOffset'] != 4
is the same thing as
config['TimerCounterConfig'] != 66
with the exception that the first method does not verify the number of counters enabled (which I don't care about, since I don't use pins above FIO5).