pigpio: Wave deletion does not happen as expected

I must first say im impressed by this library. Im using it for a hobby CNC project and it makes it possible to do parallel execution of waves for several motors based on GPIO’s.

But i think there is an issue with wave deletion.
When using a python add-create-send-delete loop for waves, i cannot always remove the completed waves. It leads to ‘No more CBs for waveform’ when creating new waves.

I can recreate the problem with a simple loop. When the deletion does not happen, the wave id increases continuously.

and here is the code

import pigpio
import time
import random

pi = pigpio.pi('navio2.local')

# system info
print 'pigpiod version: {}'.format(pi.get_pigpio_version())  # 61
print 'pigpio.py version: {}'.format(pigpio.VERSION)  # 1.36
print 'wave_get_max_pulses: {}'.format(pi.wave_get_max_pulses()) # 12000

gpio = [19, 5, 25]

total = 30000
blocksize = 3000
iter = total / blocksize

waves = []
wavepos = 0


"""
When running with different delay, the loop fails with pigpio.error: No more CBs 
for waveform'.

But when running with equal delays, the loop completes. 
Proberbly because the waves are reused in gpioWaveCreate.
"""
delays_that_fails = [200, 0]       # fails
equal_delay_does_not_fail = [200]  # to se an execution as expected

delay = delays_that_fails

for p in range(total / 6):

    waves.append(pigpio.pulse(1 << gpio[0], 0, random.choice(delay)))
    waves.append(pigpio.pulse(1 << gpio[1], 0, random.choice(delay)))
    waves.append(pigpio.pulse(1 << gpio[2], 0, random.choice(delay)))

    waves.append(pigpio.pulse(0, 1 << gpio[0], random.choice(delay)))
    waves.append(pigpio.pulse(0, 1 << gpio[1], random.choice(delay)))
    waves.append(pigpio.pulse(0, 1 << gpio[2], random.choice(delay)))

print 'pulses: {}'.format(len(waves))

pi.wave_clear()
iteration = 0
old_id = -1

# add-create-send-delete loop with a sleep delay after send
while wavepos <= len(waves) - blocksize:

    new_wavepos = wavepos + blocksize
    slice = waves[wavepos:new_wavepos]
    wavepos = new_wavepos

    iteration += 1
    print 'iteration %s' % iteration

    pi.wave_add_generic(slice)

    new_id = pi.wave_create()
    pi.wave_send_using_mode(new_id, pigpio.WAVE_MODE_ONE_SHOT_SYNC)

    while pi.wave_tx_at() != new_id:
        time.sleep(0.01)

    if old_id >= 0:
        print 'delete wave id %s' % old_id
        pi.wave_delete(old_id)

    old_id = new_id

pi.stop()

print 'complete'

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 64 (26 by maintainers)

Most upvoted comments

Perhaps

gpioWaveCreatePad(int percent) C 
wave_create_and_pad(percent)   Python
wave_create_and_pad(percent)   pigpiod_if2
WVCAP percent                  pigs

Where the percent gives the percentage of the resources to use (in terms of the theoretical maximum, not the current amount free).

So if you wanted to have three waves being rotated you could pad each to 25% leaving another 25% free for any other waves which might be wanted.

@guymcswain, I didn’t react to your comment. I tested your addition today running 4 steppers simultaneously with microstepping and it worked perfectly. I did not see or hear any jerk. I also looked at the timings with a logic analyser and saw no jitter. Step frequencies up to 100kHz for infinite time 😃

I agree not to remove/break anything that users could be relying on. That said, users shouldn’t rely on anything that is undocumented. I’m having difficulty finding anything in the documentation that explains the usage of flags with waves. If no such documentation exists, then it should be fair game to change but then nail it down with documentation. Its good to think of the documentation of the APIs as a contract.

Incidentally, I have clearly violated that contract in this experiment - changed gpioWaveCreate() to requiring an argument - so this will not be the way to implement the feature.

@Jul3k , I have pushed an experimental branch, ‘wavesize’, which allows the creation of fixed size waves. I modified the script from the top of this thread to create 4 fixed size waves using:

new_id = pi.wave_create(4)

The script now runs to completion. I did not hook up my scope to observe the waveforms, yet.

Give it a try and let me know how your application responds.