Pic16f877a+ultrasonic+leds+lcd, delay problem

Discussion in 'Embedded Systems and Microcontrollers' started by skorpion45, Apr 1, 2015.

  1. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    Hi all
    I need help as Im not expert in programming, Im doing this project source: https://electrosome.com/hc-sr04-ultrasonic-sensor-pic/
    but I need add two leds to it, where one of this leds is blinkin faster and faster when object is closer, my problem is that the delay for blinkin led is affect my lcd so when delay for led is for example 800ms the distance on lcd is changing with this delay, can someone help with this problem I attached pdf file with code from website and I added blinkin led to this project, thank you
     
  2. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,672
    2,697
    This is a primary reason why I always insist on *not* using hard-coded delays in mcu code -- a principle that is routinely violated as a matter of course here at AAC (and educational institutions everywhere).

    In this case, the author has the mpu idling nearly 1/2 second each loop where nothing else can be done (in addition to the echo wait). What a waste of instruction cycles!

    Rewrite the code and eliminate the delays.
     
  3. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    Im not sure do I understand that, but he used this delay to calculate distance?If yes, can you suggest me what other way I could calculate distatnce, thx for quick replay
     
  4. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    You're missing the point. It is fine to measure a variable delay and convert that to distance. You have other delays that must be independent of the measured delay, and they must also be variable. The point is to implement things like blinking in such a way that it does not involve sitting in a loop and spinning. Think in terms of a schedule. After X milliseconds have elapsed complement the present state of the LED. To make the LED blink faster just change the value of X. Easy Peasy.
     
  5. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,672
    2,697
    A good start would be to use the CCP module to capture transit time.
     
    skorpion45 likes this.
  6. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,672
    2,697
    And another hardware timer to process the LED (and whatever else).
     
    skorpion45 likes this.
  7. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,672
    2,697
    And, use interrupts, for Pete's sake. That's what they're there for.
     
  8. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    thx for all answers
     
  9. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    Hmm, I just used timer0 interrupt instead of Delay_ms for led blinking and didnt change structure of the code it seems to work on simulation with Proteus, so my question is, is it possible to look what is the delay_ms function based on, or someone can explain me why delay_ms impact my lcd and timer0 interrupt delay not, if this is to stupid question just let me know, as Im really beginer on this, thx
     
  10. Papabravo

    Expert

    Feb 24, 2006
    10,135
    1,786
    The delay_ms() function sits in a tight loop decrementing a counter to 0. It returns when the counter satisfies the condition. It is sometimes called "busy waiting". It is quick and dirty, but it keeps you from doing more useful things.
     
    skorpion45 likes this.
  11. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,644
    759
    And... (following Joey) is to test code thinking of "divide and conquer". That is, adding one meaninful section of code at a time.

    That piece of advice changed my way of writing code for micros when I started with the 16C57. Yes! THAT one.
     
  12. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    As I understand it is wrong way? thx for answer
     
  13. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    Hello,
    I have done ultrasonic.
    you to just use timer to capture time taken,
    then D=SXT
    for calculating distance.
     
  14. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    thx for the response, this is not about the ultrasonic, I just wish to know if iI do the interrupt this way is it ok? Lets say I`ve got 10 leds to flash in few diff konfigurations
    for example option1:
    led1 2sec on 2sec off
    led2 3sec on 1s off
    led3- blink 3sec times with 1sec intervals
    led4 5sec
    led3 1sec
    led2 3sec on 1sec off
    option 2:
    led2 3sec on 1sec off
    led4 5sec
    led5 blink 4sec with 0.5sec intervals
    led1 2sec on 2sec off
    led7 7sec
    led 8 8sec
    led10 1sec
    option3
    opttion4 and so on
    So if I've got 10 options then this will be very long code inside the interrupt function
    My question is,is it ok have a very long interrupt function,or do same as a example which I gave(but is it still interrupt in this case??????)
     
    Last edited: Apr 17, 2015
  15. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    No. Keep interrupt handlers short and to the point.

    Here you could set up some sort of timing heartbeat. When you get a heartbeat interrupt you update a counter and compare the counter with what needs to be done, what LEDs turn on or off, set these, and get out of there to do other useful things.
     
  16. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    The delay does NOT go inside the ISR. You create a "state machine" that gets tapped every so often to update the display. This works for 1 or 10 or 1 million options (or more).

    From the information you gave the shortest interval is 1/2 a second. So that is how often you run the Interrupt Service Routine (ISR). Practably your timer probably can't get that long an interval but that is a minor detail: you just update a counter and return until you're at 1/2 a sec, then look at your LED states and make the new setting.

    Off the top of my head here's how I would handle each LED inside the ISR:
    Code (Text):
    1. counter_1++;
    2. if( (LED_1 == ON)
    3.   {
    4.   if (Time_1_Hi >= counter_1)
    5.     {
    6.     LED_1 = OFF;
    7.     counter_1 = 0;
    8.     }
    9.   }
    10. else if (Time_1_Lo >= counter_1)
    11.   {
    12.   LED_1 = ON;
    13.   counter_1 = 0;
    14.   }
    15. }
    Very short and direct (and someone will wander by in 10 mins and show something even shorter). You handle all the states by changing Time_1_Hi and Time_1_Lo in your main line code (outside the ISR).

    What is great about this is not only is your main line code very repsonsive but the LEDs are managed almost by magic in that they turn on automatically once you set the state information.

    You can even add other tricks like set a time to -1 to keep a LED always on or off (of cource you need to code for that in the ISR).
     
    Last edited: Apr 17, 2015
    skorpion45 likes this.
  17. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0
    thx a lot its very helpfull
     
  18. skorpion45

    Thread Starter New Member

    Apr 1, 2015
    9
    0

    Following ur advice I wrote somthing like this to blink led1 with 2sec intervals 4 times and led2 2 times with 2sec on and one sec off, can you advice me is it good way of thinking, thx a lot for help
    void interrupt(){
    if(tmr1if_bit==1){
    /***************led1**********************/
    if(led1==1){
    cnt++;
    if(portd.b0==1){
    if(cnt>=timeon){
    portd.b0=0;
    cnt=0;
    }}
    else if(cnt>=timeff){
    portd.b0=1;
    cnt=0;
    blink++;
    }}
    /*******************************led2*****************************/
    if(led2==1){
    cnt++;
    if(portd.b1==1){
    if(cnt>=timeon){
    portd.b1=0;
    cnt=0;
    }}
    else if(cnt>=timeff){
    portd.b1=1;
    cnt=0;
    blink++;
    }}
    tmr1if_bit=0;}
    }

    void main(){
    setup();
    while(1){
    /*********************led1*****************************/
    led1=1;
    portd.b0=1;
    timeon=4;
    timeff=4;
    while(blink<4);
    portd.b0=0;
    led1=0;
    /**********************led2**************************************/
    led2=1;
    portd.b1=1;
    timeon=4;
    timeff=2;
    while(blink<2);
    portd.b1=0;
    led2=0;
    /***************************led3*************************************/
    .
    .
    .
    .
    .
    ./***************************led4****************************************/
    .
    .
    .
    .
    ..
    .
    }}
    thx for help
     
    Last edited: Apr 19, 2015
Loading...