Do i need a clever do..while loop or a timer maybe?

OLDmarty

Senior Member
Hi all,

The below code is simply monitoring for several bursts of data and flash some LEDs (at a slower rate) to indicate the presence (or lack of) data arriving.
In this case, the data is active only when activated by the external gear. it is not a constant data stream.
(i was previously using this code to monitor the picaxe programming data, to flash some leds).

I now need to add a latched relay signal out of the 08M2 (i'll use C.0, jumpered between programming mode and running mode)

I'm having trouble trying to generate a latched signal to hold a relay in place DURING the data arriving..
At the moment all my attempts are using some shady maths which obviously monitors the data becoming 0 or 1 and makes the relay chatter alot.

I'm not sure if a clever do..while/until loop will help or not, but i think maybe i need to use a timer that will timout (release the relay) after the data arriving stops interrupting the timer.
I'm not entirely sure, i haven't really used timers before


Can somebody point me in the right direction? i think it's too easy for me to see the problem lol ;-)

Thanks in advance.



Code:
#Picaxe 08M2

; set FREQ to highest speed?
; obviously ports/bits configured as INs and OUTs as needed.


Do

	IF pinC.3 <> 0 THEN	'If pin is NOT 0, then there must be activity (data/voltage present) 
        High PinC.2	'Turn Bi-Colour GREEN LED ON, on pinC.2
	Low PinC.1	'Turn Bi-Colour RED LED OFF, on pinC.1
        pause 100		'Keep LED ON at least 100mSecs so it's visible.
	Else			'otherwise.....
        Low PinC.2	'Turn Bi-Colour GREEN LED OFF, on pinC.2
	High PinC.1	'Turn Bi-Colour RED LED ON, on pinC.1
	Pause 100		'Keep LED OFF at least 100mSecs so it's visible.
	End if
      
Loop				'Keep monitoring for activity on PinC.3 and repeat.
 
Last edited:

Buzby

Senior Member
Here's a ruff'n'ready basic activity LED and relay driver ....
( Only tested in simulator, you need to set time values to something sensible. )

Code:
[color=Blue]symbol [/color][color=Purple]pindata    [/color][color=DarkCyan]= [/color][color=Purple]pinC.0[/color]
[color=Blue]symbol relay      [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol LED        [/color][color=DarkCyan]= [/color][color=Blue]C.2

symbol [/color][color=Purple]pinmem     [/color][color=DarkCyan]= [/color][color=Purple]bit8[/color]
[color=Blue]symbol [/color][color=Purple]LEDstate   [/color][color=DarkCyan]= [/color][color=Purple]bit9[/color]
[color=Blue]symbol [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Purple]bit10[/color]
[color=Blue]symbol [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]b2[/color]
[color=Blue]symbol [/color][color=Purple]LEDtimer   [/color][color=DarkCyan]= [/color][color=Purple]b3[/color]

[color=Blue]do [/color][color=Green]' main loop
      
      [/color][color=Blue]if [/color][color=Purple]pindata [/color][color=DarkCyan]<> [/color][color=Purple]pinmem [/color][color=Blue]then [/color][color=Green]' pin has changed
            [/color][color=Purple]pinmem [/color][color=DarkCyan]= [/color][color=Purple]pindata  [/color][color=Green]' update pin memory
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Navy]20 [/color][color=Green]' restart relay timer
      [/color][color=Blue]endif

      pause [/color][color=Navy]10
      
      [/color][color=Blue]if [/color][color=Purple]RelayTimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
            high relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]RelayTimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            low relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]0
      [/color][color=Blue]endif

      if [/color][color=Purple]LEDtimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Purple]LEDtimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Navy]3
            [/color][color=Purple]LEDstate [/color][color=DarkCyan]= not [/color][color=Purple]LEDstate
      [/color][color=Blue]endif

      if [/color][color=Purple]LEDstate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=DarkCyan]and [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]then
            high LED
      else
            low LED
      endif



      [/color][color=Green]'     
      ' more code here
      '
      [/color]
[color=Blue]loop[/color]
 

hippy

Technical Support
Staff member
A simplified version of what Buzby proposes -

Code:
Do
  If pinC.1 <> 0 Then
    w0 = 1000
  Else
    w0 = w0 Min 1 - 1
  End If
  If w0 > 0 Then
    High C.2
  Else
    Low C.2
  End If
Loop
An optimised version -

Code:
dirC.2 = 1
Do
  w0 = pinC.1 * 1000 Min w0 Min 1 - 1
  pinC.2 = w0 Max 1
Loop
 

OLDmarty

Senior Member
Thanks guys for your amazing answers.

Sheesh, i was sorta on the right track, but on the wrong train lol ;-)

I'll tinker with these options tomorrow and see how i go massaging it into my chip.

Thanks once again.
Marty.
 

OLDmarty

Senior Member
Hi Guys,
Sorry, but those codes don't seem to work for me.
(albeit, i used C.1 in my code example, which should have been C.3, but i changed your codes to use C.3 anyway).


To clarify, i have a test 08M2 wired up as follows:

C.3 - The DATA coming into the chip from external pic (or other 5v data source).

C.0 - a RELAY control output (a LED for now) - This needs to LATCH ON for the entire duration of incoming data, even if the data pauses for a fraction of a second then resumes, the relay must NEVER drop out.
The relay will un-latch when the data has been proven/timed out to be finished. ( i figured a 1 second duration timer, constantly reset/retriggered would do this?)
The first pulse of data being detected on C.3 will latch this relay and begin the flashing led(s) below.

C.1/C.2 - is wired to a 2-pin Bi-colour LED. This simply flashes red/green during the entire presence of incoming data on C.3 (even during any brief pauses in data) and will also stop flashing (both pins off) shortly BEFORE the relay being un-latched.
( i was using the C.1 in your example to at least flash 1 half of the LED ).

NOTE: I edited my initial code snippet to indicate the Bi-Colour LED on pins C.1 & C.2 etc...


I hope this makes my intention a little clearer ;-)
 
Last edited:

Buzby

Senior Member
Hi Marty,

I didn't study hippy's code, as usually he's spot on with the optimisations.

However, this time I think he made a couple of boo boo's.

(a) His first piece of code does not detect a change, so it will 'lock on' if the input stays high.

(b) Both codes don't include your requirement for a flashing 'activity' indicator and a separate 'signal present' relay.

In my code the 'pause 10' sets the timebase for the loop. If you try my code again you need to change the 'RelayTimer = 20' ( which is ~200mS ie. 20 x 10) to something like 100 (i.e. ~1000mS) , and change the 'LEDtimer = 3' to maybe 30.

If you get the project working with just my code and a single LED we can move on to bi-colour LEDs later.
 

OLDmarty

Senior Member
Hi Buzby,

OK, i've made the changes you suggested this works fine, it holds the relay (C.0 led) on for the whole duration of the data being detected and turns off soon after data stops....perfect! ;-)

Where your LED is C.2, i think i just need to add a small do loop that alternates C.2 and C.1 to flash the Bi-colour LED.

probably adding "symbol LEDgreen = C.1" is needed.



The up to date code (edited pin assignments to match my test board) is below.


Code:
symbol pindata    = pinC.3
symbol relay      = C.0
symbol LED        = C.2

symbol pinmem     = bit8
symbol LEDstate   = bit9
symbol relaystate = bit10
symbol RelayTimer = b2
symbol LEDtimer   = b3

do ' main loop
      
      if pindata <> pinmem then ' pin has changed
            pinmem = pindata  ' update pin memory
            RelayTimer = 20 ' restart relay timer
      endif

      pause 10
      
      if RelayTimer > 0 then
            high relay
            relaystate = 1
            RelayTimer = RelayTimer - 1
      else
            low relay
            relaystate = 0
      endif

      if LEDtimer > 0 then
            LEDtimer = LEDtimer - 1
      else
            LEDtimer = 3
            LEDstate = not LEDstate
      endif

      if LEDstate = 1 and relaystate = 1 then
            high LED
      else
            low LED
      endif



      '     
      ' more code here
      '
      
loop
 

hippy

Technical Support
Staff member
(a) His first piece of code does not detect a change, so it will 'lock on' if the input stays high.
That was the intent which I thought matched the requirement based on the original code starting point. I read "burst of data" as idle low, bursting high, then returning low. An you are right that I also did not add any PAUSE for timing.

Modified for the new pinout, a one second timeout after the last change, and flashing the LED's at 10Hz ...

Code:
#Picaxe 08M2
dirC.0 = 1
dirC.1 = 1
dirC.2 = 1
b3 = pinC.3
Do
  b2 = pinC.3
  w0 = b2 ^ b3 * 11 Min w0 Min 1 - 1
  b3 = b2
  pinC.0 = w0 Max 1
  pinC.1 = outpinC.1 ^ outpinC.0 & outpinC.0
  pinC.2 = outpinC.1 ^ 1         & outpinC.0
  Pause 100
Loop
What this doesn't do is turn the LED's off "shortly before the relay is turned off". I don't believe it would actually be noticeable in practice but it could be modified to do that -

Code:
#Picaxe 08M2
dirC.0 = 1
dirC.1 = 1
dirC.2 = 1
b3 = pinC.3
Do
  b2 = pinC.3
  w0 = b2 ^ b3 * 11 Min w0 Min 1 - 1
  w2 = b2 ^ b3 *  6 Min w2 Min 1 - 1
  pinC.0 = w0 Max 1
  b3     = w2 Max 1
  pinC.1 = outpinC.1 ^ outpinC.0 & b3
  pinC.2 = outpinC.1 ^ 1         & b3
  b3 = b2
  Pause 100
Loop
 

OLDmarty

Senior Member
Thanks Hippy, and apologies for not providing the full requirements right at the start....

I tried both your code snippets above, they generally work as per my needs, However, the Relay (C.0) tends to drop off a few times in the process....
I'm not sure which timer/delay i would extend to prevent those C.0 dropouts....


Anyway, adding onto Buzby's earlier code, i mangled it a bit to work reasonably well, but, when the data stream has finished on C.3, the Relay AND flashing led still run for approx 5 seconds before both switching off.
It would be nice if i could get the leds & relay to switch off about 1/2 second to 1 second after the data stream finishes.

Code:
#picaxe 08M2
#no_data

setfreq m8	; set as fast as possible

symbol pindata    = pinC.3
symbol relay      = C.0
symbol LED        = C.2
symbol LEDgreen   = C.1
symbol pinmem     = bit8
symbol LEDstate   = bit9
symbol relaystate = bit10
symbol RelayTimer = b2
symbol LEDtimer   = b3

do        ;main loop

      if pindata <> pinmem then ;pin has changed
            pinmem = pindata    ;update pin memory
            RelayTimer = 100     ;restart relay timer
      endif

      pause 10

      if RelayTimer > 0 then
            high relay
            relaystate = 1
            RelayTimer = RelayTimer - 1
      else
            low relay
            relaystate = 0
      endif

      if LEDtimer > 0 then
            LEDtimer = LEDtimer - 1
      else
            LEDtimer = 3
            LEDstate = not LEDstate
      endif

      if LEDstate = 1 and relaystate = 1 then
            high LED
            low ledgreen
            pause 200
            low LED
            high ledgreen
            pause 200
      else
            low LED
            low ledgreen
      endif

loop
 

hippy

Technical Support
Staff member
However, the Relay (C.0) tends to drop off a few times in the process....
I'm not sure which timer/delay i would extend to prevent those C.0 dropouts....
In my code that's the '*11', the number of 100ms loops (less one) which makes up the timeout period.

11-1 x 100 ms = 1000 ms

So that should have a one second delay after the data burst ends before the relay drops out. Increase the 11 and the timeout will be longer.
 

Buzby

Senior Member
Hi Marty,

Try reducing this 'RelayTimer = 100' to 10, or whatever.

The 100 was to give a 1 second timeout based on a total loop time of about 10mS.

Now you have added a couple of 200mS pauses into the loop, it takes a lot longer to timeout, so the 100 needs to be reduced.

Cheers,

Buzby
 

OLDmarty

Senior Member
Hi Marty,

Try reducing this 'RelayTimer = 100' to 10, or whatever.

The 100 was to give a 1 second timeout based on a total loop time of about 10mS.

Now you have added a couple of 200mS pauses into the loop, it takes a lot longer to timeout, so the 100 needs to be reduced.

Cheers,

Buzby
Hi again,
When i make Relaytimer = 30 to 50, the relay starts dropping out again, at "80" it drops out less, so i made it 100 to be solid.
 

Buzby

Senior Member
I've put the code on a real chip now, and I don't get dropouts with low values for the relay timer.

What are the characteristics of your data burst ?.

Especially pulse length, and maximum gap between pulses.

Cheers,

Buzby
 

OLDmarty

Senior Member
I've put the code on a real chip now, and I don't get dropouts with low values for the relay timer.

What are the characteristics of your data burst ?.

Especially pulse length, and maximum gap between pulses.

Cheers,

Buzby
For these tests, the data stream is from a AXE027 programmer while programming another chip for tests.
I have a wire attached to the 3.5mm program socket that feeds into C.3 on this 08M2 under test.

So, whatever pauses the programmer has (for however long) is long enough to cause a relay dropout.

Hope this helps.
 

Buzby

Senior Member
Hi Marty,

Here is the code re-jiggered so that it does not use pauses. All timing is now related to how fast the chip is running.

I've not tried it with the AXE027 data stream, but I can't see any reason why it shouldn't work.

Cheers,

Buzby

Code:
[color=Navy]#picaxe [/color][color=Black]28X2[/color]
[color=Navy]#no_data
#no_table[/color]

[color=Green]' Symbols[/color]
[color=Blue]symbol [/color][color=Purple]pindata    [/color][color=DarkCyan]= [/color][color=Purple]pinC.3[/color]
[color=Blue]symbol relay      [/color][color=DarkCyan]= [/color][color=Blue]C.0
symbol LEDred     [/color][color=DarkCyan]= [/color][color=Blue]C.2
symbol LEDgreen   [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol [/color][color=Purple]pinmem     [/color][color=DarkCyan]= [/color][color=Purple]bit8[/color]
[color=Blue]symbol [/color][color=Purple]LEDstate   [/color][color=DarkCyan]= [/color][color=Purple]bit9[/color]
[color=Blue]symbol [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Purple]bit10[/color]
[color=Blue]symbol [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]w2[/color]
[color=Blue]symbol [/color][color=Purple]LEDtimer   [/color][color=DarkCyan]= [/color][color=Purple]w3[/color]

[color=Green]' Constants[/color]
[color=Blue]Symbol LEDtimerSET      [/color][color=DarkCyan]= [/color][color=Navy]50        [/color][color=Green]' Sets LED flash speed[/color]
[color=Blue]Symbol RelayTimerSET    [/color][color=DarkCyan]= [/color][color=Navy]300 [/color][color=Green]' Sets relay dropout time


' Initialisation[/color]
[color=Blue]setfreq m8  [/color][color=Green]' Set as fast as possible[/color]

[color=Blue]do [/color][color=Green]' main loop

      [/color][color=Blue]if [/color][color=Purple]pindata [/color][color=DarkCyan]<> [/color][color=Purple]pinmem [/color][color=Blue]then [/color][color=Green]' pin has changed
            [/color][color=Purple]pinmem [/color][color=DarkCyan]= [/color][color=Purple]pindata        [/color][color=Green]' update pin memory
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Blue]RelayTimerSET     [/color][color=Green]' restart relay timer
      [/color][color=Blue]endif

      if [/color][color=Purple]RelayTimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then        [/color][color=Green]' Operate relay while timing
            [/color][color=Blue]high relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]RelayTimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            low relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]0
      [/color][color=Blue]endif

      if [/color][color=Purple]LEDtimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then          [/color][color=Green]' Make LED toggle flag
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Purple]LEDtimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Blue]LEDtimerSET
            [/color][color=Purple]LEDstate [/color][color=DarkCyan]= not [/color][color=Purple]LEDstate
      [/color][color=Blue]endif

      if [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]then        [/color][color=Green]' Toggle LEDs if relay is active
            [/color][color=Blue]if [/color][color=Purple]LEDstate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]then
                  high LEDred
                  low LEDgreen
            else
                  low LEDred
                  high LEDgreen
            endif
      else
            low LEDred
            low ledgreen
      endif

loop [/color][color=Green]' end of main loop[/color]
 

OLDmarty

Senior Member
Hi Marty,

Here is the code re-jiggered so that it does not use pauses. All timing is now related to how fast the chip is running.

I've not tried it with the AXE027 data stream, but I can't see any reason why it shouldn't work.

Cheers,

Buzby

Code:
[color=Navy]#picaxe [/color][color=Black]28X2[/color]
[color=Navy]#no_data
#no_table[/color]

[color=Green]' Symbols[/color]
[color=Blue]symbol [/color][color=Purple]pindata    [/color][color=DarkCyan]= [/color][color=Purple]pinC.3[/color]
[color=Blue]symbol relay      [/color][color=DarkCyan]= [/color][color=Blue]C.0
symbol LEDred     [/color][color=DarkCyan]= [/color][color=Blue]C.2
symbol LEDgreen   [/color][color=DarkCyan]= [/color][color=Blue]C.1
symbol [/color][color=Purple]pinmem     [/color][color=DarkCyan]= [/color][color=Purple]bit8[/color]
[color=Blue]symbol [/color][color=Purple]LEDstate   [/color][color=DarkCyan]= [/color][color=Purple]bit9[/color]
[color=Blue]symbol [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Purple]bit10[/color]
[color=Blue]symbol [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]w2[/color]
[color=Blue]symbol [/color][color=Purple]LEDtimer   [/color][color=DarkCyan]= [/color][color=Purple]w3[/color]

[color=Green]' Constants[/color]
[color=Blue]Symbol LEDtimerSET      [/color][color=DarkCyan]= [/color][color=Navy]50        [/color][color=Green]' Sets LED flash speed[/color]
[color=Blue]Symbol RelayTimerSET    [/color][color=DarkCyan]= [/color][color=Navy]300 [/color][color=Green]' Sets relay dropout time


' Initialisation[/color]
[color=Blue]setfreq m8  [/color][color=Green]' Set as fast as possible[/color]

[color=Blue]do [/color][color=Green]' main loop

      [/color][color=Blue]if [/color][color=Purple]pindata [/color][color=DarkCyan]<> [/color][color=Purple]pinmem [/color][color=Blue]then [/color][color=Green]' pin has changed
            [/color][color=Purple]pinmem [/color][color=DarkCyan]= [/color][color=Purple]pindata        [/color][color=Green]' update pin memory
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Blue]RelayTimerSET     [/color][color=Green]' restart relay timer
      [/color][color=Blue]endif

      if [/color][color=Purple]RelayTimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then        [/color][color=Green]' Operate relay while timing
            [/color][color=Blue]high relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1
            [/color][color=Purple]RelayTimer [/color][color=DarkCyan]= [/color][color=Purple]RelayTimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            low relay
            [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]0
      [/color][color=Blue]endif

      if [/color][color=Purple]LEDtimer [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then          [/color][color=Green]' Make LED toggle flag
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Purple]LEDtimer [/color][color=DarkCyan]- [/color][color=Navy]1
      [/color][color=Blue]else
            [/color][color=Purple]LEDtimer [/color][color=DarkCyan]= [/color][color=Blue]LEDtimerSET
            [/color][color=Purple]LEDstate [/color][color=DarkCyan]= not [/color][color=Purple]LEDstate
      [/color][color=Blue]endif

      if [/color][color=Purple]relaystate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]then        [/color][color=Green]' Toggle LEDs if relay is active
            [/color][color=Blue]if [/color][color=Purple]LEDstate [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]then
                  high LEDred
                  low LEDgreen
            else
                  low LEDred
                  high LEDgreen
            endif
      else
            low LEDred
            low ledgreen
      endif

loop [/color][color=Green]' end of main loop[/color]

Thankx for doing that Buzby.

I changed the led-flash speed from 50 to 25 to liven it up a bit ;-)
Otherwise, i used the code on chip and it all seems to be OK for what i wanted it to do.

Hopefully i can study your code methods to help improve my own code writing techniques ;-)

Thanx again.
Marty
 
Top