|
|
View previous topic :: View next topic |
Author |
Message |
olimathus
Joined: 13 Jul 2014 Posts: 2
|
Semaphore with push button for pedestrians |
Posted: Sun Jul 13, 2014 11:44 am |
|
|
Hello everyone. I have a school project where the objective is to make semaphore. The semaphore is working ok, however I've been having problems with the interrupts that I'm using for the push buttons, which are needed for the pedestrians. Here is the code:
Code: | #include <16F887.h>
#fuses HS,NOLVP,NOWDT
#use delay (clock=20000000)
#define BOT1 pin_B0
#define CARRED1 pin_C1
#define CARYELLOW1 pin_C2
#define CARGREEN1 pin_C3
#define PEDRED1 pin_D1
#define PEDGREEN1 pin_D2
#define BOT2 pin_B4
#define CARRED2 pin_C5
#define CARYELLOW2 pin_D0
#define CARGREEN2 pin_D5
#define PEDRED2 pin_D4
#define PEDGREEN2 pin_D3
#int_ext
void ext_isr()
{
if (input(pin_b0)==0)
{
output_low (PEDRED1);
output_high (PEDGREEN1);
output_high (CARRED1);
output_low (CARYELLOW1);
output_low (CARGREEN1);
output_high (PEDRED2);
output_low (PEDGREEN2);
output_low (CARRED2);
output_low (CARYELLOW2);
output_high (CARGREEN2);
delay_ms(8000);
}
}
#use delay (clock=20000000)
#int_rb
void rb_isr()
{
if (input(pin_b4)==0)
{
output_high (PEDRED1);
output_low (PEDGREEN1);
output_low (CARRED1);
output_low (CARYELLOW1);
output_high (CARGREEN1);
output_low (PEDRED2);
output_high (PEDGREEN2);
output_high (CARRED2);
output_low (CARYELLOW2);
output_low (CARGREEN2);
delay_ms(8000);
}
}
#use delay (clock=20000000)
void main ()
{
port_b_pullups(TRUE);
enable_interrupts(int_ext);
enable_interrupts(int_rb);
ext_int_edge(H_to_L);
enable_interrupts(GLOBAL);
set_tris_b(0x11);
set_tris_c(0x00);
set_tris_d(0x00);
while (TRUE)
{
output_high (PEDRED1);
output_low (PEDGREEN1);
output_high (CARRED1);
output_low (CARYELLOW1);
output_low (CARGREEN1);
output_high (PEDRED2);
output_low (PEDGREEN2);
output_high (CARRED2);
output_low (CARYELLOW2);
output_low (CARGREEN2);
delay_ms(2000);
output_high (PEDRED1);
output_low (PEDGREEN1);
output_low (CARRED1);
output_low (CARYELLOW1);
output_high (CARGREEN1);
output_low (PEDRED2);
output_high (PEDGREEN2);
output_high (CARRED2);
output_low (CARYELLOW2);
output_low (CARGREEN2);
delay_ms(2000);
output_high (PEDRED1);
output_low (PEDGREEN1);
output_low (CARRED1);
output_high (CARYELLOW1);
output_low (CARGREEN1);
output_low (PEDRED2);
output_high (PEDGREEN2);
output_high (CARRED2);
output_low (CARYELLOW2);
output_low (CARGREEN2);
delay_ms(2000);
output_low (PEDRED1);
output_high (PEDGREEN1);
output_high (CARRED1);
output_low (CARYELLOW1);
output_low (CARGREEN1);
output_high (PEDRED2);
output_low (PEDGREEN2);
output_low (CARRED2);
output_low (CARYELLOW2);
output_high (CARGREEN2);
delay_ms(2000);
output_low (PEDRED1);
output_high (PEDGREEN1);
output_high (CARRED1);
output_low (CARYELLOW1);
output_low (CARGREEN1);
output_high (PEDRED2);
output_low (PEDGREEN2);
output_low(CARRED2);
output_high (CARYELLOW2);
output_low (CARGREEN2);
delay_ms(2000);
}
} |
Last edited by olimathus on Sun Jul 13, 2014 12:12 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sun Jul 13, 2014 11:57 am |
|
|
Two things:
Debounce.
Delays in the ISR.
Now the first problem is that switches don't produce nice clean 'on/off' pulses. They will often make several times. You don't want to accepts a single 'I am on' edge. This could be caused by somebody holding the button a long time, then releasing it and generating another set of these edges....
Then you have massive delays in the ISR.
Rethink.
Have a single 'tick' interrupt. A timer running out at perhaps 50* per second.
Then just test the buttons in this.
If a button is seen to be 'on', record this fact and exit.
If a timer is seen 'on', and has already been recorded as on, then accept it.
Cancel the recording whenever a button is off.
This way the button has to be 'on' and stable for two successive interrupts.
Then don't do your pedestrian sequences in the ISR. Instead use a 'state machine' in the main code - I suggest using an enum for the names of the states, and using a switch...case with this, so you have states like 'pedestrian_stop' etc..
Do the timings, by using a counter updated in the same tick. Have the tick code use:
Code: |
//global variable
int16 wait=0;
#define SECS 50 //assuming the ISR is 50Hz
//Then in the ISR
if (wait)
--wait;
//Then in the main
//to delay 5 seconds
wait=SECS*5;
while(wait); //Whatever code is here will execure for 5 seconds
|
I suspect you have seen where you can use multiple #use delay declarations to allow delays in an ISR, without interrupts being disabled in the main. True, but it is still c&*p programming, unless necessary, and won't solve the problems with the approach.... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 13, 2014 12:02 pm |
|
|
You appear to have buttons on pins B0 and B4. I assume 'BOT' means
a button ? You didn't tell us.
Quote: |
#define BOT1 pin_B0
#define CARRED1 pin_C1
#define CARYELLOW1 pin_C2
#define CARGREEN1 pin_C3
#define PEDRED1 pin_D1
#define PEDGREEN1 pin_D2
#define BOT2 pin_B4
#define CARRED2 pin_C5
#define CARYELLOW2 pin_D0
#define CARGREEN2 pin_D5
#define PEDRED2 pin_D4
#define PEDGREEN2 pin_D3 |
But then in your isr code, you are checking B0 and B1 (not B0 and B4).
What are the true connections for your buttons ?
Quote: |
#int_ext
void ext_isr()
{
if (input(pin_b0)==0)
{
.
.
.
output_low (CARYELLOW2);
output_high (CARGREEN2);
delay_ms(8000);
}
}
#use delay (clock=20000000)
#int_rb
void rb_isr()
{
if (input(pin_b1)==0)
{
.
.
.
output_high (PEDRED1);
delay_ms(8000);
}
} |
|
|
|
olimathus
Joined: 13 Jul 2014 Posts: 2
|
|
Posted: Sun Jul 13, 2014 12:11 pm |
|
|
PCM programmer wrote: | You appear to have buttons on pins B0 and B4. I assume 'BOT' means |
Yes. BOT is for button
Quote: |
But then in your isr code, you are checking B0 and B1 (not B0 and B4).
What are the true connections for your buttons ? |
the buttons are in b4 and b0. My mistake, sorry |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jul 13, 2014 2:51 pm |
|
|
A few comments.
Please don't edit code after you've had replies.
The replies no longer make sense, the rest of us can't then follow the thread.
You've got a #use delay AFTER you've tried to use it.
Can't be good news, will probably confuse the compiler or produce strange results.
Indent your code to make it more readable.
As a guide, position each closing } below its opening {.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sun Jul 13, 2014 4:13 pm |
|
|
just a comment...
I find it easier to have 'same length ' variables if possible.
Using GRN for green and YEL for yellow makes them the same as RED for ,well red !
It's just a bit easier on my aging eyes and looks 'neater'.
also
you may have to read the entire PORTB inside the ISR to clear it.I can't be sure, not near the 'testPC' to confirm/deny but it sticks in my head that it's needed.
others will KNOW for sure !!
also when I did 'traffic light' programs(30 years ago !, when Motorola had a 1bit processor) we used NS for the 'north-south' lights, EW for the 'east-west' lights. It might have been a 'traffic standard' back then.It did make it easier to understand when we got into the 'real world'.
hth
jay |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Re: Semaphore with push button for pedestrians |
Posted: Sun Jul 13, 2014 5:10 pm |
|
|
olimathus wrote: | Hello everyone. I have a school project where the objective is to make semaphore. The semaphore is working ok, however I've been having problems with the interrupts that I'm using for the push buttons, which are needed for the pedestrians. Here is the code:
Code: |
set_tris_b(0x11);
set_tris_c(0x00);
set_tris_d(0x00);
|
|
Also
You do not generally need set_tris, the CCS compiler takes care of I/Os better than you.
You have neither explained exactly what you expect your code to do, nor what you perceive the real problem to be.
At this stage we are all having to second guess what's in your head.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 14, 2014 12:40 am |
|
|
This is where a 'what has to happen' list comes in.
What seems to be attempted to be done, is far too simple for anything even approaching 'real'. Normally car lights have to go 'stop', and then a little later the pedestrian lights go green. As it stands the lights all change together, which given that cars take time to stop, would be pretty certain to lead to accidents.
Real sequence would have to be something like:
Car green
Wait for button pressed.
Car lights go red
Wait two seconds
Pedestrian lights go green
Beeper starts
Wait eight seconds
Pedestrian lights go off
Beeper stops
Wait two seconds
Pedestrian lights go red
Car lights go amber
Wait two seconds
Car lights go green
This is the sort of sequence used in the UK (times are very wrong), where there is an 'allowance' time, with cars allowed to progress under 'amber', if there is nobody on the crossing, and pedestrians are not allowed to start crossing.
In the real world there is more to it, with the button not simply starting the sequence, but measurements on the traffic, and how recently the button was last pushed, also being taken into account.
So start with such a list. The actual sequence wanted, and how it progresses.
As I've already said, this sequence should really be coded in the main. This way you can't have a situation where you are halfway through going to the car green state, and a button push immediately intercepts it. Instead the state has to be in the 'car green' mode, before a button is accepted.
Then the key debounce has to be handled, before a button is accepted.
It's worth realising that the keys on your keyboard have a debounce like this, which is why they actually work the way you expect. Without this 'oddities' will be the norm.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|