Using pulsin

JPB33

Senior Member
Are there any rules about using pulsin? If I use before an if statement it stops the if working. Still tidying my code at present so rather not post it!

Also is there is any way easy to simulate pulsin? Cannot find a way also read up but I thought someone more knowledgable may be able to help, first time I've had any success with it but its a bit awkward using it "live".

Thanks
 

AllyCat

Senior Member
Hi,

PULSIN automatically sets the named pin as an input (if it has been previously set as an output). This can cause issues if it's trying to measure a signal output from the chip hardware (e.g. the SR latch or Comparator, etc.) or if it's required to remain as an output.

However, this shouldn't affect any correctly structured IF statement, because that (also) sets the pin as an input anyway. But have you perhaps forgotten to use the correct PINP.n notation in the IF statement?

A more complete answer probably needs a sample of your code and which chip and PE you're using.

Cheers, Alan.
 

Technical

Technical Support
Staff member
pulsin takes the word value on the second 'Values' tab (Simulation panel) whilst simulating in PE6.
 

JPB33

Senior Member
Thanks for your explanation Alan but not sure what I'm looking for, pulsin is new to me. The position of pulsin appears critical in my program so looks like I have some conflict. This is my code and using an 18m2.

Thanks Peter
 

Attachments

hippy

Technical Support
Staff member
File downloaded okay for me so code included below -

Code:
                         ; 18m2 Clock Pendulum Energiser
main:
			let dirsB = 0
			let dirsC = 8
			serout C.3, n2400, ( 254,1) 
waiting_for_pulse:
			if pinC.2 = 0 then
			goto energise_coil
			end if
			goto waiting_for_pulse
energise_coil:        
 			pulsin C.2, 0, w1 
			w1 = w1 /10 max 999 
			high B.0			
			pause 50			
			low B.0
			readadc B.3,b0
			bintoascii b0, b22, b23 ,  b24
			serout C.3, N2400, (254, 128,"",b22,b23,".",b24," set time ")
			bintoascii w1 ,b22, b23 , b24
			serout C.3, N2400, (254, 192,"",b22,b23,".",b24," input pulse ")
pulse_stopped:
			if w1 > b0 then			
			goto waiting_for_pulse:   
			end if
			readadc B.3, b0 	
			pulsin C.2, 0, w1 
			w1 = w1 / 10 max 999          
			bintoascii b0, b22, b23, b24 
			serout C.3, N2400, (254, 128,"",b22,b23,".",b24, " set time  ")
			bintoascii w1,  b22, b23, b24
			serout C.3, N2400, (254, 192,"",b22,b23,".",b24, " input pulse  ")
			goto pulse_stopped
I suspect the problem may be you are waiting for C.2 input to go low, and then doing a PULSIN to measure the width of a low going pulse on C.2. As PULSIN requires C.2 to be high before it will read a low pulse it may be timing out.
 

JPB33

Senior Member
I thought it was a timing issue so had the pulsin in the waiting for pulse loop. C.2 is high all the time pulled up by a 10k resistor to +5v and only goes low for around 25ms when the sensor is activated by the magnet swinging passed. The pedulum period is 500ms so it it goes low for 25ms every 500ms. Ive confirmed the levels and times with a scope. If I put pulsin into the waiting for pulse loop it stops the energise coil sequence with no 50ms pulse fed to the energising coil connected to B.0 via transistors. As it is now it allows an energising pulse to emerge every other input impulse.

Got to be someting basic and simple!

Thanks
 

AllyCat

Senior Member
Hi,

PULSIN is a "blocking" command, whilst executing, it "freezes" the PICaxe until a pulse is detected and measured, or a timeout (650 ms) occurs. This is a lmitation of PICaxe Basic (and non-multitasking processors in general).

You might be able to "work around" it using a software timing loop (instead of PULSIN), or the "Timer 1 Gate" on-chip hardware using POKE/PEEKSFR commands (not for novices).

Cheers, Alan.
 

JPB33

Senior Member
Hi Alan,

So as I've got an input pulse coming along every 500ms it explains why I get an output every other input pulse with the 650ms blocking. After much reading thought increasing the clock speed to 16meg would overcome this with the reduced timeout so to the program added the setfreq to 16meg, increased the delay to 200ms and baude rate to N9600. Runs fine on simulation but not in the real world, output pulse on, eventually display gibberish then no pulses!

Am I acting on the right lines to overcome the 650ms limitation ?

Thanks Peter
 

hippy

Technical Support
Staff member
The reason you only get an output pulse every two input pulses is probably because of the issue I described. You detect the low on the first pulse then execute the PULSIN but, as that needs a high-low-high pulse, it waits for the seconds pulse. That is, the initial pulse has to have gone back high before the PULSIN sees a pulse.

Simulation will work because that doesn't actually care about levels and when they transition, it simply takes a value from the input panel regardless.

Increasing the operating speed won't solve that, and may introduce further problems.

You should be able to get things to work without having that 'waiting_for_pulse:" code. Try commenting out everything between "waiting_for_pulse:" and "energise_coil:".
 

JPB33

Senior Member
Thanks for the explanation. Just tried as suggested but no pulse width on display or output pulses. I thought commenting out just took that section of code out of the program to stop it working?
 

hippy

Technical Support
Staff member
It is hard to tell what the code is intended to do so difficult to assess whether it is working or not, should work or would not, working but not doing as is desired. It could be the pulse width is simply too short to be shown as non-zero.

It would be worth explaining what you are attempting to achieve with the project, what characteristics the input signal has, what the software is meant to do, what the outputs should be.

Perhaps also run some test code so you can check that pulses are arriving and what values they have -

Code:
Do
  PulsIn C.2, 0, w1
  SerTxd( "Reading ", #w0, 9, #w1, CR, LF )
  w0 = w0 + 1
Loop
 

JPB33

Senior Member
Point taken about explanation. I have added some info to the code which probably makes it worse! The idea of using pulsin was suggested previously on the forum (been learning about it on and off for 2yrs) but I’ve never had much success and this is the best it’s been so far.

A magnet on the bottom of the pendulum triggers a sensor for about 25ms as it swings passed. This times the negative going pulse to energises a coil for 50ms via picaxe and transistors which reactes against a magnet on the pendulum pushing it away and building up the swing. The picaxe then loops back to “waiting for pulse “ some 400ms later it arrives as the pendulum swings back and the sequence repeats. Pulsin records the reducing pulse length into w1 as the swing increases, its compared with an adc value from a pot on B.3 into b0.

When the read pulse is less than the adc set point it loops in “pulse stopped” still reading pulsin. As the length increases as now un-powered it soon reverts back to “waiting for pulse” and the sequence repeats when the timing pulse comes along.
The scope screen shots show the negative going timing pulse in yellow and the positive going coil pulse in blue. It also shows the energising every other swing (should be every swing)and the pulse lengths. The other screenshot show when its in full swing and the pulses are reduced as expected.

Thanks Peter

Code:
 ;  18m2 Clock Pendulum Energiser. 25ms neg going pulse every 500ms from pendulum sensor at bottom of swing. Swing controlled by reading pulse and comparing with pot setting
;   to switch coil on/off at bottom  of swing as appropriate.
main:
			let dirsB = 0 
			let dirsC = 8
			serout C.3, n2400, ( 254,1) 
waiting_for_pulse:
			if pinB.1 = 0 then  '    Looped waiting for neg going 25ms pulse.
			goto energise_coil  '    Pulse arrives at correct time from pendulum sensor, bottom of swing.
			end if
			goto waiting_for_pulse
energise_coil:
			pulsin B.1, 0, w1    '   Read pulse length
			w1 = w1 /10 max 999   ' 10us resolution      
			high B.0			
			pause 50		    ' Coil energised pushing pendulum for 50ms	
			low B.0
			readadc B.3,b0        ' Read adc B.3 into b0 from pot on leg 9
			bintoascii b0, b22, b23 ,  b24
			serout C.3, N2400, (254, 128,"",b22,b23,".",b24," set time ")      ' Display setting on pot from B.3 and pulsin
			bintoascii w1 ,b22, b23 , b24
			serout C.3, N2400, (254, 192,"",b22,b23,".",b24," input pulse ")
pulse_stopped:
			if w1 > b0 then     'Compare input pulse length with b0 if greater back to waiting for pulse to repeat energise coil sequence. If pulse less loop until greater. 
			goto waiting_for_pulse:   
			end if
			readadc B.3, b0 	        ' Read adc B.3 into b0 from pot on leg 9
			pulsin B.1, 0, w1         ' Read pulse length
			w1 = w1 / 10 max 999      ' 10us resolution   
			bintoascii b0, b22, b23, b24 
			serout C.3, N2400, (254, 128,"",b22,b23,".",b24, " set time  ")   '  Display setting on pot from B.3 and pulsin
			bintoascii w1,  b22, b23, b24
			serout C.3, N2400, (254, 192,"",b22,b23,".",b24, " input pulse  ")
			goto pulse_stopped     ' Looping until pulse becomes greater than setting b0. Then back to waiting for pulse to repeat sequence.

Starting Off.jpg Up to  Speed.jpg
 

hippy

Technical Support
Staff member
Thanks. I think I can see why just removing the 'waiting_for_pulse' code did not work; there is a second PULSIN when energising and that then leads back to the first PULSIN which needs to execute and see a pulse before the second is encountered again.

I think you just need a simpler structure, a single PULSIN ...

Code:
Do
  PulsIn C.2, 0, w0
  If needs a kick Then
    energise magnet
  Else
    do nothing
  End If
Loop
 

JPB33

Senior Member
Thanks Hippy. Not sure how complete the code you posted is but no succes with it as yet.

It looked like it was a timing out issue with pulsin from pervious replies so now got out my TTL derived pulse genny out and using this to generate pulses instead of the pendulum. The results are in the scope screen pics. Using a 400ms period negative going pulse, which is a similar timing to one from the clock shows the postive going engergised coil pulse at 800ms or every other input pulse as before. With a 1 sec input pulse the output is still every other input with a period of 2 secs but more out of sync with the input.

As pulsin timeout should be constant at 650ms (?) shouldnt there be an output for every input as there is now plenty of time to recover?

Didnt think using pulsin would be so difficult, Please be gentle, I'm only a novice!

Thanks Peter


400ms .jpg 1 sec .jpg
 

hippy

Technical Support
Staff member
Your results are entirely consistent with the code it appears you are using.

You are waiting for the pulse to go low which will be the falling edge of the first pulse.

You then PULSIN a low going pulse; that can only happen after the falling edge has returned high and the second pulse occurs.

Only after this second pulse will you get the energising pulse.

Basically you can't detect a low going pulse with "IF pinX.Y=0" and measure that low going pulse with a "PUSLIN X.Y". You can only measure the low going pulse which comes after that.

As to why it's not doing what was expected with a long low and longer periods; that's perhaps due to timeout setting the result variable to zero and whatever the code does then. If it's going to wait for the signal going low again it will still exhibit this only energising every second pulse behaviour.
 

hippy

Technical Support
Staff member
You can try running this code. It should always generate an energising pulse after each pendulum input pulse. This is complete code which should work -

Code:
Do
  Do
    PulsIn B.1, 0, w0
  Loop Until w0 > 0
  w1 = 0
  If w0 >= w1 Then
    High B.0			
    Pause 50
    Low B.0
  Else
    ; do nothing
  End If
Loop
If that does work as it should the LCD display code and the conditional energising code can be added to it.
 

JPB33

Senior Member
Thanks Hippy, brilliant, that works every time.

Added the LCD code but cannot find a true length of the pulse into B.1 as read by pulsin. Thought is would be w0 but w0 is a constantly changing number prefixed by a letter combination so it looks like J1.3 etc. As its looping until B.1 heads low is that disabling pulsin from reading correctly?

Thanks
 

JPB33

Senior Member
Nearly There!

The code from Hippy worked fine and I added the display bits as suggested. Unfortunatly due to being a novice I have now hit another brick wall and despite much reading and testing I cannot make sense of the number showing on the display.

I realized Hippys code is working ok as the reading changes as the pendulum swing increases. Putting the pulse gen back on to give a stable input pulse gives a reading of 999 for 1ms and S46 for 36ms so reckon I've got some wrong code for the display?

Never read and displayed a word variable before and would be really grateful for an explanation of whats going on to allow me to progress or point a direction for further reading. If thats the problem!

Many Thanks

Peter


1ms.jpg 36ms.jpg





Code:
   Do
   Do
   PulsIn B.1, 0, w0   ' read 25ms negative going pulse from B.1
   Loop Until w0 > 0
   w1 = 0
   If w0 >= w1 Then
    High B.0	' energise coil		
    Pause 50
    Low B.0
    readadc B.3,b4        ' Read adc B.3 into b4 from pot on leg 9
    bintoascii b4, b22, b23 ,  b24
    serout C.3, N2400, (254, 128,"",b22,b23,".",b24," set time ")      ' Display setting on pot from B.3 and pulsin
    bintoascii w0 ,b22, b23 , b24
    serout C.3, N2400, (254, 192,"",b22,b23,".",b24," input pulse ")	' Display pulse length from		
    Else
    ; do nothing
   End If
   loop
 
Last edited by a moderator:

edmunds

Senior Member
I'm not sure I'm following all of the thread correctly, but this line seems no good:

bintoascii w0 ,b22, b23 , b24

You must be loosing tens and units if this is compiling at all. The correct syntax for a word variable is:

BINTOASCII wordvariable, tenthousands, thousands, hundreds, tens, units


Regards,

Edmunds
 

hippy

Technical Support
Staff member
^ As edmunds suggests. PULSIN reads in 10us units so this will display the time in us ...

bintoascii w0 , b21, b22, b23, b24, b25
serout C.3, N2400, (254, 192, b21, b22, b23, b24, b25, "0us")

And in ms ...

bintoascii w0 , b21, b22, b23, b24, b25
serout C.3, N2400, (254, 192, b21, b22, b23, ".", b24, b25, "ms")

Or just the integer part of ms ...

bintoascii w0 , b21, b22, b23, b24, b25
serout C.3, N2400, (254, 192, b21, b22, b23, "ms")

Those erroneous empty strings ("") you have in the SEROUT may perhaps also be causing problems.
 

JPB33

Senior Member
Many thanks to you both. Quickly tried it out and displaying fine. Thought it was something like. Cleared the "" from display, left over after converting from flow chart helped by my good friend the so quite bit of leaning all round. Leaves axe.com in the display but no time left to try more.

When I read the adc from B.3 into w2 it reads as per the slider setting direct ie 0 to 255, was expecting to see 3200? seems different rules?

Thanks again.

Peter
 

JPB33

Senior Member
Thanks everyone for all the help, I'm really chuffed!

Got it working well now with additions to the code to give a display etc, sure the code could be improved but at least its working, I thought adding my code would prevent the loop for pulsin working. pulsin is reacting nicely to the 22.50ms input pulse every time and the display is hovering around 22.50ms by about + - 0.2ms so a real improvement in performance, see pic.

Looping pulsin as put together by Hippy completely overcomes the second pulse issue but I (or my good friend The Bear) don’t understand the principle of operation at present?

The energising pulse needs to vary in strength as the loading varies. At present I’ve got the time varying according to the reading from pulsin trimmed with adc from B.2. I have tried using PWM with values from the wizard, it works in simulation but not on my board, are there any issues using PWM along with pulsin?

Also is it possible to add leading zero suppression easily to the display? Often pondered about adding it to other displays without much success.

Thanks

Peter



Code:
;   23-4-15 		18m2 Clock pendulum impulse. Now use value from pulsin to time energising pulse, with value from B.2 to trim energised time. 
;                       Centers around 22.50ms to maintain running.
   
   Do
   Do  
   readadc B.3,w2   	' Read adc B.3 into b4 from pot on leg 9
   readadc B.2,w6   	' Read adc B.2 into w6 from pot on leg 8
   w6 = w6 /10      	' w6 divide by 10
   w2 = w2 *150     	' w2 x 150
   bintoascii w2, b21,b22,b23,b24,b25
   serout C.3, N2400, (254, 128,b21,b22,b23,".",b24, b25, " set time ")      ' Display setting from B.3 ADC
   bintoascii w0 , b21, b22, b23, b24, b25
   serout C.3, N2400, (254, 192, b21, b22, b23, ".", b24, b25, "ms pulsein")  'Display pulsein
   PulsIn B.1, 0, w0   	' read 25ms negative going pulse from B.1 into w0
   w5 = w0/100 - w6    	' divide value from pulsin by 100 and put into w5
   Loop Until w0 > 0
   w1 = 0
   If w0 <= w1 Then 	' compare pulsein with value of w2 ie pot on B.
   endif
   If w0 >= w2 Then  	' compare pulsin with value read from B.3
   High B.0			
   pause w5  	      ' energise coil using number from w5 tyrimmed by ADC into w6
   Low B.0
   Else
   End If
   loop
23-4-15 -2.jpgEvery impulse.jpg
 

westaust55

Moderator
For the leading zero suppression part, after the BINTOASCII command insert:
Code:
IF b21 ="0" THEN
    B21= " "
    IF b22 = =0" THEN
        B22 = " "
    ENDIF
ENDIF
Add more tests if the hundreds/3rd digit might also be zero

Note that each digit tested is nested within the previous loop.
This is so that a zero is only blanked if it is the first digit or if all the earlier digits are also zero.
 

JPB33

Senior Member
Leading zero success

Thanks Westaust, a lot more learned! That works perfectly and makes the display look much better. Going to add it to my other displays.

Peter


28-4-15.jpg
 

techElder

Well-known member
Among all else in life, there is just something quite satisfying about getting output to display properly. Congratulations!
 
Top