Ultrasonic Rangefinder, Part III: Receiver / LogoChip Interface Attempt

I haven’t touched the DIY rangefinder project for a couple of weeks, but I realized I also never wrote up my latest work on it.

Receiver Comparator

After my previous post about building two amplifier stages, I intended to use one of the spare channels on the LM324 as a comparator to “digitize” the amplified receiver signal and provide a clean input to the LogoChip. Unfortunately, the first time I prototyped it was late in the evening when my brain doesn’t work too well, and I built it just like the first two stages–as a linear amplifier. I was really surprised to see more analog waveforms on my scope when I expected sharp edges. At only 24kHz, I didn’t think it should be a slew rate problem, but I wasn’t thinking clearly and just set it aside for the night.

The next day, my error was obvious, and I pulled out the feedback resistor to let the op amp run open loop with infinite gain. It cleaned up the signal, although still not as much as I would have expected. Once the basic circuit was working, I replaced the fixed voltage divider with a 20k trimpot and tuned it as well as I could, trying to find the sweet spot to weed out all the noise but pass all the real signals.

I hadn’t seen it before, but now I wondered whether I was getting some false readings from noise, as John suggested he had encountered when working on similar circuits. I looked briefly at adding a low-pass filter to the circuit (it’s already high-pass filtered by the capacitive coupling from the receiver to the first amplifier stage due to the single-ended op-amp I’m using), but haven’t done it yet. First I wanted to connect it to the LogoChip and see what kind of results I got.

PIC CCP

An ultrasonic rangefinder measures distance by emitting a “ping” and counting the time until the echo is detected; dividing by the speed of sound translates the round-trip time into a distance. Because of the short durations involved, the easiest way to do this on a PIC microcontroller is with the “capture” section of the Capture/Compare/PWM (CCP) subsystem. It uses a high-resolution timer and interrupt circuitry to give a very precise measurement of how long something takes to happen.

I started with John Harrison’s CCP code from his srf_demo.txt example on the TechArt wiki LogoChip with Ultrasonic Sensor page. His code was using the PIC’s CCP module #1; but in my application, I was already using CCP1 to provide the 24kHz signal for my transmitter, so I started translating to use CCP2. The control and behavior of the two CCP channels are rather different, so it wasn’t a matter of simple substitution. Here’s what I ended up with:

Here’s the receiver section of the code:

;------------------------------------------------------------------------------
;   Routines for manipulating CCP2 and timer 3 for capture.
;------------------------------------------------------------------------------

constants [
    [CCP2CON $fba]                      ;   capture/compare/PWM 2 control reg
        [CCPxM-CAP-EVERY #0100]                 ;   capture every falling edge
    [CCPR2H $fbc]                       ;   CCP 2 register low byte
    [CCPR2L $fbb]                       ;   CCP 2 register low byte
    [PIR2 $fa1]                         ;   peripheral interrupt request 2
        [CCP2IF 0]                              ;   timer 3 interrupt bit
    [CCP2-PORT portc]                   ;   uses portc pin 1
        [CCP2-BIT 1]
    [CCP2-DDR portc-ddr]

    [T3CON $fb1]                        ;   timer 3 control register
        [T3CCP2 6]                              ;   timer 3 CCP mode bit 2
        [T3CCP1 3]                              ;   timer 3 CCP mode bit 1
                                                        ;   1x src CCP1+2
                                                        ;   01 src CCP2
        [T3CKPS1 5]                             ;   timer 3 prescale bit 1
        [T3CKPS0 4]                             ;   timer 3 prescale bit 0
                                                        ;   11 = 1:8
        [TMR3ON 0]                              ;   timer 3 enable bit
    [TMR3H $fb3]                        ;   timer 3 high byte
    [TMR3L $fb2]                        ;   timer 3 low byte
]

;   Initialize CCP by configuring timer 3 and enabling capture mode.
to ccp-init
    write CCP2CON CCPxM-CAP-EVERY       ;   config to capture every falling edge

    clearbit T3CCP2 T3CON               ;   set T3CCP to 01 to make T3 src CCP2
    setbit T3CCP1 T3CON                 ;       and T1 src CCP1

    setbit T3CKPS1 T3CON                ;   set T3CKPS to 11 to use 1:8
    setbit T3CKPS0 T3CON                ;       prescalar

    setbit TMR3ON T3CON                 ;   enable timer 3

    setbit CCP2-BIT CCP2-DDR            ;   set CCP2 (RC1) pin for input
end

;   Record starting value of timer 3 and clear capture flag.
global [ccp-before]
to ccp-start
    setccp-before ((read TMR3H) * 256) + read TMR3L
    clearbit CCP2IF PIR2
end

;   Wait for capture event and return duration.
global [ccp-after]
to ccp-wait
    waituntil [testbit CCP2IF PIR2]     ;   wait for capture interrupt
    setccp-after ((read CCPR2H) * 256) + read CCPR2L
    output ccp-after - ccp-before
end

I added code to send a ping and take a measurement:

;------------------------------------------------------------------------------
;   Top-level routines to tie it all together.
;------------------------------------------------------------------------------

;   For the sake of testing, activate on powerup.
constants [[standalone 0]]
to powerup
    pwm-init
    ccp-init
    if standalone [ pwm-on ]
end

;   Send a short burst of tone.
to ping
    pwm-on
    mwait 1
    pwm-off
end

;   Ping and measure time to reply.
to range
    ccp-start                           ;   record start time
    ping
    output ccp-wait                     ;   wait for echo and return duration
end

Wrote a little loop to display the results on the PC, and was disappointed to see that they really didn’t vary at all in proportion to the distance from the sensor to an obstacle. After a few minutes of head-scratching, I noticed that I hadn’t wired the comparator output to the LogoChip’s CCP input. Oops! And that’s when I realized I had a much bigger problem.

Overloading Port C1

The PIC’s CCP modules are implemented in hardware, and they’re hard-wired to specific pins. The input pin for CCP2 is the same as general-purpose pin C1–in fact, most if not all of the PIC’s pins have multiple functions that are selected by configuration registers.

My problem arose because C1 is already being used by the LogoChip firmware–as the Go/Stop input! Because LogoChip Logo isn’t open-source, I can’t see exactly how it’s being used, and have to guess what would happen if I tried to use it as a capture input. Since pressing a button attached to that pin makes the LogoChip stop executing user code and return to an idle state, I can’t imagine I’d have an easy time overriding that behavior and getting it to use the pin solely for CCP with no interference.

So what now? I need both CCP modules–one to use the PWM output to drive the 24kHz transmitter, and the other to watch and count time on the receiver. I don’t think I’ll be able to overload C1 with CCP2 for the receiver, so I’m left with a couple of options: swap the pins, or use CCP1 for both transmission and reception.

Swap the Pins

My first thought was to use CCP1 as the receiver (since its corresponding port, C2, is otherwise unused) and make CCP2 the transmitter (on port C1, the Run/Stop button). John says he has previously overridden C1 and used it as an output when the Run/Stop functionality wasn’t needed, so this should work.

In the long run, though, I’m a little uncomfortable giving up the Run/Stop button. I’d like to be able to integrate this technology into hobby robots, and I’d like to be able to leave them powered up but in an idle state, without having to duplicate the preexisting Run/Stop behavior myself in software. Swapping the PWM-transmit / capture-receive pins should work for a quick fix, but I’m not sure it’s where I want to be in the larger game.

Use CCP1 for Both Transmission and Reception

Alternately, I could overload CCP1 for both transmitter and receiver. There’s precedent–another student in class is using the Parallax PING))) (TM) sensor module, which has only three pins–ground, power, and bidirectional signal.

To do that, I’d need to make sure that transmission and reception don’t interfere with each other. Keeping transmissions out of the receiver circuit is easy–put a diode from the comparator output to the LogoChip so the transmitter signals don’t go “upstream” into the comparator.

Keeping comparator signals out of the transmitter driver is a little trickier, but I think I have a reasonable solution, based on something I was considering doing anyway. I’d like to be able to drive multiple sensors from one LogoChip, but there’s only one (er, two, maybe, sorta) PWM output available. To drive multiple rangefinders, I’d need to multiplex the PWM signal somehow–and there are plenty of ways to do that.

The most straightforward is to use a few LogoChip output pins to select which transmitter to drive and AND (or NAND) them with the PWM signal. Cake! And it tidily solves my receiver-interfering-with-transmitter problem–the receiver can dump whatever it wants onto the PWM output, but it won’t go anywhere harmful unless one of the transmitter select lines is activated.

Sounds like a win all around, and I think I’ll investigate it as soon as things calm down with the exhibit and I can get back to tinkering. It means a little more work on the software side (switching CCP1 back and forth between PWM and capture modes), but I’ve never been afraid of writing code.

8 Responses to “Ultrasonic Rangefinder, Part III: Receiver / LogoChip Interface Attempt”

  1. Horatiu Vornica says:

    I need to use a “simple” ultrasonic positioning; there is no need for echo sonar. I only need a ultrasonic burst from a mobile transmitter and at maximum 35 meters a receiver; “one way” positioning for an elevating platform. The same controller board will give the transmit signal(though a flexible cable) and receive the signal.
    Could you recommend some websites or some technical documentation about this?

  2. Keith Neufeld says:

    Horatiu, I’m not sure what you mean by “no need for echo sonar,” unless you mean that the ultrasonic rangefinder doesn’t need to rotate.

    I’m not aware of any with a range of 35m — the ones I’ve used max out at about 5m. I would guess you might be able to find some from industrial automation suppliers, but I don’t have anything specific in mind.

  3. Horatiu Vornica says:

    By “no need for echo sonar” I was trying to say: I don’t need to transmit a signal and wait for the reflected signal to come back. I need to transmit a signal and in the other part to have the receiver who will receive the direct signal; The transmitter is mobile on one axis, so in this way I can measure the distance between the transmitter and the receiver; the distance between the transmitter and the receiver is 35 meters, but the signal is much stronger then is in the “echo sonar” method.

  4. Horatiu Vornica says:

    Actually the distance from the transmitter to the receiver is varying between 1 meter and 35 meters. The speed the transmitter is moving is 1m/s, which is the mobile platform speed; to this mobile platform I need to know the position. This platform has a vertical up and down movement, like an elevator.

  5. Keith Neufeld says:

    Horatiu, I understand now what you mean about separate transmitter and receiver, rather than a single transceiver. However, I’m still not familiar with the market and am not specifically aware of any components that would work for you.

  6. Joe Hoerl says:

    Horatiu, the Senscomp (formerly Polaroid) ultrasonic range finder has the best distance at around 10 meters. The problem with not waiting for the echo would be the synchronization of timing to understand the time the signal is sent vs. received. I’m not aware of any devices that work in this manner. Possibly there are some laser range finders which might suit your need and are commonly used in surveying and aligning of cranes, etc.

  7. Jon says:

    Hi Keith,

    I have really enjoyed reading your blog entries! However I have a few questions.

    I am currently working on a robot and am hoping to add some ultrasonic sensors. I have read all of your DIY Ultrasonic entries but was wondering if the only modification that you made to the original schematic was removing the 1M feedback resistors on the amplifiers.

    I was also wondering if you knew whether or not long leads (about 1ft) to the transducers would cause interface problems. Should the 1nf capacitor be very close to the transducer? If possible I would like to build the reciever/xmitter circuit only once and then use a set of relays to multiplex the circuit to multiple pairs of transducers. If not I will have a fun time soldering 8+ PCBs :)

    Any advice would be greatly appreciated and again I have to compliment you on having such a great, well-maintained site!

    Thanks!

    Jon

  8. Keith Neufeld says:

    Jon, I have to confess that I haven’t touched this project in a long time, and had to reread my own entries to catch myself up to date. I really don’t remember exactly what modifications I made to the original.

    One thing I do remember is discovering to my embarrassment that Gerald Coe’s schematic on which I based my design was in fact the schematic for one of the wildly successful SRF series of ultrasonic rangefinders, the very ones I described as too expensive and was trying to supplant. At this point, I would actually encourage you to look into his sensors, available from Acroname. I’ve used them and they’re very robust, reliable, and easy to interface.

    That said and regardless of which way you choose to go, I can’t imagine that 1′ leads will be a problem at 24kHz. I don’t think the placement of the 1nF capacitor matters — it’s just capacitive coupling for the op-amp section, to block DC and begin to high-pass filter the input.

    I don’t see any reason you couldn’t use relays to multiplex your sensors, although I don’t think I’d choose to do it that way myself. Relay-related problems aren’t insurmountable, but you’ll want to be careful to put a back-EMF protection diode across the coil; and you won’t be able to change sensors as rapidly because you’ll have to allow time for the relay contacts to settle; and for a mobile robot, if I were doing it, I’d find which way the relay’s lever moves and lay the relay on its side so that jostling over rough terrain doesn’t make and break contact when not desired by the controller.

    Best of luck with your project; and if you have a blog or a site for it, I’d love to you have you post another comment linking to it!

Leave a Reply