/** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include "pico/stdlib.h" #include "hardware/pwm.h" #include "hardware/clocks.h" // This example drives a PWM output at a range of duty cycles, and uses // another PWM slice in input mode to measure the duty cycle. You'll need to // connect these two pins with a jumper wire: const uint OUTPUT_PIN = 2; const uint MEASURE_PIN = 5; float measure_duty_cycle(uint gpio) { // Only the PWM B pins can be used as inputs. assert(pwm_gpio_to_channel(gpio) == PWM_CHAN_B); uint slice_num = pwm_gpio_to_slice_num(gpio); // Count once for every 100 cycles the PWM B input is high pwm_config cfg = pwm_get_default_config(); pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_HIGH); pwm_config_set_clkdiv(&cfg, 100); pwm_init(slice_num, &cfg, false); gpio_set_function(gpio, GPIO_FUNC_PWM); pwm_set_enabled(slice_num, true); sleep_ms(10); pwm_set_enabled(slice_num, false); float counting_rate = clock_get_hz(clk_sys) / 100; float max_possible_count = counting_rate * 0.01; return pwm_get_counter(slice_num) / max_possible_count; } const float test_duty_cycles[] = { 0.f, 0.1f, 0.5f, 0.9f, 1.f }; int main() { stdio_init_all(); printf("\nPWM duty cycle measurement example\n"); // Configure PWM slice and set it running const uint count_top = 1000; pwm_config cfg = pwm_get_default_config(); pwm_config_set_wrap(&cfg, count_top); pwm_init(pwm_gpio_to_slice_num(OUTPUT_PIN), &cfg, true); // Note we aren't touching the other pin yet -- PWM pins are outputs by // default, but change to inputs once the divider mode is changed from // free-running. It's not wise to connect two outputs directly together! gpio_set_function(OUTPUT_PIN, GPIO_FUNC_PWM); // For each of our test duty cycles, drive the output pin at that level, // and read back the actual output duty cycle using the other pin. The two // values should be very close! for (int i = 0; i < count_of(test_duty_cycles); ++i) { float output_duty_cycle = test_duty_cycles[i]; pwm_set_gpio_level(OUTPUT_PIN, output_duty_cycle * (count_top + 1)); float measured_duty_cycle = measure_duty_cycle(MEASURE_PIN); printf("Output duty cycle = %.1f%%, measured input duty cycle = %.1f%%\n", output_duty_cycle * 100.f, measured_duty_cycle * 100.f); } }