Generic Prop programming question
sylvie369
Posts: 1,622
Here's a question I have that's probably pretty commonplace. I have a project that has one cog receiving data constantly while other cogs do things like update an LCD screen. That's working fine.
I've recently added indicator lights and a buzzer, all controlled by simply making I/O pins high or low. The lights are "set and forget", so they're no problem. That's all working fine already. But the buzzer pin needs to be set high for a certain amount of time, and then taken low again (that is, I don't want the buzzer buzzing constantly - just for a second or so, and then off again). The other cogs need to be continuing to read data and control the LCD screen while I'm using the buzzer. Clear?
So it seems like I should write a simple method that turns on the buzzer for a certain amount of time, and then off again, and run that method in a new cog each time I run it (so that the other cogs can continue to do their things):
The problem - if I understand things correctly, each time I run the Buzz method in a new cog, I "use up" (as it were) that cog, so after buzzing a couple of times, it's going to stop working, right?
So I assume the answer is to identify the cog that was started when I called the Buzz method, and explicitly release that cog after I'm done buzzing, so it's available again the next time I want to call Buzz.
Am I making this far more complicated than it needs to be?
But if I do something like this
I'd think it would try to stop the cog while the buzzer was still sounding. And if·I put the Cogstop inside of Buzz, how is it going to know the ID of the cog it's trying to stop?
I'll bet there's some straightforward way of doing this, and I'm just missing it, right?
I've recently added indicator lights and a buzzer, all controlled by simply making I/O pins high or low. The lights are "set and forget", so they're no problem. That's all working fine already. But the buzzer pin needs to be set high for a certain amount of time, and then taken low again (that is, I don't want the buzzer buzzing constantly - just for a second or so, and then off again). The other cogs need to be continuing to read data and control the LCD screen while I'm using the buzzer. Clear?
So it seems like I should write a simple method that turns on the buzzer for a certain amount of time, and then off again, and run that method in a new cog each time I run it (so that the other cogs can continue to do their things):
Pub Buzz(Duration) OUTA[noparse][[/noparse]Buzzpin] := 1 Delay(Duration) OUTA[noparse][[/noparse]Buzzpin] := 0 Pub Main Some stuff before I want to sound the buzzer Cognew(Buzz(1000), @Buzzstack) Some other stuff, and then I want to sound the buzzer again Cognew(Buzz(1500), @Buzzstack)
The problem - if I understand things correctly, each time I run the Buzz method in a new cog, I "use up" (as it were) that cog, so after buzzing a couple of times, it's going to stop working, right?
So I assume the answer is to identify the cog that was started when I called the Buzz method, and explicitly release that cog after I'm done buzzing, so it's available again the next time I want to call Buzz.
Am I making this far more complicated than it needs to be?
But if I do something like this
Pub Buzz(Duration) OUTA[noparse][[/noparse]Buzzpin] := 1 Delay(Duration) OUTA[noparse][[/noparse]Buzzpin] := 0 Pub Main Some stuff before I want to sound the buzzer BuzzCog := Cognew(Buzz(1000), @Buzzstack) Cogstop(BuzzCog) Some other stuff, and then I want to sound the buzzer again BuzzCog := Cognew(Buzz(1500), @Buzzstack) Cogstop(BuzzCog)
I'd think it would try to stop the cog while the buzzer was still sounding. And if·I put the Cogstop inside of Buzz, how is it going to know the ID of the cog it's trying to stop?
I'll bet there's some straightforward way of doing this, and I'm just missing it, right?
Comments
Is the main routine you show above is repeated constantly ? If so set the pin on and initialize the timer variable where you now start a cog and compare "cnt" to the variable where you now stop the cog and set the pin to off if "cnt" is equal or greater.
Here's an example:
Steve
In your main loop, first call
Buzzer.Init(@BuzzerPin)
Then, when you need to do a "BEEP" just use any of the PUB methods with preset durations and timings,
eg
BeepFast
Beep
BeepShort
BeepError
etc
You can make up as many "beeps" as you like, I believe this is a waste of a cog, but if you have spare cogs , then keep it simple, But I am planning to do this different in the future with a global timer and Watch routine, As I have other things like LEDS that need to "BLINK" or stay on for short periods of time.
Dave M
Yep you are 100% correct!, Thats a good way of thinking, But A cog can be under-utilised as well!
by the way , my code to init the buzzer should be called as follows
Buzzer.Init(BuzzerPin)
NOT - Buzzer.Init(@BuzzerPin)
Dave m
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
· Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
"The problem - if I understand things correctly, each time I run the Buzz method in a new cog, I "use up" (as it were) that cog, so after buzzing a couple of times, it's going to stop working, right? "
As far as I understand you, you believe that the COG will still be in use, even if the SPIN code has been finished. That's at least what explains the cogstop in the second code snippet of the original post.
First of all:
COGSTOP would stop the COG before it had a chance to run. Doing a COGNEW with a SPIN function means that a SPIN interpreter has to be loaded into the COG. This takes several thousand clocks while the COG which did the COGNEW can continue with the next instruction. From COGNEW to COGSTOP it will only need a few hundred clocks.
When SPIN finishes a function (either by calling return or by implicit return because there are no more instructions) the last return in the call-stack will free the COG. The only reason for eating up COGs in your code is that you call COGNEW without waiting for it to finish (first code snippet). If you do this 7 times no more COGs will be free. And you have the problem that all 7 COGs use the same pin. So the Buzz function looks like not doing the right thing. Oh ... and your buzz function does not set dira. Each COG has it's own copy of dira which is defaulted to 0 when doing a COGNEW.
Have a look at DavidM's code. He uses beepstatus to make sure that beep will only start one COG.
Yes, My code works because the COG is release when when its finished, the status variable handles this.
I use this code in several of my products it works!
Also, I have many BEEP calls thought my designs, the advantage of my code is that ..
a) You Call the BEEPER as much as you like, It won't hold up your main loop, use simple one line calls.
b) You can call the beeper even if its running, but nothing will happen, but there are no hang ups!
You can make up unique beep sounds and then give them simple meaningful names ( refer to my PUB Methods), that way you get consistency. but you don't need to type in any parameters ( i.e repeat, on time, or off time etc,) makes coding a lot simpler.
Thanks
Dave M
If I can get it to work I'll post how I wound up doing it. No luck so far, but I think I've got some good stuff here.
BTW, I've got 5 cogs just sitting here looking for work. I'm trying to find them something to do before they start applying for unemployment.
You're saying that's not the case - that I should set DIRA inside the same method·that's trying to buzz the buzzer, right? (so that it's set for the cog running that method)
If your not getting anything working, Just try out my code I posted earlier.
Make a new object called Buzzer.Spin
Set this in your MAIN (TOP) Object, in the OBJ Block
Then initialize the buzzer object.. ( just once )
Then Somewhere in your main loop call your Beeper to run it
How are you hooking up your buzzer ? Do you have a schematic?
Regards
Dave M
I will try your code, per your instructions. It looks promising - maybe I'll get to it tomorrow. Thanks for the clear directions.
My hookup to the buzzer is straightforward - it works fine when I'm just running a simple program, so I'm sure my issues are all programming, not wiring. When I take pin 16 high, the buzzer starts, and when I bring it low again, it stops. No problem there.
Are you using a transistor?
I use a LOGIC LEVEL Mosfet, By buzzer I use is 6-15V ( run at 12V) Self Oscillating.
In a previous post I have a schematic & PCB Layout that shows this if you wish to look at it.
Dave M
And please keep in mind, that all OUTA of all COGs that use the same pins as output are OR ed together. Usually each COG should use a different set of PINs.
So, yes ... in your case the buzz method should set DIRA before buzzing.
I'm using one of these:
http://www.learn-c.com/tip120.pdf
My buzzer is self oscillating as well: when I set the I/O pin high, it buzzes until I set it low again. Your code would work just fine, and in fact your BEEPRUN method is essentially what I've already been using to make it buzz.
MagIO2 -
Somehow I knew that the OUTAs were ORed together, but didn't realize that each cog had its own OUTA and DIRA. Still there's something else going on.
Did you try my code, I would like you to test out the different beep sounds, as I said it make you code easier to read and you will get consistent sounds.
Also,
That TIP120 Is overkill for a buzzer!
Use something smaller like a BC337 if you want to use a transistor, You will need a series resistor!
But Ideally you should use a MOSFET, like ZVN2106A
A mosfet will not consume any Amperage from the prop pin, and you can drive the mosfet harder, you will not need a series resistor, But you may need a pull down resistor (10K) for start up reasons if you are fussy and depending on the mosfet.
There are plenty of LOGIC LEVEL MOSFET'S that are inexpensive in both through-hole & SMD
Regards
Dave M
give us your latest code and we can have a look.
Take a look at pages 26-27 of the Propeller Manual. There are some simple rules provided that help clarify how the cogs handle the dira and outa details and this ORing business.
Post Edited (ElectricAye) : 4/15/2010 1:35:27 PM GMT
I haven't had the time to work on the buzzer part of this, because the launch was this weekend (did I mention that my project is the receiver for my rocket telemetry thingie?). I discovered in setting up and testing on Wednesday that I had a bad power switch on the rocket, so fixing that took priority, and then I needed to get down to the rest of the wiring for the rocket.
The good news - I flew the thing today, all-up, and it worked perfectly, and it wasn't nearly as cumbersome as I'd thought it might be. I had good altitude readout on an LCD screen during the flight, and a separate cog monitoring XBee pins set up for digital line passing responded quickly to report the deployments of the drogue and main parachutes. I flew low, and fortunately landed right in front of where I was standing, so I had the chance to see chutes come out and my green indicator lights go on immediately with each chute deployment. I did have the buzzer report landing, since there's no need to be concerned about losing data after that point, and that worked perfectly as well. The lights I used were visible in the direct noon sunlight, so I feel like it was worth the trouble of setting up the 12V system.
I believe this is the 9th time I've flown with altitude telemetry, and the second time using a Prop as the receiver (the first 7 all used a BS2px board with the LCD Appmod that I still have set up right here). All of those flights were successful. This is also the second flight with pull-pins for reporting parachute deployment, and that worked perfectly both times as well. These last two flights were the only two that used the same altimeter for altitude reporting and for controlling the ejection charges - I was a little worried that something about sending down the data by radio might interfere with the ejection charges, but that just hasn't happened.
I won't have the chance to get back to work on the buzzer thing until next week, but there's a while before the next launch anyway. The Prop is really shining in this use - it's really helpful to be able to do more than one thing at a time.
http://s282.photobucket.com/albums/kk265/psmithalverno/?action=view¤t=XMTelemetry14.flv
For the fun of it, here's the code:
Post Edited (sylvie369) : 4/24/2010 5:40:41 PM GMT