Sunday, November 18, 2018

Fake ultrasonic transducer

The goal here is to provide a fake ultrasonic transducer that can reproduce a constant echo signal, useful for production testing (produce a known fixed signal that can be tested against) or software development (produce a known fixed signal to determine if math/timing is correct for measuring distance).  An ultrasonic transducer works by converting voltage pulses into ultrasound, and then receiving an ultrasonic echo and converting that back into a voltage that can be read.  By measuring the time between the transmit and the echo received, the distance between the transducer and the floor (or whatever caused the signal to bounce, water, etc) can be determined using the speed of sound.

Recently I was working on a few products using ultrasonic transducers for measuring volume in a tank, and the need for testing or developing without a tank of water was needed.  The product was generating > 100V pulses into the transducer, and the converted echo response was going into an AM detector.  The signals looked like so:


The purple plot is the raw voltage on the product; the first edge is the > 100V signal generated to excite the transducer and the second smaller edge the echo received.  So what we need is a simple circuit that can take >100V, delay a short fixed period of time, and then generate a simple echo.  Here is what I came up with:
These products actually contained 2 transducers, as they were placed in the middle of the tank to measure if the bottom of the floor moved.  For that reason there are two transducer signals on the schematic, XDCR_1 and XDCR_2; however the circuitry for both is the same.  The >100V excited signal goes thru a simple transistor amplifier to bring the voltage down to ~5V and input into a comparator input on the PIC MCU.  The PIC comparator is configured to interrupt if the signal on the PIC MCU pin goes over 4.096V (using the PIC's internal voltage reference as the other input to the comparator).  On a comparator interrupt, the PIC has a short delay and then generates a response echo which goes back to the XDCR_x input thru a Schottky diode.

When I prototyped this design on old development kit with the old PIC16F877A on it, I had no problems.  But after moving to this design with the newer PIC16F18325, the PIC was resetting when the board was sending the >100V ultrasonic pulses.  After removing the Schottky diode to verify it wasn't some kind of weird ground bounce on the circuit, I added the BAV99 diodes to act as transient suppression and the problem went away.  It makes me wonder if Microchip is going cheap on PICs and not making them as hard as they used to.  Otherwise I liked the 16F18325; every pin was peripheral reprogrammable, which allowed me to tie all 3 LEDs to 1 PWM for brightness control.  As a side note, I can't believe how bright surface mount LEDs are getting these days.

Here is what a 3D model of the PCB and the final board (blue jumper wire on the final board is due to having to cram the BAV99 diodes on the design after the PCBs were made):






Monday, October 1, 2018

Python code for controlling a West Mountain Radio CBAIV

This one is pretty simple: a Python library for controlling a West Mountain Radio CBAIV.  It was tested in Windows and Linux using libusb.  Windows users can also use the official drivers provided by West Mountain Radio.  Package can be installed with pip, or you can grab the source and examples from GitHub.

Thursday, September 26, 2013

USB to Commodore 1351 Mouse converter

I'm heading to the Midwest Vintage Computer Festival and Fall Commodore Expo this weekend and wanted to bring something down to show-off. I grew up with an Apple ][, but today I still enjoy retro computing - I particularly enjoy finding new ways of interfacing new technology to these old computers. In college I saved a Commodore 64 out of the garbage bin, and the first time I ever used a soldering iron was to make a serial cable between my PC so I could get the Commodore 64 on the internet. I lost that Commodore 64 a few years ago, but recently I've upgraded to it's big brother the Commodore 128.

 One piece of software on the Commodore 64 that I always liked was GEOS. However, I never really had a mouse to go with it, in particular the Commodore 1351 mouse. You could use a joystick to control the cursor, but I want the real thing. A while ago I was looking at the specifications of the mouse and how it worked, and I thought I could make a USB to 1351 converter.  Lots of people have made a PS2 mouse to Commodore 1351 mouse converter, but I hadn't seen a USB one.


To summarize how the 1351 mouse works, it sends X and Y location to the computer by varying the duration of a pulse on the X and Y line. The computer starts grounding the X and Y line for 256us to discharge any holding capacitors on the line, and then the computer floats the line for 256us. At the period where the computer floats the line it starts looking for the mouse to pull the line up, the duration between the time the computer floated the line and the mouse pulled the line up is the new position location. The computer then performs math on the previous position and the new position and determines the delta of movement. If one of those 512us cycles is missed by the mouse, then the mouse position will be calculated incorrectly and the mouse cursor will jump - meaning there are some strict timing rules.

To create this USB to 1351 converter, I started with a PIC24USB Development kit from CCS. This development kit has everything you need for developing USB host applications, like a 5V 1A regulator for powering USB devices. I replaced the PIC24 that was on the board with a Microchip dsPIC33EP256MU806. It's pin compatible with the existing board, and the EP family can run at 70MIPS while handling USB (the PIC24 is limited to 16MIPS when handling USB). For software development I used the CCS C Compiler - I've been using it for years and have gotten addicted to all the libraries it provides, and the IDE runs well on my low performance netbook.




The 1351 Mouse connects to the Joystick port of computer, which runs at 5V. The dsPIC runs at 3.3V. So I created a small daughter board that plugs into the development kit that has two 4 channel buffers and a DB9 port for the joystick port of the computer. I probably didn't need two 4 channel buffers, the up/down/left/right/fire controls on the port I could have connected to a 5V tolerant pin on the PIC and just floated/grounded the pin for control. The X and Y lines are the only ones that really need the buffering as they require 5V output from the PIC.

I did make a mistake in the design, hence the jumpers above. I originally tied output re-programmable pins to the latch pins of the buffer - but then I realized I want to use the output compare pin to control enable pin of the buffer (to toggle between floating and 5V). The pins I had tied to the enable pins of the buffer were not re-programmable to the output compare peripheral, so I had to swap some. The schematic above is correct.

To recreate the 1351 Mouse on the PIC, EXT1 interrupt pin and two output compare (OC) pins were used. OC peripheral pins were tied to the X and Y enable pins of the buffer. The EXT1 interrupt pin was tied to the X line directly on the DB9 connector of the joystick - that means this pin has to be 5V tolerant. EXT1 interrupt was used to detect when the computer pulled the line low, at which point the X and Y OC pins were primed to create a rising pulse at the desired position. The X and Y lines are floating during the time between the computer floating the line and the OC fired to bring the line high. While it's floating the voltage was hovering around 1-2V, kind of an intermediate state for the input buffers for the PIC so this was causing spurious EXT1 interrupts. So after the OC is primed, I had to turn off the EXT1 interrupt and then turn on the OC1 interrupt. Once the OC1 interrupt fired, then the OC1 interrput got turned off and the EXT1 interrupt turned back on. 

To handle the USB and controlling the mouse I used Microchip's USB stack. Reading through the code in the stack, it was pretty smartly written in how it can determine from the HID descriptor which bytes in the HID report are the cursor position and which bytes are the button press indicators. They also provided a demo mouse program, of which I used and added a few key calls to my new 1351 library. It worked pretty much right away but there was occasional glitches - I am guessing it's because the USB stack used interrupts and that was interfering with the interrupts in the 1351 library (and it's strict 512us timing). I was about to turn on nested interrupts and make the 1351 interrupts a higher priority, but then I realized it's probably easier to just poll the USB in the main loop instead of using USB interrupts. Microchip didn't provide this feature, so I made some modifications to their Stack to support polling instead of interrupts. USB interrupts out of the way, mouse movement and cursor position was glitch free!



Happy computing!