Generic Prop programming question
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:
CON _clkmode = xtal1+pll16x _xinfreq = 5_000_000 BUZZER_PIN = 24 'pin the buzzer is hooked to VAR long stack[noparse][[/noparse]10] long sound_the_buzzer PUB MainProgram cognew(BuzzerProcess, @stack[noparse][[/noparse]0]) 'start the buzzer processor sound_the_buzzer := true 'make the buzzer buzz waitcnt(clkfreq*4+cnt) 'delay 4 seconds sound_the_buzzer := true 'make the buzzer buzz again repeat 'forever 'end PUB BuzzerProcess dira[noparse][[/noparse]BUZZER_PIN]~~ 'set pin as output repeat if sound_the_buzzer 'make some sound? sound_the_buzzer := false 'clear flag outa[noparse][[/noparse]BUZZER_PIN]~~ 'turn on the buzzer waitcnt(clkfreq + cnt) 'wait one second outa[noparse][[/noparse]BUZZER_PIN]~ 'turn off the buzzerSteve
'' Controls a Piezo Buzzer via a transistor using 1 pin. '' Uses a COG so as not to halt system '' BuzzerState = 0 = Not Running '' BuzzerState = >0 = Running VAR LONG BeeperStack[noparse][[/noparse]20] LONG BuzzerStatus LONG BuzzerPin PUB Init ( vBuzzerPin ) BuzzerPin := vBuzzerPin BuzzerStatus := 0 PUB BeepFast Beeper ( 25, 1, 1 ) PUB Beep Beeper ( 200, 1, 1 ) PUB BeepShort Beeper ( 50, 1, 1 ) PUB BeepError Beeper ( 100, 50, 3 ) PUB BeepSave Beeper ( 500, 100, 2 ) PRI Beeper ( OnDuration, OffDuration, NoOfBeeps ) IF BuzzerStatus == 0 BuzzerStatus := COGNEW( BeepRun( OnDuration, OffDuration, NoOfBeeps ) , @BeeperStack ) PRI BeepRun ( OnDuration, OffDuration, NoOfBeeps ) DIRA[noparse][[/noparse]BuzzerPin] := 1 REPEAT NoOfBeeps OUTA[noparse][[/noparse]BuzzerPin] := 1 WAITCNT((CLKFREQ/1000)*OnDuration+CNT) OUTA[noparse][[/noparse]BuzzerPin] := 0 WAITCNT((CLKFREQ/1000)*OffDuration+CNT) BuzzerStatus := 0In 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:
''** XBee-MAWD Receiver with pull-pins ** ''** and 12v-controlled indicator lights ** ''** and buzzer. ** ''** Paul C. Smith, April 24th, 2010 ** ''XBee RX on pin 0 ''XBee TX on pin 1 ''LCD connected to pin 8. Parallax 4x20 LCD. ''Pull-pins from XBee DIO0 to Prop pin 22, XBee DIO1 to Prop pin 23 ''Event '' Buzzer : Pin 16 ''Lights for Event 1: '' Red : Pin 17 '' Green : Pin 18 ''Lights for Event 2: '' Red : Pin 19 '' Green : Pin 20 {{ XBee Settings: Transmitter: Channel C Can be any channel, but must match receiver PAN ID 3332 Can be any PAN ID, but must match receiver DH 0 Must be 0, to match receiver. DL 0 Must be 0, to match receiver. MY 1 Must be 1 so that I/O line data are properly bound NI XM TX 0 This can be anything, but may be used specifically in later revisions D0 3 (DI) Must be 3, to read I/O line pull-pin status D1 3 (DI) Must be 3, to read I/O line pull-pin status IU 1 (ENABLE) Doesn't really matter, as onboard UART not being used. Could be used for other functions, though. IT 2 (Samples before TX) The IT and IR settings mean that the pull-pins are checked and reported... IR 1F4 (=500 msec sample rate) ...once every second (sample twice/second, transmit after two samples). This could be adjusted to taste. Receiver: Channel C Can be any channel, but must match transmitter PAN ID 3332 Can be any PAN ID, but must match transmitter DH 0 Doesn't really matter as this XBee is only being used to receive DL 0 Ditto MY 6 (Set by program to 0) Doesn't matter where it starts - program sets it properly. NI XM RECEIVER 6 This can be anything, but may be used specifically in later revisions D0 (Set by program to 5: DO HIGH) D1 (Set by program to 5: DO HIGH) IA (Set by program to 1: Input Address 1, bind input to Module 1) IU (Set by program to 0: Prevent I/O line data from going out UART) }} CON _clkmode = xtal1 + pll16x '80MHz operating frequency. _xinfreq = 5_000_000 Hz = 100 OBJ XB : "XBee_Object" Comm : "FullDuplexSerialPlus" Num : "Numbers" LCD : "Debug_LCD" BS2 : "BS2_Functions" Buzz : "Buzzer" VAR byte Alt[noparse][[/noparse]6] ' Variable to hold the first 6 bytes of altitude data from MAWD. First 5 bytes are 5 digits of altitude, then CR (then LF, unread). word AltN ' Variable to hold numerical value of altitude, after conversion from string. word MaxAlt ' Variable to hold maximum altitude byte Event1 ' Has pull-pin 0 pulled? byte Event2 ' Has pull-pin 1 pulled? long PinStack[noparse][[/noparse]65] ' Stack for cog running PinsCheck (stack size set by trial and error: 9 is too small, and overwrites E1). long LCDStack[noparse][[/noparse]65] ' Stack for cog running LCDUpdate word LCDBuffer[noparse][[/noparse]8] ' Variable to hold values to be displayed on the LCD. { 0 - AltN 1 - MaxAlt 2 - Flight status: 0 = Ready, 1 = In flight, 2 = Landed 3 - Event 1: 0 = No event, 1 = Event 4 - Event 2: 0 = No event, 1 = Event 5 - Data received: 0 = No, 1 = Yes 6-7 (reserved) } word LCDBufOld[noparse][[/noparse]8] ' Temporary buffer to be compared with current contents to determine whether or not to update LCD. byte temp, flag ' General purpose variables byte LandingFlag ' Flags for landing detect, event 1 and event 2 status. byte Event1Flag, Event2Flag ' Flags: False = event has not occurred. ' True = event has occurred. Pub Start XB.start(0,1,0,9600) ' XBee Comms - RX,TX, Mode, Baud XB.AT_init XB.AT_Config(String("ATMY 0")) ' Config to receive as Module 0 to match XBee-MAWD telemetry output DL setting. DIRA[noparse][[/noparse]22..23]~ ' Set pins 22 and 23 as inputs from the XBee I/O pins 0 and 1 XB.AT_Config(String("ATD0 5")) ' Config to use XBee DIO pin 0 as a digital output, default HIGH XB.AT_Config(String("ATD1 5")) ' Config to use XBee DIO pin 1 as a digital output, default HIGH XB.AT_Config(String("ATIA 1")) ' Config to receive DIO data from module whose MY = 1. XB.AT_Config(String("ATIU 0")) ' Config so that DIO pin states are not sent out UART, where they would interfere with alt data Num.init ' Initialize Numbers object used to convert alt input string to a number BS2.start (31,30) ' Initialize BS2 object used to receive serial data from XBee Buzz.init(16) ' Initialize Buzzer object with output pin to buzzer ' Zero out the LCD buffers temp := 0 repeat while temp < 8 LCDBuffer[noparse][[/noparse]temp] := 0 LCDBufOld[noparse][[/noparse]temp] := 0 temp := temp + 1 Cognew(LCDUpdate, @LCDStack) ' Start the LCD updating method continuously in a separate cog. ' Initialize Flight Variables AltN := 0 ' Start at 0 altitude MaxAlt := 0 ' Set max altitude to 0 as well. Event1 := %00000000 ' Clear the pull-pin variables Event2 := %00000000 ' Event1 and Event2 ' Clear flags for... LandingFlag := False ' - Landing Event1Flag := False ' - Event1 Event2Flag := False ' - Event2 Cognew(PinsCheck, @PinStack) ' Run the PinsCheck method continuously in a separate cog. Repeat while LCDBuffer[noparse][[/noparse]2] <> 3 ' While not "Landed"... If XMCheck ' If data received XMReceive ' Get and display the data Else XMBadData Pub LCDUpdate ' Method to initialize LCD, display splash screen, screen labels, and then update the LCD display data. LCD.init(8, 9600, 4) ' Initialize LCD Pause(1500) ' Let the LCD settle in LCD.cls ' Clear the screen Splash ' Show startup screens LCD.cls Screenlabels ' Label the values LCD.gotoxy(9,2) LCD.str(String("Ready ")) ' Set up Indicator Lights and Buzzer DIRA[noparse][[/noparse]16..20]~~ ' Set pins 16 through 20 as outputs to control lights and buzzer OUTA[noparse][[/noparse]16] := 0 ' Turn off buzzer and green lights OUTA[noparse][[/noparse]18] := 0 OUTA[noparse][[/noparse]20] := 0 OUTA[noparse][[/noparse]17] := 1 ' Turn on red lights OUTA[noparse][[/noparse]19] := 1 Repeat 4 OUTA[noparse][[/noparse]16] := 1 ' Buzz four times, blink all lights to indicate ready. Pause(200) !OUTA[noparse][[/noparse]17..20] ' Toggle indicator lights each time. OUTA[noparse][[/noparse]16] := 0 Pause(200) ' Leave indicator lights at reds on, greens off. Repeat ' Repeat this part continuously... ' See if the LCD Buffer status has changed Flag := 0 ' Clear change flag temp := 0 ' Start with LCDBuffer[noparse][[/noparse]0] repeat while temp < 8 ' Step through the buffer locations if LCDBuffer[noparse][[/noparse]temp] <> LCDBufOld[noparse][[/noparse]temp] ' If there is a change Flag := 1 ' Set the change flag temp := temp + 1 ' If the LCD Buffer status has changed, update the LCD If Flag ' If the change flag is set LCD.gotoxy(10,0) ' Write the AltN variable to LCD LCD.decf(LCDBuffer[noparse][[/noparse]0],5) LCD.gotoxy(10,1) ' Write the MaxAlt variable to LCD LCD.decf(LCDBuffer[noparse][[/noparse]1],5) LCD.gotoxy(9,2) ' Write the flight status case LCDBuffer[noparse][[/noparse]2] 0 : LCD.str(String("Ready ")) 1 : LCD.str(String("Ascending ")) 2 : LCD.str(String("Descending")) 3 : LCD.str(String("Landed ")) If not LandingFlag ' If Landing just detected, sound beeper to indicate landing Buzz.BeepLanding LandingFlag := True ' Set LandingFlag so that Beep does not continue LCD.gotoxy(9,3) case LCDBuffer[noparse][[/noparse]3] ' Write the value of pull-pin Event 1 0 : LCD.str(String("No ")) OUTA[noparse][[/noparse]17] := 1 ' Set the Event 1 indicator lights to red on, green off OUTA[noparse][[/noparse]18] := 0 1 : LCD.str(String("Yes")) OUTA[noparse][[/noparse]17] := 0 ' Set the Event 1 indicator lights to red off, green on OUTA[noparse][[/noparse]18] := 1 If not Event1Flag ' If Event1 just detected, sound beeper to indicate Event 1. Buzz.BeepEvent1 Event1Flag := True ' Set Event1Flag so that Beep does not continue. LCD.gotoxy(15,3) case LCDBuffer[noparse][[/noparse]4] ' Write the value of pull-pin Event 2 0 : LCD.str(String("No ")) OUTA[noparse][[/noparse]19] := 1 ' Set the Event 2 indicator lights to red on, green off OUTA[noparse][[/noparse]20] := 0 1 : LCD.str(String("Yes")) OUTA[noparse][[/noparse]19] := 0 ' Set the Event 2 indicator lights to red off, green on OUTA[noparse][[/noparse]20] := 1 If not Event2Flag ' If Event2 just detected, sound beeper to indicate Event 2. Buzz.BeepEvent2 Event2Flag := True ' Set Event2Flag so that Beep does not continue. temp := 0 repeat while temp < 8 LCDBufOld[noparse][[/noparse]temp] := LCDBuffer[noparse][[/noparse]temp] ' Set the temporary buffer to reflect the current data temp := temp + 1 Pub XMCheck : Success ' Check to see if receiving data Success := XB.RxCheck Pub XMReceive ' Uses BS2 function to receive simply because I couldn't get the XBee object working BS2.SERIN_STR(0, @Alt, 9600, 1, 8) ' Receive a CR-terminated string to Alt through pin 0 Alt[noparse][[/noparse]5] := 0 ' Convert to z-string for use by LCD and Num objects AltN := Num.FromStr(@Alt, %000_000_000_0_0_000110_01010 ) ' Convert to 5-digit number for use by MaxAlt if (AltN > MaxAlt) & (AltN < 50000) ' < 50000 check is to avoid bad data at landing MaxAlt := AltN LCDBuffer[noparse][[/noparse]0] := AltN ' Update the LCD buffer LCDBuffer[noparse][[/noparse]1] := MaxAlt ' with the new values If MaxAlt > 0 ' If the rocket has launched... If AltN < 1 ' Sometimes the Alt drops below 0 after landing - this accounts for that. LCDBuffer[noparse][[/noparse]2] := 3 ' Change flight status to "Landed". else If MaxAlt > AltN LCDBuffer[noparse][[/noparse]2] := 2 ' "Descending" else LCDBuffer[noparse][[/noparse]2] := 1 ' "Ascending" Pub XMBadData LCDBuffer[noparse][[/noparse]5] := 0 ' Set to indicate no reception Pub PinsCheck ' This will have to go into a different cog to run at the same time at the altitude data receiver. Repeat Event1 := INA[noparse][[/noparse]22] ' Get value of input pin 22 Event2 := INA[noparse][[/noparse]23] ' Get value of input pin 23 If Event1 <> %00000001 ' Default is pulled high to 1 LCDBuffer[noparse][[/noparse]3] := 1 ' If it's not pulled high, flag that the event has occurred else LCDBuffer[noparse][[/noparse]3] := 0 ' Otherwise continue to indicate no event If Event2 <> %00000001 ' Same for the other pull-pin LCDBuffer[noparse][[/noparse]4] := 1 else LCDBuffer[noparse][[/noparse]4] := 0 Pub Splash ' Display startup screen LCD.home LCD.backlight(TRUE) LCD.gotoxy(0,0) LCD.str(@Splash1) LCD.gotoxy(0,1) LCD.str(@Splash2) LCD.gotoxy(0,2) LCD.str(@Splash3) LCD.gotoxy(0,3) LCD.str(@Splash4) Pause(1000) ' LCD.backlight(FALSE) ' Uncomment to turn off backlight after startup. Pub Screenlabels LCD.gotoxy(0,0) LCD.str(String("Alt : ")) LCD.gotoxy(0,1) LCD.str(String("MaxAlt: ")) LCD.gotoxy(0,2) LCD.str(String("Status: ")) LCD.gotoxy(0,3) LCD.str(String("Events 1: 2: ")) PUB Pause(mS) waitcnt(clkFreq/1000 * ms + cnt) DAT Splash1 byte "XM Telemetry ",0 Splash2 byte "Version 1.4 ",0 Splash3 byte "Paul C. Smith",0 Splash4 byte "Apr 24, 2010 ",0Post Edited (sylvie369) : 4/24/2010 5:40:41 PM GMT