Thursday, August 30, 2012

Roland MDX-20 with Linux

I've been setting up a Makers' lab at work recently, and one of the bits of kit we have there is a Roland MDX-20, it's a great little CNC mill for the price (it comes with a piezo scanner attachment too, for all of your object duplication needs), however, as is often the case, the software provided by the manufacturer only runs on Windows.

One of the provided programs is something called the Modela Player 4, and this is what loads in your 3D model, generates the corresponding tool paths for the loaded model, and spits those out to the MDX-20 ready to carve out your Star-Trek communicator badge (or whatever it is you want to make).

Rather than having to deal with the extra baggage that having a Windows machine often entails, I thought that there must be some alternative path we could follow, and started looking around.

It turns out that the MDX-20 uses a language called RML-1 rather than the more commonly seen g-code, and because RML-1 is a little obscure and is not really used much elsewhere, a lot of the alternative software options don't support it.

(For the curious, there's a document describing the RML-1 language available here.)

Tempting as it was to immediately disappear down the rabbit-hole of RML-1, what we really wanted was to get the mill up and running so that people could use it ASAP, so an obvious thing to try was to get the Roland provided software running under WINE.

I installed the various bits of software that came on the CDs in the box, and then downloaded and installed the updates from the Roland website, here: http://download.rolanddg.jp/en/3d.html#mdx1520.

It turned out that the software runs reasonably well under the version of WINE I tested (1-4-0ubuntu4.1 running atop Ubuntu 12.04 LTS); the 3D model display worked, and the various dialogs seemed fine, and, apart from a couple of lockups that I couldn't really nail down to any particular cause, it seemed like we were on to a winner.

A little more about the set-up, software and hardware:  the MDX-20 itself only has an old-school 25-pin serial port for communications with a computer, so I used the supplied 25-pin to USB cable which appeared as /dev/ttyUSB0 as you would probably expect;   the Modela Player 4 software treats whatever mill it's talking to as though it were a printer (RML-1 is not a million miles away from HPGL so you can see why that happened).  WINE uses the host's CUPS printing system so after a short bit of fiddling to add the mill's USB serial port as a local printer under CUPS the mill appeared in the mill config screen of the Modela Player 4 software.

So I tried a test mill... oh boy, what a disaster.

The tool head was moving about all over the place, so fearing damage to to the milling bit I killed the job and reset the mill.  Double checking that I'd configured CUPS in what seemed to be the correct fashion I tried again, got the same result, and sat back with no small measure of sadness, more or less resigned to the fact that I'd have to relent and accept that my immediate future now included looking after a Windows machine in a shared lab.

That evening, while doing something entirely unrelated I had a thought:  the random tool head movements I'd witnessed earlier seemed to be getting slowly deeper with time (before I stopped it), what if what I'd been watching was the mill skipping through to later parts of the tool path ?  Like, say, if there was a buffering/flow-control problem between the host computer and the mill - that might explain it right ?

So I double-checked the serial port settings with stty but hardware flow control was allegedly set, thinking that perhaps the mill's internal buffer was overflowing (reasoning that the perhaps the Roland Windows driver had some other magical way of handling flow-control) I tried using pv (PipeViewer - awesome little util by the way) to rate limit the RML-1 program as it was sent to the mill.  Neither of these things made any difference whatsoever.

The last thing I tried was to ditch the USB cable entirely and just use a Real serial port instead...
...bingo: Now the mill is behaving sensibly* doing what it's told !  (* more on that in another post.)

Making it work for you too

So, the steps are:

  1. Throw the USB serial cable in the recycling-bin and use a real serial cable (you may have to buy a PCI/PCI-E serial card for this if you don't have one on your computer).
  2. Add a local serial printer to your CUPS setup, pointing to the serial port to which your mill is connected.  Set the serial port options to baud=9600 databits=8 parity=none flow=ctsrts.
    I did this step via the gnome printer entry in the control panel.
    When you add the printer entry, make sure to configure it as as a Raw Queue device - we don't want CUPS trying to make our RML-1 files look pretty before sending them to the mill !
  3. Edit /etc/cups/cupsd.conf and add the following line to it:
      Timeout 0
    This should help CUPS cope when you pause the mill for an extended period of time (otherwise CUPS will think the job has stalled and abort it.
  4. Edit /etc/cups/printers.conf and add/modify the ErrorPolicy line to say:
      ErrorPolicy abort-job
    otherwise CUPS may 'helpfully' decide to retry the whole job if you pause the mill.  The previous line should really obviate the need for this change, but we don't really want CUPS doing the retry under any circumstances.
  5. Install WINE if it's not already installed.Instructions for this vary by distribution, but for apt-based distros it's
        sudo apt-get install wine
  6. Install the Roland Modela Player 4 software from the provided CDs using WINE
  7. Download and install the update patches from the Roland website
  8. Run the installed Modela Player 4 software, configure the mill to use by selecting the new 'printer' you just added to cups


With a bit of luck you should now be up and running and ready to mill as many Star-Trek communicator badges as you could possibly want.





Sunday, July 26, 2009

Rotary DECT Phone


+ = ?


Background

We're off to Hacking At Random next month, where the nice folks from EventPhone will be running the customary DECT network providing wireless digital telephony to a few thousand geeks camping out in a field.

In the past we've each taken a DECT handset from our respective homes which we've dutifully carried around, but this year I thought it'd be nice to provide a telephone which we could use in our home-from-home: the Echo Base village.

You could be forgiven for thinking that this task should only really involve finding another handset to leave on the table in our shared living-room-tent, and fundamentally you'd be right. However, being British and thereby genetically predisposed to going to unreasonable lengths to bring civilisation to a muddy field in a faraway land, I wanted something a bit homelier, and nothing says homelier in a more homeliererer way than the sweet tinkling ring of a 1960's GPO rotary telephone.


The Bits

A very nice lady on Freecycle gave me a cream GPO model 746 phone (just like the one above) for the eminently reasonable price of free, and I picked up a Phillips CD245 DECT handset from ebay for a couple of quid. So far so good. Since I wanted to this to be a portable phone I ordered a 1100mAh LiPoly battery and charger board from RoboSavvy, along with an Arduino Pro Mini, and a USB Serial breakout board for programming and debugging.

To make the ringer work I figured it was unlikely that I'd want to re-use the original whacking great big solenoid arrangement which is built like a soviet tank but likely to flatten my little LiPo battery after just a couple of incoming phone calls, so instead I ordered a few replacement mobile phone vibrate motors from the interwebs for a couple of quid, despite not yet being entirely sure about how I was going to use them.

First things first: the dialer

After ripping the rotary phone apart and giving it a damn good clean, I decided to start with working out how to decode the rotary dialer.

It turns out that the dialer is a marvelous bit of design:

The white wheel in the middle is connected to the finger wheel on the front (where you poke in your finger and turn to dial a number), and when you release the wheel and allow it to rotate back to its home position, the cam peaks around the edge of the wheel push against the little white lever you can see on the right, which in turn momentarily breaks a connection between two of the wires leading into the unit. There is one cam-lobe per number on the front, and sure enough when you dial 5 on the front, the little white lever causes 5 momentary breaks in the circuit.

That magical little white wheel has another trick up its sleeve too: on the face of the wheel there's a small sticky-outy bit -- please forgive my use of deep technical jargon -- which holds a spring switch closed when the dial is in its home position, but when you rotate the dial to dial a number, the spring switch is allowed to remain open until the dial rotates fully home.


Here's a plot from my 'scope which makes things a lot easier to see:
The upper trace shows the output of the switch on the right which counts the number the user dialed, the lower trace is the rotor-is-at-home-position signal. On the left you can clearly see where I started dialing by rotating the wheel, then I pulled my finger out and let go and you see the 5 pulses on the right, quickly followed by the home signal going high again.
With these two signals I'll be able to know when the user has dialed and number, and which number they dialed.



Next: How to spoof key presses on the DECT handset ?

Unfortunately there isn't yet a Pokie-Finger Arduino shield, so I had to find another way to spoof the key presses on the handset.

To scan a bunch of keys you could have a wire for each key which you watch to see if they has been pressed, but people worked out a long time ago that you can do it cheaper if you arrange the key connections in a matrix and multiplex the scanning. What this means is that for a 3x4 matrix (like a phone keypad) you'd have 4 outputs (say A to D) and 3 inputs (1-3) arranged as a grid, with a key at each intersection. To scan for key-presses you bring output A high and then check each input in turn, if you see a non-zero voltage on an input then you know that the pressed key must be connected to output A and the input on which you saw the voltage, otherwise you put output A low and bring output B high, check each input, and so on.

Armed with my trusty multimeter set on continuity beep mode, I traced the key matrix on the circuit board of the DECT handset, this is what it looks like:




Using my 'scope I found out that the Orange, Red, Light Green, and Purple lines were the outputs, and the other lines the inputs.


Here's a scope plot of two of the output lines, it seems that there's some sort of synchronization pulse which goes out on all lines simultaneously, but just after that you can see the real key scanning pulses which are indeed staggered as expected.

So, the obvious way to spoof key-presses would be to have an NPN transistor connected across each of the key connectors, then applying a small voltage to the base of the transistor would allow it to conduct the scanning pulses through, so in theory it should be almost indistinguishable from the real thing.
This would work, but maybe there's a better way...

Since I'm using a Arduino as the brains of this project, rather than pass on the actual key scan pulse, I can connect the handset's output and input lines directly to my Arduino, detect when the scanning pulses are present and then if I want to press a key I can bring high the Arduino pin connected to the handset input line which corresponds to the key I want to "press". It turns out that this works fine, but is very timing sensitive, so much so that while I could use the PinChange interrupt to detect the start of the keyscan pulse, I needed to have a tight busy loop inside the ISR to copy the pin state to the right output. This is fine though because we'll only be in this state for short amounts of time, and only when we're trying to dial a number on the handset.

With the approach sorted, I used the multimeter to find points on the reverse of the DECT handset circuit board which were connected to the various key contacts - these turned out to be a mix of test points and through-hole vias, so without further ado I soldered a bunch of fly leads to the newly discovered points:





On/Off hook switch:


I decided the easiest thing to do here was to re-use the existing micro-switch setup which I removed from the original board and placed onto some prototyping board.








The Ringer

The original ringer in these phones consists of a hammer striking against two bells. The hammer itself is moved by two great big solenoids which are driven by the 50v ringing voltage which is sent down the line when there's an incoming call. I'm sure it'd be possible to build some sort of ladder circuit to generate the required voltage to drive the solenoids from my 3.7v battery, but I think the current necessary to shift the weight of the hammer around would not be good for the battery life of the phone.


Instead, I ordered a couple of of the vibrating motors that you find inside mobile phones and pagers, and I constructed a pair of spring mounts which would hold the motor heads next to, but not quite touching, the edge of the bells. When voltage is applied to the motors and they spin up, the vibration on the end of the springy mount causes the motors to shift about by 4-5mm which brings the head into contact with the bell edge. For now it seems to work quite well, although I suspect that the stress of the collisions of the spinning weight and the bell probably doesn't bode well for the longevity of the motors. On the other hand they were only a quid each...

To drive the motors, I used a couple of BC485 NPN transistors switched by a couple of Arduino outputs. I kept the motors on separate outputs so that I could vary the duty time of each motor to make distinct ring sounds that could be used to indicate status etc., currently I just drive them in unison.

It turns out, by the way, that in the UK the BT standard ringer pattern is 0.4s on, 0.2s off, 0.4s on, 2s off, rinse, repeat.


Detecting incoming calls

I spent quite a while poking around with my 'scope trying to find a way to detect when the DECT handset was in ringing mode, I found some very bizarre 4-level digital signaling going on, but nothing particularly useful, until I came across a signal that does almost what I'm after.



You can see on the 'scope traces above that there's a pulse of about 100µs when the DECT handset is dormant (left hand trace), but when there's an incoming call this pulse widens to about 400µs (right hand trace).


Again, I used the pin-change interrupts to monitor this pulse, by saving off the count from one of the Arduino's timer registers at the rising edge, and comparing it with the current timer count at the falling edge we can determine the pulse length asynchronously.


Pulling it all together

Now it was just a matter of fixing everything together, I used the prototyping board which holds the off-hook micro-switch as a base, mounted the Arduino to it using a bunch of pins soldered through, and soldered the various fly leads in to the appropriate places.

I reused the grommet from the phone socket lead to make a power socket housing which fits in more-or-less with the style of the rest of the phone.
Put it all back together, and voilà !

In case you're interested or you want to make your own Rotary DECT Phone, the source code for the Arduino is available here.