1

With reference to this question ::I have written a program by using 16-bit timer,

The program is as follows .

volatile uint32_t ovfCount = 0;

struct Pulse {
  uint32_t last_toggle;
  uint32_t width;
  bool stateHigh;
  uint32_t get_width() {
    noInterrupts();
    uint32_t width_copy = width;
    interrupts();
    return width_copy;
  }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

void setup() {
  Serial.begin(115200);

  pinMode(13, OUTPUT);

  /*
     Pin Change Interupt for
     measuring the pulse width
     from the receiver

  */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCIFR = 0; // resetting the flags
  PCIFR  = _BV(PCIF2);
  PCMSK2 = B00111111; // activating from A8:21 :: 6
  PCICR = B00000100; // activating 2 nd PCINT

  /*
     16 bit timer setup for counting
     timer 3 is used
  */
  TCCR3B = 0x00;
  TCCR3A = 0x00; // wave generation is normal:: all zeros
  TCNT3 = 0x00;
  TIFR3 = 0x00; // resetting all flags
  TIMSK3 = 0x01; //timer overflow enable
  TCCR3B = 0x01; // no prescaling

}


ISR(TIMER3_OVF_vect) {
  ovfCount++;
}


ISR(PCINT2_vect) {
  uint8_t tcnt3 = TCNT3;
  uint32_t ovf_count = ovfCount;

  if ( bit_is_set(TIFR3, TOV3) && tcnt3 < 32768 ) {
    ovf_count ++;
  }

  uint32_t time = ovf_count << 16 | tcnt3;

  pinChangeFunction(&ch1, time, PK0);

}


void pinChangeFunction(Pulse *channel, uint32_t time, uint8_t pin) {
  bool input_is_high = bit_is_set(PINK, pin);
  if (input_is_high && !channel->stateHigh) {
    channel->stateHigh = true;
  } else if (! input_is_high && channel->stateHigh) {
    channel->width = time - channel->last_toggle;
    channel->stateHigh = false;
  }
  channel->last_toggle = time;
}

void loop() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(200);

  Serial.println(ch1.get_width() / 16e3, 5);


}

The output for the same is attached below,

999.42663
999.43060
999.42645
999.42614
999.42730
999.42889
1003.52416
999.41473
999.42681
999.42211
999.42077
999.42718
999.42016
1003.52447
999.41802
999.42480
999.42541
999.43603
999.42767
1003.52075
999.42199
999.42767
999.41876
999.42816
999.41143
999.41998
1003.52429
999.42730
999.42950
999.41149
999.42028
999.42700
1003.50775
999.43743
999.42858
999.42584
999.41381
999.42852
999.43347
1003.52490
999.41925
999.41540
999.42510
999.42895
999.42980
999.42883
1003.52526
999.43658
999.43707
999.42889
999.41284
999.42401
1003.52343
999.42901
999.42950
999.42822
999.43481
999.42718
999.41986
1003.52398
999.42303
999.41442
999.42498
999.42950
999.42547
1003.51074


When I observed the output , I am seeing 999 millis almost instead of 1000 as expected and in-between 1003 is coming instead either of 999/1003.

Also if we look carefully it can be observed that ,999 is coming 6 times then one 1003 is coming and is going 2 times like that then 5 times 999 then 1003

so I want to know what mistake I am making in my program , and what is the reason behind these kind of behaviour .

3
  • Please answer @edgar-bonet . – Lawliet Mar 6 at 0:49
  • 1
    TCNT3 does not fit in a uint8_t. – Edgar Bonet Mar 10 at 14:50
  • Thanks . Its working – Lawliet Mar 10 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.