Hello.
There are several topics on the forum already touching on this but I wanted to create a new one because I cannot find an example that is specific enough to really help me.
I am slowly learning how to work with PIO. I have played around with several examples from the pico-examples github repo but I have not been able modify any of them to work for what I need.
I have a rotary encoder that reports absolute position via pulse width. The PWM frequency of the absolute position is 975 Hz and the pulse width varies from 1-1024 microseconds (0-360 degrees position).
I tried measuring the pulse width with PIO but the results were terrible at best. I am most definitely not implementing it correctly. After struggling massively with PIO, I went back to the PWM measurement example (https://github.com/raspberrypi/picoexam ... duty_cycle) and modified it to get what I need working. With all that being said, I would still like to figure out how to do the same thing with PIO.
Does anyone have a good example of doing this with the pico sdk and a PIO state machine? I found this example (https://github.com/GitJer/Some_RPI-Pico ... main/PwmIn) but it did not work well for me either. I cannot say for sure because I am a noob but the pio code from that example did not seem correct. The 'jmp start' instructions confused me because it appeared that they would reset the PIO program prematurely (please let me know if I am wrong about that). I'd also really like to see an example of measuring PWM that is pure C and not C++. I believe it would be easier to learn from an example if it uses the pico sdk more clearly.
To summarize, I was able to get a value from the PIO state machine but the value was not usable. I can however use the PWM hardware api and get it to work. I am just curious if anyone else out there has struggled with this and figured it out. Any tips or examples would be greatly appreciated. I will include the code (that did not work) for the PIO.
Thank you.
There are several topics on the forum already touching on this but I wanted to create a new one because I cannot find an example that is specific enough to really help me.
I am slowly learning how to work with PIO. I have played around with several examples from the pico-examples github repo but I have not been able modify any of them to work for what I need.
I have a rotary encoder that reports absolute position via pulse width. The PWM frequency of the absolute position is 975 Hz and the pulse width varies from 1-1024 microseconds (0-360 degrees position).
I tried measuring the pulse width with PIO but the results were terrible at best. I am most definitely not implementing it correctly. After struggling massively with PIO, I went back to the PWM measurement example (https://github.com/raspberrypi/picoexam ... duty_cycle) and modified it to get what I need working. With all that being said, I would still like to figure out how to do the same thing with PIO.
Does anyone have a good example of doing this with the pico sdk and a PIO state machine? I found this example (https://github.com/GitJer/Some_RPI-Pico ... main/PwmIn) but it did not work well for me either. I cannot say for sure because I am a noob but the pio code from that example did not seem correct. The 'jmp start' instructions confused me because it appeared that they would reset the PIO program prematurely (please let me know if I am wrong about that). I'd also really like to see an example of measuring PWM that is pure C and not C++. I believe it would be easier to learn from an example if it uses the pico sdk more clearly.
To summarize, I was able to get a value from the PIO state machine but the value was not usable. I can however use the PWM hardware api and get it to work. I am just curious if anyone else out there has struggled with this and figured it out. Any tips or examples would be greatly appreciated. I will include the code (that did not work) for the PIO.
Thank you.
Code:
; ;; PIO Program to measure PWM pulse width; while pin is high, implement counter in X register; count down until pin is low;;.define public ENC_ABS_PIN 27.program measure_pwm.wrap_targetstart: mov x, ~NULL wait 0 gpio ENC_ABS_PIN wait 1 gpio ENC_ABS_PINtimer_high: jmp x-- test_pintest_pin: jmp pin timer_hightimer_stop: mov ISR, ~x push.wrap% c-sdk {static inline void measure_pwm_program_init(PIO pio, uint sm, uint offset, uint pin){ // set default state machine config as config pio_sm_config c = measure_pwm_program_get_default_config(offset); // set the input pin and jmp pin sm_config_set_in_pins(&c, pin); // for WAIT, IN sm_config_set_jmp_pin(&c, pin); // for JMP // set pin direction pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false); // connect GPIO's to PIO pio_gpio_init(pio, pin); // slow the clock down to 1 Mhz sm_config_set_clkdiv(&c, 125.0); // set the clock divider so clock runs at 1 MHz // set shift direction sm_config_set_in_shift(&c, false, false, 0); // init state machine with config and enable pio_sm_init(pio, sm, offset, &c); pio_sm_set_enabled(pio, sm, true);}static inline uint32_t measure_pwm_get_timer(PIO pio, uint sm){ uint ret; pio_sm_clear_fifos(pio, sm); ret = pio_sm_get(pio, sm); return ret;}%}
Code:
/**/#include <stdio.h>#include "pico/stdlib.h"#include "hardware/pio.h"#include "hardware/pwm.h"#include "measure_pwm.pio.h"#define ENC_ABS_PIN 27 // Encoder Absolute Position GPIO Pin// function prototypesvoid pico_led_init();void pico_set_led(bool led_on);/************ MAIN ************/int main(){ // main function local variables int32_t encPos = 0; // setup function calls stdio_init_all(); pico_led_init(); // Built-in LED setup // encoder PIO setup PIO pio = pio0; uint offset = pio_add_program(pio, &measure_pwm_program); uint sm = pio_claim_unused_sm(pio, true); measure_pwm_program_init(pio, sm, offset, ENC_ABS_PIN); /************ FOREVER LOOP ************/ while (true) { // get encoder position from PIO sm encPos = measure_pwm_get_timer(pio, sm); } } /************ END FOREVER LOOP ************/ }/************ END MAIN ************//************ FUNCTION DEFINITIONS ************/// initialize the built-in Pico LEDvoid pico_led_init() { gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);}// turns the built-in Pico LED on/offvoid pico_set_led(bool led_on) { gpio_put(PICO_DEFAULT_LED_PIN, led_on);}
Statistics: Posted by beezkneez — Tue Dec 10, 2024 4:29 pm — Replies 2 — Views 36