PDA

View Full Version : switches & LEDs ... my first attempt



yankee
- 24th August 2005, 14:43
Hi, a newbie to digital here. I'm having trouble getting a PIC16f628A to do more than one function at once with switches.

I have two switches and two LEDs. One switch operates one LED, the other switch operates the second LED.

I need each LED to operate independently of one another and together when their respective switches are activated. Right now, one switch interupts the others function. Here is my code:

Swstb var Porta.0 ' switchstb is on porta.0
Switchleft VAR PORTA.3 ' switchleft is on portb.0

LTS VAR PORTB.0 ' left portb.0
STB VAR PORTB.5 ' STB

TRISA.0 = 1 ' porta.0 is now an input
TRISA.3 = 1 ' Porta.3 is now an input
TRISB.0 = 0 ' Portb.0 is left
TRISB.5 = 0 ' Portb.5 is STB


Main:
IF Switchleft = 0 THEN left 'Pressing switch lights left led
if switchstb = 0 then strobe 'Pressing switch stobes led

Lts = 0 ' If switch is pressed, light the LED otherwise turn it OFF
stb = 0 ' If switch is pressed, strobe the LED otherwise turn it OFF

pause 83

GOTO Main

left:
LTS = 1 'Turn ON LTS
Pause 333 'Wait .333 seconds
LTS = 0 'Turn OFF LTS
Pause 333 'Wait .333 seconds
GOTO Main

strobe:
stb = 1 'Turn on strobe
pause 100 'wait for .1 seconds
stb = 0 'Turn off strobe
pause 100 'wait for .1 seconds
goto main

GOTO Main

Any help on this is greatly appreciated.

Melanie
- 24th August 2005, 15:00
Switchstb var Porta.0 ' switchstb is on porta.0
Switchleft VAR PORTA.3 ' switchleft is on portb.0

LTS VAR PORTB.0 ' left portb.0
STB VAR PORTB.5 ' STB

TRISA.0 = 1 ' porta.0 is now an input
TRISA.3 = 1 ' Porta.3 is now an input
TRISB.0 = 0 ' Portb.0 is left
TRISB.5 = 0 ' Portb.5 is STB

CMCON=%00000111 ' ensures PortA is in Digital Mode

Main:
IF Switchleft = 0 THEN ' Pressing switch lights left led
High LTS
else
low LTS
endif
if Switchstb = 0 then ' Pressing switch strobes led
High stb
pause 100
low stb
pause 100
endif
Goto Main

end

yankee
- 24th August 2005, 16:09
Wow, thanks! Now, that works to make one LED on steady and the other blinking. Is it possible to make them both blink at different rates and still operate independently of one another? I tried to modify that code with no success. I don't understand the comparisons well enough yet.

Melanie
- 24th August 2005, 16:52
So the requirement is as long as the switch is closed you want the respective LED to blink, but they blink at different rates?

Melanie
- 24th August 2005, 17:00
Your request is slightly more complex than you first imagine, because if the PIC is busy timing one LED, it can't really be attending to the other. So we have to do a bit of magic...

Here I've changed the Labels to make association between Switches, LED's, Constants and Variables more readable.

Like Clint Eastwood said in the Dirty Harry films... "Every man has to know his limitations". Now this applies equally to PICs and programs as well. Here, in our example program, the limitation I've set, is that everything happens in multiples of 10mS... but the flip side is that with this method you can add as many LED's and Switches as you have pins on your PIC and each can have different timing rates...



SwitchA var PORTA.0 ' switch on porta.0
SwitchB var PORTA.3 ' switch on portb.0

LedA VAR PORTB.0 ' LED on portb.0
LedB VAR PORTB.5 ' LED on PortB.5

TRISA.0 = 1 ' porta.0 is now an input
TRISA.3 = 1 ' Porta.3 is now an input
TRISB.0 = 0 ' Portb.0 is left
TRISB.5 = 0 ' Portb.5 is STB

CMCON=%00000111 ' ensures PortA is in Digital Mode

LedABlinkRate con 10 ' Blink Rate in Steps of 10mS (10=100mS)
LedBBlinkRate con 33 ' Blink Rate in Steps of 10mS (33=330mS)

LedACounter var BYTE ' Counter for LedA
LedBCounter var BYTE ' Counter for LedB

Low LedA ' Startup with all LEDs OFF
Low LedB
LedACounter=0 ' Startup with all Counters OFF
LedBCounter=0

Main:
If SwitchA=0 THEN ' Closing SwitchA blinks LedA
If LedACounter=0 then
Toggle LedA
LedACounter=LedABlinkRate
else
If LedACounter>0 then LedACounter=LedACounter-1
endif
else
LedACounter=0
low LedA
endif

If SwitchB=0 THEN ' Closing SwitchB blinks LedB
If LedBCounter=0 then
Toggle LedB
LedBCounter=LedBBlinkRate
else
If LedBCounter>0 then LedBCounter=LedBCounter-1
endif
else
LedBCounter=0
low LedB
endif

Pause 10
Goto Main

end


Just added a minor change (zeroing LedACounter and LedBCounter in the main loop), so if you missed it first time, copy the code again.

picnaut
- 24th August 2005, 17:06
Hello,

I generally use a fairly tight loop with small delays and counters.

For the LEDs I use flash-pattern words.
I start at bit 0 of the flash-pattern word and, if it's a ONE, I turn the LED ON.
If it's a ZERO I turn the LED OFF.

Each time I pass through the loop I increment the flash-pattern word's bit counter by one and do the check again.
When the bit counter reaches 16 I reset it to 0 again (a word variable's bits are numbered 0 to 15).

Currently, I have a project with 5 switches and 5 LEDs.
Each LED has a flash-pattern word variable associated with it.

It works well, the flashing is smooth, and does not require interrupts.

If I want an LED to flash on and off quickly (50% duty-cycle), I load it's flash-pattern word variable with %0101010101010101. If I want the LED to flash on and off slowly (but also with a 50% duty-cycle), I load %0000000011111111. If I want it ON all of the time I load it with all ones. If I want it off all of the time I load the variable with all zeros. Basically, you have 65536 different flash-patterns to choose from and all you have to do is load one variable.

The beauty of this is that each LED "seems" to be operating independently with a mind of it's own. Other LEDs' flash-patterns are unaffected when one LED's pattern changes. Also, you can define flash-patterns for different modes as constants. This makes your code much more readable.

For instance...

Main:
If Button1 = 0 Then
LED1Pattern = OPERATING_MODE
Else
LED1Pattern = STANDBY_MODE
EndIf

Pause 10

Gosub UpdateLEDState

Goto Main


In the above example, "Button1" is the aliias for a switch input pin (active low). "Led1Pattern" is a word-sized variable the holds the flash pattern for LED #1. OPERATING_MODE and STANDYBY_MODE are 16-bit constants declared at the beginning of your program. And finally, "UpdateLEDState" is a subroutine (not shown above) that increments the flash-pattern bit-counter and then turns LED #1 on or off, depending on whether the current bit in "LED1Pattern" is a ONE or a ZERO. You could have as many LED flash-pattern words being "updated" in this routine as your RAM allows. I generally use arrays for my flash-patterns and then use a loop.

Anyway, have fun and welcome to PIC programming!

:)

yankee
- 24th August 2005, 20:26
I just love it when someone quotes Clint!

Well, it looks like it's going to be a rough transition to digital after 25 years of analog. I tried your code Melanie, but I couldn't get it to work either LED. I must have gone wrong somewhere. I'll have to double & triple check things on my end.

picnaut is talking WAY above my head, but I'm going to try and figure that one out too, eventually. I can understand all zeros for "off" all of the time and all ones for "on" all of the time, but the rest of it baffles me, so far.

What I need is a picbasic pro for idiots book. Does anything like that exist?

Melanie
- 24th August 2005, 20:32
I posted the code as an example without testing... hmmm.... I'll go check...

picnaut
- 24th August 2005, 20:44
picnaut is talking WAY above my head, but I'm going to try and figure that one out too

Sorry about that.

I'm not at a computer that has Pic Basic Pro installed on it.
Also, I haven't programmed using PBP for a while, so I didn't want to type a bunch of code with a bunch of syntax errors.
That would just confuse you more.
That's why I tried to keep it to mostly theory.

Maybe I can take a look at it tonight and whip something up.
It's a lot easier than my description sounds at first.

How much do you know about binary and hexadecimal number systems?
It would help to know what your background is so that I know where to start.

Anyway, you're going to love programming PICs with basic.
It's a great way to start.
Especially, if you've been working with strictly analogue for a quarter century.

;)

Cheers.

yankee
- 24th August 2005, 20:58
Oh my, don't be sorry, I do appreciate the help!

My background is electronics, 100% analog. I remember learning about binary & hex back in school ... nineteen seventy something *grin* and that's about the only place that I've ever used it. I do understand it, but relating it to electronics has me scratching my head. Old Dog New Trick Syndrome?

Now, if we need to take a single D cell battery and light up 3 white LEDs in series, I'm your man! I'd just as well like to leave that world behind though and learn digital. It's making my life easier, even though I've just begun.

picnaut
- 24th August 2005, 23:00
Hi,

OK. I've attached a program (in a ZIP file) that illustrates the LED flashing method that I described earlier.
It doesn't generate any PBP code, but it will give you a better idea of what is going on so that you can do it for yourself.

The 16 checkboxes at the bottom of the program represent the 16 bits (0 to 15) of the flash pattern word.
Checking or unchecking these boxes will change the "Flash Pattern Word Value" at the top.

NOTE:
I'm only displaying the "Flash Pattern Word Value" in binary format.


The little blue circle below the check boxes and the number in the "Current Pattern Bit Selected" text box indicate at what point in the flash pattern the LED (the big red box) is getting it's status from. Checked = ON, Unchecked = OFF.

Now, neither of the top 2 text boxes accept data input. They are simply indicators. However, the bottom 2 text boxes do accept input. These are the "Loop Delay (PAUSE)" text box and the "LED Update Count" text box. Any changes in these boxes will turn the box yellow. You will need to click the "Update Values" button to enter the changes you make here.

The "Loop Delay (PAUSE)" text box indicates the delay in milliseconds between each launch (i.e. a GOSUB) of the LED's status update routine. In PBP code, look at it as the delay between loops through "Main".

The "LED Update Count" is sort of a countdown between updates of the LED's status. It gets decremented each time the LED's status update routine is launched, and when it hit's zero the LED's flash pattern bit gets advanced by one.

The reason that I use a delay and a count is because a program is often doing several things. You may only want a 10ms delay between loops to handle debounce on switches. 10 milliseconds is way too short for 16 part LED flash though. You need a longer interval like 100ms. So, you end up using a count of ten with a loop delay of 10 milliseconds. Every ten milliseconds the switches are checked and the LED status update routine is launched. Within that routine the count gets decremented. If it's reached zero, the LED pattern bit is advanced and the count is reset to 10.

NOTE:
Due to some "VB issues", you can't make the loop delay value less than 100 milliseconds in the simulation. You can make it as small as you want on an actual PIC though.

Anyway, it will make much more sense to you when you run the program. Try it out by checking and unchecking the boxes. For example, checking the first 8 boxes and unchecking the last 8 boxes will produced a slow flashing pattern.

Enjoy!

yankee
- 25th August 2005, 13:54
Hey, that's a neat lil' demo. Thanks! Now it does make sense. Lets see if I can get something working now.

I'm also still interested in seeing what Melanie comes up with. I keep trying different things with no luck.

Melanie
- 25th August 2005, 19:38
Silly mistake in the code (which everyone should have spotted!)...

Change the two lines (one in each LED control block)...

If LedACounter>1 then...

and

If LedBCounter>1 then...

to both be >0 and not >1

Runs like a trooper...

(I have edited my posted code to reflect the corrections, just copy and run)

yankee
- 13th December 2005, 13:33
... I've been out of commission since August and just wanted to say thanks! Now that I'm back in the game, I'll try this out.

~ Dave

jessey
- 28th January 2006, 12:51
Hello,

Each time I pass through the loop I increment the flash-pattern word's bit counter by one and do the check again.
When the bit counter reaches 16 I reset it to 0 again (a word variable's bits are numbered 0 to 15).

For instance...

Main:
If Button1 = 0 Then
LED1Pattern = OPERATING_MODE
Else
LED1Pattern = STANDBY_MODE
EndIf

Pause 10

Gosub UpdateLEDState

Goto Main

:)

Hello picnaut,

I just found this post and I find it really interesting. I'd love to see your complete program if you could post it with all the defines and variables declared as I've never played with led's the way you explained it here but it sure sounds cool. I think I could learn a lot if I could take it apart and play with it.

Thanks
jessey