Jump to content
ELFORUM - Forumul electronistilor

Arduino DUE - masurare intarziere intre doua semnale


mmihai94

Recommended Posts

Salutare.

De cateva zile imi bat capul sa inteleg timerele si sistemul de intreruperi din ATSAM3X8E, dar ma cam depasesc. Vreu sa masor intarzierea intre doua semnale PWM aplicate la doua intrari diferite. Nu stiu cum sa fac asta. M-am gandit la o varianta ,folosesc un timer pe care il pornesc pe frontul crescator al unuia dintre semnale si il opresc tot pe frontul crescator al celullalt semnal. Am gasit pe net exemple care masoara frecventa, perioada, factor de umplere etc, dar toare folosesc doar o intrare pentru masura. Atasez un exemplu care masoara frecventa si care ar merge modificat cumva, dar..... A mai facut careva chestia asta? Am incercat sa modific pinul pe care se citeste frecventa, dar nici macar asta nu reusesc. Am pus PIOA->PIO_PDR = PIO_PA5A_TIOA2; PIOA->PIO_IDR = PIO_PA5A_TIOA2; in void pio_TIOA1() si nu schimba nimic.

 

Am citit si pe aici, dar ma prind.

https://forum.arduino.cc/index.php?topic=130423.120
https://forum.arduino.cc/index.php?topic=386981.0
https://arduino.stackexchange.com/questions/8782/how-to-use-timer1-at328mega-to-measure-the-time-between-rising-edges-of-two-in
https://forum.arduino.cc/index.php?topic=480228.0
https://forum.arduino.cc/index.php?topic=400516.0
http://forum.arduino.cc/index.php?topic=80239.0

 

HELP!!!

volatile uint32_t tmr_RA = 0;  
volatile uint32_t tmr_RB = 0;   

void setup()
{
  Serial.begin (115200); 
  Btmr_setup();         
  pio_TIOA1();  // IN, AN - 7 (max 3.3V -> keep safe !!!).
}

void loop() 
{
    uint32_t period = tmr_RB / 42;
    uint32_t duty_c = (100 * (tmr_RB - tmr_RA)) / tmr_RB;
    uint32_t freq = 42000000UL/ tmr_RB;    
      Serial.print("\n\tPeriod: ");
      Serial.print(period, DEC);
      Serial.print("\tmicroseconds");
      Serial.print("\n\tDuty Cycle: ");
      Serial.print(duty_c, DEC); 
      Serial.print("\t%");
      Serial.print("\n\tFrequency: ");
      Serial.print(freq, DEC);       
    delay(1000);  
}
void TC1_Handler(void)
{
if ((TC_GetStatus(T
C0, 1) & TC_SR_LDRBS) == TC_SR_LDRBS) {
  tmr_RA = TC0->TC_CHANNEL[1].TC_RA;
  tmr_RB = TC0->TC_CHANNEL[1].TC_RB;
  }
}
void Btmr_setup()  // Counter
{
  pmc_enable_periph_clk (TC_INTERFACE_ID + 0 *3 + 1);

  TcChannel * t = &(TC0->TC_CHANNEL)[1];
  t->TC_CCR = TC_CCR_CLKDIS;
  t->TC_IDR = 0xFFFFFFFF;   
  t->TC_SR;   

  t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1

             | TC_CMR_LDRA_RISING     
             | TC_CMR_LDRB_FALLING    
             | TC_CMR_ABETRG          
             | TC_CMR_ETRGEDG_FALLING;
             
  t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; 

  t->TC_IER =  TC_IER_LDRBS;
  t->TC_IDR = ~TC_IER_LDRBS;

  NVIC_DisableIRQ(TC1_IRQn);
  NVIC_ClearPendingIRQ(TC1_IRQn);
  NVIC_SetPriority(TC1_IRQn, 0); 
  NVIC_EnableIRQ(TC1_IRQn);
}

void pio_TIOA1() 
{
  PIOA->PIO_PDR = PIO_PA2A_TIOA1;  
  PIOA->PIO_IDR = PIO_PA2A_TIOA1;
}
Link to comment
  • Replies 8
  • Created
  • Last Reply

Top Posters In This Topic

  • mmihai94

    5

  • nico_2010

    4

Cred ca singura solutie este sa citesti cu multa atentie asta: http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf

Si chiar si asta: http://www.atmel.com/Images/Atmel-42123-SAM-Timer-Counter-%28TC%29-Driver_ApplicationNote_AT03263.pdf

Stiu, are doar 1459 de pagini, insa in domeniul microcontrollere-lor cu 32 biti, cam asta este solutia .. si e dureroasa.

Link to comment

Job done! Am reusit sa fac programul, in proportie de 90% e ok. Mai are o mica problema de care nu stiu cum sa scap.

In momentul de fata folosesc intrarile TIOA0, TIOA1 adica AN7 si D2 de pe arduino. Am setat intreruperile sa se declanseze la incarcarea registrilor RA de pe fiecare canal TC0 si TC1. Practic, pe frontul crescator al prinului semnal se incarca in registrul RA al canalului 0 valoarea din counter la momentul aparitiei frontului. Acelasi lucru se intampla si pt celalalt semnal. Dupa care e simplu, fac diferenta intre registrii RA si obtin intarzierea dintre semnale. Calculez intarzierea la ON( cu reg. RA) si la OFF(cu reg. RB - care se incarca pe frontul descrescator). Pana aici totul bine. Vreau sa vad datele si trimit pe serial. 90% primesc datele corect, dar apar cate o data niste valori uriase. De ce se intampla chestia asta? Trebuie sa resetez vre-un registru?

volatile uint32_t tmr_RA0 = 0, tmr_RA1 = 0;  
volatile uint32_t tmr_RB0 = 0, tmr_RB1 = 0;
volatile float on_d, off_d;

void setup() {
  Serial.begin (115200);  
  Tmr_setup();         
  pio_TIOA0();
  pio_TIOA1();
}

void loop() {
    
    on_d = (tmr_RA1 - tmr_RA0) * 0.0238;
    off_d = (tmr_RB1 - tmr_RB0) * 0.0238;

    Serial.print("\n\nON Delay  ");
    Serial.print(on_d);

    Serial.print("\nOFF Delay ");
    Serial.print(off_d);
    
    delay(500);
}

void Tmr_setup()
{
    pmc_enable_periph_clk(ID_TC0);        // configure Power Management Clock
    TC_Configure(TC0, 0,
    TC_CMR_TCCLKS_TIMER_CLOCK1 |          // set timer clock to 42MHz
    TC_CMR_WAVSEL_UP |                    // ????
    TC_CMR_LDRA_RISING |                  // set loading edge of Register A to Rising
    TC_CMR_LDRB_FALLING);                 // set loading edge of Register B to Falling

    pmc_enable_periph_clk(ID_TC1);
    TC_Configure(TC0, 1,
    TC_CMR_TCCLKS_TIMER_CLOCK1 |
    TC_CMR_WAVSEL_UP |
    TC_CMR_LDRA_RISING |
    TC_CMR_LDRB_FALLING);

    TC0->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS;
    NVIC_EnableIRQ(TC0_IRQn);
    
    TC0->TC_CHANNEL[1].TC_IER = TC_IER_LDRAS;
    NVIC_EnableIRQ(TC1_IRQn);

    TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN;
    TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN;
    TC0->TC_BCR = TC_BCR_SYNC;
    }

void TC0_Handler() {
    uint32_t status = TC0->TC_CHANNEL[0].TC_SR;
    if (status & TC_SR_LDRAS) {
        uint32_t tm = TC0->TC_CHANNEL[0].TC_RA;
        // rising edge of TIOA0 happened at "tm",
        // do something here to deal with it...
        tmr_RA0 = TC0->TC_CHANNEL[0].TC_RA;
        tmr_RB0 = TC0->TC_CHANNEL[0].TC_RB;
    }
}

void TC1_Handler() {
    uint32_t status = TC0->TC_CHANNEL[1].TC_SR;
    if (status & TC_SR_LDRAS) {
        uint32_t tm = TC0->TC_CHANNEL[1].TC_RA;
        // rising edge of TIOA1 happened at "tm",
        // do something here to deal with it...
        tmr_RA1 = TC0->TC_CHANNEL[1].TC_RA;
        tmr_RB1 = TC0->TC_CHANNEL[1].TC_RB;
    }
}

void pio_TIOA1() 
{
  PIOA->PIO_PDR = PIO_PA2A_TIOA1;  
  PIOA->PIO_IDR = PIO_PA2A_TIOA1;
}

void pio_TIOA0() 
{
  PIOB->PIO_PDR = PIO_PB25B_TIOA0;  
  PIOB->PIO_IDR = PIO_PB25B_TIOA0;
  PIOB->PIO_ABSR |= PIO_PB25B_TIOA0;
}

post-208062-0-60650400-1498160332_thumb.png

Link to comment

De la STM32 citire: Frecventa cu care se produc evenimentele (pe front crescator sau/si pe front descrescator) trebuie sa fie mai mica decat frecventa semnalului de masurat (in regim de functionare Input Capture), altfel apare overflow si brusc te trezesti ca valoarea inregistrata este 65535. Cam asta cred ca ti se intampla si tie.

 

O imagine este mai buna decat o mie de cuvinte:

post-194122-0-85044400-1498220491_thumb.png

Link to comment

Nu cred ca asta e motivul. Frecventa timerului este MCLK/2 adica 42MHz, iar frecventa care produce acele forunturi de masurat e de maxim 5KHz. Diferenta e uriasa.

Link to comment

Nu stiu daca stergi flagul de intrerupere sau nu o faci in IRQ, dar cred ca ar fi bine s-o faci (cel putin asa se face la STM32

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines