Replacing the controls of the IKEA LÅNESPELARE Ringlight with WLED

Ikea does sell a reasonably nice Ringlight called ‘LÅNESPELARE’. It runs of 5V and has a USB-A-Plug for its supply. A simple controller is build into the cord. Unfortunately, it does not remember its last setting/power status after it has been unplugged. If I switch it off via my home-automation using a zigbee outlet, I always need to also switch it on using its own controller. That kinda defeats the whole idea.

Controller case opened

The case does not open that easy. I had to use some force, but managed to not break it. Perhaps the left domes have been welded, I heard a crack when I finally got it open.

Controller PCB

The original controller is pretty straightforward. It has a LDO (U1, “7136”, SOT-89 package) some kind of microcontoller (U2, SO-8 package), and two output transistors. One for Warmwhite and one for Coldwhite. The slikscreen reveals that those are low side switches. Seems like a simple PWM output.

So we can replace it with another PWM controller. I choose to use https://github.com/Aircoookie/WLED since it integrates nicely into home-assistant. Its also really easy to configure and use. It already comes with a mode for PWM Output for warm/cold-white LEDs. All I had to do is to upload the firmware using esptool.py, no coding required at all. On the hardware-side two N-Channel-FETs (BS170) in TO-92 were used as low-side-switches. Then everything was fitted into a plastic case using excessive amounts of hot glue.

ES8266 as new controller

The BS170 is not the best FET for this application. Its Threshold-Voltage does not work well with the 3.3V of the esp8266. But those were the only available at the time. Below it the chart from its datasheet, with the working point circled in red. Perhaps I should just use the transistors from the original controller board 🙂

BS170 output characteristics

Food delivery service webshops vulnerability

Earlier this year I started to look at food deliveries, more specifically fresh and local vegetables and fruits. There are quite a few companies that provide that service in Germany. Really nice.

I found a local one that delivers to my home. They offer a convenient web shop where I registered.

Vulnerability ‘research’

The weird part was the registration confirmation: they did set the initial password to my post-code. That immediately caught my attention. The user names are numeric and seem to be incrementing. That can’t be good. So I wrote a small piece of python code that just enumerates users and tries to login with post-codes from the area. And bingo, I got quite a few successful logins. I did verify one of them by looking at the user profile of the poor person that did not change their password. And yes, I could see personal data.

Since my goal was not to steal data I stopped there and did concentrate at the API again. I did some googling to see if there are similar shops. And yes, actually quite a few. They are all provided by oekobox-online.de. A quick check of a arbitrary other shop in another part of Germany proved that the same method of guessing the postcode and just enumerating the user-ids also worked to perform a successful login.

The API is actually well documented by the vendor:

API documentation

I personally think that a verbose API answer like in the table below adds to the problem. This allows the attacker to first figure out if a user-id is valid before starting to guess the password. Instead the API should just return success of fail, but now why it failed.

API documentation, return codes

The tblocked response was also not well implemented. First of all, it took quite a while for me to be blocked. And even if one is blocked, logins with the correct username/password combo still work.

Contacting the vendor

I did contact the vendor the same day (06.01.2021) and received an answer less than 24 after that. This seems to be one of the few cases where responsible disclosure actually works.

The communication was friendly even though we have quite different opinions about the actual issue. The vendor was already aware of it, but because customers like the easy workflow did not change it.

Nevertheless, a few weeks later (02.02.2021) I received a mail with promising news:

  • Affected customers have been informed
  • The rate-limit is now better enforced
  • Login via user-ID will be disabled soon. Only logon via email-address will be possible
  • Better passwords will be enforced step-by-step in the next weeks

To be honest, I did not check if all of that is actually properly implemented now. I am to lazy for that.

Diesel engine cooling-radiator ghetto repair

For this years EMF camp I was traveling together with the belgian embassy. We had two busses filled with people and material to drive from belgium to the campsite and back.

One of the busses had a blown tire on our way, that was fixed by fitting the spare:

Blown tire

On our return trip however, we had a major issue. The radiator was leaky, as seen in this picture. The water on the road used to be in the cooling system.

busWe did discuss how to fix it. One option was to just put an egg into the cooling liquid, in the hope that the protein would coagulate and stop the leak. But that is a process we can’t control, so we switched our focus to other methods.

Next up was soldering. We had lots of solder-equipment with us, after all we were coming form a hacker-camp. But soldering on a heat-sink is doomed to fail. Perhaps we could have done it with a propane torch, but we did not have one with us.

All that was left was to glue it. I had some 5-Minute-Epoxy at hand. First we drained the radiator and dried it with the hot-air. Then some cleaning using wire-brushes and isopropanol was done. The epoxy was mixed and stuffed into the radiator with tootpicks and other pointy objects, then heat-cured with the hotair for 30minutes.

This is how it looked after the curing:

radiatorIts messy and ugly, but it did seal the leak. I did expect that it would still leak a little, but to our surprise it was perfectly sealed. The cooling system was even able to build up pressure again.

With that repair we made it back over the canal back to belgium 🙂

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:

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.

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

Replace the battery of a Digital caliper with a supercap

I got the calipers off ebay (<10$) quite a while ago, but they kept draining the battery really fast. After i discovered this blogpost I decided to modify my calipers in a similar way.

Modified caliper with charging cable

The basic idea is the same:

  • replace the battery with a supercap
  • build a charging device

The only real difference compared to trevors project is the voltage used. I didnt have a 1.8V LDO around, so i decided to go with 3.3V.  An additional SI-Diode in the charging-path drops 0.7Volt, so the actual voltage for a charged cap is 2.6V which seems to be fine for the caliper (i did no long-time test yet). Also, with that diode one cant blow the cap by charging with reverse polarity.

I only used parts you can get from the german distributor Reichelt. The cap is a “SPK 1.0F”, the switch is called ‘T215″.

I did not much testing yet. But the cap kept enough power to work with the caliper even after 80 hours ‘standby’ 🙂