InputCapture vs. PulseIn w/CallTask
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
InputCapture vs. PulseIn w/CallTask
My new ground bot features a high rate feedback control system to track close objects with IR range sensors. Now I want to add an ultrasonic range sensor for long distances, however the measurement update rate is slow and highly variable. The InputCapture function seems ideal for the sonic ranger because it runs in the background, but I'm concerned the data array argument will take too much RAM (I'm using a ZX-40n device). So that leaves the PulseIn function, but the bot program has to wait for PulseIn to return results. App. note AN-210 ("Sharing Data between Tasks") makes me believe that I can use "CallTask" to call a separate subroutine to calculate distance from the sonic ranger as an independent background task. Will this work? Will PulseIn clash with my PWM functions?
Re: InputCapture vs. PulseIn w/CallTask
Probably not. The problem is that PulseIn disables interrupts so no other task will be allowed to run until the pulse is seen.liam.zbasic wrote:Will this work?
As for using InputCapture() you may be able to get by with shorter sequences. Another alternative is to switch to the ZX-40s which has 16K of RAM.
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Yes, the ZX-40s is very enticing. For now, I want to make due with what I already own. I have a bunch of ZX-40a and ZX-328n chips. I'm thinking of using one of those to process the sonic range sensor, then output the result as a voltage with the DAC function. Then I'll read that voltage with an ADC from the ZX-40n device running the main bot program. Will DAC to ADC from separate chips work? And for the matter, will high/low states transfer between chips? Thanks.
Yes to both provided that they share a common ground connection.liam.zbasic wrote:Will DAC to ADC from separate chips work? And for the matter, will high/low states transfer between chips?
Rather than using the PutDAC function you may be better served by using a PWM output on the slave device. I say this because, once set up, the PWM runs continuously with no further attention needed by the processor. In contrast, PutDAC needs to be called regularly to reduce "droop" on the generated analog level.
Another possibility is to use SPI or I2C and set up the device as a slave. If you already have other SPI or I2C devices the additional pin count required is minimal.
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Yes, all devices will share the same ground connection. So I plan to use an ADC pin from the master to read an "analog" voltage from the slave. If the slave outputs a PWM signal, will the master ADC interpret that as an "analog" signal? I suppose the PWM frequency will need to be very high, otherwise the master will "see" a square signal.
Only if you add an RC filter to "average" the PWM signal. The cutoff frequency of the RC filter needs to be perhaps an order of magnitude lower than the PWM frequency. Of course, the lower the cutoff frequency of the filter, the slower the filtered voltage will respond to changes in the PWM duty cycle.liam.zbasic wrote:If the slave outputs a PWM signal, will the master ADC interpret that as an "analog" signal?
The cutoff frequency of a simple low pass R-C filter is 1/(2*pi*R*C) where R is in ohms and C is in Farads. A 1K resistor and a 100nF capacitor will yield a cutoff frequency of about 1600Hz.
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
dbkinzer - appreciate your comments. I'll set the PWM frequency to 20khz and I'll do a 2nd order low-pass filter with a cutoff at 500hz.
Is it correct to say that the "averaged" output voltage from the slave will be 16bit resolution? When passed to the master ADC, the reading will be knocked back down to 10bit (which is adequate for my application). If I want to retain 16bit resolution, SPI or I2C is better, but at the cost of speed, more code and more pin connections.
Separate question, I'm having a tough time finding an ultrasonic range finder with a separate burst frequency so as to not interfere with my standard ~40khz device. Any links?
Is it correct to say that the "averaged" output voltage from the slave will be 16bit resolution? When passed to the master ADC, the reading will be knocked back down to 10bit (which is adequate for my application). If I want to retain 16bit resolution, SPI or I2C is better, but at the cost of speed, more code and more pin connections.
Separate question, I'm having a tough time finding an ultrasonic range finder with a separate burst frequency so as to not interfere with my standard ~40khz device. Any links?
I suspect that a simple RC filter would suffice, e.g. 220nF/1.5K.liam.zbasic wrote:I'll do a 2nd order low-pass filter with a cutoff at 500hz.
Yes, assuming 16-bit PWM is used.liam.zbasic wrote:Is it correct to say that the "averaged" output voltage from the slave will be 16bit resolution?
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
I'm perplexed. My 328n device seems to either skip the PulseOut echo to my ultrasonic range sensor or perhaps the PulseIn statement is not waiting for the return echo. However, if I un-comment the debug.print statement, the code works fine. Is the native device too fast?
Code: Select all
option base 1
option TargetDevice zx328n
public const ping_pin as byte = 14 ' Ping sonar sensor output (zx328n)
public const ping_level as byte = 1
public const sos as single = 13397.2441 ' Speed of sound (in/sec)
public const runtime as single = 10.0
sub main()
dim hour as byte, minute as byte, sec as single
dim t as single, told as single, dt as single
dim ping_tau as single, ping_dx as single
t = 0.0
dt = 0.0
told = 0.0
while t < runtime
call GetTime(hour, minute, sec)
t = CSng(minute)*60.0 + sec
dt = t - told
told = t
' PROCESS PING SENSOR
'----------------------------------
call pulseout(ping_pin, 9, 1) ' A single pulse is 1.085 us; want 10us for ping sensor
call PulseIn(ping_pin, ping_level, ping_tau)
ping_dx = ping_tau * sos / 2.0 ' Distance divided by two for one-way distance
'debug.print "time = " & t & " " & "one-way = " & ping_dx & " dt= " & dt
wend
end sub
Perhaps the sonar device has a minimum cycle time or has a recovery time requirement. The datasheet for the device may give some guidance in that regard.liam.zbasic wrote:Is the native device too fast?
I suspect that it is not the Debug.Print, per se, that is allowing it to work but the delay introduced by it. You could test this hypothesis by replacing the Debug.Print with a Sleep() call that produces the equivalent delay (number-of-characters * 10 / baud-rate). If that works, you could reduce that delay gradually until it stops working.
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Yes, I figured the ultrasonic sensor worked because the debug.print statement added a small delay. And yes, last night I tried the "sleep" command and it worked. My confusion is that I understood PulseIn would provide the necessary delay because it make everything wait until it "returns". Not sure what's happening here.
PulseIn() only guarantees a wait until the pulse is returned. It doesn't guarantee an additional delay before asking for the next pulse to be sent. I don't know if your ultrasonic device requires such a delay but the results suggest that it does. What is the make/model of the U/S device?liam.zbasic wrote:I understood PulseIn would provide the necessary delay because it make everything wait until it "returns".
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
It's the parallax Ping distance sensor:
http://www.parallax.com/dl/docs/prod/ac ... G-v1.3.pdf
To bring you up to date, I'm setting up the zx328 device as a slave dedicated to measuring distance, and I'm considering using I2C for communication with the master zx40n device. If I include a "sleep" delay in the slave to make the ping sensor work, will that force the delay on the master?
http://www.parallax.com/dl/docs/prod/ac ... G-v1.3.pdf
To bring you up to date, I'm setting up the zx328 device as a slave dedicated to measuring distance, and I'm considering using I2C for communication with the master zx40n device. If I include a "sleep" delay in the slave to make the ping sensor work, will that force the delay on the master?
According to the datasheet, it requires a delay between measurements (see attachment). The required 200uS delay comprises about 3000 CPU cycles for a device running at 14.7MHz. I doubt that that requirement is met in your code without an explicit delay call after the measurement.liam.zbasic wrote:It's the parallax Ping distance sensor:
The TWI slave mode is interrupt driven so the slave should respond as long as you don't make calls that disable interrupts for long periods of time. In this respect, it is probably not a good idea to use PulseIn() since it does disable interrupts until the trailing edge of the pulse is seen.liam.zbasic wrote:If I include a "sleep" delay in the slave to make the ping sensor work, will that force the delay on the master?
PulseOut() also disables interrupts but the duration is short enough that it may not matter. You could use PutPin() in combination with Pause() to generate the pulse to the PING sensor.
Code: Select all
Call PutPin(ping_pin, 1)
Call Pause(1) ' delays about 4uS
Call PutPin(ping_pin, 0)
- Attachments
-
- ping.jpg (29.05 KiB) Viewed 3932 times
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Now I'm sand-trapped. I added a "Pause" delay for 0.02sec to account for a max possible delay of 18.5 msec (per spec) associated with longest measurable distance. The code runs fine and calculates the correct distance. However, when I add PWM statements to output voltage proportional to distance, the PULSEIN command fails - the returned pulse width is always zero. I set the "Pause" delay to 1.0sec, but no luck. Seems there is a Timer conflict between PWM and PULSEIN. I'm using a ZX-328n device. I tried both PWM channels and made sure to include OpenPWM at beginning of program. Could it by that PWM and PULSEIN will not work together in the same program and 328n device? Thank you.