allwpilib icon indicating copy to clipboard operation
allwpilib copied to clipboard

DigitalOutput pulse doesn't scale linearly with input

Open MqxS opened this issue 2 years ago • 8 comments

Describe the bug When calling DigitalOutput.pulse(); the RIO outputs pulses of arbitrary lengths that don't correlate with the input value.

To Reproduce Steps to reproduce the behavior:

  1. Create a DigitalOutput DigitalOutput digitalOutput = new DigitalOutput(0);
  2. (Not sure if this is necessary but our code has it) Set the digitalOutput to false digitalOutput.set(false);
  3. Pulse the digitalOutput digitalOutput.pulse(20);

Expected behavior We expected the output to to scale with input value (eg. increasing input value would increase pulse length) but instead the pulse is of an arbitrary length that doesn't reflect changes of input value.

Screenshots Pulse output length was measured in milliseconds using an oscilloscope with different input values. We didn't take photos of the oscilloscope screen but our data is here below: https://docs.google.com/spreadsheets/d/1m2L3OeYdsEEMhN6ocPFskpC3ENEAc3giSgxebHkpqXE/edit?usp=sharing

Desktop (please complete the following information):

  • WPILib Version: [e.g. 2021.3.1] Version: 2022.4.1
  • OS: [e.g. Windows 11] Windows 10
  • Java version [e.g. 1.10.2] 11.0.15
  • C++ version [e.g. 17] N/a

Additional context None

MqxS avatar Jul 08 '22 03:07 MqxS

The pulse output duration is in seconds. Did you really intend to generate a 20 second pulse (versus 20 milliseconds, in which case you should pass 0.020)? Internally the pulse duration is truncated to a 16-bit integer after scaling by the PWM loop timing, so what you are seeing is a result of this truncation. https://github.com/wpilibsuite/allwpilib/blob/faa29d596c9a01447a36fd5eaa18e8ad28434ad4/hal/src/main/native/athena/DIO.cpp#L428-L429

If you really need a 20 second pulse, you should be able to trade total duration against pulse accuracy by decreasing the PWM loop timing to keep the scaled pulse duration value within 16 bits.

PeterJohnson avatar Jul 08 '22 03:07 PeterJohnson

Though originally, I had wanted it to be a 20ms pulse I found out that the pulse length wouldn't correlate to a linear change in the pulse output. So even if I had put in 20 it still should have shown 20 of something instead it would pulse for a completely random duration in ms.

MqxS avatar Jul 08 '22 04:07 MqxS

If you put anything over then I think 0.5 the result will be random. It depends on where in the rollover the value you use actually is. I’d have to check the exact maximum, but iirc it’s somewhere around half a second.

ThadHouse avatar Jul 08 '22 04:07 ThadHouse

Even with a number below 0.5 I still couldn't get it to pulse for a given length.

MqxS avatar Jul 08 '22 04:07 MqxS

According to the API docs on the parallel C++ method, the maximum pulse length is 0.0016 seconds.

https://github.com/wpilibsuite/allwpilib/blob/faa29d596c9a01447a36fd5eaa18e8ad28434ad4/wpilibc/src/main/native/include/frc/DigitalOutput.h#L78-L86

Perhaps this is worthy of adding a range check and warning?

Starlight220 avatar Jul 08 '22 12:07 Starlight220

The actual maximum depends on the PWM loop timing rate, which is settable.

PeterJohnson avatar Jul 08 '22 13:07 PeterJohnson

So that false info in the API docs should be fixed.

Starlight220 avatar Jul 08 '22 15:07 Starlight220

Thanks, we were able to get our 20ms pulse after setting the PWM Rate to 10000.

MqxS avatar Jul 10 '22 14:07 MqxS

It turns out the pulse API isn't affected by the PWM rate. Its just a microsecond pulse. Just opened a PR to update both the API and the docs

ThadHouse avatar Aug 31 '22 02:08 ThadHouse

I saw in your PR you set a maximum length of 65535 microseconds. Would this max value not be affected by changing the PWM rate?

MqxS avatar Aug 31 '22 02:08 MqxS

Its not mattering what I'm setting PWM rate to. No matter what, the same pulse length results.

ThadHouse avatar Aug 31 '22 03:08 ThadHouse

Thats strange. We were able to get different pulse lengths when we changed our pwmrate. Before setting it we couldn't get any pulse but now we're able to do 20ms up to around 70 before it doesn't pulse the right length again.

MqxS avatar Aug 31 '22 03:08 MqxS

The highest you'd be able to go is 0.065. Anything higher then that, and it will roll over. Thats why going above 70 ms breaks. Anything above 65.5 ms will roll over.

ThadHouse avatar Aug 31 '22 03:08 ThadHouse

Would a longer pulse be possible at all?

MqxS avatar Aug 31 '22 03:08 MqxS

No. Its capped there.

ThadHouse avatar Aug 31 '22 03:08 ThadHouse

Alright, Thanks!

MqxS avatar Aug 31 '22 03:08 MqxS