Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Odd values reading rotary encoder

Compact RIO 9053 with 9411 Module

Python 3.9.5

Wheel encoder:  (The GKZ-1000 model)

 https://cdn.automationdirect.com/static/specs/encoderhd.pdf

My goal here is to determine distance travelled by the wheel based on encoder pulses.

 

I've tried two different approaches in the attached code:

 

Angular encoder

With this snippet, I see noisy samples (at least that is my interpretation) as I obtain readings even with there is no movement.  This doesn't always happen.  Sometimes the readings stop when the wheel does.

 

total = 0.0
with ni.Task() as task:
channelA = task.ci_channels.add_ci_ang_encoder_chan(counter = 'Mod3/ctr0', decoding_type = EncoderType.X_1, zidx_val=0, zidx_enable=True, units=AngleUnits.DEGREES, pulses_per_rev=1000, initial_angle=0.0)
#task.timing.cfg_samp_clk_timing(rate=1000.0, sample_mode=AcquisitionType.CONTINUOUS,samps_per_chan=1000)
#task.timing.samp_timing_type = nidaqmx.constants.SampleTimingType.ON_DEMAND
#channelA.ci_count_edges_count_dir_dig_fltr_min_pulse_width = 0.001
#channelA.ci_count_edges_count_reset_dig_fltr_enable = True
task.start()
previous = 0.0
while True:
ang=task.read()
if ang != 0:
total += ang
print("Total movement{:.3f}".format(total))
previous=ang

 

But, attempts to debounce the signal by setting the pulse width always fail, and I get complaints about setting an external clock, so clearly I am doing something wrong.

 

Another attempt -- rising edge/change detection, shown in this snippet

 

task = ni.Task()

# These are the three pins on the encoder for a,b, and z
channelA = task.di_channels.add_di_chan("Mod3/port0/line0")
channelB = task.di_channels.add_di_chan("Mod3/port0/line1")
channelZ = task.di_channels.add_di_chan("Mod3/port0/line2")


# Detect the rising edge
#task.timing.cfg_change_detection_timing(rising_edge_chan="Mod3/port0/line0,Mod3/Port0/line1", sample_mode=AcquisitionType.CONTINUOUS,samps_per_chan=10)
task.timing.cfg_change_detection_timing(rising_edge_chan="Mod3/port0/line0,Mod3/port0/line1", sample_mode=AcquisitionType.CONTINUOUS)
task.timing.samp_timing_type = nidaqmx.constants.SampleTimingType.CHANGE_DETECTION
#task.timing.cfg_dig_edge_start_trig(trigger_source="Mod3/port0/line0", trigger_edge=Edge.RISING)

# Debounce the signal for 0.01 second
channelA.di_dig_fltr_min_pulse_width = 0.0001
channelB.di_dig_fltr_min_pulse_width = 0.0001
channelZ.di_dig_fltr_min_pulse_width = 0.0001

channelA.di_dig_fltr_enable = True
channelB.di_dig_fltr_enable = True
channelZ.di_dig_fltr_enable = True

channels = task.di_channels
print(channels.channel_names)


task.start()
value = task.read(number_of_samples_per_channel=nidaqmx.constants.READ_ALL_AVAILABLE)
#value = task.read()
aPrevious = self._isPositive(value[0])
bPrevious = self._isPositive(value[1])
i = 0
# The distance traveled in mm
totalClicks = 0
# We want to detect rising to rising as a single click, so the first indicates the start, and the second, the
# end
armed = False

while True:
i = i + 1
#value = task.read(number_of_samples_per_channel=nidaqmx.constants.READ_ALL_AVAILABLE)
value = task.read(number_of_samples_per_channel=1)
#value = task.read()
# Determine if the samples are mostly true or false
if(len(value[0]) > 0):
aCurrent = self._isPositive(value[0])
bCurrent = self._isPositive(value[1])
totalClicks += 1
print("aCurrent {} bCurrent {} (previous {},{})".format(aCurrent, bCurrent, aPrevious, bPrevious))
#print("Total distance: {:.2f} mm Total Clicks {:d}".format(totalClicks * self._distance_per_click, totalClicks),end="\r")
aPrevious = aCurrent
bPrevious = bCurrent
#print("{} -> {}".format(value[0],aCurrent))

My problems here are multi-fold

- I get a reading of true, true, true for most readings I take

- Except I get the occasional false reading if I move the wheel quickly.

 

Am I off the the weeds here?  Any pointers for getting this to work?

 

I've attached the code to this post, but it imports other things from my environment, so it's not completely usable as a standalone sample.

I can strip this down to an example if that helps.

 

python PhysicalOdometer.py -c "Mod5/port0"


Thanks,

-Evan-

0 Kudos
Message 1 of 1
(989 Views)