A USB Interface for a Mitutoyo Caliper

I am in need for a z-measurement device for my cnc. So I checked ebay and got me a used mitotuyo depth gauge for ~60€. It has an ‘SPC’-Interface for digital readout. Fortunately there is some information on the Web on howto access that interface.

IMG_2912.small
DIY connector

I didn’t want to buy an expensive Mitutoyo-cable, so I decided to solder on my own connector.

Pinout is:
1. GND (red cable)
2. Serial Data Out (OpenCollector)
3. Serial Clock Out (OpenCollector)
4. (unused)
5. Request In

The USB-Conversion is done by a tinymega microcontroller board which features an Atmega32U4 CPU. With the LUFA USB-Stack  it presents itself to the host as a virtual serial port.

The implementation of  the SPC-Protocol decoding is pretty straightforward. Send a request on one pin, read in data via SPI. I chose to do all of this in software with one interrupt (not using the SPI peripheral of the CPU). You can see my implementation here on github.

caliper + tinymega
caliper + tinymega

Now all that is left is to hook it up to linuxcnc. I haven’t done that yet, but most likely it only requires 10 lines of python to generate a HAL-Module.

WS2812 LED Pixels with ola using SPI

Controlling WS2812 LED-Pixels from an Raspberry-Pi can be done. Other people have done this before: https://github.com/jazzycamel/ws28128-rpi/
My approach is different, but not that new either. I already implemented similar code for the Lightpainting-Stick-Clone.

To get the required timing with the SPI we can output some patterns to make it look like the WS2812-Protocol.

ws2812_spi_transfer
The yellow line is MOSI (DIN). The 50us Reset is visible on channel 2.
ws2812_spi_transfer_close
Closeup of the actual timing. This image shows the first 7 bits (1000010)

 

However, there are some issues as metioned in the inline-comments. At first it seems like the code does not work when sending dmx-data with ola_dmxconsole. Once there are more changes in a short period of time, the pixels start to react. My guess here that this is related to the scheduler of the kernel. When as the kernel switches tasks the SPI output-stream gets interrupted, thus making the timing invalid. I will investigate this further.


void SPIOutput::IndividualWS2812Control(const DmxBuffer &buffer) {
  /*
   * This is an hack!
   *
   * Basically the RaspberryPI cant drive WS2812 Pixels because they have
   * some strict timing requirements.
   * Using the SPI-Module we can emulate those pulses.
   * This will only work if the SPI-Module outputs all data in one consecutive
   * stream without any pauses. More recent versions of the Raspberry Kernel
   * seem to implement DMA for SPI which makes this possible.
   *
   * WS2811-Chips have similar timings but not exactly the same as WS2812.
   * Some sources say the most important part is the total period-time
   * of one bit. There are lots of descriptions of WS2812-timing requirements
   * out there, one of them is: (with +-150ns tolerance)
   * 0-Bit 0.25us high, 1us low
   * 1-Bit 0.6us high, 0.65us low
   *
   * Running the SPI at 4Mhz gives us a pulse-width of 250ns
   * Using a 5-bit pattern we can emulate those timings
   *   0-Bit: 10000 (0.25us high, 1us low)
   *   1-Bit: 11110 (1us high, 0.25us low)
   * Those values are not an exact match, but they seem to work for both
   * WS2812 and WS2811 in high-speed-mode.
   *
   * We need to send 8 of those 5-packs for each byte. Those 40 bits are
   * precalculated and stored in a lookup table.
   *
   * To issue an reset, the data-line needs to be low for 50us, thats
   * 200 bits, or 25 bytes. For safety, we will send 27 bytes.
   *
   * Connect the Data-In-Pin of the LEDs to the MOSI Pin of the SPI-Module,
   * ignore the clock Pin.
   *
   */
  const uint8_t reset_bytes = 27;
  const unsigned int first_slot = m_start_address - 1;  // 0 offset
  // We always check out the entire string length, even if we only have data
  // for part of it
  const unsigned int output_len = reset_bytes + m_pixel_count *
                                  WS2812_SLOTS_PER_PIXEL * WS2812_SPI_LUT_LEN;
  uint8_t *output = m_backend->Checkout(m_output_number, output_len, 0);

  if (!output)
    return;

  // set the reset-bytes to zero
  memset(output, 0, reset_bytes);

  // loop over all pixels
  unsigned int output_pos = reset_bytes;
  for (uint16_t px = 0; px < m_pixel_count * WS2812_SLOTS_PER_PIXEL; px++) {
    uint8_t c = buffer.Get(px + first_slot);
    // now output 5 bytes from the LUT
    for (unsigned int lut = 0; lut < WS2812_SPI_LUT_LEN; lut++) {       output[output_pos++] = WS2812_SPI_LUT[c * 5 + lut];     }   }   m_backend->Commit(m_output_number);
}

I pushed that code here: https://github.com/cpresser/ola/tree/ws2812-spi

This is the config I used:

base_uid = 7a70:00000100
device_prefix = spidev
enabled = true
spidev0.0-0-device-label = SPI Device - spidev0.0
spidev0.0-0-dmx-address = 1
spidev0.0-0-personality = 9
spidev0.0-0-pixel-count = 10
spidev0.0-backend = software
spidev0.0-ports = 1
spidev0.0-spi-ce-high = false
spidev0.0-spi-speed = 8000000
spidev0.0-sync-port = 0

Demo time:

PCB fixture for applying solderpaste

I have done a few PCBs using the reflow  process. To apply the solder-paste using a stencil one requires some sort of fixture to hold the PCB.

So far I helped myself with other PCB Material which I glued on the table to get to the same height. This is okay when only one PCB needs to be made. However, when doing multiple PCBs on after another, the position needs to be constant for every board.

So I designed a simple spring loaded fixture to hold the PCB in place. Its made out of 1.5mm acrylic.

PCB fixture springs

Scara Robot Repair – Learning stuff the hard way

Turns out the drives of my Scara Robot are not velocity-mode drives but torque-mode drives instead. Setting the drive input to a constant voltage results in constant accelleration. I learned this the hard way by crashing the robot :-/

Even though I had it fixed on an Europalette it managed to fall on its side. Second lesson learned: even ‘small’ a 200W drive can turn the whole thing in a fraction of a second. Hitting the floor broke some pieces. But see for yourself:

B-Arm and Z-Motor-Plate destruction
B-Arm and Z-Motor-Plate destruction

Those parts are both made out of cast aluminium. I do lack the equipment and skill to weld, so I asked a Friend of mine to do it. However, even with his long time experience he wasn’t able to fix the parts together. At first I got desperate and tried hard-soldering the Z-Motor-Mount. But even using two torches I wasnt able to get the part hot enough to accept the solder.

Z-Motor-Plate fixed with clamps ready to solder
Z-Motor-Plate fixed with clamps ready to solder

As a last resort I deceided to glue the parts. Fortunately my sister works as a postdoc and is an expert for aluminium epoxy bonds. She did some rought calculations for me and helped select the correct adhesive: 3M Scotch-Weld DP490.

I prepared the parts by grinding away all paint and about 100microns of the aluminium. The last step helps because cast aluminium has different properties on the outer layers compared to the inner bulk material due to the casting process. I also cut some reinforcement plates from 6061 Aluminium. Then I cleaned everything several times with water/soap and acetone. Everything was clamped down on a clean plate and glued together in two steps: First the two broken bits were fixed together. After curing the residual glue was removed by grinding, then the reinforcement plates were glued. To improve the curing process I put a box over it to trap the air inside and heated everyhing which a hot air gun to 80°C. Unfortunately I didnt take that many pictures of the process:

After that, I did some cosmetics. With a lot of car putty, grinding and even more putty and finally a red finish the part looked like this:

Fixed B-Arm with W-Motor already mounted
Fixed B-Arm with W-Motor already mounted

 

That concludes the B-Arm. Fixing the Z-Motor-Plate was basically the same. Here are some more pictures:

That concludes the repair. I will cover the mechanical and electrical rebuild in a seperate Blogpost.

Hirata AR-c270 Scara Robot Retrofit – Part1

Hirata Scara Robot
Hirata Scara Robot

Recently I bought a Scara-Robot from Ebay. Its an older model with an outdated control. Motors, servos and encoders are in working condition. Using the Teach-Pendant I can move the Robot around.

My plan is to retrofit the control using linuxcnc. All IO will be done with a MESA 7i77+5i25 combo. I will try to reuse everything besides the original control.

There was quite a lot of documentation included in the Ebay auction, but most of it only covers software. No hints on the pinouts of the servo amp. The company producing the robot still exists, so I gave them a phone-call to request additional docs. I bought the manuals they offered me, but unfortunately they didn’t help at all. So I had to take the thing apart and try to reverse engineer the important parts. My findings so far are all in this 20150422_doku_hac214a.

servo-amp
HPC-53IDI Servo Amplifier

There are some diagramms for the motor- and encoder connections. And yes, the encoders produce a nice A/B-Signal:

As a next step I will test on of the amps standalone. Hopefully the info extracted so far is okay. Running the amps in velocity mode will make it easy to connect everything to the 7I77.

Fix broken pins on QFP Package

That is how my new HW-0.30-mini Quadcopter Flightcontrol looked prior to the repair:

broken pins

Since a few of the Pads already were delaminated I decided to do a repair instead of soldering in a new CPU. For a repair I would need to get rid of the expoxy mold to directly acces the pins of the leadframe. Initially I was thinking of using a ‘dreml’ tool to remove the exoxy, but watching the Uncaging Microchips talk at 31C3 taught me that using a CO2-Laser will also work.

Those pictures were taken during the laser-removal:

 

After lasering, all left to do was attach new wires. I did use a microscope for that. For scale, the wire running on top of the CPU has a 0.3mm diameter.

I ran some quick tests with the software to make sure the repair worked. Then a blob of hotmelt was applied to secure and protect the repaired pins:

HW-0.30-mini fixed

 

Backstory: I am also responsible for breaking the pins. I did solder the CPU at 31C3 without proper lighting using borrowed equipment. The temperature on the soldering iron was set to 450°C, I failed to check that. This lead to some major fuckup. Since I wanted to work with the board, the decision was made to simply cut of the broken pins. At the time I didnt need them.

LinuxCNC Pendant

To make jogging easier (doing this with the keyboard sucks) I decided its time to build a remote pendant for my Mill. From ebay I ordered a Device with a MPG (Manual Pulse Generator) and two rotary switches. Its prebuild with a case and cable. Like most china-ware, there was no documentation. But I could open the case to check the wiring and cable-colors.

The USB-Interface is a BU0836A device. It allows 8 analog inputs (unused) and 12 switches.

To make the MPG work one needs to configure a pair of inputs of the BU0836 for quadrature encoder. Fortunately there is a config utility for linux. The acutual connection was done by soldering female headers to the open cable ends of the pendant (as seen in picture 1). The pinout is as following:

  • Encoder +5V -> +5V
  • Encoder GND -> GND
  • Encoder A -> SW5
  • Encoder B -> SW6
  • COMM -> GND
  • LED- > GND
  • LED+ -> +5V, with 470R in series
  • X1 -> SW4
  • X10 -> SW3
  • X100 -> SW2
  • AxisX -> SW12
  • AxisY -> SW11
  • AxisZ -> SW10
  • Axis4 -> SW9

The BU0836 PCB was build into a PVC for protection.

 

Not only the software-part ist left. To make it work in linuxcnc only a few lines of HAL code are required 🙂

Download it here: pendant.hal

Pizzaoven Reflow Soldering

Using a pizza oven for reflow soldering has already been done a million times by hackers/makers all over the world. You can even buy a ready made reflow controllers for such setups. Still, I will present my approach here since it is a little bit different from others I have seen so far.

Most setups use a relay to switch the heating element on/off. Some designs use a SSR and even have elaborate features like zero-crossing-detect. However, I didnt want to mess around with mains voltage. Thats why I decided to use a DMX512-Dimmer do control the heating element. When you think about it, its just another kind of lamp. So why not use a device made to control lamps?

The actual control is done with a Raspberry-Pi. I used a “max6667” Thermocouple amplifier from ebay which is interfaced via SPI. Fortunately there was enought sample code available on the net, I only had to do a litte copy&paste to get it running. I did modify the code to use the py-spidev library. My sourcecode is attached to this post. I also used python to run the PID-Temperature-Loop. Since that code is really ugly I wont publish it now  😀

Here is a picture of the complete Setup:

I did label some of the Items on the picture:

  1. Thermocouple
  2. max6667 board
  3. DMX Dimmerpack
  4. Raspberry Pi
  5. Temperature Monitor for Control/Debugging
  6. USB2DMX-Dongle

As mentioned above, a PID-Algorithm was used to control the temperature. The Profile is rather slow, but it does work. I might add insulation to the oven to allow faster heating.

Modified max6667-lib: max6667

Lasercut MyLittlePony CollectibleCardGame Action-Tokens

Recently I bought a 2-Player Starterdeck for the “My Litte Pony” CCG. One of the aspects of the game is managing you ActionsPoints.

The StarterBox did include some counters/tokens made from thin cartboard, but those are not easy to use. I also tried using dice to keep track of the actionpoints, but thats also not optimal.

Thats why I decided to create some tokens:

The material I used is Perspex (color-codes 2TL2 and 4TL1) in 3mm thickness.

 

The Design is based on My Little Pony Printable Cutie Marks which can be found on Thingiverse. I did some small modifications. The butterfly had some parts which were to small to lasercut; I enlarged those.

You can download the modified .eps files here: MLP.CCG.Tokens