Driver for counting rising edges using TC on an ATSAMD51

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I Have the following situation:

I have a motor controller SPEED leg connected to pin #40 (PB11: EXTINT.11 / TC5.1).

The motor controller sends over that leg a rising edge for every one third of a rotation of the motor and I'm interested in figuring the rounds per second (RPS) of the motor.

 

I found 2 ways to figure out the RPS:

  1. Assign an interrupt handler to that pin and increase a counter on every event.
    Once a second divide that counter by 3 and you get the RPS.
  2. Use TC to do that for you instead of implementing most of it in software.
    Whenever I feel like it I will read the CC register and get the current speed.

 

Problem with number one is that it involves too much software work in the sense that it halts execution etc.

 

My problem with the second possible implementation is that I havent found a driver for that.

When I look in start.atmel.com I can find 2 drivers that use TC/TCC:

Timer & PWM.

 

Is there a driver that does what I'm interested in or do I need to write a driver from scratch ?

Is there an example on how to do something similar ? (TC that does "something" based on input from IO pin)

 

Thanks

Last Edited: Wed. Oct 14, 2020 - 01:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could use input capture also (compute the RPS from the period of the signal). No driver but this info:
https://microchipsupport.force.c...

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SAMD5x has a built-in frequency meter peripheral, FREQM, though I don't see an example for it on Start.

 

The peripheral is pretty simple however, just set up a suitable reference clock on GCLK_FREQM_REF, and feed the motor speed signal to a GCLK input pin and use that for GCLK_FREQM_MSR. The ratio between the two clocks can be read from FREQM.VALUE which, with a bit of simple arithmetic (described in the data sheet), yields the frequency of the speed signal.

 

Steve

Maverick Embedded Technologies Ltd. Home of Maven and wAVR.

Maven: WiFi ARM Cortex-M Debugger/Programmer

wAVR: WiFi AVR ISP/PDI/uPDI Programmer

https://www.maverick-embedded.co...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a mention for an attached atstart project in that post .. cant seem to find it

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is only one FREQM peripheral and I need to measure the speed of 8 motors, so I figured the TCs will do the job.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've switch tactics and what I want to achieve now is get an interrupt on every rising edge on TC5 WO/1.

Here is what I did:

1. right before "hri_tc_write_CTRLA_ENABLE_bit(TC5, 1 << TC_CTRLA_ENABLE_Pos); /* Enable: enabled */" I added the lines:
    NVIC_DisableIRQ(TC5_IRQn);
    NVIC_ClearPendingIRQ(TC5_IRQn);
    NVIC_EnableIRQ(TC5_IRQn);

 

2. Implemented TC5_Handler() to catch interrupts with the following content:

    if (hri_tc_get_interrupt_OVF_bit(TC5)) {
    hri_tc_clear_interrupt_OVF_bit(TC5);
  }
  if (hri_tc_get_interrupt_ERR_bit(TC5)) {
    hri_tc_clear_interrupt_ERR_bit(TC5);
  }
  if (hri_tc_get_interrupt_MC1_bit(TC5)) {
    hri_tc_clear_interrupt_MC1_bit(TC5);
    spd_counter++;
  }

 

3. Configured TC5 the following way:   

if (!hri_tc_is_syncing(TC5, TC_SYNCBUSY_SWRST)) {
        if (hri_tc_get_CTRLA_reg(TC5, TC_CTRLA_ENABLE)) {
            hri_tc_clear_CTRLA_ENABLE_bit(TC5);
            hri_tc_wait_for_sync(TC5, TC_SYNCBUSY_ENABLE);
        }
        hri_tc_write_CTRLA_reg(TC5, TC_CTRLA_SWRST);
    }
    hri_tc_wait_for_sync(TC5, TC_SYNCBUSY_SWRST);

    hri_tc_write_CTRLA_reg(TC5,
                           0 << TC_CTRLA_CAPTMODE0_Pos       /* Capture mode Channel 0: 0 */
                               | 0 << TC_CTRLA_CAPTMODE1_Pos /* Capture mode Channel 1: 0 */
                               | 0 << TC_CTRLA_COPEN0_Pos    /* Capture Pin 0 Enable: disabled */
                               | 1 << TC_CTRLA_COPEN1_Pos    /* Capture Pin 1 Enable: enabled */
                               | 0 << TC_CTRLA_CAPTEN0_Pos   /* Capture Channel 0 Enable: disabled */
                               | 1 << TC_CTRLA_CAPTEN1_Pos   /* Capture Channel 1 Enable: enabled */
                               | 0 << TC_CTRLA_ALOCK_Pos     /* Auto Lock: disabled */
                               | 0 << TC_CTRLA_PRESCSYNC_Pos /* Prescaler and Counter Synchronization: 0 */
                               | 0 << TC_CTRLA_ONDEMAND_Pos  /* Clock On Demand: disabled */
                               | 0 << TC_CTRLA_RUNSTDBY_Pos  /* Run in Standby: disabled */
                               | 0 << TC_CTRLA_PRESCALER_Pos /* Setting: 0 */
                               | 0x1 << TC_CTRLA_MODE_Pos);  /* Operating Mode: 0x1 */

    hri_tc_write_CTRLB_reg(TC5,
                           0 << TC_CTRLBSET_CMD_Pos           /* Command: 0 */
                               | 0 << TC_CTRLBSET_ONESHOT_Pos /* One-Shot: disabled */
                               | 0 << TC_CTRLBCLR_LUPD_Pos    /* Setting: disabled */
                               | 0 << TC_CTRLBSET_DIR_Pos);   /* Counter Direction: disabled */

    // hri_tc_write_WAVE_reg(TC5,0); /* Waveform Generation Mode: 0 */

    // hri_tc_write_DRVCTRL_reg(TC5,0 << TC_DRVCTRL_INVEN1_Pos /* Output Waveform 1 Invert Enable: disabled */
    //         | 0 << TC_DRVCTRL_INVEN0_Pos); /* Output Waveform 0 Invert Enable: disabled */

    // hri_tc_write_DBGCTRL_reg(TC5,0); /* Run in debug: 0 */

    // hri_tccount8_write_CC_reg(TC5, 0 ,0x0); /* Compare/Capture Value: 0x0 */

    // hri_tccount8_write_CC_reg(TC5, 1 ,0x0); /* Compare/Capture Value: 0x0 */

    // hri_tccount8_write_COUNT_reg(TC5,0x0); /* Counter Value: 0x0 */

    // hri_tc_write_PER_reg(TC5,0x0); /*  Period Value: 0x0 */

    hri_tc_write_EVCTRL_reg(TC5,
                            0 << TC_EVCTRL_MCEO0_Pos /* Match or Capture Channel 0 Event Output Enable: disabled */
                                | 1 << TC_EVCTRL_MCEO1_Pos /* Match or Capture Channel 1 Event Output Enable: enabled */
                                | 0 << TC_EVCTRL_OVFEO_Pos /* Overflow/Underflow Event Output Enable: disabled */
                                | 0 << TC_EVCTRL_TCEI_Pos  /* TC Event Input: disabled */
                                | 0 << TC_EVCTRL_TCINV_Pos /* TC Inverted Event Input: disabled */
                                | 4);                      /* Event Action: 4 */

    hri_tc_write_INTEN_reg(TC5,
                           0 << TC_INTENSET_MC0_Pos         /* Match or Capture Channel 0 Interrupt Enable: disabled */
                               | 1 << TC_INTENSET_MC1_Pos   /* Match or Capture Channel 1 Interrupt Enable: enabled */
                               | 0 << TC_INTENSET_ERR_Pos   /* Error Interrupt Enable: disabled */
                               | 0 << TC_INTENSET_OVF_Pos); /* Overflow Interrupt enable: disabled */

 

What happens when I do that is that I get interrupt calls, but apparently not due to rising edges.

 

What am I doing wrong ?

 

Thanks