Measuring width of a pulse using avr capture

Discussion in 'Embedded Systems and Microcontrollers' started by thinkanish, Mar 29, 2013.

  1. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    Hi,
    I want to interface a ultrasonic sensor to attiny2313. The code I developed using avrgcc. I used capture interrupt of the avr to capture the rising and falling edge of the pulse and calculate the time elapsed in doing so. In this process, after capturing the falling edge of the pulse, the timer is switched of and again it is switched on only after triggering the sensor. The code below works fine but when the distance is low (say 10cm), timer overflows and everything stops. But by seeing the speed of the avr core and timer, it has no chance to overflow. I cannot sort it out.
    Code:
    #include "avr/io.h"
    #include "avr/interrupt.h"
    #define F_CPU 8000000
    #include "util/delay.h"
     
    volatile unsigned int pulseStart;
    volatile unsigned int pulseEnd;
    volatile unsigned int pulseInUs = 2013;
    volatile unsigned char edge =0;
    volatile unsigned int success = 0;
    volatile unsigned int failure = 0;
     
    #define START_TIMER TCCR1B |= ((1 << CS11) | (1 << CS10))
    #define STOP_TIMER TCCR1B &= ~((1 << CS11) | (1 << CS10))
    void pulseSensor(void){
       PORTB |= (1 << 0);
       _delay_us(10);                        
       PORTB &= ~(1 << 0);                    
    }
     
    void initialisePorts(void){
       DDRD &= ~(1 << 6);                  //PORTD.6 = INPUT
       DDRB |= (1 << 0) | (1 << 1) | (1 << 2);   //PORTB.0 = PORTB.1 = OUTPUT
    }
     
    void blinkLED(unsigned int port){
       DDRB |= (1 << port);
       PORTB ^= (1 << port);
       _delay_ms(200);
    }
     
     
    int main(void){
       initialisePorts();
       TIMSK |= ((1 << ICIE1)| (1 << TOIE1));   //Set capture interrupt
       sei();                           //Set global interrupt
       TCCR1B |= (1 << ICES1);               //Set capture rising edge
       pulseSensor();
       START_TIMER;
       for(;;){
         
          if(success){
             success = 0;
             if(pulseInUs <= 200)         //Obstacle in range  
                PORTB |= (1 << 1);
             else
                PORTB &= ~(1 << 1);         //Obstacle not in range
             pulseSensor();
             START_TIMER;
          }
          if(failure){
             failure = 0;
             PORTB |= (1 << 2);
          }
       }
       return 0;
    }
     
    ISR(TIMER1_CAPT_vect){
       if(edge == 0){
          pulseStart = ICR1;               //copy capture value
          TCCR1B &= ~(1 << ICES1);         //toggle capture edge
          edge = 1;                    
       }
       else{
          pulseEnd = ICR1;               //copy capture value
          TCCR1B |= (1 << ICES1);            //toggle capture edge
          edge = 0;
          STOP_TIMER;
          TCNT1 = 0;  
          pulseInUs = pulseEnd - pulseStart;
          success = 1;
       }
    }
     
    ISR(TIMER1_OVF_vect){
       failure = 1;
       TCCR1B |= (1 << ICES1);
       STOP_TIMER;
       TCNT1 = 0;
       edge = 0;
    }
    
    
    What is the problem in this code which makes the timer overflow?
    Thanks.
  2. Motardo

    Motardo New Member

    Joined:
    Sep 21, 2011
    Messages:
    17
    Location:
    Apex, NC, USA
    Most ultrasonic ping sensors need a minimum distance of 7-10cm to work. If the distance is less than that, the sensor doesn't receive the echo, so it doesn't interrupt the uC, and the uC timer overflows. Which ultrasonic sensor are you using, and do you have a link to the datasheet?
  3. Bhavin Tailor

    Bhavin Tailor New Member

    Joined:
    Mar 30, 2013
    Messages:
    3
    As per reply from Motardo, make ensure that are getting pulse from sensor.
    Do you have any LED or display device...?
    So, first make ensure you are getting rising & falling both edge from sensor. Just increment one variable on rising & falling edge & display value on LCD.
    So, make ensure you are getting pulse or not from your sensor.
  4. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    Hi, thanks for your replies, i am using this 4 pin ultrasonic sensor : HC-SR04

    The minimum resolution is 2cm but timer overflows even at 10 / 15cms

    But the sensor works well with arduino pulseIn function up to (1 cm)

    I have designed the program such that, if there is obstacle within some 20cm range, the LED in PORTB.1 glows. else it switches off. Also, an led is connected to PORTB.2 to indicate timer overflow. PORTB.0 is used to ping the sensor and PORTD.6 is the capture input.

    Thanks.
  5. kubeek

    kubeek AAC Fanatic!

    Joined:
    Sep 20, 2005
    Messages:
    3,563
    Location:
    Prague, Czech Rep
    I am not quite sure why you do it the way you do. If I were doing this, I would reset the count on the timer and start it on the rising edge, then capture the value from the timer on the falling edge.
  6. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    I tried even this method. Doesnt seem to work :(
    Even in the above method, the timer overflows when distance is short. I think the controller is failing to capture the falling edge?
    In that case what can be done?
  7. kubeek

    kubeek AAC Fanatic!

    Joined:
    Sep 20, 2005
    Messages:
    3,563
    Location:
    Prague, Czech Rep
    Do you have an oscilloscope to crack this? I would toggle a pin to see for example when you enter and leave the ISR and use the other channel on the echo wire.
    thinkanish likes this.
  8. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    Hmm. I dont have a scope. I ll try this at my college and see.
    Thanks for the tip :)
  9. Bhavin Tailor

    Bhavin Tailor New Member

    Joined:
    Mar 30, 2013
    Messages:
    3
    Just for time being don't configure interrupt. As you are saying, timer overflow so there is enough time to sense. So, just make one WHILE loop to sense pin which is connected with sensor. Observe below logic,............

    Code:
    PORTB.1 = 0;            // LED1 Off
    PORTB.2 = 0;            // LED2 Off
    while(PORTB.0==0);           // Wait here until you found High State from Sensor
    PORTB.1 = 1;           // You come here when you will get rising edge from sensor, 
    while(PORTB.0==1);           // Wait here until you found High State from Sensor
    PORTB.2 = 1;           // You come here when you will get falling edge from sensor, 
    

    So, if your both LED will glow it means, you are getting pulse from sensor and you have to look at in your code. Here, i assume that, by default state at your pin is LOW, Sensor will give High pulse & then it will maintain low state at pin.
    Last edited by a moderator: Apr 1, 2013
  10. djsfantasi

    djsfantasi Well-Known Member

    Joined:
    Apr 11, 2010
    Messages:
    1,084
    Location:
    Northeast US
    Code:
    while(PORTB.0==1); // Wait here until you found Low State from Sensor
    I think you meant Low state in your comment.
  11. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    Hi, thanks for your suggestion:
    Here is what I observed in the scope. actually its not as expected / as given in the datasheet of the sensor.
    wave.jpg

    The above is what i observe. See the output when there is no obstacle, for 5 meters ! the pulse is below zero.(not as given in the datasheet). But the code works regardless of this and I dont understand. As you can see, as the obstacle comes closer, the pulse width shrinks (less distance) and also, the pulse train slowly raises above zero (weird?):mad:

    Light?
  12. kubeek

    kubeek AAC Fanatic!

    Joined:
    Sep 20, 2005
    Messages:
    3,563
    Location:
    Prague, Czech Rep
    Looks like you had it AC coupled maybe? Doesn´t the scope have the ability to save a screenshot?
  13. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    No. It doesnot have screen shot ability. What do you mean by AC coupled? I am completely working with DC. No way it is AC coupled.! even for the probe, i used only one probe (single channel).

    I think you don't get the operation of the system?

    The wave forms represented in the picture are correct. But they must be above zero.(everything)
  14. kubeek

    kubeek AAC Fanatic!

    Joined:
    Sep 20, 2005
    Messages:
    3,563
    Location:
    Prague, Czech Rep
    That´s what I mean, the oscilloscope channel can be set to either ground, DC, or AC on a scope. The AC coupling on the scope would remove the DC component and would provide very similar readings to what you show in the pictures, assuming it is a purely digital output which should never go below 0V.
  15. thinkanish

    thinkanish Thread Starter New Member

    Joined:
    Mar 29, 2013
    Messages:
    8
    Hi kubeek, sorry, The scope has screen capture via PC (USB). I ll post the screen shot by today. But for that software, I have to borrow a windows machine. Do you know any scope screen capture software for linux? (I'm running linux 3.8.3). If no, i will get a windows machine to capture the screen and post it.

    Bye.
Similar Threads
Forum Title Date
Embedded Systems and Microcontrollers measuring 220V ac with MCU Jul 11, 2014
Embedded Systems and Microcontrollers measuring ac signal with microcontroller Jul 4, 2014
Embedded Systems and Microcontrollers Measuring 330V dc with MCU Apr 10, 2014
Embedded Systems and Microcontrollers Measuring signal of mV range using PIC 16F877A Jun 28, 2012
Embedded Systems and Microcontrollers Measuring current across inductor? Apr 4, 2012

Share This Page