Tuesday, August 15, 2017

This post is less of a guide and more of a collection of thoughts. It assumes some Java and camera operation knowledge.

My S7 has become my main camera since it handles low-light, uploading, water and time zones very well. It does have a few big weakness though, oversharpening being one of them and over-confidence the other. By over-confidence I mean it will gladly lower the shutter speed to 1/4s, thinking OIS will take care of the shake. It can't.

The Samsung camera app on Android Nougat has shed a lot of features in exchange of user-friendliness. Gone are the sharpness controls, OIS cannot be disabled, RAW mode is available only in the "Pro" camera mode. Quite a lot of artificial limitations which third-party apps don't seem to bring back.

Start

To analyze the application we need to take a look at some binaries: SamsungCamera6.apk, semcamera.jar and seccamera.jar. There are some other binaries but they are written in native C (libcamera_client.so) or even for FPGA (e.g. fimc_is_fw2_2l1.bin).

For taking a look inside the jars I'm using dex-tools 2.1, jd-gui 1.4.0 and Eclipse. The classes.dex file is extracted from each app, sent to dex2jar, imported into jd-gui and saved as a zip collection of .java files, then imported into an Eclipse project. There's probably a better workflow for this.

From those various jar files a structure emerges: SemCamera is the bridge between the native camera binary and Android/Java.
FaceAreaManager seems to take care of face detection, HRMSensorFusion enables use of the HR sensor to take selfies.

The camera modes are defined inside the application, even though they need to be downloaded in order to be used:

Interestingly enough, there are a few camera modes which do not have an equivalent app in the Samsung App Store: Antifog, BurstPanorama, Night / NightScene, ProductSearch, ProLite, RichTone, TagShot.

Antifog might be targeted towards the Asian market, as a mode that reduces smog smear. Night might be a sub-mode for the Auto. ProLite might be a Pro implementation for phones with less features (Samsung A7). RichTone might be a sub-mode for Auto+HDR.

I find it both curious and disturbing that features are being hidden from the user at the cost of a "purchase". Not sure if the idea was to monetize camera modes or to simplify camera usage. A simple checkbox list would've sufficed.

Saturday, August 5, 2017

In one of my most-viewed articles, from quite a few years ago, I've teared down a Saeco Talea Coffee machine and noticed a strange protrusion on top. I assumed it was an IrDa transceiver, then thought that maybe it was a coffee cup detector.

It indeed turned out to be an infrared port.

Armed with this knowledge - and some time to kill - I've decided to try and talk to the machine, wirelessly.
While it might sound easy, there are many steps involved: get hold of the service tool application, reverse engineer (RE) it, RE the service dongle, RE the machine protocol, write an IrDa implementation for Arduino, write the web app to serve the page - and coffee.

Step 1 - .NET reverse engineering

Ever since I've discovered JetBrains' DotPeek, my life has been changed. I don't know C#, in fact I barely know C, but I can pretend to be a .NET developer.
After getting hold of the SSC2 application (that's another topic in itself) we can try to see how it can talk to the machine.

The baud rate for talking to the serial tool is 19200, for my machine. Since the baud rate is different for other machines, I could make an educated guess and assume that the serial tool is just a transparent proxy between a USB to serial converter and either IR or RS232.
The serial protocol is 8N1 - 8 bits, no parity, 1 start and 1 stop bit - pretty standard.

Let's see what we can speak:

The program sends the "(MA)\r\n" command on a button press.

Let's see where Button17 is declared.

That button has a text called "BU up", which in slang means "Move brew unit to the upper position".

Similarly, we can find a pretty long list of commands that can be sent.

Tuesday, August 1, 2017

I haven't had much time to write full articles but I can go through a quick rundown until I tackle each subject:

CTC 3D Dual (Bizer) Printer

Will create a separate article about the mods and results.

I've re-tightened all the screws and tried to take out the backlash of the Z carrier. This has improved the jagged edges a bit and also reduced the noise.

I made a small DIY enclosure: A4 plastic sheet on one side, the glass from a picture frame in the front, the particle wood panel from that frame in the other side. The glass frame was affixed with some 3D printed clamps as well as a modified Tic-Tac box.
On the top of the printer I've cut some Ikea Schottis blinds (3$) that fold with the moving head. I found out afterwards that I'm not the first one to do this: https://ultimaker.com/en/community/9484-umo-dust-cover

I've cut a few pieces of 2.5-3mm glass to the bed dimensions. Rather, I've had a glass manufacturing company cut them for me (<10$). Then from the remains of another Tic-Tac box some springy corners were created that keep the glass in place. This allows the glass to be easily removed and replaced with great repeatability.

With the covers in place the printer gets warmer quicker and ABS can finally be printed, though still a bit fiddly. It also reduces dust a lot.

Some nice LED lights were also added, allowing to take better pictures of the things.

Lenovo Thinkpad Backlight control

I've partially reverse-engineered the Win10 app that controls the keyboard backlight and now I have a Macbook-like backlight behavior on my X230. Source code and binaries will be published as soon as I clean them up, there is already an alpha version available for testing. I've been using that for at least a month and it's been running great.

Saeco infrared port

The mystery part on my Saeco Saleo teardown article was indeed an IrDa transceiver. I thought that it was just a coffee cup sensor, to keep the cup warm. I've reverse engineered the Saeco Service Center tool (SSC) and figured out how to talk to the machine - in theory - including how the checksum is calculated.
I've seen a few pictures of the service unit and it looks to be just a USB to UART to IrDa converter. Hopefully.
The next step would be to build an ESP8266 Wifi-to-IrDa converter. I've read a bit on the IrDa SIR protocol and it looks manageable, even without interrupts, there are quire large tolerances specified.
I think that, with the ESP8266 build, the SSC tool should be able to directly talk to the coffee machine

Automotive-type projects

The DieselBooster is still in tests, the fuel savings are quite a lot lower than anticipated, but still tangible. I've had nobody contact me about publishing the latest sources, so I've delayed that.

I've designed a module that allows a 3S LiPo battery to be left in parallel with the lead-acid ones, especially for motorcycle use. It will boost the voltage on cranking, allow it to be recharged up to 12.4V and generally keep the LiPo safe from overcharge and discharge. I will still need to build the project and test it, but it looks fine so far.

I've built a module that interfaces with Hall speed sensors on motorcycle/scooter wheels. These become weak over time (either the transistors or the magnets, not sure), but it's basically a hysteretic comparator.

At least on my bike, the sensor and cable comes in a single piece and costs 140 EUR second-hand. The module above can be built for ~1$.

Batteries

I've been meaning to do a test of low-cost batteries for a while now. But, for my German readers, the gist is: Varta, Eneloop, Energizer- they all have their rated capacities or more. Ja! - very close, for a quarter of the price. Lidl/Aldi - junk.
I read all these German reviews that the Lidl/Aldi batteries are being developed by Varta. They very well may be, but the capacity is less than half, shrinking to under a quarter under load (0.5A).
Haven't tested the IKEA batteries yet.
As a price breakdown: you can buy the 4-pack AA Energizer at Rewe for ~6E or more, the Ja! batteries are 1.59E. I've tested the Ja! AA batteries to provide at least 1800mAh under small load compared to 2500 for the Energizer.
Here's a snapshot from a work-in-progress:

Sunday, July 9, 2017

I recently had to work with a home fiber router that was supplied by the ISP, the FiberHome AN5506-02-F.

Compared to the previous internet access solution, which was based on a cable modem and required the user to use their own router, the new solution has both advantages and disadvantages. The advantages would be: integrated WiFi, security and firewall. The disadvantages: only one LAN port available (@100Mbps), only 2.4GHz (@150Mbps), outdated software, locked-down interface, no easy way to expose a second router.

Exposing the inner router

To get around the issue of the (old) router not being accessible from outside, the solution is to add that router into the DMZ setting. This is needed for things like web hosting, ftp server, some chat clients, torrents, etc.

You can log in with your supplied standard username and password, no need for admin rights for this. The usual link is http://192.168.1.1 . Write down your old router's MAC address, either from the 'Status -> LAN -> DHCP Clients List' or from its label.

Add the MAC address to the static leases list, just to be sure that the old router will always get the same IP. Might not be needed, but in case something happens you want to be sure that you don't expose the wrong host to the Internet.

Add the IP address from above to the DMZ zone.

Every time your IP will be accessed, the ports exposed to the outside will be the ones on your old router. Assuming the old one is more secure than the new router, this will also improve security.

There are also other ways to do this, but this one is the easiest. Not a hack, just poorly documented functionality.

Studying the firmware

The router home page uses a framed design, with the left frame (./left.asp) consisting on some hardcoded data and JS includes and the right frame being the active UI.

The hardcoded data is a crude state machine to select a different skin or menu structure based on the ISP values.
"checkResult" is the result of the login, with all values except 1,3,4,6,11 being accepted. So you can set it to 0 or 2 to signal the JS that the user is logged in. The check is only done in one place, utils.js, so you can set a breakpoint at the method entry point and override the value:

Each time the script pauses at that line, you can set the checkResult value to a valid one and press continue - most the pages will happily load. You can automate this process with a Tampermonkey script, which could override the security function with a dummy one:

web_access_check = function(i){}

We can already see two critical security problems: only client-side security and unique checkpoint.

Looking further into the request and responses (XHR) I could see that for this version of router/ISP an XML resource is being loaded:

Looks like the menu and submenu layout, this could have been deduced as well by looking at the JS code.
Changing 1.xml to 2.xml yields an advanced menu:

Tracing back how this XML is loaded, leads us back to another semi-hardcoded page:

Long story short, setting a breakpoint just before Frame.show() and setting curUserType to "2" will load the admin version of the UI.

The exposed menu items are not interesting for a normal user (they don't add features or increase speed or anything else) and can brick the router if modified.

I haven't played much more with this, but I suspect the unit might be susceptible to some basic attacks: directory traversal, RCE, privileges elevation, ...

There are some other topic that are left as an exercise for the reader: switching to different skins and languages, dumping the file system, finding out the admin username/password combo.

As mentioned in the previous post, I tried to set the curve opposite of that the 'tuning' units on the market do. So the reported fuel rail pressure would be higher, causing the ECU to decrease the rail pressure, and, hopefully, fuel consumption.

After a long test test I can say that this is the way to go. Most numbers have been tweaked so that it would result in 15-20% lower pressure.

For mostly highway driving the fuel consumption is now down to 6.28L/100km 7L/100km, with an average speed of 102kph (cruise control set for 130kph). For the same driving conditions, the factory result would be around 7.4-8L/%. This is corroborated by the fact that I was able to drive >1200km with a full tank.

I don't have any numbers yet on city / heavy traffic consumption, it might be a different story.

I don't know the long-term effects on neither reliability nor pollution, the injector nozzle spray pattern might not be suitable for such low pressures.TL;DR: >15%6-7% fuel savings with the DieselBooster values set to 115-120%, opposite of the initial ones.

Edit: article was amended after I discovered some miscalculations. I forgot to take into account a mid-trip refueling. New calculation falls within statistical error. This project seems like a fail.

Sunday, May 28, 2017

I've been lagging on the project for a long time, but the issue was that the long-term results were not correlated with the initial test data. That, and the fact that I don't use my car that much. Each test requires at least 25L of fuel.
Moreso, 25L (just above a quarter of my tank) is not enough to let the car calibrate its closed loop. Usually it requires a full tank and lots of driving, about 800km each test. It's hard to do a consistent driving cycle for that distance.

My aggregated data shows that the circuit DECREASES mileage now, perhaps with about 10%. And that is with settings almost identical to the ones used by RaceChip, a bit more aggressive. In other words, with a REPORTED LOWER rail pressure and ACTUAL HIGHER rail pressure the CONSUMPTION INCREASES by ~10%.
I suspect that most of the people that report decreased consumption actually use on-board-computer data and do not perform precise measurements.

So I've changed my strategy now, The reported (fake) rail pressure was increased, so that it yields a lower actual pressure. This means that the software is now set to -20% instead of +20%, so the curve is reversed.
The on-board reported consumption is ~30% higher at idle (1.1L/h stock, 0.7L/h previous, 1.4L/h now). The car stays longer in high gears which also improves mileage. This makes sense, as the engine ECU now thinks the engine has 'more power' so it signals the automatic gearbox ECU to shift earlier up and retarded down. Or something....

The driving conditions were not identical, but the actual figures are slightly higher than stock, taking into account the driving style.

I will need at least two more months of testing to draw a definitive conclusion. But the initial conclusion is that most of the aftermarket units that report a [fake] lower rail pressure do not increase mileage. Sorry to burst anyone's bubble, but I'm into that group as well.

The other conclusion is that the circuit and software can still be used as-is, no changes are required if you want to do your own testing. I do have an improved, unpublished, Android application, but it mostly increases usability. If anyone wants the apk for that just drop me a note.

There are quite a few steps and preparations needed to do this, however, this is for documentary purposes only. You don't need to do any of the stuff below (except backup), you can just flash my OpenWRT firmware and be none the wiser. However it might be useful if you want to port it to a new device, I could not find any tutorial about this.

How booting works

When the CPU starts up it goes to the first address inside the flash memory to look for an executable. It finds uBoot at position 0x00 and hands over control to that. uBoot then does some housekeeping and decides where to jump next.

In the case of this device, if the reset button is kept pressed while powering on, uBoot will jump to 0x50000 (mtd4), otherwise it will jump to 0x21000 (mtd5).

Conclusion: wifi led (blue), power led (blue), charge led (yellow) seem to be hardwired, Red led is bit 9+1 of GPIO; reset is pin 10+1
There's also a low battery indicator that I was not able to read or write to.

Getting dirty - OpenWRT configuration

The first step is to retrieve the repository, set up all the tools and dependencies. I will not go into those details as they are a moving target.

We already know from the teardown that the CPU is Ralink RT5350F. Luckily, OpenWRT already provides this platform for us under the name rt305x.

Add the following entry into /target/linux/ramips/base-files/lib/ramips.sh :

+*"i.onik Wi-Fi Cloud Hub")+name="ionik-cloud-hub"+;;

Then this under /target/linux/ramips/base-files/lib/upgrade/platform.sh, under the ip2202 entry :

+ionik-cloud-hub|\

Not sure how correct is that. I think this file controls how the original (factory) firmware does checksumming in order to get your "trojan" firmware accepted as an upgrade.

Then this under /target/linux/ramips/image/rt305x.mk :+Image/Build/Profile/IONIKCLOUDHUB=$(call BuildFirmware/Default8M/$(1),$(1),ionik-cloud-hub,IONIKCLOUDHUB,Linux Kernel Image)

I found out that - after a test build - my custom firmware only recognized 32M of RAM instead of the 64M that are available. So modify the CONFIG_CMDLINE parameter inside target/linux/ramips/rt305x/config-4.4 b/target/linux/ramips/rt305x/config-4.4 :+CONFIG_CMDLINE="rootfstype=squashfs,jffs2 mem=64M"

Specifying the network interfaces, I probably goofed on this but it still works, add the platform inside target/linux/ramips/base-files/etc/board.d/02_network :@@ -142,6 +142,7 @@ ramips_setup_interfaces()"0:lan" "1:wan" "6@eth0";;b2c|\+ionik-cloud-hub|\nw718|\psr-680w|\sl-r7205|\

I wanted to flash the red LED when booting but it did not work. target/linux/ramips/base-files/etc/diag.sh :@@ -138,6 +138,7 @@ get_status_led() {status_led="$board:blue:status";;miwifi-mini|\+ionik-cloud-hub|\zte-q7)status_led="$board:red:status";;

I also want the wireless to be up after booting since the 'router' lacks an ethernet port. This could be done in a better way, with a default password or one based on MAC. So from package/kernel/mac80211/files/lib/wifi/mac80211.sh you need to comment out the line that says 'option disabled 1'.

This is the most important part. It specifies the flash configuration, for example it tells that uBoot resides between addresses 0x0 and 0x30000. I don't know if this is correct, but it works for me. The important bit is the "firmware" partition at the end. Everything else was mostly guesswork and might be wrong. But it works.

I have no idea what anything above does. But every other device seems to have them, so I added them in. EHCI and OHCI refer to USB ports, as far as I can tell.

Building the custom firmware

After making sure all the files above are modified/added, you just need to type "make menuconfig".
Then go wild adding options to your ROM. You will quickly run out of flash space.

An option marked as 'm' means module. The option is compiled but not included inside the image. Rather, you can add it later to your device, temporarily, via a USB stick or similar. It might trigger (on) some other features which will eat precious Flash space. So just add only what you need, check the size of the image, repeat.

To build run "make -j4". This builds the firmware using 4 threads. If anything fails, you will have to build single-threaded and with verbose mode one. Refer to the documentation.

The system is goingRestarting system.ps-rt305x-ionik-cloud-hub-squashfs-sysupgrade.bin to mtd5 ... [w]

I don't remember the details right now, the above might be reversed, but you can play around if you have a backup. Make sure you are writing to the correct partition and do not touch uBoot and minisystem.

If you mess up, you will have to use an SPI flasher to restore the flash contents. There are various tools and tutorials online, you could probably use a Raspberry PI or Arduino for this, but you would still have to solder the tiny wires or buy a SOIC-8 clip.

After the first OpenWRT image is flashed from the command line, and it works, subsequent images can be uploaded from the web interface.

Sunday, February 12, 2017

Living close to a densely populated area means that it's hard to do consistent testing without spending a lot of fuel, which is also expensive.

Nevertheless, I took the pen&paper approach and started working my way from the basics.

I studied all the Bosch sensors from this page, used a bit of common sense and figured out that my sensor is a Bosch 0281002691, or similar, with a 180 MPa (26000 psi) nominal rating. This might be wrong but It's a good place to start.

I've already used Torque and my multimeter to get some data and it seems to fit with the sensor I've chosen. It might be wrong, but so far it clicks into place.

Using the data I've gathered I've created a simple JS page that shows some logs and tries to simulate what my module (and sensor) does: https://jsbin.com/goyavabuju/edit?html,output
(Note that this is the HTML/JS result after I did the interpolation.)

So the basic function is: the ECU commands the pump, this delivers a pressure, my module receives the sensor data (voltage), offsets it, outputs a new voltage to the ECU, the ECU processes it. I missed a step the last time: the ECU will receive the adjusted pressure, output a new pressure, the pump delivers, a new pressure is measured. This can cause oscillations within the engine, as the tuning module attempts to adjust for the new value.

I am no specialist on this stuff but I've managed to keep my unit running after it was used in an office environment (>50000 coffees). So for me it's mostly guesswork and some logic, but I'll display this so that you can help figure out the problem with your own unit. I'll try to make this accessible to non-technical people, let me know if some idioms are too advanced.

I will try to update this guide with usual questions, but this is not a replacement for professional servicing.

Before troubleshooting make sure that the unit is cleaned and descaled and has enough water. Use the manual for this, each unit is different. Also, try turn the unit off and on, perhaps leaving it 1h undisturbed. This works around some of the bugs in software (firmware).

Learn the sounds of the machine and try to understand what it does in its normal state. There are several motors and they are easy to identify by sound.

Wednesday, January 18, 2017

Currently (early 2017) selling for 15E, I think I paid 12E including shipping. This post will focus on basic features and some early data. Later posts will go into some reverse-engineering, featuring a great YouTuber, LiveOverFlow. If you like reverse-engineering you will surely enjoy his tutorials. By the time you read this he will have probably published his first video showing you how to get into the device.
He also discovered that a very similar device is being sold under the Strontium Mobile Wifi Cloud (Sri-CUBa-3KW) moniker in US and India. However that one is advertised as having a 3000mAh battery while this one only has a 1900mAh one.

Saturday, January 14, 2017

I've been using a 4GB on an rPI "clone" - the Banana PI - and have been happy so far with everything the board has to offer, as a headless server. However, I started getting some errors after ~3 years of usage, with the card and at one point it stopped booting completely. Nice timing as well, it's not fun losing your music streaming server at Christmas time.

Long story short, the card has been used at 80-90% most of the time, which left very little space for wear leveling. I hooked it up to HDMI and could see a lot of error messages on the screen about mmc. So the card was dead and I feared the worst. last backup having been made a month prior to this.

Never fear, just writing imaging the card (Win32DiskImager) and copying the image to another 16GB card worked fine. So if you run into this it might be worth it to just try and duplicate the card to another one. In my case, no other changes were required.

Thursday, October 20, 2016

I was tasked with the issue of getting contact data from a broken Android phone (in this case Xiaocai X9). The touchscreen was functioning erratically, the display was blank, adb/developer debug was not enabled.
I've tried for some time to enable debug by dragging randomly on the screen, making a screenshot (hold down volume key + power) and trying again but gave up after an hour or so.
So: broken touch, broken LCD, no adb.

With that out of the way, I've had about a month of testing with the new prototype and several months already with the old one. The definitive result is that there are significant fuel savings.

Outside city limits I now get better than 6L/100km, at highway speeds (130 km/h) better than 6.5/%. I believe the highway consumption can be further improved but I haven't used the car so much lately to be able to fine-tune the settings.

Previously I would get 7.6L/100km at best on country/county roads and 7.4/% on highways. So that would be a 12% mileage increase on highways and 21% on slower roads.

Inside the city is where the story changes since that's where I did most of my driving and had time to tune the parameters. I am now getting an average of 9L/100km (actually better) compared to 11L stock or 12.5L with RaceChip. So that's 18% mileage increase from stock and 28% increase from RaceChip..

Why such a difference?
The issue is a bit more complicated and I found it related to matching between sensor output impedance and ECU input impedance. That's why the improved prototype has provisions for adjusting this. On my car, with the default 'Arduino' circuit I need to set the offset correction to -50mV and gain correction to +3% in order to match the factory settings.
I doubt any of the aftermarket solutions account for this and is the reason why I get such poor city mileage with the commercial tuning unit.
The commercial units are likely ok at higher rpms since the gain correction is built-in (part of the tuning) and the offset error becomes insignificant.

The app

Building a mobile app was a great idea since it allows me to connect to the module, adjust the settings on-the-fly and save them.

I would probably redesign it now since I know now the usage pattern: adjust gain and offset once, play with the curve point gains indefinitely, save them. Currently the gain and offset are the biggest UI elements since the majority of the improvements can be achieved through those.

The 'Apply immediately' checkbox is also really useful as it allows the user to play with the values without having to hunt for the 'Apply' button. As soon as some settings are changed the application waits for a while (1-2s) and sends the new settings to the car.

It's cool showing the phone to someone and watch the consumption modify as you play with the values. A bit silly, but makes for a 'wow! never thought this would be possible' moment.

Adjusting the individual gains however is a bit tricky to do while driving (or stopped for that matter) since they are quite small and a lot of them.

I opted to add +/- buttons on the sides of each point setting instead of the classic numpad editor which is impossible to use at the wheel.

The app will also helpfully highlight the currently selected point (in blue) so you can see where the engine is at.

With the 'Apply immediately' feature it's just a matter of tapping '-' and wait 1-2s and see the effect.

Speaking of effect, the whole concept now seems a bit wrong to me - you are adjusting the END value not the START value so anything that you've adjusted affects where the next value will be. E.g. if you adjust the value for 200 (ADC = .244V) to lower it by 10% the ECU will compensate and now the new value will be 200+10%. I cannot explain this properly in words but I'm working on the EFFECT rather than the CAUSE.

Another interesting issue is that the engine does not run well at very low fuel rates, regardless of the setting. As long as the stationary consumption is above 0.7L/h the engine sounds fine, as soon is it goes below that it starts shaking. The 'solution' is to raise the consumption back by putting it in gear or starting A/C. So a 'cold engine' tuning should be different than a 'warm engine' one since consumption decreases as the engine warms up (emissions-related). At 0.4l/h the engine shakes badly.

Speaking of shaking, the automatic gear shift is not so smooth anymore since it's probably hand-tuned for specific torque values.

I haven't noticed any significant loss of power but I'm not the street racer type.

Future

I'll probably stop working on this project for a while and deal with the other pending projects since I think the goal was achieved.

Would be nice to have a separate control module with real buttons and knobs instead of a smartphone.

Would be nice to use the internal Arduino temperature sensor to select different curves or values depending on ambient (engine) temperature. It should be good enough for most purposes.

Would like to find out if there is any damage that can occur when setting an extremely low consumption. I'm using the engine sound (smooth, rough, shaking, ...) to tune the settings now but I don't actually know why it's behaving like that since the rail pressure is well within parameters.

Tuesday, August 2, 2016

Six years ago I bought a Lexmark Pro205 all-in-one printer, one of the few affordable ones that had WiFi. This has proven a disastrous investment, so let's go quickly through the numbers:

purchasing price (10 Mar 2011): 140 EUR

black cartridge replacement (21 May 2012): 12E

full ink refill set (21 Dec 2013): 18E

full cartridge replacement (25 Mar 2014): 13E

full cartridge replacement (12 Mar 2015): 12E

In total 195E, there might be other expenses as well.

Electricity costs are not included and the printer is not very economical in standby.

Printed pages - as per printer counter - 691. I would estimate the total number of usable pages to be ~200, out of which ~15 were full-color photos. This is because most of the pages from beyond number 80 had streaks and the printer required at least 50 deep cleaning cycles. About one page in five is usable, but certainly not great.

So running costs until now are 1 EUR / page. That's definitely the most expensive printer I have owned.

In comparison, around 5 years ago I bought a Kyocera FS-1020D laser printer refurbished for 30 EUR. It has printed around 1000 pages with a discard rate of 1:50. That is, 1 in 50 pages came out bad because of the printer. So the running cost for this printer is <4 cents/page. No maintenance required other than the thermal fuse blowing out because it was sitting in an enclosed area (2h, see a recent article about fixing that).

Sunday, July 31, 2016

This a departure from my normal subjects, but I don't have a blog dedicated to my software work.

I have recently attended the first HackerX instance in Frankfurt. For those who don't know, it's like a speed-dating event where potential employees and potential employers are face-to-face for 5 minutes, then the candidates (employees) rotate over to the next company.

Right off the bat I should mention that I did not receive my own invitation but I used one from a colleague. However the only difference is a missing email.

Tuesday, July 26, 2016

I was assuming that having some time off would allow me to update this blog more frequently but there is always something shinier.

Diesel Tuning Box (for lack of a better name)
I've tested extensively the latest iteration that does semi-automatic calibration and found no issues with the circuit itself. However there were many issues with the ghetto-style DB15 connector made using hot glue. Once I got the proper connector in it will stay in the car at all times.

The issue was caused by raised temperatures under the hood deforming the hot glue and leaving just a tiny contact patch that allowed very little current to flow in. Anything over 20mA would break the contact yielding 'check engine' errors. If you are fast, the errors go away when restarting the engine. If you are slow (>2 minutes) you need to reset the error using an OBD2 diagnosis kit. I used a bluetooth OBD2 connector (~12$) with the Android app Torque, while driving.
I'm testing these limits so you don't have to.

Otherwise, with the new software it has proven reliable enough and allows for realtime (while driving) control of tuning. However the serial interface has proven prone to error - while trying to insert comments in the log files my co-pilot inadvertently altered some settings. This will be improved by writing a phone app that will allow adjustment on the fly and saving of the log files. Currently still in the process of getting up-to-date with Angular2 and Ionic2, but I already have a working app. The source code - once final - will be published on my github page.

Printer repair
While doing the taxes my Kyocera FS-1020D laser printer died with a strange blinking error: the first three LEDs blinked slowly, then just the second LED blinked. After a bit of service manual hunting I found out this was error 6000 - fuser unit error.
It took a bit over an hour (including pictures) to work around the problem: the thermal cutoff (fuse) was triggered which left the fuser lamp without power. I just soldered a wire between the fuse contacts since the printer already has a thermistor in place for monitoring and cutoff. Not 100% safe but I doubt it will start a fire. The fuse was rated for 157C, will write a detailed post once I find the time.

Odys Winpad V10
After an uneventful Windows 10 upgrade the tablet has been running fine with no significant drawbacks compared to Windows 8. To get the most battery life and keep the tablet cool I suggest setting the wireless connection to metered: this will stop the automatic updates and maintenance.
I also cut the cord from the power supply and attached a standard USB male connector to the tablet end and a female connector to the other end. This allows me to charge it using any USB supply.
Battery life is between 6h under moderate load (frontend development) and 12h idle (while connected to HDMI). To get the most of the battery I recommend turning on airplane mode whenever WiFi is not needed.

I scanned the steel paperweight inside the keyboard (230g) and looking for a way to replace it with some 1-2mm aluminium sheet. The new backplate would then be less than 75g, but some counterweights (~30g) might be needed to keep it from toppling over.

I have replaced/removed/re-soldered some caps inside the keyboard that made an annoying whine (5-15kHz). Just look for the biggest ceramic capacitors there and either resolder them to be less rigid or replace them with something of improved quality.
I have tried every other possible solution: using a strong glue to dampen them, changing orientation, adding some padding material - nothing except the above worked.

CTC 3D Printer
A gen 1 Raspberry PI was setup up as a remote web interface using OctoPrint. However there are many issues with it that prevent me from slicing files remotely (including the rPI speed). It also requires an OctoPrint restart whenever a job is cancelled, so it's far from ideal.
I installed the SailFish firmware on the printer and it has proven a huge benefit: the temperatures and speeds can be altered in realtime, allowing for example to print the first few layers slowly and the middle ones twice as fast.
I have been unable to use Simplify3D on it, currently MakerBot seems the best option.

Li-Po powered compressor
For my bikes I have to check the tires pressure quite often and this poses several problems: I don't have a nice high-pressure pump, it takes quite a while to bring racing tires up to pressure (8 bar) and it also takes a lot of energy. So I made a connector that has on one end alligator clips and a female XT90 connector and on the other end a 12V automotive (female) socket, the ones used for cigarette lights. With a cheap (15EUR) compressor I can now check and adjust the pressures in just a few seconds and can use either a 3S LiPo battery or a small motorcycle (or UPS) 12V battery.

Monday, May 23, 2016

As I wrote in the previous article, the barebones design has been through some basic testing - 500km mixed environment driving - and has been mostly successful so far.

I had a suspicion that the output impedance of the circuit must somehow match a known impedance, but was not sure which. The clue was that the RaceChip unit raised city consumption by 5-15% even though it had no effect during the bench testing.

For testing they are using a pull-up resistor, so on the input side of the ADC the same circuit must be simulated in order to drive the sensor. I used a 10k resistor, but perhaps even the internal pull-up could work.

At the DAC/PWM output I found out that a 1.5k resistor was too large and could not sink the ECU input line low enough. With a 10ohm resistor it seemed to work fine, perhaps 47ohm would also be ok. I don't have a definitive value yet as I want to implement it in another way.

The initial barebones circuit used an Arduino Nano (v2?) without RTS/CTS lines on the serial port. This means that on startup, the bootloader takes around 2 seconds until it jumps to the main loop. The car does a basic check and reports the sensor as faulty. The solution: turn the ignition off and immediately back on, before starting the engine. This is because there is a 30s delay from ignition off until the systems are powered down, at least on my car. It's also a nice anti-theft measure, the thief can only drive with reduced power, I think around 20%.

Consumption

Idle consumption with my unit is now at 0.5l/h when warm, compared to 0.8-0.9L/h stock, 0.9-1.1L/h with RaceChip. So >30% fuel savings while idle.
The idle is a little shaky if unloaded, runs smooth if some load is added (A/C or in drive gear). Incidentally, with the unit disabled but in-circuit, the behavior is almost the same (0.6L/h) which means the input/output impedance is mismatched.

Highway consumption yielded a 5.7L/100km average on one trip, and then 6.3l for the return trip, so I would say a 6L/100km is achievable. Stock was around 8L, with RaceChip around 7L. I think that's pretty impressive, 25% highway mileage increase - see updates at the end of the post.

Here are the settings used during the test drive:

Power

Torque is lower, but still adequate for day-to-day driving. I measured a stock 0-100km/h time of 8s, I would guesstimate now it's 10-12s. The car had no issues reaching 170km/h so there was no reason to do more tests, for now. My goal is improved mileage, a target of 1300km with one tank.

Findings and improvements

As I wrote above, the input/output impedance is really sensitive and there is no way to get a precise setting for each car. So my next step would be to design another simplified circuit with a relay. The relay would initially pass the sensor line to the ECU while de-energized, and use the Arduino 'passthrough' if energized.
During the calibration phase the Arduino would sample the input at the relay while it's off. When turning on, it will check if the input is the same through it's own circuit; if not, it will calibrate the input. It will then measure its own output and compare it to the input, when no modifications are applied. It will then save the output calibration constant.
Either way, there should be at least two trimmer pots or perhaps digital pots, 1-15k for the input pull-up and 10-100ohms for the output. Of course the RC constant of the output filter is also affected by this.

Firmware

There was an error in the Arduino playground EEPROM snippet, it reads a byte (0-255) and compares it with a char (-128 to 127) which fails the verification on values larger than 127.
I found the need of storing several curves inside the EEPROM, perhaps number 1 should be the default and have another 5 or so for testing (focused on power, consumption, city, highway etc).

The curve size of 10 points is a bit too coarse, perhaps I will increase it to 20 points.

'Packaging'

I've used a plastic food container to house the circuit. The plug was molded with hot glue as I cannot find any DB25 in my parts bin and still cannot source the original connectors. Bluetooth reception from inside the car is ok.

The small circuit board provides the input pullup, RC output filter and a way to probe and connect signals. I had to change its layout and components many times, which is why it looks like it has survived a war.

Update December 2016

In September I've had some problems with the DPF which caused me to initially suspect the custom module. However it turned out to be just a bad sensor that had to be replaced.
At that time I also took careful measurements of the consumption and found out that the OBC display was erroneous - the actual consumption was higher than reported.

I was worried that the increased consumption could flood the DPF causing costly repairs with seemingly no added benefit. However, I took the car to a dealer to have the real DPF soot measured and it was within nominal parameters (i.e. <6 grams).

I've since removed the module from the car but haven't done a lot of driving so without a definitive consumption baseline it's hard to tout any benefits. So far, stock, I'm getting 9L/100km in mixed driving and 12-15L in heavy traffic. I will need to do more precise measurements when refueling to see if that is a real value. If that is indeed a real value then the saving of the module is probably not 25% but still could be above 10%.

I need to see if I can access some real fuel flow data through OBD instead of the one derived by the OBC (which probably uses the rail pressure in addition to the flow meter).

TL;DR: the OBC display is way off sometimes and I cannot confirm any measurements. No negative side-effects have been observed.