Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Decrementing counter of encoder reading

cRIO 9053

9411 module

Wheel encoder GKZ-1000

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

Python 3.9.5 with nidaqmx API

 

I can read the counter and see it increasing as I rotate the wheel, but I need to detect changes in both directions, so my preference would be that the counter decrease in one direction, increase in the other.

 

Here's a snippet of what I am doing (With some leftovers from previous attempts).  

 


def startUsingRotation(self):
global running
total = 0.0
task = ni.Task(new_task_name="readCtr0")
# Can't seem to make this work, and perhaps this is not what we need, as direction matters
#channelA = task.ci_channels.add_ci_ang_encoder_chan(counter = 'Mod3/ctr0', decoding_type = EncoderType.X_1, zidx_enable=True, units=AngleUnits.DEGREES, pulses_per_rev=4000, initial_angle=0.0)
#channelA = task.ci_channels.add_ci_ang_encoder_chan(counter = 'Mod3/ctr0', decoding_type = EncoderType.X_1, zidx_phase=nidaqmx.constants.EncoderZIndexPhase.AHIGH_BHIGH, zidx_val=0, zidx_enable=True, units=AngleUnits.DEGREES, pulses_per_rev=1000, initial_angle=0.0)
#task.timing.cfg_samp_clk_timing(rate=10000, sample_mode=AcquisitionType.CONTINUOUS,samps_per_chan=100)
#task.timing.samp_timing_type = nidaqmx.constants.SampleTimingType.ON_DEMAND

channelA = task.ci_channels.add_ci_count_edges_chan(counter='Mod3/ctr0')
channelA.ci_count_edges_dig_fltr_min_pulse_width = 0.0003
channelA.ci_count_edges_dig_fltr_enable = True

#task.timing.samp_clk_dig_sync_enable = True
task.timing.samp_clk_overrun_behavior = nidaqmx.constants.OverflowBehavior.TOP_TASK_AND_ERROR
#channelA.ci_encoder_decoding_type = nidaqmx.constants.EncoderType.X_1
#channelA.ci_count_edges_active_edge = nidaqmx.constants.Edge.RISING
task.start()
previous = [0.0]
running = True
while running:
try:
count=task.read(number_of_samples_per_channel=nidaqmx.constants.READ_ALL_AVAILABLE)
print("Current register is {}".format(channelA.ci_count))
except nidaqmx.errors.DaqError:
print("Read error encountered")
continue

if count[0] != previous[0]:
if count[0] != previous[0] + 1:
print("Increased count by more than one")
#total += (count[0] - previous[0])
total = count[0]
print("Total movement {:.3f} Total clicks {}".format(total, count[0]))
if total % self._encode_clicks == 0:
print("revolution complete")
previous=count
print("Cleanup")
task.stop()     

 

0 Kudos
Message 1 of 14
(2,272 Views)

I don't know the syntax for the Python DAQmx API, but can offer up these general thoughts:

 

1. You *will* want to configure the task for an angular encoder rather than for edge counting

2. You'll need to further configure the task to specify where the A and B channels are wired.   (And Z if you're using it).  Sorry, I don't know the Python syntax for this.

3. At least at first, try to get this running without configuring a sample clock so that you keep the task in on-demand mode.

4. With no sample clock, you'll need to read single values from the task rather than an array.  Again, dunno what the Python syntax looks like for that.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
0 Kudos
Message 2 of 14
(2,251 Views)

I did make an attempt at setting the task up as an angular encoder, but I could never get the signal debounced by setting the minimum pulse width. So, I could read movement, and the values were what I expected (0.36, since I have a 1000 pulse encoder), but I have the same directional problem (my reading is -0.36 in both directions), and sometimes I just get a stream of readings even when there is no motion:

 

Thanks for the advice -- I will try again.

 

-Evan-

0 Kudos
Message 3 of 14
(2,235 Views)

I revisited the code treating this as an angular encoder, and corrected my mistake on debouncing the signal.

 

Now I don't see the spurious readings while the wheel is stationary.

 

However, I still get odd readings: negative values in both directions of rotation -- mostly.  Sometimes, I see a positive value read evan while rotating in one direction.

 

I've tried various things, so there are likely settings in the code that may not be needed.  I don't intend to use Z, but things are really odd if I don't enable z index support.

 

def startUsingRotation(self):
global running
total = 0.0
self.log.debug("Begin rotation detection using counters")
task = ni.Task(new_task_name="readCtr0")
#channelA = task.ci_channels.add_ci_ang_encoder_chan(counter = 'Mod3/ctr0', decoding_type = EncoderType.X_1, zidx_enable=True, units=AngleUnits.DEGREES, pulses_per_rev=1000, initial_angle=0.0)
channelA = task.ci_channels.add_ci_ang_encoder_chan(counter = 'Mod3/ctr0', decoding_type = EncoderType.X_1, zidx_enable=True, zidx_phase=nidaqmx.constants.EncoderZIndexPhase.AHIGH_BHIGH, units=AngleUnits.DEGREES, pulses_per_rev=1000, initial_angle=0.0)

channelA.ci_encoder_a_input_dig_fltr_min_pulse_width = 0.0003
channelA.ci_encoder_a_input_dig_fltr_enable = True
channelA.ci_encoder_a_input_term = 'PFI0'
channelA.ci_encoder_b_input_dig_fltr_min_pulse_width = 0.0003
channelA.ci_encoder_b_input_dig_fltr_enable = True
channelA.ci_encoder_b_input_term = 'PFI2'
channelA.ci_encoder_z_input_dig_fltr_min_pulse_width = ODOMETER_DEBOUNCE
channelA.ci_encoder_z_input_dig_fltr_enable = True
channelA.ci_encoder_z_input_term = 'PFI1'

#task.timing.samp_clk_overrun_behavior = nidaqmx.constants.OverflowBehavior.TOP_TASK_AND_ERROR
#channelA.ci_encoder_decoding_type = nidaqmx.constants.EncoderType.X_1
#channelA.ci_ang_encoder_units = nidaqmx.constants.AngleUnits.DEGREES

task.start()
previous = 0.0
running = True
while running:
try:
ang =task.read() #number_of_samples_per_channel=nidaqmx.constants.READ_ALL_AVAILABLE)
#print("Current register is {}".format(channelA.ci_count))
except nidaqmx.errors.DaqError:
self.log.error("Read error encountered")
continue

if ang != 0:
total += ang
print("Total movement {:.3f} Angle change {}".format(total, ang) 

 

0 Kudos
Message 4 of 14
(2,206 Views)

When you perform ang=task.read(), the value 'ang' is *already* the cumulative total change in angle.  There's no need for "total += ang", just display "ang" itself.   See how that goes.

 

 

-Kevin P

 

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
0 Kudos
Message 5 of 14
(2,197 Views)

Ah! This is a helpful observation.  The read mostly returns -0.36 each time, so I was totaling it up.  Now that I set the zidx_val to 100, I see the ang always reading -100.36, so it must always be resetting.

 

I actually don't need z values -- can I just not wire that up and turn support off?  I think I tried to just set it off, and got strange readings for the angle.

 

-Evan-

0 Kudos
Message 6 of 14
(2,191 Views)

You should be able to change the config to set "zidx_enable=False" to turn off the reset action, whether or not you disconnect the physical wiring.  You may also want to consider setting "decoding_type = EncoderType.X_4" to get a boost in resolution.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy coming to an end (finally!). Permanent license pricing remains WIP. Tread carefully.
0 Kudos
Message 7 of 14
(2,185 Views)

Reading your description, I assume that the polarity of the a, b and/or z signals is incorrect.

0 Kudos
Message 8 of 14
(2,173 Views)

It's even worse, and I finally got around to scoping the signals to check the polarity.  The reason that all I can do is count edges is that things are a bit fried -- A, B, and Z all have pulses _at the same time_.  Now I know why Z was constantly resetting to zero with every small move.  I've ordered a new one, and I'm sure I will have a new flurry of questions why I try to get that one working.

0 Kudos
Message 9 of 14
(2,159 Views)

This indeed explains a lot!

 

Is there any doubt about how you wired the signals or is it obvious that the encoder is defective?

0 Kudos
Message 10 of 14
(2,148 Views)