Pic16f877a+ultrasonic+leds+lcd, delay problem

Thread Starter

skorpion45

Joined Apr 1, 2015
9
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
 

Attachments

joeyd999

Joined Jun 6, 2011
5,237
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.
 

Thread Starter

skorpion45

Joined Apr 1, 2015
9
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
 

Papabravo

Joined Feb 24, 2006
21,159
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.
 

Thread Starter

skorpion45

Joined Apr 1, 2015
9
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
 

Papabravo

Joined Feb 24, 2006
21,159
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.
 

atferrari

Joined Jan 6, 2004
4,764
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.
 

Thread Starter

skorpion45

Joined Apr 1, 2015
9
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:

ErnieM

Joined Apr 24, 2011
8,377
is it ok have a very long interrupt function??????)
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.
 

ErnieM

Joined Apr 24, 2011
8,377
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:
counter_1++;
if( (LED_1 == ON)
  {
  if (Time_1_Hi >= counter_1)
    {
    LED_1 = OFF;
    counter_1 = 0;
    }
  }
else if (Time_1_Lo >= counter_1)
  {
  LED_1 = ON;
  counter_1 = 0;
  }
}
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:

Thread Starter

skorpion45

Joined Apr 1, 2015
9
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:
counter_1++;
if( (LED_1 == ON)
  {
  if (Time_1_Hi >= counter_1)
    {
    LED_1 = OFF;
    counter_1 = 0;
    }
  }
else if (Time_1_Lo >= counter_1)
  {
  LED_1 = ON;
  counter_1 = 0;
  }
}
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).

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:
Top