Hacking the Neutrogena visible light therapy system to get 99 lives

Here’s a thing. It illuminates you with blue and red light which is apparently effective. Possibly because light, especially high energy light causes phototoxicity. Anyway, the device consists of a mask full of LEDs and an “activator” which is a power supply which gives 30 uses before you have to replace it.

They’re clearly going for a printer ink model and the activator is £14 or so which is aimed at the expensive-but-not-outrageously-painful price point. The thing is though it’s extremely wasteful because the batteries are still good1 as is the hardware. Its just burning stuff to make money which is kind of objectionable, so we must deal with it. Or hack it.

By the way after this point I was using the post to make notes as I went along so it’s a bit stream of consciousness.

Day 1

(note these aren’t full days)

OK, first some disassembly pictures:

IMG_20171231_152434

The device

 

 

 

 

 

 

 

 

 

IMG_20171231_152458(1)

The battery cover removed

IMG_20171231_152612

The back cover removed

IMG_20171231_152832

The bare board

So far, so good.

The design for manufacture is pretty good: excluding screws there are 5 parts and they slot together with minimal effort. The plastic parts are decently moulded and aimed at a low price point. The draft angles are large and those holes at either end of the battery compartment where the springs are have highly drafted sliding shutoffs.  The board is pretty interesting. It’s a single sided soldering process with a mixture of connection types. There’s SMD for the small stuff and a number of THM parts as well. Note that the THM hasn’t been wave soldered since the gold test pads are not tinned. The joints look very uniform so it’s either top notch hand soldering or a selective soldering machine. Here’s a cool video:


I have nothing to do with that company, but they had a nice video on the technique.

Anyway, the mix is quite unusual because of the extra cost except it allows them several things. Firstly, they can use a stock THM 3.5mm 4 way barrel plug. You can’t see this from the photos, but it’s obvious from the plug. Second, they can use some very cheap battery connectors which are simply bent pieces of spring.

Also note the 100uF electrolytic capacitor. Fujicon is one of the very cheap brands, and given they’ve already got a THM stage, this means they can use the cheapest of the cheap caps. Its hard to find Fujicon retailers, the first one I found sells these caps for 1.195¢ a pop (they blinged it up and went for the pricey 105C one, not the 85C 1.111¢ one). The cheapest 100uF 16V electrolytics on Digikey are 4 cents a pop.

Also, with the cut out they can fit the cap in a very low profile and hey that’s weird, there’s a track going right into the middle of the snapped off tab.

weird

The LCD is connected with your common or garden zebra strip. The final bit is the metal diaphragm switch. This has two lugs which go through the board and are bent in place on the back side, no soldering required:

cheap

There appears to be some hand finishing on the back where the crystal is anchored in place with solder:

hand

Now for the components. The 3 terminal THM device has code SS8050 and is a Fairchild NPN transistor rated for 1.5A/2W. Graphs indicate that at 1A with a 100mA base drive, wed expect Vce sat to be about 50mV, giving a equivalent resistance of 50mOhm. This is not that bad since the base drive voltage would be about 0.8V. They’re cheap (0.47¢ from Mouser). Maybe a little inefficient but the LED power draw is high and you only get 30 uses out of the 4 AA batteries, so that’s not a concern.

Before I get to tracing with a multimeter, here’s a rough trace of the board:

IMG_20171231_161225

At a first glance it looks like the transistor and switch both feed into the little COB blob meaning that’s probably the microcontroller as well as the LCD driver. I’m not sure what the ATMLH640 chip is. My guess is it’s an EEPROM to store the number of remaining uses. Perhaps the super cheap COB chip doesn’t have one because that would require a different process. Web searches don’t reveal anything especially informative.

My guess is the SOT23ish part labeled 7533 is some sort of 3.3V LDO linear regulator. It connects to the main power after the big cap and before the largish ceramic. Also, look at the power: it won’t be connected unless something’s plugged into the jack, since the battery goes into the jack only.

So, what about that small chip, eh?

After a little tracing, here’s the layout:

eprom

and it’s connected to the μC via 1k resistors. Interestingly so is the transistor. In that region, the base drop is about 0.6, giving a base current of 2.7mA. That would give a collector current in the region of 0.4 to 0.45A, I reckon. Since there appears to be no other mechanism, I think this may be the current limiting for the LEDs. Note that the datasheet says it’s designed for class B audio amplification so it’s built to run in the active region dissipating power.

Here’s the result of the first bit of tracing with a continuity meter on the socket and using a 4 pin plug I got from Maplin:

plug.jpg

Two of the 5 pins connect to one conductor and get bridged only when the plug is in. This appears to be used to connect the battery to the main power, meaning this thing won’t drain any power when the mask isn’t connected. Two(!) of the 4 conductors are unused, so this thing only has power in and power out (no ground) with current limiting on the board. Kinda wonder why they used a weird 4 conductor plug. Maybe obfuscation?

Looking further there’s a B, C and D type transistor. Mine has an isolated D on it as well as a 331. I guess it’s the D type, which has hFE in the range 160 to 300. Kind of a high range for anything approaching reasonable current limiting, but perhaps the actual range is somewhat narrower in practice.

But this is good and implies that there is no DRM in the mask, since there’s no way to communicate from the mask to the uC. Hopefully a simple current supply will do the job, but how much? (more later).

Back to the enigmatic SOIC. A friend on IRC put me on to http://www.smdmark.com. The ATML mark corresponds to Atmel (I guessed that), but ATMLH only matches a few EEPROMS. None of them match the code exactly, but the AT93Cxx series have the correct (unusual) pin layout, or at least a vague match. I can’t find the exact match for the code, so it’s off to the logic analyser to see if the bus is correct.

First some bodgewires and some hot glue to stop them falling off. To get it clean, put a little chip of cold glue in the right place the heat gently to 150 degrees C with an air gun. It’s much cleaner than trying to blob on hot glue:

Now to partially reassemble, but where the heck is the LCD???? Ah buried behind the brass tip cleaner. Anyway they have very kindly provided a very neat hole for precisely this kind of thing:

IMG_20171231_184558

Given my ordering (1234->GBRW) I hypothesise from the datasheet that:

  1. Green = CS
  2. Blue = SK
  3. Red = DI (that’s MOSI: master out slave in)
  4. White= DO (that’s MISO: master in slave out)

Personally I prefer the MOSI/MISO naming since it’s unambiguous. Now, time for the scope! How do you get the blasted thing to trigger? How how how how?? Oh has to be logic triggering and pod input. Apparently selecting pod input and edge triggering isn’t enough. Okey dokey. Here’s the first shot, and of a packet that doesn’t return all zeros:

SCR02

I think my hypothesis is confirmed! Note how CS goes high then the clock starts. DI is set in advance of the pulses and DO changes on the clock edge. Though it seems glitchy. Look at those weird spikes on the data lines.

Day turns into night and back again.

Day 2

Huh is the clock really that non uniform or am I reaching the resolution limit given the very long capture window?

So now there’s two choices. I can attack the mask itself and measure the current. Once I know that it’d be easy to build a different driver that provides that current for a fixed time. The other choice is to attack the EEPROM and see if I can figure out what’s going on and reset the counter. I hope the program isn’t stored there, just the data!

Hm well OK! Based on the wiring I can drive it with a current limited source just fine and it appears to work perfectly. That was easy!

So yeah how the heck does the bus decoding work??? I’ve got it to work before. Also the DO pin gives bad noise without a 100k pull down. Nothing in the datasheet about that but it’s not the right datasheet anyway so there’s that! Ho hum got one half working…

So the EEPROM only receives 10 commands so it’s not storing the program for the uC, which is nice. According to the maybe wrong datasheet the commands are:

  1. Write enable
  2. Read 0x60
  3. Read 0x64
  4. Write disable
  5. Write enable
  6. Read 0x55
  7. Write disable
  8. Write enable
  9. Read 0x50
  10. Write disable

Well that’s a bit strange but not exactly out of the ordinary for embedded devices!  Anyway fine WHATEVER I’ll decode it by hand. Only a few reads. Here it is along with MISO decoded by the scope and my notes on what it means from a “close” datasheet:

IMG_20180101_212753

Right well commands (names like EWEN, EWDS are from the datasheet) are 10 bits and reads should be 8 but it clocks 9. A bug? But that means the value at register 0x50 is 1, and this device just happens to have one use left in it. Coincidence? Time to use up the last use, measure the current as best we can and see what changes in the ROM. I just measured my multimeter (90’s era White Gold WG020) as having 66mV burden at 5A. Which is fine. Except then I realised my PSU also measures current and the LEDs will be the  bulk of the draw.

Well it draws 400 mA aaaand it’s down to 0 uses left. Oh hey!! 400mA is exactly what I figured from the datasheet!! whoooo! Oh the hFE thing is small signal gain anyway. The large signal stuff seems pretty well characterized. It’s actually a pretty impressively cheap way of regulating current. The regulator is probably plus minus a few percent, the base resistor, 1%. Being transistor designed for class B audio it’s probably decently narrow in spec so it matches well with it’s complementary PNP (SS8550). Huh. I’m impressed. It’ll probably regulate current to within 10% no problem which is good enough for a non critical task like this. When the battery level gets low the power will drop and there’s no warning but it’s only meant to work for 30 uses so that’s not an issue. A very cheap solution to the problem!

Anyway, looking at the bus now it’s got 0 uses left, at a first glance, both 0x55 and 0x50 have counted down by 1. Not sure what to make of that. The other two numbers don’t change at all.

The AT93C46 datasheet seems close enough. The next step is to try to write to it using my Arduino to reset those registers back to the previous values. Going to have to be a bitbang because of (a) the rather odd bit count and (b) because the D0 pin is not data but an asynchronous write/erase finished signal. OK that explains why the clocking is so messy: it’s bitbanged.

Day 3

OK, here’s the Arduino sketch:

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
static const int led = 13;

static const int CS = 4;
static const int CK = 5;
static const int mMOSI = 6;
static const int mMISO = 7;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(CS, OUTPUT);
  pinMode(CK, OUTPUT);
  pinMode(mMOSI, OUTPUT);
  pinMode(mMISO, INPUT);
  Serial.begin(9600);
}

//Write out the N low order bits of data as MSB first
//and return the collected data.
uint32_t write_N_MSB_first(uint32_t data, int n)
{
  uint32_t ret = 0;

  //First shift everything to the 16th bit
  data <<= (32-n);
  digitalWrite(mMOSI, LOW); //Make the scope trace look nice
  delay(1);

  for(int i=0; i < n; i++)
  {
    digitalWrite(mMOSI, (bool)(data& (uint32_t(1)<<31)));
    delay(1);
    digitalWrite(CK, HIGH);
    delay(1);
    digitalWrite(CK, LOW);
    delay(1);
    int r = digitalRead(mMISO);
    ret <<=1;
    ret |= r;
    data<<=1;
  }
  digitalWrite(mMOSI, LOW); //Make the scope trace look nice
  return ret;
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(100);               // wait for a second

  digitalWrite(CS,1);
  write_N_MSB_first(0x360, 10);
  int v = write_N_MSB_first(0, 8);
  Serial.write("val =0x");
  Serial.print(v, HEX);
  Serial.write("\n");

  digitalWrite(CS, 0);

}

It’s a straightforward bitbang, except you can read/write in variable length chunks, and it prints the read value to the serial port. It looks fine on the scope (the bus decoding works today!) so the next step is to wire it into the device.

The device is a 3.3V one and the Arduino is 5V so we need to shift the levels down. The easiest way is to make a potential divider using an LED and 1k resistor. The LED will drop more than a normal diode: the scope tells me it’s dripped about 2V. We don’t need to level shift the input since the EEPROM gives a nice clean 3.3V and that’s easily enough for the Arduino to register high.  All we need to do is bodge it in (I reckon those 1k resistors on the device will protect things) after switching the device on, so the bus is not busy…

img_20180102_135950.jpg

And it WORKS!!! Here’s the scope screenie:

SCR12

And the Arduino is printing out a steady stream of 0x95, which is the correct value: we got that from earlier analysis. This also confirms that they are writing utterly unnecessary write-enable, write-disable commands and they are clocking in an extra bit at the end too.

I did initially OR both channels together using some diodes so one bus would decode read and write. That of course doesn’t work: for MOSI, the data should be read on the rising edge of the clock, but with MISO, it’s set after the rising edge, and won’t be changed until the next bit-after-rising-edge. It’s safe to read on the falling edge of the clock, so I set up the other decoder to do that.

OK, so now to try a write. Here’s the code:

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
static const int led = 13;

static const int CS = 4;
static const int CK = 5;
static const int mMOSI = 6;
static const int mMISO = 7;

static const int BUTTON = 2;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(CS, OUTPUT);
  pinMode(CK, OUTPUT);
  pinMode(mMOSI, OUTPUT);
  pinMode(mMISO, INPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.write("Booted...\n");
}

//Write out the N low order bits of data as MSB first
//and return the collected data.
uint32_t write_N_MSB_first(uint32_t data, int n)
{
  uint32_t ret = 0;

  //First shift everything to the 16th bit
  data <<= (32-n);
  digitalWrite(mMOSI, LOW); //Make the scope trace look nice
  delay(1);

  for(int i=0; i < n; i++)
  {
    digitalWrite(mMOSI, (bool)(data& (uint32_t(1)<<31)));
    delay(1);
    digitalWrite(CK, HIGH);
    delay(1);
    digitalWrite(CK, LOW);
    delay(1);
    int r = digitalRead(mMISO);
    ret <<=1;
    ret |= r;
    data<<=1;
  }
  digitalWrite(mMOSI, LOW); //Make the scope trace look nice
  return ret;
}

void ewen()
{
  digitalWrite(CS,1);
  write_N_MSB_first(0x260, 10);
  digitalWrite(CS,0);
  delay(1);
}

void ewds()
{
  digitalWrite(CS,1);
  write_N_MSB_first(0x200, 10);
  digitalWrite(CS,0);
  delay(1);
}

uint8_t read(uint8_t addr)
{
  digitalWrite(CS,1);
  write_N_MSB_first(0x300 | (addr&0x7f), 10);
  int v = write_N_MSB_first(0, 8);
  digitalWrite(CS, 0);
  delay(1);
  return v;
}

void write(uint8_t addr, uint8_t val)
{
  digitalWrite(CS,1);
  write_N_MSB_first(0x280 | (addr&0x7f), 10);
  write_N_MSB_first(val, 8);
  digitalWrite(CS,0);
  delay(1);
  digitalWrite(CS,1);
  while(digitalRead(mMISO) == 0)
  {
  } //Wait for the status to come up
  digitalWrite(CS,0);
  delay(1);
}

// the loop routine runs over and over again forever:
void loop() {
  if(!digitalRead(BUTTON))
  {
    delay(200);
    Serial.write("Sequence begin\n");
    while(!digitalRead(BUTTON))
    {}

    int v1 = read(0x55);
    int v2 = read(0x50);
    ewen();
    write(0x55, 2);
    write(0x50, 1);
    ewds();

    int v3 = read(0x55);
    int v4 = read(0x50);

    Serial.write("0x55, 0x50 :=  0x");
    Serial.print(v1, HEX);
    Serial.write(" 0x");
    Serial.print(v2, HEX);
    Serial.write("\n");

    Serial.write("new 0x55, 0x50 :=  0x");
    Serial.print(v3, HEX);
    Serial.write(" 0x");
    Serial.print(v4, HEX);
    Serial.write("\n");
  }
  else
  {
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(100);               // wait for a second
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(100);               // wait for a second
  }

}

So I’ve also added a switch too (one of those incredibly bouncy microswitches): it’s connected to ground, and the input pin is set to pullup. When the Arduino detects a zero (a press), it waits 200ms, then waits until the switch is released before starting the write sequence. That way I have plenty of time to set up the scope and triggering etc.

Oddly enough it doesn’t work if you send the wrong instruction for EWEN (write enable). Who knew?

Huh, OK so I successfully wrote (I discovered this after), but my state machine didn’t work for reason that the write finished signal never happens. OK. Maybe I’ll just try waiting 15ms (wrong datasheet says 10 max…). Now it’s in an inconsistent state because it blocked after one attempted write. So the new write function is simply:

void write(uint8_t addr, uint8_t val)
{
  digitalWrite(CS,1);
  write_N_MSB_first(0x280 | (addr&0x7f), 10);
  write_N_MSB_first(val, 8);
  digitalWrite(CS,0);
  delay(15);
}

And the output of the serial monitor is:

Booted...
Sequence begin
0x55, 0x50 :=  0x1 0x0
new 0x55, 0x50 :=  0x2 0x1

That’s promising. Now to disconnect the Arduino and reboot the device…

IMG_20180102_180251

YESSSS!!!! I WIN!!!!

Q96tJbBN

Yes, I tried using using it, and the LEDs all come on and it goes back down to 0. And I can reset it to 1 again and so on and so forth.

The next step is to get infinite, or at least many lives. I’ll probably try setting it to something intermediate first like 15, then 99, then 255. I wonder if it will work with more than 2 digits or if it will crash. Also, I should probably check what voltage is required to push 400mA through the LEDs: when it’s not limited to 30 uses the batteries will get used up and it would be good to know if it’ll cut out or slowly go dim.

Day 4

Huh OK, 400mA requires 5.43V.  According to these guys https://www.powerstream.com/AA-tests.htm at a 500mA discharge or under AA cells deadify at  about 1V. At 1V, we’d have a about 4V total which I measure as about 225mA through the mask, so the power is about halved. After that it will drop off very quickly. That link also says a decent battery will get 2Ah ish. The average discharge is very roughly 360mA over that range. That would give about 2000/360 * 60 = 331 minutes of use. Oh LOL!!! The mask lasts for 10 minutes a time so at that rating, the batteries will last about 33 uses or just over the number it claims to give you.

That means the regulation isn’t as good as I  thought before, or more to the point the low voltage condition bites almost instantly. The regulation will decently accurately stop the current from being very high when the battery is fresh but will do little after that.

That’s pretty funny. I’ll bet they chose the power levels based on AA batteries. Well, according to Powerstream above, the expensive batteries pull ahead at a 500mA discharge but are on a par with the cheaper ones at 100mA. So, I can replace the batteries for a grand total of 60p from Maplin, a lot cheaper than £15. It came with “Excell” brand batteries which you can only get with a minimum order of 2000 from Alibaba.

IMG_20180103_223007

Quality.

I wonder what they cost: no price for these but AA prices seem to vary from 1¢ to 10¢ on Alibaba for bulk buys. Even reputable brands (Panasonic) are only 11p in quantity from Digikey.

So on to 99-UP. Actually come to think of it…

If I was an engineer working on a product (ahem) and there was some spare ROM space, I might be tempted to leave an Easter Egg in there. So let’s do a ROM dump and see. So, all I’m doing is modding the code to simply read 127 bytes from the EEPROM.

Then I got a bunch of:

avrdude: stk500_getsync(): not in sync: resp=0x??

errors. There was a lot of cargo culting on Stack Overflow. the correct answer (not there) was that I accidentally changed the board type setting. Check the github page for the source for the ROM dumper if you’re interested. Its just a combo of read(), sprintf and serial write. And the ROM contents is:

0x00: ff aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x10: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x20: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x30: aa ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x50: 01 ff ff ff ff 02 ff ff ff ff ff ff ff ff ff ff
0x60: 95 ff ff ff 34 ff ff ff ff ff ff ff ff ff ff ff
0x70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Well, that’s dull 😦 Oh well.

So, OK, on to infinilives. I still don’t know the significance of 0201 going to 0100. I’m going to try 0209 to see if we get 9 lives. Tried it and now it reads 0 lives. How odd. Let’s try n+1, then, so 0302 and 2n next. So, n+1 first.

img_20180103_205335.jpg

Yep! That works!

OK, what about, let’s say, 99, because that’s clearly the most the display can handle. I’d also hypothesise that going higher might go funny, if they do decimal conversion by say %10 and /10, then looking up the segment results in an array. By the way the device won’t boot when the programmer is plugged in, displaying “–” instead of a number. So it’s checking the results of those initial reads and won’t work if they’re corrupted. I just discovered that I only need disconnect the MISO line, rather than everything. This makes experimenting much faster. Right, so, 100,99:

img_20180103_210014.jpg

you… uh… huh. huh. HUH.

222xv1

well well. Looks like they have a straight up lookup table. Maybe because it’s a multiplexed LCD? It doesn’t have enough wires for a static one (8 wires for 14 segments). Anyway, looks like they’re checking bounds which is nice. I’ll bet if I do a ROM dump, I’ll see the 100,99 in there.

0x00: ff aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x10: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x20: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x30: aa ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x50: 63 ff ff ff ff 64 ff ff ff ff ff ff ff ff ff ff
0x60: 95 ff ff ff 34 ff ff ff ff ff ff ff ff ff ff ff
0x70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

No. Well that’s even more unexpected. First lets’s see what happens with 0,255 and 255,254. The plot thickens!! Oh no, stuuuppppiiidddd! 64,63 in hex is 100,99 in decimal, so hasn’t rewritten the values.

If I upload 0,255 then when I reboot it, I get back to the original 30 uses. Even stranger is the ROM dump:

0x00: ff aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x10: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x20: aa aa aa aa aa aa aa aa aa aa ff ff ff ff ff ff
0x30: aa ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x50: ff ff ff ff ff 31 ff ff ff ff ff ff ff ff ff ff
0x60: 95 ff ff ff 34 ff ff ff ff ff ff ff ff ff ff ff
0x70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

but after one use, it goes to the expected:

0x50: 29 ff ff ff ff 30 ff ff ff ff ff ff ff ff ff ff

Curious. OK, so what about 255,254? Now we have blank-blank. Disappointing? Well, I tried activating it and it comes on! And the ROM indicates that it’s counted down.So OK, that works. Back to loading up 100,99. It displays 63. If I use it, it counts down to 62?? WTF? The ROM dump indicates it’s still 0x63,0x62. One more use and it displays 61. Then 60. Now it should get interesting… Oh wait I just noticed above, it’s got 0x29, 0x30. The little devil is counting in BCD!!! So, now it’s diplaying 59 and the ROM dump is:

0x50: 59 ff ff ff ff 60 ff ff ff ff ff ff ff ff ff ff

Confirmed! Gosh, I’ve not seen BCD in so long! Let’s try uploading 0x100 0x99. And my hypothesis about the 63 element LUT is clearly wrong. Oh huh 0x100, 0x99 gives 0 on the display.

WLPjJ2i

Yes, 0x100 is 2 bytes, so it would only load up the first 00 which is of course not valid for this setup. Right moving on, I’ll bet its BCD is a bit dodgy, because it happily counted down from 255,255. Maybe 0x9a99 will work.

img_20180103_214858.jpg

H4X SUCCESSFUL!

YOU'RE_WINNER_trophy

So I wonder…

CONFIRMED! So if you upload 0xfaf9, then it displays blank-9. Because it can’t decode f. OK, so I’ll bet if I load it up with 0xf1f0, it will count down to 0xf0e9 and display blank-9. And sure enough it does. That means the maximum number of uses is the first 99, then the 10s for a9 b9 c9 d9 e9 giving 159 and the remaining 15 giving 174.

But I think I’ll leave it at 99 because it looks cooler.

😎

PS if you’re interested here’s the code

 

 1NOT!!! Actually it uses up most of the batteries, but the hardware is fine

Advertisements

A simple light chasing robot

I’ve been meaning to try this idea for a simple direction finding car for ages. The idea is you place down a light source (i.e. a torch) and the car will head towards it. This was going to make the core of a practical but that wasn’t to be, so it’s been on the back burner for a while. It’s not only simple but very cheap, so I didn’t want to spend a lot on it.

The impetus came when someone released some sort of Arduino car the result of which is you can now get wheel/gearbox/motor assemblies on EBay for 99p if you’re prepared to wait for a boat from China (£1.50 if you’re impatient). That allowed me to make tis for a very very low budget.

Before I continue, I do realise this would have needed fewer components and been more flexible with a microcontroller. I prefer playing with not-computers on the weekend and I also like the appeal of the “no magic” aspect of it. Even an 8 pin uC like an ATtiny or a PIC12F675 would have been more expensive.

Anyway, the first part is to make a directional light sensor. I made this from an LDR (10p in a bag of 20), black card, tape and glue. They look like this:

sensors

And here’s how I made them:

  1. Make a tube of black card and tape it up.
  2. Push an LDR into it so the back of the LDR is about 5mm in.
  3. Fill up the hole at the back with grains of hotmelt glue.
  4. Heat gently with a heat gun (100C) to melt the glue.
  5. Repeat 2-4 until it’s full.
  6. While the glue is molten, gently wiggle the LDR to spread the glue.
  7. Tape over the back with opaque electrical tape to prevent light ingress

They’re pretty directional by my reckoning. It’s hard to get a good measurement of sensitivity because I don’t have an infinite point light source and by the time the resistance gets to 200k, even small stray reflections can have a quite large effect. Even so, here’s some hacky measurements:

a

On order to tell which direction a light source is, you need to have two pointing in different directions and compare their level. The light is on the side which has lowest resistance. To make a direction finding car, you need to turn towards the side with the lowest resistance. Since I have motorised wheels, this is a question of running one motor or the other.

Then of course, you need to build it into a car:

Note how the two sensors are pointing outwards in different directions. There’s also a castor at the back. The body is just a bit of scrap pine, and the motors are screwed to it with some M3 studding. It also turns out the tyres are a bit slippery and the motors spin up fast with plenty of torque, so the first version just sat and span the wheels going nowhere. I velcro’d the battery to the front to get more traction. It’s tricky to get velcro to stick to end grain stronger than it sticks to itself, about the only thing I’ve found reliable is gorilla glue.

Plus this is the first and only time I’ve used the sticky pad on the bottom of a breadboard.

The circuit diagram is very simple:

IMG_20171210_191625

Total cost about 90p (not including batteries).

The two LDRs form a divider and the midpoint is compared to a reference with a comparatorvery cheap opamp. The op-amp switches on one motor using a massively overspecced MOSFET. The other is connected via an ad-oc not gate, so either one motor is on or the other is. I could have used the other half of the dual op-amp for the inverter, but I have future plans for that.

As long as you get the LDRs and motors the right way round, it will always turn towards a strong light source. Here’s a video of it in operation!

There’s an LED torch down at the far end of the hall and the car heads right towards it. The wild swinging backwards and forwards is because it can only have one motor on at once and because there’s a fair amount of momentum and slip. So it spins one wheel cranks up to speed, and passes the midpoint. The other wheel comes on, but it keeps on swinging until eventually the other wheel bites at which point it’s way over. So it has a long way to come back by which time it’s got plenty of speed by the time it crosses the mid point and so on…

Works pretty well for sucg a simple version 1 🙂

 

Die grinder woz ‘ere

In the world of heavy automation and mass production it’s sometimes easy to forget that there’s a person around at every stage. But sometimes a nice little reminder finds its way through. A while back I bought a Raspberry Pi universal power supply. It’s universal in that it comes with a selection of mains prongs which clip on.

There’s a disposable plastic cover for the area in which they clip on, and on the inside of the cover, some person wrote the initials “bc” by hand with a die grinder, between the ejector pin holes:

bc_woz_ere

It’s probably a little messy because it’s hard to write with a die grinder and they had to mirror-write it so it looked right after moulding.

Blog as you go: sigma delta DAC

I have some piezo speakers from another project. That one used a bi-level amp to drive them. I figured it would  be fun to try a tri-level drive, using an H bridge allows you to have +, – and 0V across the device. And for fun, why not make it a direct sigma delta encoder?

It’s going to run on a microcontroller (an arduino). It’ll need very precise timings, so I’ll not be using the arduino environment.

Here’s a first pass in C++ for linux:


#include <iostream>
#include <cmath>
#include <utility>

using namespace std;

float signal(int t)
{
	//Roughly 0-1
	return (1 + sin(t/20. - 1))/2.1;
}

float quantize(float f, int levels)
{
	return min(levels-1.f, max(0.f, floor(f*levels)))/(levels-1);
}

int main()
{

	float integral = 0;

	for(int i=0; i < 200; i++)
	{
		float output = quantize(integral, 3);
		float difference = signal(i) - output;
		integral += difference;

		cout << signal(i) << " " << output << endl;
	}

}

And this produces output like this (mildly prettified):
graph.png

Which looks about right. The code will pretty much stink on an arduino since it’s all floating point. It’s easy to convert to integer code though:

#include <iostream>
#include <cmath>
#include <utility>

using namespace std;

uint16_t signal(int t)
{
	//Roughly 0-1
	return 65535 * (1 + sin(t/20. - 1))/2.1;
}

uint16_t quantize(int32_t i)
{
	if(i < 21845)
		return 0;
	else if (i < 43690)
		return 32768;
	else
		return 65535;
}

int main()
{

	int32_t integral = 0;

	for(int i=0; i < 200; i++)
	{
		uint16_t output = quantize(integral);
		float difference = signal(i) - output;
		integral += difference;

		cout << signal(i) << " " << integral << " " << output << endl;
	}

}

I’ve used a uint16_t for the value, which will effectively represent both positive and negative levels with 32768 being the zero point. Note that the error integral must be both signed and wider since the errors can grow beyond the signal range:

graph.png

Now to port to the arduino. So, I’ll get my Makefile from here.

I’m going to pick pins 8 and 9 on the UNO, that is PB0,1 on the chip for my outputs. and here’s how you get 3 way opposed outputs as +/-/0. To demo, I connected a pair of LEDs in parallel but facing the other way:


#include <avr/io.h>
#include <util/delay.h>
int main()
{
	int i=0;

    while(1)
    {
		if(i==0)
		{
			DDRB = 3;
			PORTB = 1;
		}
		else if(i==1)
		{

			DDRB = 3;
			PORTB = 2;
		}
		else
		{
			DDRB=0;
			PORTB = 0;
		}

		i++;
		if(i > 2)
			i=0;

        _delay_ms(200);
    }
}

So I started the port and BOOM! 😦

It stopped working. The reason was simple: the simple makefile takes one object file and converts it to HEX. Since I’m using sin(), we actually need to link the .o and .a into a .elf file, then convert THAT to HEX. The snippet is:

%.hex: %.elf
avr-objcopy -j .text -j .data -O ihex $< $@

prog.elf: delta_sigma.o
avr-gcc $(FLAGS) -o prog.elf delta_sigma.o -lm

Obvious, really, in hindsight…

So, OK, now to convert the modulator code to the arduino. Lots of things went wrong. But first, here’s the code:

#include <math.h>
#include <stdint.h>
#include <avr/io.h>

uint16_t signal(int32_t t)
{
	float u = t / 1024.f;

	//Roughly 0-1
	return 65535 * (1 + sin(2*3.151592f*u))/2.1;

}

uint16_t quantize(int32_t i)
{
	if(i < 21845)
		return 0;
	else if (i < 43690)
		return 32768;
	else
		return 65535;
}

int main()
{

	int32_t integral = 0;

	DDRB|=32;

	for(uint32_t i=0; ; i++)
	{
		uint16_t output = quantize(integral);
		int32_t difference = (int32_t)signal(i) - output;
		integral += difference;

		if(output == 0)
		{
			DDRB=255;
			PORTB=1; //Output 1 0
		}
		else if(output == 65535)
		{
			DDRB =255;
			PORTB=2; //Output 0 1
		}
		else
		{
			DDRB=255;
			PORTB=0; //Output 0 0
		}
	}
}

What didn’t go wrong? Nothing! I wasn’t nearly careful enough with my ints (only 16 bits on AVR), ints of specific width, overflow and that sort of thing. Also, initially, I decided to output a 0 level by tri-stating the two outputs, so they both float to the middleish. Turns out that didn’t work well since they float extremely slowly (not surprising really!). Forcing them both down to 0 worked much better.

After all that, I then connected a simple RC filter across it so you an see the results:

That’s actually a pretty nice sine wave there! It ought to be: there’s really not much room for nonlinearity and other distortions to creep in. I’ve zoomed in a few levels so you can see how it looks in detail.

It is however really really slow. I’m using full floating point, and a transcendental operation every iteration of the sigma delta encoder. That is really slowing down the cycle time since the AVR isn’t very fast. That accidentally solves the other problem which I’ve made no attempt to make sure every path takes the same number of cycles. But that sin() is dominating so heavily that it doesn’t matter.

And that’s it for part 1: a working sigma delta encoder. For part 2, I’ll make it fast enough to generate audio tones which aren’t simply the sigma-delta encoder transitions (I hope).

Oh also here’s tehe obligatory github link.

 

How bad is switch bouncing really?

TL;DR: it’s worse.

ETA: I think every electronic engineer goes through this at one time or another. You have a switch that bounces, so you debounce it. I mean every knows that switches bounce. The code doesn’t work 100%, so you fix all the bugs and it still doesn’t work. So then you break out the scope and hells bells! How can it be that bad?! I mean everyone says it’s bad and you knew it was bad but it’s BAAAAAAD.

So, I recently had a switch which needed debouncing. It happens to be a Marquardt (seems to be a good brand) microswitch. In terms of current it’s massively overspecced (16A, 250V), but it turned out to be ideal for the combination of size, button stroke, force and of course price. I guess that sort of switch is used for mains interlocks or something, but I’m using it to switch a GPIO input to a raspberry pi.

Here’s how it’s connected up:

IMG_20170504_184225.jpg

I’d like to say I connected it to both power rails to show how the different contacts bounce. Actually my brain disconnected and that’s how I originally connected up the switch in my project. It’s a terrible idea because you get bouncing from both sets of contacts for twice the fun. The potential divider pulls the middle up to half the voltage so you can see which contacts are bouncing and when.

On the plus side, it’s great for illustrating bouncing…

Here’s what the setup looks like:

IMG_20170504_185448

I use the mini vice (which I’m quite unreasonably proud of) to close the switch really, really slowly. And this is what pushing the switch looks like:

SCR01

(Note: I can’t figure out how to take a screenie without the annoying “take a screenshot” dialog showing…)

It’s quite amazing. Note the “pre-bounce” where a disconnect happens 225ms before the switching starts. In fairness, I couldn’t reliably reproduce that, but it does happen occasionally. Thar main transition looks suspicious though:

SCR02

That’s semi-horrid. The 0V contact opening is pretty clean. It then takes about 9ms for the + contact to start closing. It bounces all over the place, and even after the main bounce has stopped, it still takes 4ms for the voltage to stabilise. I guess connecting only 0V and a pullup would work much better. And here’s the bounces in detail:

SCR03

Horrible, but par for the course. You can see it’s not settling cleanly on the contact in between the bounces. And here’s a different one for comparison (RTFM n00b, the fine manual says how to sake screenies properly):

SCR05

This is bad in a rich and interesting variety of different ways. Like the vast majority of traces, there’s no awful pre-bounce. However, the disconnect is unclean and takes 10ms before it starts to rise properly. After the bouncing nominally finishes, it still takes a whopping 100ms to really settle.

Amazing!

Here’s some samples to fill you with horror as well as a couple of fairly standard ones. Some of them have a longer timebase to show a 200ms settling time.

Some of them have some really weird behaviour as they open. I haven’t figured why and the speed at which I actuate the switch doesn’t seem to affect things much. The same can’t be said for releasing the switch. The slower you release it, the gungier it is. See the enormous 100ms timebase:

yuck yuck yuck 😦 Faster actuation (and the actual bouncing) looks much as you’d expect:

SCR04

though, the time between the break and make is rather shorter.

Either way, the +V contact (the one connected by closing the switch) seems surprisingly much worse than the 0V one. We can of avoid that contact by connecting the switch as a single throw one with a pullup:

IMG_20170504_193440.jpg

And if I’m quick, I can manage to get an open and close on the screen with a 10ms timebase:

SCR05

The push still has some pre-bounce, but it’s nothing like as bad as from the other contact. For the switch being pushed, there is on bounce whatsoever; it’s astonishingly fast:

SCR06

for the release, there’s a bit of bouncing as expected.

Conclusion: don’t connect up switches in a silly way like I did!

Can it be true? That I hold here in my mortal hands, a splat of purest crud?

Today, a semi-successful experiment. I tried to make a small arc furnace using an arc welder, a graphite crucible and some inanimate carbon gouging rods. The goal was to melt aluminium successfully enough to do some casting. The idea behind using the arc welder is that it’s accessible and doesn’t require faffing around with fire, and getting the consumables brought in (gas, for example). The whole thing ought to be less messy and quicker to set up and tear down.

The furnace consists of a solid, 4kg sized graphite crucible (remarkably inexpensive) sitting in a badly welded, but very stable steel holder steel holder:

img_20170118_203057

An arc furnace. The white stuff on the inside is alumina fumes which settled on the side.

The idea was to strike an arc with the crucible and a copper clad carbon rod (a gouging electrode). It kinda worked, but the arc was pretty unreliable and surprisingly weedy even on the highest setting on the welder. I had much better luck striking the arc between two carbon rods and moving that around as a heat source.

img_20170118_203610

The rods are very much a consumable!

That kinda worked, and I was certainly able to get some melting (as you can see in the splat). Enough to prove the principle but not enough to actually do some casting. The summary is kind of:

  • Someone stole my flux (own brand lo-salt), so I got a lot of aluminium oxide for my troubles.
  • The welder doesn’t like the 16A breaker for the outdoor power socket. Works fine on the other 16A breaker in the basement but keeps tripping out.
  • Not enough insulation, a rather large crucible, repeated cutouts and cold weather meant I couldn’t retain enough heat to make a pour.

The thing to do now it appears is to make the furnace by hollowing out an alumina firebrick. They’re very porous and so excellent insulators (one video has the person picking up his brick with bare hands with a pool of molten aluminium in the central hole).

Nonetheless, it proves the principle. The 400 and 600A (one of each) crocodile clip style rod holders hold the carbon rods well. The rods work, strike an arc and provide aluminium melting heat.

 

Adventures in gluing

The thing I’m working on has some metal parts glued into a plastic case. The plastic is smooth (the mould is finished to the “Society of Plastics Engineers” 600 paper spec), and the metal is shiny chrome plated brass. I never considered either of those to be especially hard to glue, so I went for a pretty straightforward epoxy, Loctite 5 minute instant mix clear. It’s a decent enough go-to, much like any other random 5 minute clear epoxy. The short curing time is great for the impatient (me) and the clear finish is great because you can be a bit lax about the cleanup, which is especially important given the short curing time.

So, I splurged some on the metal part, shoved it in the hole and wiped off any egregious amount of excess with white spirit. A week later, I was fiddling with the part seeing how strong it was and was kind of surprised/distressed about how easily the joint broke. Like, really far too easily. And incidentally always the same way: the glue detaching from the plastic.

Then it got me thinking. I had a vague recollection that 5 minute epoxies kind of suck and come to think of it, so do clear ones. In a sort of ad-hoc way I think I’d come up with this:

Ed’s  rule of glue

Every feature added to glue makes it worse.

Fast curing? worse. Non, tinted transparent? That’ll cost you. Conductive? [sucks air through teeth]. It kind of makes sense, you can’t optimize everything at once.

That’s not to say you should never use that glue, it’s still perfectly fine for a lot of stuff, but slower curing and/or those ones that cure a nasty brown colour will almost certainly perform better. So, anyway, I tried  some polyurethane glue I had lying around and it seemed to be a bit better.

Time to experiment!

So,  which one to use? So first, the selection. There’s roughly an infinite number of glues out there, give or take a few. Some have wild and wacky properties, but even if you stick to the middle ground of generally gluing stuff to other stuff, there’s still a large selection.

So, I picked some somewhat arbitrary criteria and selected some glues that generally fitted:

  1. Specced to glue metal to plastic, bonus points for having ABS in the list.
  2. Available from local shops or next day delivery from RS
  3. Reasonable curing time to handling strength.
  4. Auto mixer if possible where applicable (better for large volumes).
  5. Not wildly expensive.
  6. Decent brands and available in the US (I’d normally be happy with RS pro stuff, but I need to be able to get it abroad easily).

The brands are mostly big, well known ones. 3M is always good. Loctite likewise seems fine. The other one, Araldite, I have a particular soft spot for. For years in the home gamer space it was pretty much synonymous with epoxy. My old DT teacher was a huge fan (rightly so) because you could fix all manner of sins with it. Countless projects were rescued with Araldite at my school.

And so, I came up with the following list:

  1. Loctite 5 minute instant mix. That’s the baseline, and my gut feeling says that other clear, fast setting epoxies won’t differ wildly.
  2. Araldite Standard. Bog-standard DIY shop glue. Slow setting (pot time of an hour, high strength in 24), dries kind of opaque yellowish.
  3. Araldite 2011. One of about a billion varieties. Similar to 2, but dries clear yellow. Allegedly slightly stronger on ABS. Also a pro glue, so comes in pro packaging which means you need one of those applicator guns and a clip on mixing nozzle for the auto mixer.
  4. Loctite 330. It’s an acrylic glue which I didn’t even know was a thing before today. You put glue on one surface an spray the activator on the other surface and put them together. Datasheet specifies 7387 or 7386 activator, but Loctite actually sell it packaged with 7388 of course. Fast cure time (30 mins to half strength) , and almost indefinite pot time, which is handy, since you don’t mix it with the activator. Not much by the way of instructions though.
  5. Araldite 2028. OK, I lied about not bothering with other fast curing clear epoxies. This one claims excellent performance on ABS, not so much in the datasheet which is not anywhere official I could find, but in this handy selection guide, which has a mysteriously chosen subset of the glues on offer. Also pro packaging with an auto-mixer.
  6. 3M ScotchWeld DP8005. Now I’ve heard about acrylic adhesives, I’m on a roll. Also RS had a relatively small selection of 3M and I felt things wouldn’t be complete without one. Claims to work well on ABS. Has an annoyingly short pot life (3 minutes and they’re not messing around).
  7. Everbuild gator glue. Bog standard polyurethane glue (basically the same as Gorilla
    Tasteful.

    I love the logo too!

    Glue). Generally considered OK for metal and plastic. Reasonable pot life and cure time. Single part, so no mixing needed. Also expands as it cures. This is not (as is popularly thought) useful for filling gaps since it expands as foam when the pockets of glue get too large. However, it does slightly splurge out so if you miss small areas, they get filled from the nearby ones. If you’re not familiar with British knock off brands, Everbuild is basically an adhesive company which makes cheaper versions of the well known stuff. So Gator glue/Gorilla glue, One Strike Filler/Pollyfilla, Stixall/No More Nails, etc etc. They also sell the delightfully named ASBO brand anti climb paint and anti graffiti painting. That makes me chuckle every time.

  8. Polycaprolacetone. I remember that sticking to everything really hard when I tried to use it. Applying it as an acetone based slurry, then reflowing it thermally after it’s dried. This is basically me messing around.

    crud

    White crud on the two snaps on the right hand side. No glue was applied there.

  9. Cyanoacrylate (generic brand). Another baseline, known to be strong and effective, but outgasses this white crud everywhere which is electrically insulating and has to be cleaned off.

Oh and the surface prep. Did I mention I forgot the surface prep before?

  1. Clean both surfaces with IPA (isopropyl alcohol).
  2. The full monty: clean with IPA, sand with 400 grit paper (3M as it happens), then clean again with IPA.
  3. As-is, with whatever crud and release agent is left on by the moulding processes.

And it’s arrived!

Swag! Lots of glue arrived

Swag!

Check out the swag, including a spiffy (and necessary) applicator gun, because as you can see, the pro packages don’t have full syringes. And 3 hours of cleaning, sanding, mixing, gluing and wiping off the excess, I present:

img_20161207_172650

That’s a lot of gluing and there’s more to come.

So now, I need some way to measure the force required to eject the metal bits from a case. Naturally, since I’m doing the whole thing at short notice and in rather a hurry,  I had to cobble together something with whatever was lying around or could buy locally. My solution is to go to a local DIY shop and enter a kind of trance until a solution based on the weird selection on offer presents itself. The result was this:

img_20161209_111453

After a few iterations, I settled on pushing down on a set of old kitchen scales held down with cable ties and string. The lever is 4x and the scales go to 5Kg, and the extra weights on the end are 2.5Kg at 5x. Maximum force it can apply is 32.5Kgf.

It’s basically a parallel action mechanism with a long lever. I balanced it to make it neutral and marked graduations on the lever so I can put a weight at a known position to apply a known force. You can’t see the M4 screw on the underside which is embedded into the pressing bit with some brass threaded inserts. I used some 5 minute epoxy (surprise!) to glue them in, but not a clear one and the horrendous brown colour made me think I should have tried it too. Though being nasty coloured and fast curing (hard to clean off) is not a great combo. The big M10 studding isn’t going into bare pine. The holes are lined with some sort of plastic tubing which felt a lot like HDPE. Naturally it was 15mm, and they only had 14 and 16mm drills, so a lot of sanding was involved (later I found just hacking off the outer layer with a Stanley knife was faster. Oh well). It’s also quite loose (inner diameter 11mm), which is good because I can’t drill straight apparently.

Oh, also, I glued on the main pillar upside-down first time (look: it’s not symmetric) at the other end with the Gator glue (scar is visible just by the pliers). I realised after about 20 minutes and that was enough that one of the end grain to long grain joints was already stronger than the wood. Even if I find doesn’t measure up here, I’ve become a fan of the speed of polyurethane glue and strength on end grain for woodworking

Oh and check out how straight the pillar is 8-). There’s nothing to keep it straight except for the square planed end. I’m excessively pleased about that.

RTFM, n00b.

So the spare DP8005 didn’t cure in a nice solid lump, at least in not in a few hours, and it’s meant to have a pot time of about 3 minutes. I think it was a mixing problem. I’m not 100% sure I got the right nozzles and since it’s a 10:1 mix, that really matters. So I mixed some by hand, too (strongly not recommended) and tried that. But since mixing is slow and it has a short pot time, I didn’t have a chance to glue up all variants. When it’s properly mixed, this stuff sets FAST.

The first results.

Thoughts so far during gluing:

  1. The Loctite 330 activator is this yellow gunk that has to be cleaned off. It’s pretty nasty and it’s more or less impossible to clean it off interestingly shaped surfaces.
  2. Scotchweld DP8005 is made by 3M and being 3M they’ve really put the effort into the packaging. It reseals really well by plugging up the holes (unlike the Araldite which has a simple cap), with a keyed cap, so you don’t mix the two sides. Also it’s gritty! That’s apparently to keep the surfaces apart by the minimum spacing. 3M think of everything.
  3. Cyanoacrylate is and always will be a pain in the neck.
  4. My lab now smells of glue and solvents. Niiiice.

Anyway, I left them curing for 36 hours in my lab. Then I spent I don’t know how long pressing snaps out of cases and writing down the results. And then some awk code to collate and prettyprint the results of course.

 

                        Surface prep||     IPA clean     |clean, sand, clean |       none        
Glue                                ||    ave     min    |    ave     min    |    ave     min    
------------------------------------++-------------------+-------------------+-------------------
Loctite instant mix 5 minuted epoxy ||    14.7    8.8    |    12.1    9.2    |     9.1    8.0    
Araldite standard                   ||*    7.9    5.6    |*   11.2   10.0    |*    4.8    4.0    
Araldite 2011                       ||*    6.5    4.8    |    11.5   11.2    |     5.4    5.2    
Loctite 330                         ||*   12.3    7.2    |*   16.3   14.4    |*   13.6   10.4    
Araldite 2028                       ||     7.1    5.6    |     6.9    6.4    |     5.9    5.2    
Scotchweld DP8005 badly mixed       ||*    4.4    3.6    |*    4.1    4.0    |*    4.5    4.4    
Scotchweld DP8005                   ||    22.1   20.0    |                   |    17.5   13.6    
Gator glue (no water)               ||*   11.7   11.2    |*    7.5    4.8    |*    9.7    8.8    
PCA                                 ||     3.2    2.8    |     5.1    3.6    |     3.0    2.0    
Cyanoacrylate                       ||    21.0   15.7    |    22.6   18.4    |    21.6   19.7    

* = Clean off excess glue with IPA

 

And… ehhhhhh.

It’s a bit mediocre.

Well OK. I’ve established that it’s really important to clean the parts before gluing. Sanding seems to help a bit, mostly, but to be honest I didn’t do a great job of it.

The 5 minute epoxy came out pretty strong comparatively and although it seems strong enough it’s not exactly decisive. The CA is strong (as expected), but has outgassing problems. The DP8005 is excellent if done properly, but I think it cures a bit fast to be useful for this application. The Loctite 330 is decent, but that spray is just too horrible for this application.

My ad-hoc experiments earlier had Gator Glue doing better relative to the Loctite epoxy. I think something might be wrong there.

And wow, Araldite, you kinda suck 😦 Is this the end of my fond childhood memories?

No, seriously, RTFM, n00b.

OK, so I forgot a bunch of stuff. I forgot to dampen one of the surfaces with the polyurethane glue (Gator Glue). That might explain the so-so results. Time to repeat the experiment. This time, I also switched to genuine Gorilla glue, not because I expect it to be better, but because the results are going to be used in the US and Gator glue isn’t available there.

Also, the lumps of left over araldite 2011 seemed kinda not fully cured even after 36 hours. I mean they’re sort of hard, but not really solid like I’d expect. The data sheet claims it cures at 10 degrees C (colder than the room I used) but rather sneakily, the strengths are not listed for low curing temperatures.

Double also, in the DP8005 datasheet, it mentions that you should discard the first bit out of the nozzle because it won’t be properly mixed. Not only did I not do that either, but it seems like a really good idea for the other auto mixers as well.

Round 2. Fight!

I’m only re-testing the ones which (a) didn’t seem to come out quite as expected (b) won’t cause massive wastage and (c)  don’t have other issues. So, I’m doing Araldite 2011 with a bake at 80 degrees C for an hour (far more than enough) and Gorilla glue with a water spray. I’m also going to be a bit more generous with the Araldite and apply it to both surfaces. I chose 80 based on a kind of gut feeling compromise: the datasheet listed curing times up to 100, but 80 still cured fast and the plastic starts to soften slightly at 85.

For surface prep I’m only doing the IPA clean since it works well, but not the sanding since it’s variable, hard to do and possibly too awkward to be good in production.

The only thing I am varying consistently is whether or not  to wipe off any excess with IPA.

aaand….

                        Surface prep||     IPA clean     
Glue                                ||    ave     min    
------------------------------------++-------------------
2011, both sides, bake              ||*   20.7   16.8    
2011, both sides, bake              ||    26.9   19.7    
Gorilla Glue, wipe after            ||*   19.9   17.6    
Gorilla Glue                        ||    17.2   15.6    
Scotchweld DP8005                   ||    22.1   20.0    

* = Clean off excess glue with IPA

Well, that’s a bit better.  The Araldite 2011 is the clear winner in strength terms. One measurement actually hit the maximum 32.5Kg the default setup of the press could reach and tore a chunk of the chrome plating off the underlying brass of the snaps . And the Gorilla Glue puts in a very respectable showing. Not quite as strong, but the worst cases are pretty similar. I’m pretty confident now that either of these will do in the final application with the correct surface prep.

winnar

TL;DR