InputCapture vs. PulseIn w/CallTask

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

liam.zbasic wrote:Could it by that PWM and PULSEIN will not work together in the same program and 328n device?
That is correct. The mega328 only has one 16-bit timer and its uses for PWM and for I/O timing (e.g. PulseIn) are mutually exclusive. If you're not using Timer2 for other purposes, you could use 8-bit PWM instead. Besides 8-bit PWM the only other routines in the ZBasic Library that use Timer2 are the software UART channels (3-6).
- Don Kinzer
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

That's a relief - only one 16-bit timer. I was beginning to think my 328n chip was damaged. It's an early device with limited program memory. Anyway, 8-bit resolution for output-distance-in-volts is too low. I'll trying using the "GetElapsedMicroTime" function and count how long the sensor is HIGH. This approach will not interrupt the 16-bit timer, right?
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

liam.zbasic wrote:This approach will not interrupt the 16-bit timer, right?
Correct. The "micro time" value is merely a combination of the RTC tick value and the RTC timer count value at the time of the call. It's the latter element that gives the resultant value the higher resolution, equal to the inverse of Register.RTCTimerFrequency.
- Don Kinzer
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

It Works! I am able to measure ultrasonic distance without PulseOut and PulseIn commands and continuously output distance as a voltage with PWM. Now I can use my zx328n device as a slave dedicated to streaming pseudo-analog distance without SPI or I2C communication.

The trigger-pulse was done with simple PutPin & Pause combinations, and the echo was measured with GetElapsedMicroTime. The calculated distance has a negligible error due to "ticks" stolen by the if/then statements. I enclosed the code for those interested.

Code: Select all

option base 1
option TargetDevice zx328n

public const runtime    as single = 300.0        ' (sec)
public const ping_pin   as byte   = 14           ' Ping sonar sensor output (zx328n)
public const pwm_hz     as single = 20000.0      ' PWM Frequency (hz)
public const sos        as single = 13397.2441   ' Speed of sound (in/sec) at sea-level (std. atm.)
public const max_dx     as single = 108.0        ' Ping sensor max distance (inches)


sub main()

   dim hour as byte, minute as byte, sec as single
   dim t as single, told as single, dt as single, tick as single
   dim listen as byte, wait as byte, go as integer, t0(1 to 5) as Byte
   dim n as UnsignedLong, echo_n as UnsignedLong, echo_t as single, echo_dx as single, duty as single

   
   ' INITIALIZE PWM
   '---------------------------
   call closepwm(1)                           'zx328 device: pwm1 is pin 15
   Call OpenPWM(1, pwm_hz, zxFastPWM)          
   Register.TCCR1B = Register.TCCR1B Or &H01  ' temporary workaround to set prescaler for freq. > 225Hz  


   ' MAIN LOOP
   '--------------
   tick   = csng(Register.RTCTimerFrequency)
   max_dt = max_dx / sos
   t      = 0.0
   dt     = 0.0
   told   = 0.0
   duty   = 0.0

   while t <= runtime
   
      call GetTime&#40;hour, minute, sec&#41;
	  
      t    = CSng&#40;minute&#41;*60.0 + sec
      dt   = t - told
      told = t
 	  
      ' BUILD TRIGGER PULSE 
      '----------------------------------
      Pause&#40;0.001000&#41;                                  ' delay for next measurement
      Call PutPin&#40;ping_pin, 0&#41;&#58;  Call Pause&#40;0.000005&#41;  ' trigger pulse low
      Call PutPin&#40;ping_pin, 1&#41;&#58;  Call Pause&#40;0.000005&#41;  ' trigger pulse high
      Call PutPin&#40;ping_pin, 0&#41;&#58;  Call Pause&#40;0.000005&#41;  ' trigger pulse low   

      ' COUNT RETURN PULSE
      '---------------------
      go   = 1
      wait = 0 

      do while &#40;go = 1&#41;
	  
         listen = GetPin&#40;ping_pin&#41;
		 
         ' PULSE LEADING EDGE
         if &#40;listen = 1&#41; AND &#40;wait = 0&#41; then
            Call GetMicroTime&#40;t0&#41;
            wait = 1		   
         end if
		 
         ' PULSE TRAILING EDGE
         if &#40;listen = 0&#41; AND &#40;wait = 1&#41; then
            echo_n = GetElapsedMicroTime&#40;t0&#41;  
            echo_t = csng&#40;echo_n&#41; / tick
            go     = 0
         end if
		   
      loop

      ' CALCULATE DISTANCE
      '---------------------
      echo_dx = echo_t * sos / 2.0   ' Equation halved for one-way distance, not round-trip

      ' CONVERT DISTANCE TO PWM DUTY-CYCLE
      '-----------------------------------
      duty = echo_dx/max_dx * 100.0

      Call PWM&#40;1, duty&#41;
	   
      'debug.print  "time = " & t & " dx = " & echo_dx & " duty = " & duty & " v = " & duty/100.0*5.04
   wend
   
end sub
Post Reply