Skip to content

Commit

Permalink
[test] fixes TEST=wiring/no_fixture_long_running PWM test
Browse files Browse the repository at this point in the history
Test was broken due to a bad ABS macro that was spitting out mostly negative values, also refactored to iterate from 20-90% Duty Cycle PWM in 5% steps, and made adjustments to keep it from hanging (20-30us pulses still too low to measure on Gen 3), and lightened the rigid accuracy calculations `Pulse width should be within 15% error margin resolution > 6, else 40%` and finally we don’t bother to test 2 and 3 bit PWM anymore since it’s very crude.
  • Loading branch information
technobly committed Apr 11, 2019
1 parent 2653274 commit a34adad
Showing 1 changed file with 30 additions and 36 deletions.
66 changes: 30 additions & 36 deletions user/tests/wiring/no_fixture_long_running/pwm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#include "pwm_hal.h"
#include <cmath>

#ifndef ABS
#define ABS(x) (x < 0 ? -x : x)
#endif // ABS

#ifdef ABS
#undef ABS
#endif
#define ABS(x) ( ((x) < 0) ? -(x) : (x) )

static const uint32_t maxPulseSamples = 100;
static const uint32_t minimumFrequency = 100;
Expand Down Expand Up @@ -57,11 +57,13 @@ test(PWM_01_CompherensiveResolutionFrequency) {
// when
pinMode(pin, OUTPUT);

uint8_t resolution = 2;
// 2 or 3 bit resolution PWM is crude at best and hard to be accurate, we won't test it here.
uint8_t resolution = 4;

for (resolution = 2; ; resolution++) {
for (resolution = 4; ; resolution++) {
// Set resolution
analogWriteResolution(pin, resolution);
// Serial.printlnf("pin=%d res=%d res_act=%d", pin, resolution, analogWriteResolution(pin));
if (resolution <= 15) {
// All PWM pins should support resolution of up to 15 bits
assertEqual(resolution, analogWriteResolution(pin));
Expand All @@ -82,45 +84,41 @@ test(PWM_01_CompherensiveResolutionFrequency) {
// Test all frequencies up to analogWriteMaxFrequency() with logarithmic step
for (freq = minimumFrequency; freq <= analogWriteMaxFrequency(pin);) {
float fp = floor(log10((float)freq));
if (fp < 1)
if (fp < 1) {
fp = 1;
}
freqStep = ((uint32_t)pow(10.0, fp + 1.0)) / 3;
if (freqStep < 33)
if (freqStep < 33) {
freqStep = 33;
}

// Test all analog values with logarithmic step
uint32_t valueStep = 1;
float vp = floor(log2((float)maxVal));
if (vp < 2.0)
vp = 2.0;
valueStep = ((uint32_t)pow(2.0, vp - 2.0)) / 3;
if (valueStep < 1)
valueStep = 1;
for (uint32_t value = 1; value < maxVal;) {
//Serial.printf("val=%d\r\n", value);
for (uint32_t duty = 20; duty <= 90; duty += 5) {
uint32_t value = (uint32_t)(((double)duty / 100.0) * (double)maxVal);
analogWrite(pin, value, freq);
uint32_t period = 1000 / freq;
delay(period ? period : 1);

// Check if the write resulted in correct analog value
assertEqual(HAL_PWM_Get_AnalogValue_Ext(pin), value);

float duty = (float)value/(float)maxVal;
float refPulseWidthUs = duty * (1000000.0 / (double)freq);
double refPulseWidthUs = ((double)duty/100.0) * (1000000.0 / (double)freq);
// pulseIn cannot measure pulses shorter than 10us reliably, limit to 20us
if (refPulseWidthUs < 20.0) {
if (refPulseWidthUs < 30.0) {
// Skip
} else if ((1.0 - duty) * refPulseWidthUs < 20.0) {
} else if ((1.0 - ((double)duty/100.0)) * refPulseWidthUs < 30.0) {
// pulseIn will not be able to accurately measure high pulse that is followed by <20us low pulse
} else {
uint32_t pulseAcc = 0;
uint32_t pulseSamples = freq < 1000 ? maxPulseSamples / 10 : maxPulseSamples;
#if HAL_PLATFORM_NRF52840
// Dummy read to wait until the change of PWM takes effect
pulseIn(pin, HIGH);
pulseIn(pin, LOW);
#endif
for (uint32_t i = 0; i < pulseSamples; i++) {
ATOMIC_BLOCK() {
pulseAcc += pulseIn(pin, HIGH);
}
// 0 and maxVal should result in a timeout
if (value == 0 || value == maxVal) {
Serial.printlnf("timeout: %lu", i);
assertEqual(pulseAcc, 0);
assertEqual(digitalRead(pin), 0);
break;
Expand All @@ -129,25 +127,21 @@ test(PWM_01_CompherensiveResolutionFrequency) {
double avgPulse = (double)pulseAcc / pulseSamples;
double err = ABS(avgPulse - refPulseWidthUs);

float errPulseWidth = 0.05 * refPulseWidthUs;
// Pulse width should be witin 5% error margin
// Pulse width should be within 15% error margin resolution > 6, else 40%
float errPulseWidth = (resolution > 6) ? 0.15 * refPulseWidthUs : 0.40 * refPulseWidthUs;
// Serial.printlnf("pin=%d freq=%d duty=%d res=%d res_act=%d val=%d ref=%f avg=%f err=%f err_max=%f pcnt=%0.2f", pin, freq, duty, resolution, analogWriteResolution(pin), value, refPulseWidthUs, avgPulse, err, errPulseWidth, 100*(ABS(avgPulse-refPulseWidthUs)/refPulseWidthUs) );
assertLessOrEqual(err, errPulseWidth);
}

// Clamp to maxVal
if (value < maxVal && (value + valueStep) > maxVal)
value = maxVal;
else
value += valueStep;
}

// Clamp to analogWriteMaxFrequency(pin)
if (freq < analogWriteMaxFrequency(pin) && (freq + freqStep) > analogWriteMaxFrequency(pin))
if (freq < analogWriteMaxFrequency(pin) && (freq + freqStep) > analogWriteMaxFrequency(pin)) {
freq = analogWriteMaxFrequency(pin);
else if (freq < analogWriteMaxFrequency(pin))
} else if (freq < analogWriteMaxFrequency(pin)) {
freq += freqStep;
else
} else {
break;
}
}
}

Expand Down

0 comments on commit a34adad

Please sign in to comment.