Playing with code

TEZARM

Senior Member
Ok, I am just mucking around with code at the moment and have now got stuck again. How do I make this led turn off? I know if I put
'low 3' it will stop but I don't want to do that. Can someone please modify this code so I can see how you do it. Thanks guys

symbol ledstop = input2

start:

if ledstop = 0 then stopled

go:

high 3
pause 5000
if ledstop = 0 then stopled
goto go

stopled:

low 3
goto start
 

Jeremy Leach

Senior Member
Nice to see you breaking the problem down ;-)

I can't see anything wrong with this code ...if the input is held low then it should keep going back to StopLED and keep making pin 3 low.

So ...er....are you really holding input 2 low, and is output 3 really going to your LED, and is the LED configured to be 'on' when the output is raised high?

Edited by - Jeremy Leach on 13/11/2006 11:49:08
 

TEZARM

Senior Member
If led is on already, pulling input 2 low will not turn off led? I think problem is here?

pause 5000
"PROBLEM IS IN THE MIDDLE OF THE CODE HERE"
if ledstop = 0 then stopled
 

Michael 2727

Senior Member
Have you got a pullup resistor for when the
switch is not low ?
Apart from that I can't see what may be wrong.
Check your switch, soldering, wire, breadboard etc.


Edited by - Michael 2727 on 13/11/2006 12:21:43
 

MartinM57

Moderator
Hi TEZARM

You're almost certainly correct - it's the PAUSE 5000 messing you up since the PICAXE is effectively stuck in an internal loop for 5 seconds in that PAUSE statement so can't do any of your other code.

It's actually pretty tricky to get a LED to light for 5 seconds whilst being able to run code to detect input switches etc at apparently the same time. I'll let others offer solutions.

On another matter, it's good to have code with a single main loop that runs continuously and calls subroutines to do specific tasks only when required.

Initially this makes it look overcomplex, but once you get the hang of it, it becomes quite easy. The code you show is called "spaghetti code" in the trade and ends up leading to complexity and unmaintainability (ie being able to come back later and change it)

So I would offer you something like the following (untested)

symbol led_on = b9 '..or whatever
led_on = 0 'led is initially off

mainloop:
' if led should be off, but is still on...
if ledstop = 0 and led_on = 1 then call_stop_led
' if led should be on, but is off...
if ledstop = 1 and led_on = 0 then call_start_led
goto end_main_loop

call_stop_led:
gosub stop_led
goto end_main_loop

call_start_led:
gosub start_led
goto end_main_loop

end_main_loop:
goto mainloop


start_led:
high 3
led_on = 1 'indicate that the led is now on
return

stop_led:
low 3
led_on = 0 'indicate that the led is now off
return

Actually, this code is far more complex than if needs be, because the PICAXE V4 editor doesn't do IF...THEN GOSUB, so you have to have a lot of GOTO statements - but V5 of the editor fixes that
 

Michael 2727

Senior Member
You could replace the paues with a 5 Sec "Count"
That way you still get the LED ON for 5 Sec
but any button press above 0 could be
counted into a variable then acted upon.
 

BeanieBots

Moderator
There are two ways around detecting button pushes during a timed loop.
One is to use interrupts. This is generally accepted as the better solution but it is not for the beginner.
The other is to break the time delay into smaller segments and do the test after each segment.
For example, a 5 second delay which tests the button every 100mS

High LED ' turn on the LED
For b0=0 to 50 'do this loop 50 times
pause 100' 100mS delay
if input.... then... ' check and act on button press
next b0 'end of loop structure
Low LED 'turn LED off

The above example can be 'nested', that is, one loop inside another loop so that the whole thing is repeated giving you a flashing LED (on 5 secs, off 5 secs) whilst still testing to see if the button has been pressed.

Well done for breaking things down and getting to learn how each bit works. The effort will pay off in the end.

Edited by - beaniebots on 13/11/2006 13:30:23
 

TEZARM

Senior Member
Ahh, This one had some of you thinking didn't it. Well done Martin and Beaniebots for quickly picking up the problem area. Thanks to all for your help. I will have more of a play with this tonight after work. Thanks guys and thanks for the examples Martin and Beaniebots. I do like examples, makes life so much easier.
 

Michael 2727

Senior Member
Tezarm try this,


start:
count 2, 5000, b0
if b0 = 0 then stopled
go:
high 3
count 2, 5000, b0
if b0 = 0 then stopled
goto go
stopled:
low 3
goto start

Seeing as you are lazier than myself ~ 'o)
 

TEZARM

Senior Member
Error 'Count' command not supported in this mode.

Huh? Doesn't work, don't know why.

I am not lazy at all thanks. Wat you talking about sucker? Lol
 

TEZARM

Senior Member
Beaniebots, your example is a little confusing to me. It turns the led on for about maybe 8 seconds or so and than turns off by itself but it will also turn off by pulling input low. Maybe it was the way I read it and made it work. Sorry I couldn't get that one of yours to work Martin but thats ok as it looks way to advanced for me to understand anyway. But Beaniebots, I was playing with your code (cos it's the easiest looking) and I got it to work. I changed it a little as I have introduced an input to trigger the led now but it works perfect. That was easier than I thought. Can you guys just double check this code for me to see if I have done it properly?


start:

symbol ledstart = input0

if ledstart = 0 then ledon:
goto start

ledon:

High 3 ' turn on the LED
For b0=0 to 50 'do this loop 50 times
pause 100' 100mS delay
if input2 = 0 then wup
next b0 'end of loop structure
goto start

wup:
low 3
goto start

 

TEZARM

Senior Member
Thanks inglewoodpete. Nope, it still won't work even using w0. It's got me beat. Thats one for Micahel 2727 to figure out as I don't understand it enough to solve it.
 

TEZARM

Senior Member
Oops, forget what I said about not understanding you Beaniebots. I understand perfectly now. What does the pause 100 part do though?
 

TEZARM

Senior Member
What does the pause 100 part do though?

Sorry Beaniebots, TEZARM is an idiot. You have clearly said in your post above what it does. I get it. Sorry for the stupid question. I need to learn to read thing more carefully first.
But a more sensible question, How do I get the led to flash? That part I definitely do not undersdtand.
 

Jeremy Leach

Senior Member
Should let Beanie answer really ...but his code does 50 lots of 100 millisecond Pauses instead of one big 5000 millisecond Pause. It does this by having a FOR...NEXT loop, which we can explain if necessary.

And between each 100 millisecond pause there's a quick check on the state of the input pin, rather than having to wait the full 5000 milliseconds before checking the pin.

This makes the code more responsive (ie it will detect quicker) to changes on the input pin.
 

TEZARM

Senior Member
Oh, hang on a second, you mean like this Beaniebots. Now my led flashes but only monitors the input pin every 100ms for the first 2 SECONDS ONLY? NIt needs to monitor it all the time. How do I do that? Unless of course I am wrong with the below. Sorry I know the pins have all been renamed and are different etc, so I hope I am not confusing you to much by doing this.
 

TEZARM

Senior Member
Oh boy, forgot to post the code again, didn't I. Thanks for that Jeremy by the way.

symbol ledstart = input0


start:

if ledstart = 0 then ledon:
goto start

ledon:
loop:
pause 300
High 7 ' turn on the LED
For b8=0 to 2 'do this loop 250 times which is 25 seconds
pause 100' 100mS delay
if input2 = 0 then wup
next b8 'end of loop structure
low 7
goto loop


wup:
low 7
goto start
 

BeanieBots

Moderator
Looks fine.
It will wait until you push the button, then flash the LED until it pressed again.
In theory, the LED should be on for about 5 secs but in practice it will be longer because the loop which is executed 50 times also takes some time.
You can change the flash rate by changing either the (50) loop count or the pause 100 values.
One small issue, if the trigger to start the flashing is a brief pulse, then all is well. If it is a human pushing a button, then it could easily still be low when the test is made in the flashing part of the code. To avoid this, you could put in another test jus before entering the flashing code that waits until it has been released.
Well done. That's quite a nice a little routine you have created that will probably have many uses within a larger programs.
When you're ready, have read about interrupts.
 

Michael 2727

Senior Member
Teza, the "Count" only works on 08M, 18X, 28X and 40X.
What are you using ?
Pity it does exactly what you want.

Pete, "Count" counts the number of switch
presses over 5 Sec into the byte.
you only have to press the switch once for
it not to be ZERO, anymore does not even
matter, b0=1, or b0=75 is still not zero.
You would have to be very quick to press
more than 255 needing the W byte.

 

TEZARM

Senior Member
Thanks Beaniebots. But the problem I have when like this is because I have:

For b8=0 to 2

Am I correct in thinking that the code is only going to monitor input 2 for the first 2 flashes and then after that the only way to stop led is to catch it after a pause in the flashing of led. Because thats the way it is working unless I increase the 2 to say 255 which will than monitor input 2 for about 30 seconds and than after that the same problem again. You know what I mean? Um, the trigger is a negative pulse which is good, it's not a push button.

Micahel 2727. Ahh, than thats why it won't work cos I am using an 18A.
 

MartinM57

Moderator
Am I right in thinking that this, currently standalone, code will eventually find it's way into the rest of your alarm system??

If not, and this is just a bit of diversionary fun, then disregard the rest of this....

But I think you need to realise what you are doing here...
...although your code is sort of working and your are 'getting the bugs out' what is the code doing most of the time? The answer is that it is (still) sitting inside PAUSE statements most of the time - instead of one big PAUSE, you've lots of tiny ones with a gap between them that you are using to detect switches and flash the LED. But percentage wise, you are forcing the PICAXE into doing nothing for maybe 99% of the time.

So...how is this all going to work when you have to put this in the rest of the code, which is a lot more complex? When are you going to detect all the other buttons and do the processing that they demand, when most of the time you have stopped the PICAXE working by having it sit in PAUSE statements just so you can get one LED to flash?

Requirements like the one you have ('do your normal stuff, but when something specific happens do something else for the next 5 seconds, but at the same time still do all the normal stuff) are actually extremely hard to do in software with a PICAXE, if not impossible.

You could use a 'flashing LED' - with these, you just turn them on (HIGH 2, or whatever) and they flash themselves until you turn them off (LOW 2, or whatever) removing the need to flash it in software...
...but how to code it so that it it is only on for 5 seconds whilst monitoring all the other switches is very very hard.

My $0.02 etc...Martin
 

TEZARM

Senior Member
Martin, I am just trying to understand the basics at the moment as you have told me to do and others aswell. Yes eventualy it will result in improvements to my car alarm but for now it's just learning and getting the experience to be better at this programming.
Yeh I could just use a flashing led but I can't learn anything from that plus eventually (for the alarm anyway) I hope to be able to use this led to flash diagnostics of the alarm. A flashing led is to easy. I want to get a little more advanced and be good at programming for a change. Thanks
 

Michael 2727

Senior Member
Just a warning on flashing LEDS.
You can run them on 5V without a resistor.
With a Picaxe DON'T TRY IT.
You <b>must </b> use a resistor anyway.
Many of the FLED's will run up to 12 to 15V
DC but when they flash at that voltage they
can draw almost 1 AMP briefly.
 

Rickharris

Senior Member
Although the pixaxe isn't actually looking at the switch all the time t does so very often and for the most part you would press a switch for possibly several look cycles of the programme and so would catch the press.

This is a very common way to do things. A microprocessor only does things one at a time. BUT it does them so very fast it looks like it is doing several things at once.
 

BeanieBots

Moderator
TEZARM, my last replay sat in the input box for a few hours before sending.
It did not answer your last set of questions. No time right now but I'll try to send something later. Hang in there, all the other replies are all good stuff for you to note.
 

BeanieBots

Moderator
'TEZARM, this an example program for you to play with.
'it's written for an 18X so uses input6 and output 0
'you can change accordingly.
'input6 is &quot;active&quot; when high, change the symbol deff to 0
'it starts off by flashing an LED on output0 3 times then waits about 600mS before repeating
'the input can be activated at any time
'when it is, it will wait until the 'activation' is removed
'and then start to flash 5 times.
'again the input can be activated at any time.
'a second activation will make it go back to flashing 3 times.
'It's not pretty, it's not fancy, but it works. Have fun with it.
'I'm too lazy to use symbol for everything but you should use it.


symbol activated=1

start:
b0=3'do three flashes to start with

main:
for b1=1 to b0 'set up loop for number of flashes
high 0 'LED on
for b2=1 to 15 'set up timed loop that also tests input
if pin6=activated then changeflash 'jump if input activated
pause 10 'short delay that is repeated 15 times
next b2 'end of inner timed loop
low 0 'turn off LED
for b2=1 to 15 'another timed loop but with the LED off
if pin6=activated then changeflash 'test the input
pause 10 'wait a short while (15 times)
next b2 'end of loop with LED off
next b1 'end of flashing loop

for b1=1 to 60 'a longer loop, 60 times 20mS for the off period after flashing
if pin6=activated then changeflash 'mustn't forget, keep testing the input
pause 20
next b1' end of longer loop

goto main' go back and do it all again

changeflash:
pause 10 'wait a short while for any switch bouncing.
if pin6=activated then changeflash ' keep waiting until the 'activation' clears
if b0=3 then fiveflashes
if b0=5 then threeflashes

fiveflashes:
b0=5
goto main
threeflashes:
b0=3
goto main 'go back to the main program with a new number to flash.
 

BeanieBots

Moderator
This is exactly the same program but using interrupts. Notice how much smaller and neater it is.

symbol activated=1
symbol yourinputs=%01000000 'check only input 6
symbol yourmask = %01000000 'interrupt when it goes high

start:
b0=3'do three flashes to start with
setint yourinputs,yourmask 'activate interrupts

main:
for b1=1 to b0 'set up loop for number of flashes
high 0 'LED on
pause 180
low 0
pause 180
next b1 'end of flashing loop
pause 1200 'longer off pause
goto main

interrupt: 'this is where the interrupt routine starts
changeflash:
pause 10 'wait a short while for any switch bouncing.
if pin6=activated then changeflash ' keep waiting until the 'activation' clears
if b0=3 then fiveflashes
if b0=5 then threeflashes

fiveflashes:
b0=5
goto endofinterrupt
threeflashes:
b0=3

endofinterrupt:
setint yourinputs,yourmask 're-activate the interrupts
return 'go back to the main program with a new number to flash.
 

TEZARM

Senior Member
Ah yes, I see your point Rick. But leaving the code this way is just not perfect enough for me. I keep thinking to myself, Yeh TEZARM just leave it like it is, but I can't as it seems wrong to me to do it this way, so thats why I persevere with a solution.

Whoa, now we are getting technical Beaniebots. Um, ok im going to have to have play with that one. Yeh, those damn interrupts, I just cannot understand them no matter how many times I try to. That &amp;01000000 part confuses me soooo much. Cannot understand for the life of me how
%01000000 means Input 6? Very confusing to me? But anyway I'll give it another go anyway. Thanks so much Guys
 

TEZARM

Senior Member
Hey Beaniebots, I can get your first example to work with my 18A if I modify it like this below: But as for the second example with the Interrupts, No way. That has got me really stumped, that one. I have tried modifying it to work but haven't got a clue what I am doing? But now I am going to have a bit more of a play with that first example again.

symbol activated=0

start:
b0=3'do three flashes to start with

main:
for b1=1 to b0 'set up loop for number of flashes
high 3 'LED on
for b2=1 to 15 'set up timed loop that also tests input
if pin2=activated then changeflash 'jump if input activated
pause 10 'short delay that is repeated 15 times
next b2 'end of inner timed loop
low 3 'turn off LED
for b2=1 to 15 'another timed loop but with the LED off
if pin2=activated then changeflash 'test the input
pause 10 'wait a short while (15 times)
next b2 'end of loop with LED off
next b1 'end of flashing loop

for b1=1 to 60 'a longer loop, 60 times 20mS for the off period after flashing
if pin2=activated then changeflash 'mustn't forget, keep testing the input
pause 20
next b1' end of longer loop

goto main' go back and do it all again

changeflash:
pause 10 'wait a short while for any switch bouncing.
if pin2=activated then changeflash ' keep waiting until the 'activation' clears
if b0=3 then fiveflashes
if b0=5 then threeflashes

fiveflashes:
b0=5
goto main
threeflashes:
b0=3
goto main 'go back to the main program with a new number to flash.
 

BeanieBots

Moderator
It should work on your system with
symbol activated = 0

For the interrupt version change:
symbol yourinputs=%01000000 'check only input 6
symbol yourmask = %00000000 'interrupt when it goes low

The setint values are straightforward enough when you realise that all those 0's and 1's represent the inputs.

input 7654321
use IP^^^1^^^

The 1 lines up with input 4
Thus setint %00010000,.... means use input 4
The % is just to tell the editor that are using a binary number instead of 1000 with three leading zeros.
The other bit works the same way but tells it to trigger on high or low input.
Read the manual a few times. It will suddenly click into place but they can be very confusing at first. Don't worry, the other method will work OK for your application. It just means a lot more code writing and things to worry about but a good paper flow diagram will sort all that out for you.



Edited by - beaniebots on 15/11/2006 07:53:44
 

TEZARM

Senior Member
Beaniebots said:

For the interrupt version change:
symbol yourinputs=%01000000 'check only input 6
symbol yourmask = %00000000 'interrupt when it goes low

The setint values are straightforward enough when you realise that all those 0's and 1's represent the inputs.

input 7654321
use IP^^^1^^^


TEZARM:

Still don't understand Beaniebots?
Above you have %01000000 (Eight digits)
Then in your example you have input 7654321 which is (seven digits). Now I do understand it numbers backwards, but, does it need 7 or eight digits and does it always start with the first 0 (the one at the end) as a 0 or 1?
I have tried changing it again but still can't get it to work. Heres the code so far, can you see the problem? Please note, I am trying to use input2 , not input 6. Oh, and how does the mask work? Going back to your first example, I can get that to work but find it very complicated to sort out so it's hard for me to understand. Maybe I am a little bit far ahead for my knowledge so far, you reckon?

symbol activated=0
symbol yourinputs=%00000100 'check only input 2
symbol yourmask = %00000000 'interrupt when it goes high

start:
b0=3'do three flashes to start with
setint yourinputs,yourmask 'activate interrupts

main:
for b1=1 to b0 'set up loop for number of flashes
high 3 'LED on
pause 180
low 3
pause 180
next b1 'end of flashing loop
pause 1200 'longer off pause
goto main

interrupt: 'this is where the interrupt routine starts
changeflash:
pause 10 'wait a short while for any switch bouncing.
if pin2=activated then changeflash ' keep waiting until the 'activation' clears
if b0=3 then fiveflashes
if b0=5 then threeflashes

fiveflashes:
b0=5
goto endofinterrupt
threeflashes:
b0=3

endofinterrupt:
setint yourinputs,yourmask 're-activate the interrupts
return 'go back to the main program with a new number to flash.
 

TEZARM

Senior Member
Don't worry Beaniebots, I think I have just figured it out. My input is going low, not high, so it should be like this right?

symbol your mask=%00000000 'interrupt when low
symbol yourinputs = %00000100 'check input 2
 

BeanieBots

Moderator
My mistake, sorry for confusing you further.
The inputs should read 76543210.

As far as I know, (I'm not 100% sure myself) the following should work for you.

symbol yourinputs = %00000100 'check input 2
symbol your mask=%11111011 'interrupt when low
I don't have editor or manual to hand to check.
Try swapping inputs &amp; mask value over just in case I have got them the wrong way around.

When specifying a number using %, you should always state all 8 digits.
For input 2 you could use the decimal value 4 but it would not make the code very readable.

Just checked with the fancy new simulator and I got it wrong. (it's so spooky watching your code run like that!)
I've corrected the values above which work for input2 going low (at least they do in the simulator).

Edited by - beaniebots on 15/11/2006 18:44:05
 

TEZARM

Senior Member
Beaniebots. To get your ezample in paericukar to work i simply just used.

symbol yourinputs = %00000000 'check input 2
symbol your mask=%00000100 'interrupt when low

It seems to work fine this way. Is it not right?
 

Fowkc

Senior Member
Just jumping in without reading much of the post.

Your interrupt above will trigger when input2 is LOW, and will only check input2 (other pins do not matter).

You code works, but your comments make more sense (at least to me) if they were swapped over...
 

BeanieBots

Moderator
The manual explains it better than I can.
If it works for your example, then it IS correct. If my (interpreted) example of your situation does not work, then my example is WRONG for your application. It really is as simple as that.
The important thing is that you now have two different methods of making a program do several things at once. That is one of the biggest hurdles to get over. You can now use them as building blocks to make some really quite sophisticated applications.
Keep playing with each example until you confident about how each bit works and happens you change certain values.
Might be a good idea to run them in the simulator and watch the lines being executed.
 

TEZARM

Senior Member
Actually I was going to ask you if when you have time, if you could give me another little example of interrupts. I mean something really simple thats not using variables and maybe that just turns an led on and off by monitoring 2 inputs. Although your example works it is incredibly hard for me to try and figure out how it works as I seem to be getting really confused with all the variables. But from what you have shown me so far I am actually starting to undestand interrupts now but if possible a simpler example would be great aswell. In my opinion, the manual is not easy to understand as it only gives you an example of the interrupt command by itself only. So when trying to put this into other code it makes it near impossible to get working unless you have a complete example like you have given. I spent about 5 hours straight with your example last night trying to understand interrupts so want to keep going a little bit more with them so I can use them for everything.
 
Top