Capturing a PWM pulse using timers?

Post here first, or if you can't find a relevant section!
Post Reply
PouchCotato
Posts: 1
Joined: Mon Sep 04, 2023 7:21 pm

Capturing a PWM pulse using timers?

Post by PouchCotato »

I am trying to capture the input of an RC receiver using an STM32F411CE board. I have checked that the input is correct and that it is being read at the pin I'm attaching, however the interrupt routine is never getting called, even though the pulse is being generated at the correct pin, the code I'm using is as follows, based off the example in the stm32duino github.

Code: Select all

#define pin PA15
bool flag = true;
uint32_t channel;
volatile uint32_t t, LastCapture = 0, CurrentCapture;
HardwareTimer *MyTim;

void InputCapture_IT_callback(void)
{
  pinMode(PA15,OUTPUT);
  CurrentCapture = MyTim->getCaptureCompare(channel);
  if (flag==true) {
      LastCapture = CurrentCapture;
      MyTim->setMode(channel,TIMER_INPUT_CAPTURE_FALLING,pin);
      flag=false;
    }
  else{
  if (CurrentCapture > LastCapture) {
    t = (CurrentCapture - LastCapture);
  }
  else{
    t = (0xFFFF + CurrentCapture - LastCapture);
  }
  MyTim->setMode(channel,TIMER_INPUT_CAPTURE_RISING,pin);
  flag = true;
  }
 }

void setup()
{
  Serial.begin(115200);
  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(pin), PinMap_PWM);
  channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin), PinMap_PWM));
  MyTim = new HardwareTimer(Instance);
  MyTim->setMode(channel, TIMER_INPUT_CAPTURE_RISING, pin);
  uint32_t PrescalerFactor = 1;
  MyTim->setPrescaleFactor(PrescalerFactor);
  MyTim->attachInterrupt(channel, InputCapture_IT_callback);
  Serial.println(channel);
}


void loop()
{
  Serial.println((String)"Interval = " + t);
  delay(1000);
}
I've been trying this for a while and the output is always 0 (captures only occur once and never update). What am I doing wrong here? (P.S am noob, please help)
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Capturing a PWM pulse using timers?

Post by dannyf »

someone posted something very similar - so you may want to check.

if i were to do this, assuming you are measuring the period + duty cycle, i would do something like this in the isr:

Code: Select all

uint32_t pwm_pr, pwm_dc;  //pwm period + duty cycle
IC_ISR:
  static uint32_t lastcapture=0, uint32_t currentcapture;  //last capture and current capture
  static [char] edge=TIMER_INPUT_CAPTURE_RISING;  //use whatever the right data type here.

  currentcapture=readCapture(); //read the current capture
  if (edge == TIMER_INPUT_CAPTURE_RISING) {pwm_pr = currentcapture - lastcapture; lastcapture = currentcapture; edge=TIMER_INPUT_CAPTURE_FALLING; /*optionally set a flag here indicating availability of data*/}
else {pwm_dc = currentcapture - lastcapture; edge=TIMER_INPUT_CAPTURE_RISING;}
  MyTim->setMode(channel,edge,pin);  //capture the next edge
not debugged obviously.
Post Reply

Return to “General discussion”