RX8 Project – Part 20, Canbus #5, RX8 Odometer

So again for this post I’m going to concentrate on one specific aspect of the RX8 CANbus system which a few people have asked me about and that’s making the ODOmeter on the cluster tick up correctly without the factory PCM (ECU) being fitted to the car. This also allows the trip A and B meters to work correctly as they are all linked to the same register.

I’ve mentioned in previously to people that the odo requires a state change to update and I think this is why people haven’t been able to identify what controls it – simply writing a value doesn’t do anything. It is controlled via byte 1 of what I defined as statusMIL, this is CAN ID 0x420 which is the same ID which also controls things like the temperature and oil pressure displays on the dash.

I originally identified how this was controlled during some of my early reverse engineering work on the cluster when I was just sending blocks of values (initially cycling between 00 and FF for all bytes in the array) to CAN ID’s to see if I could make anything happen and I noticed at some stage the trip had increased. Clearly this meant one of the ID’s was doing something and because the same ID also controls various warning lights they also flashed on and off at the same time as the odo incremented which made the identification of the ID rather simple.

Next up I edited the program to count each byte in the CAN data up in order, so for example start with an array with only 00 in each byte then starting at byte 0 increment the value by 1, send the whole array, wait briefly and increment again and so on. When the top value of FF is reached set it back to 00 step on to byte 1 and so on. This allowed me to isolate the specific byte that was controlling the odo changes. Anyway the story goes on and after a lot of trial and error with values and timings I got to this bit of fairly horrible test code:

#include <mcp_can.h>
//#include <mcp_can_dfs.h>      //Declaration for Standard Can
#include "mcp2515_can.h"        //Declaration for Seeedstudio Can Library

#define CANint 7  // Normally 2
#define LED2 23   // Normally 8
#define LED3 0    // Normally 7

#define NOP __asm__ ("nop\n\t")
const int SPI_CS_PIN = 17;
mcp2515_can CAN0(SPI_CS_PIN);   // Declaration for Seeedstudio library
//MCP_CAN CAN0(SPI_CS_PIN);     // Set CS to pin 10 - Older Library version


void setup() {
  Serial.begin(115200);

    delay(1000);    //delay to allow for monitor
    Serial.println("Init…");
    Serial.println("Setup pins");
    pinMode(LED2, OUTPUT);
    pinMode(SS, OUTPUT);
    pinMode(LED3, OUTPUT);
    pinMode(CANint, INPUT);

    Serial.println("CAN init:");
    
    if (CAN0.begin(CAN_500KBPS) == CAN_OK) 
    {
        Serial.println("OK!"); 
    } 
    else 
    {
        Serial.println("fail :-(");
        while (1) 
        {
            Serial.println("Zzz… ");
            delay(1000);
        }
     }

Serial.println("Good to go!");
}

unsigned char statusPCM[8]  = {125,0,0,0,156,0,0,0};                            // Write to 201
unsigned char statusMIL[8]  = {140,0,0,0,1,0,0,0};                              // Write to 420

void loop() 
{
    
    unsigned int i=0;
    unsigned int j=0;
    unsigned int k=0;
    float mile=0;
    unsigned char num;
    
    
   
    //Warning Lights - 0=Error, 1=OK

        for(k=0;k<200;k++)
        {
          
          for(i=0;i<=206;i++)
          {
          
          statusPCM[0] = 50;           //RPM  Value*67 gives 8500 RPM Reading Redline is 127
          statusPCM[1] = 0;           
          statusPCM[2] = 0;
          statusPCM[3] = 0;
          statusPCM[4] = 93;           //Speed  Value=0.63*(Speed)+38.5
          statusPCM[5] = 0;
          statusPCM[6] = 0;
          statusPCM[7] = 0;

          statusMIL[0] = 145;         // Temp 91-0%; 96-10%; 107-25%; 152=50%; 158-75%; 164=100%    
          statusMIL[1] = i;           // Odo / Trip     
          statusMIL[2] = 0;
          statusMIL[3] = 0;
          statusMIL[4] = 1;           // Oil Pressure (0=Off, >=1 is OK)         
          statusMIL[5] = 0;           // Check Engine Light
          statusMIL[6] = 0;           // Battery Charge Light
          statusMIL[7] = 0;
          
            CAN0.sendMsgBuf(0x420, 0, 8, statusMIL);
            delay(20);
            CAN0.sendMsgBuf(0x201, 0, 8, statusPCM);
            delay(20);
          }
          
        Serial.println("Miles : ");
          mile=(k+1)*0.05;
          Serial.println(mile);
      
        } 
while(1){}
}

Basically much of it is the includes and setup which is common on all CAN code but the more interesting bit is the main loop. In essence it just uses two nested loops to count up to a certain value and transmit the new value each time. All the other CAN is just static values to turn off warning lights on the cluster – the the ID 201 isn’t actually required here but it stops extra things blinking at you! Additionally ignore the comments on the statusPCM, while these sort of work I realised later that the speed and RPM use 2 byte blocks rather than a single byte to display all values.

So in the code there are 2 loops, the first is counter “i” which in this counts up to 206 (which is 207 steps including 0) and the second outer loop “k” which counts up to 200 and for each increment of “i” the new byte value is sent over CAN. Now through experimenting with various values for counters in earlier versions of this code I’d come up with the values you see here which seem to be consistently accurate for me. Basically 207 changes of the byte sent to the dash = 0.05 Miles counted so the extra loop “k” multiplies this up to a useful mileage change we can measure on the cluster. every time “k” increments it also sends and update to the serial monitor so we can keep track of it. We can see that 200 loops of 0.05 miles should result in a count of 10 miles and that’s exactly what we get on the trip meter.

The very last line is one you don’t see in many Arduino programs, “while(1){};” makes the program hang at this step. Basically what it’s doing is a normal while loop except using a static 1 as the condition makes it always true but there’s no code in the curly brackets so it will just sit there endlessly doing nothing rather than starting the main loop again as it would normally. This was simply so I could leave the code running to completion (at this stage I was sending CAN data with much wider time delays than needed to make sure none got missed) without it looping back round without me noticing.

So now we can count it up which is interesting but not especially useful as it is but since my car didn’t move I left it here for a long time with the plan to sort it out later. Anyway following my recent posts resurrecting this project there’s been some interest in how to sort it out so I started working on it within my already butchered about derivative of Dave Blackhursts code, which in itself was a further development of much of my earlier work. I’m aiming to post a version of my finalised code for the complete system once I’m happy I’ve got all the features I want but this should give you enough info to understand how this bit works.

Updates by Timer1 Interrupt

First off lets just say this didn’t work quite right for this task so I moved away from timer interrupts but it does include some interesting bits of timer manipulation so I’m including it anyway.

The best idea I had initially was to use the data from the ABS system which gave an accurate speed for all the wheels individually but the problem was I would need to vary the frequency at which the ODO byte was changed such that the ODO rate matched the speed. My first idea here was to use a hardware timer on the Arduino and use a hardware interrupt to increment and send the CAN packet. This would require the timer count value to be calculated on the fly from the ABS data. First I built and Excel spreadsheet which firstly calculated the frequency we need to update and send CAN data at to give the right ODO reading for a given wheel speed.

excel mph to freq conversion

So all this does is some basic calculation,

Pulses per mile * mph = pulses per hour

pulses per hour / 3600 = Hz (updates per second)

1000 / Hz = Millisecond interval per update (used to cross reference from the CAN logger)

From this we can fiddle about with values to see what gives enough range on timer1 (because it’s 16 bit which gives us a much wider range of intervals, timer 0 is only 8 bit and usually used elsewhere in the Arduino IDE) to make this work, or for that matter if it even is possible without dynamically changing the pre-scaler value.

Timer 1 is controlled primarily by register OCR1A which is the value it counts to before the timer resets so we need to work out the correct value for the register to do what we want. Rearranging the standard equation gives us this:

OCR1A = (( Clock_Freq / Required_Freq ) / Prescale ) – 1

Now because the count is a 16 bit integer there will be some error created by rounding on the count value so I added another section which updates to show the error vs the required value.

Excel OCR1A count value calculation

The top two lines are just the standard calculation the middle two lines are where the clock and prescaler values are entered and the OCR1A value is calculated. The 230 and 1.15 come from the previous step automatically. The bottom two lines then return the degree of error resulting.

It looks like we can cover the range we want with a prescaler of 1024 however as the speed goes down below 1mph the period between CAN sends becomes excessively long and beyond the range of the timer (max value of OCR1A is 65535), the limit is approximately 0.21 mph which seems reasonable. This means only 1 update over CAN every 4.1s which it turns out is about the limit anyway because if you make the updates longer than about 4.5s for this ID all the warning lights turn on again between updates but we can handle this case seperately.

Now to get the timer working we need to set up a few other things

TCCR1B options

We want to use CTC mode resets the count value at the top of the count to make it loop round constantly so WGM12(CTC1) in register TCCR1B should be set to 1.

TCCR1B options

Next to get the prescaler value of 1024 we need we set CS12 and CS10 to 1. Lastly OCIE1A in TIMSK1 needs to be set to 1 to trigger the interrupt every time the count reaches the count value set bring it all together and we get something like this :

void setupTimer1() {
  noInterrupts();
  // Clear registers
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  // Freq (Hz) (Clock (Hz) /((OCR1A + 1) * Prescaler))
  OCR1A = 64700;
  // Set CTC mode - trigger interrupt on TOP
  TCCR1B |= (1 << WGM12);
  // Prescaler 1024
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // Output Compare Match A Interrupt Enable
  TIMSK1 |= (1 << OCIE1A);
  // Enable Interrupts
  interrupts();
}

// Send update to cluster on interrupt
ISR(TIMER1_COMPA_vect) {
    // Increment ODO byte each time function is called
  // this makes ODO update based on ISR frequency call.
  // Check speed is > 0.21 mph ( (left+right/2) * 0.337962 * 100
  if ( (frontLeft + frontRight) >= 68){
    send420[1]++;   
  }
   
  CAN0.sendMsgBuf(0x420, 0, 7, send420);
 
  return;
}

Next up to convert from a speed to a timer count value we need to do the same thing on the Arduino that we did in Excel earlier so here’s a quick function which just calculates count.

int calcTimer1Count(float speedKMH){
  float freq;
  int count;
  float speedMPH;
  
  //Serial.print("speed = ");
  //Serial.println(speedKMH);
  speedMPH = speedKMH / 160.934;
  // Required frequency for timer 1 ISR
  //  1.15 is 4140 (Pulse per Mile) / 3600 (1hr in seconds)
  //  0.7146 is 2572.5 (pulse per KM) / 3600
  freq = speedMPH * 1.15; 
  //Serial.print("freq = ");
  //Serial.println(freq);
  // Required OCR1A value based on 16Mhz clock, works best with 1024x prescaler giving minimum 0.21mph
  count = ((16000000 / freq) / 1024) - 1;
  //Serial.print("count = ");
  //Serial.println(count);
  return count;
}

The input here is km/h because that’s what the ABS values are given in so we might as well convert that here as well.

Now in the main loop we’re scanning for incoming data on CAN and checking what the ID is already for the bits to manage the immobiliser exchange and handily in this Dave Blackhurst has already added code to read the ABS data which we know is coming in on ID 4B0 in two byte blocks so we can just update OCR1A with a function call to our new calculation function with the average of the front wheel speeds whenever new ABS data is received.

    if(ID == 0x4B0) {
      frontLeft = (buf[0] * 256) + buf[1] - 10000;
      frontRight = (buf[2] * 256) + buf[3] - 10000;
      rearLeft = (buf[4] * 256) + buf[5] - 10000;
      rearRight = (buf[6] * 256) + buf[7] - 10000;
      
      //Going to check front wheel speeds for any issues, ignoring the rears due to problems created by wheelspin
      if (frontLeft - frontRight > 500 || frontLeft - frontRight < -500) { //more than 5kph difference in wheel speed
        checkEngineMIL = 1; //light up engine warning light and set speed to zero
        vehicleSpeed = 0;
      } else {
        vehicleSpeed = (((frontLeft + frontRight) / 2) / 100); //Get average of front two wheels.
      }
      //Update timer count value with live speed for ODO
      OCR1A = calcTimer1Count((frontLeft + frontRight) / 2);
      
      // Dump speed to serial for debug - this is just a cropped int.
      //Serial.println(vehicleSpeed);
      
    }

Now when I ran the whole program I hit a minor issue, it worked initially and the timer speed changed correctly but after a small number of can packets the Arduino stopped sending any other CAN data. I don’t know what caused it – best guess is when the interrupt was called it was blocking something and causing a buffer overrun somewhere else making the Arduino crash but either way I felt a different approach would probably be quicker than solving that so I moved on.

Updates by Delay

So the alternate approach relies on the main loop running quite quickly and simply counts how much time has elapsed since a function was last called and if over the set value calls the function. This basically allows functions to be called in the loop without needing to slow the loop itself down. The down side here vs interrupts is the accuracy of this is entirely based on the speed of the main loop so if the loop slows down the events will move about in time. Also obviously if the loop is only doing something like 10ms per iteration you will never get something to go faster than that!

void loop() {
  //Send information on the CanBus every 100ms to avoid spamming the system.
  if(millis() - lastRefreshTime >= 100) {
    lastRefreshTime += 100;
    sendOnTenth();
  }

So this is the initial version Dave used in his code to keep the scanning at a decent pace for the CAN reads. The function millis() just returns a counter value in milliseconds since startup. Unfortunately scanning at millisecond rates isn’t going to cut it for the ODO because at say 200mph the update period is 4.35ms so if we work in ms the best we could do assuming the loop ran fast enough is 5ms which means the ODO would be going 15% slower than the vehicle speed. Luckily Arduino also has a similar built in function ‘micros()’ which does the same thing but counts in microseconds. Some of you familiar with binary might be thinking an integer counting up in microseconds will hit its limit very quickly and then it is likely to cause a problem with the calculation however we get round this because the returned value is of type ‘unsigned long’ which gives us a range of up to about 70 minutes before the count resets. Interestingly because of the way data types wrap round like this the variable “lastRefreshTime” can actually be either signed or unsigned and it works the same.

long calcMicrosecODO(float speedKMH){
  long uS;
  float freq;
  float speedMPH;
   
  Serial.print("Speed = ");
  Serial.print(speedKMH/100);
  Serial.println(" km/h");
  speedMPH = speedKMH / 160.934;
  // Required frequency for timer 1 ISR
  //  1.15 is 4140 (Pulse per Mile) / 3600 (1hr in seconds)
  //  0.7146 is 2572.5 (pulse per KM) / 3600
  freq = speedMPH * 1.15; 
  Serial.print("Freq = ");
  Serial.print(freq);
  Serial.println(" Hz");
  uS = 1000000/freq;
  if(uS < 4500000 && uS > 0){
    return (uS);}
  else {
    return (4500000);
  }

Similarly to the previous interrupt version we have a function which calculates the correct delay required to keep the ODO at the right frequency, there are some minor differences to work in microseconds and if the speed is too slow cap the output at 4500000us (4.5s). Otherwise it’s much the same.

    if(ID == 0x4B0) {
      frontLeft = (buf[0] * 256) + buf[1] - 10000;
      frontRight = (buf[2] * 256) + buf[3] - 10000;
      rearLeft = (buf[4] * 256) + buf[5] - 10000;
      rearRight = (buf[6] * 256) + buf[7] - 10000;
      
      //Going to check front wheel speeds for any issues, ignoring the rears due to problems created by wheelspin
      if (frontLeft - frontRight > 500 || frontLeft - frontRight < -500) { //more than 5kph difference in wheel speed
        checkEngineMIL = 1; //light up engine warning light and set speed to zero
        vehicleSpeed = 0;
      } else {
        vehicleSpeed = (((frontLeft + frontRight) / 2) / 100); //Get average of front two wheels.
      }
      //Update timer count value with live speed for ODO
      ODOus = calcMicrosecODO((frontLeft + frontRight) / 2);
      
      Serial.print("ODO Step : ");
      Serial.print(ODOus);
      Serial.println("us");
      // Dump speed to serial for debug - this is just a cropped int.
      //Serial.println(vehicleSpeed);
      
    }

Above we see the call for ‘calcMicrosecODO’ which is basically the same as the interrupt version but gives an actual time delay in microseconds rather than a timer count. It is called in this way with a calculation in the parameter field because if it is stored in a variable in between the number gets cropped off at the decimal point even if the variable is a float – I believe this is due to the way Arduino processes floats.

void loop() {
  //Send information on the CanBus every 100ms to avoid spamming the system.
  if(micros() - lastRefreshTime >= 100000) {
    lastRefreshTime += 100000;
    sendOnTenth();
  }
  // Call function to updateMIL on variable timebase
   if(micros() - ODORefreshTime >= ODOus) {
   ODORefreshTime += ODOus;
    sendOnClock();
  }

So our extra call for the variable timed refresh is above, it varies a bit from the first one because we have a varying time delay depending on the frequency required which here is a long we are calling ‘ODOus’ which we calculated previously. Obviously because we are using two comparisons we need another refresh time variable to keep them distinct, this is also a long. Also the second one calls a specific function for the variable time refreshes ‘sendOnClock()’

void sendOnClock(){
  // Do not increment ODO byte when step is = 4.5s
  // slower than this updateMIL must still be called so 
  // warning lights don't turn on but speed may be zero!
  if ( ODOus < 4500000){
    send420[1]++;   
  }
  updateMIL();
  CAN0.sendMsgBuf(0x420, 0, 7, send420);
}

This function is pretty basic, all it’s doing is checking the resulting ODOus value isn’t 4.5s because if it is this value is means the calculation is at it’s upper limit and the car isn’t moving (specifically the speed is below 0.21 mph). In this state it still updates the warning light registers and sends the CAN packet to keep the warning lights from blinking on but it doesn’t increment the ODO byte value so the ODO doesn’t continue to tick on.

// Time delay for Odo
long ODOus = 4500000;      

// Set to max 4,500,000 to keep dash 
// MIL warning lights awake at 0 speed

The declaration for ODOus is set as 4,500,000 at start up so it correctly. The only downside to this is it takes a few seconds for the dash lights to go out initially and the oil pressure gauge goes to normal in two steps. This could be dramatically improved either by setting a higher minimum speed at which the ODO ticks because even increasing to 0.5 mph would improve the maximum duration to 1.7 seconds. Another option to avoid this is just to send an update to 0x420 in between the ODO calls. If we keep the one to the other loop ‘sendOnTenth’ without incrementing the ODO value it will just display any changes to the warning lights almost instantly while keeping the ODO working correctly.

void sendOnTenth() {
  //  PCM Status's to mimic the PCM being there, these may be different for different cars, 
  //  and not all are always required, better safe and include them all.
  CAN0.sendMsgBuf(0x203, 0, 7, send203);
  CAN0.sendMsgBuf(0x215, 0, 8, send215);
  CAN0.sendMsgBuf(0x231, 0, 8, send231);
  CAN0.sendMsgBuf(0x240, 0, 8, send240);
  CAN0.sendMsgBuf(0x620, 0, 7, send620);
  CAN0.sendMsgBuf(0x630, 0, 8, send630);
  CAN0.sendMsgBuf(0x650, 0, 1, send650);
  
  updateMIL();
  CAN0.sendMsgBuf(0x420, 0, 7, send420);    // Duplicated in sendOnClock to update ODO

  updatePCM();
  CAN0.sendMsgBuf(0x201, 0, 8, send201);

So that’s it but I should probably mention that I’ve not tested this on a live car however I have a program which works out the correct CAN byte values and then builds a correctly formatted string which can be pasted into USBtinViewer and sent to simulate an update from the ABS and the Arduino and cluster all seem to respond correctly:

Labview speed to CAN bytes converter  front panel
Labview speed to CAN bytes converter  front panel code

In this code you will see a scaling factor of 100 which should be correct but on my cluster I seem to get a speedometer reading 1 mph higher than intended from a calculated 5-185mph I actually see 6-186 mph on the cluster. I’m not sure why this is but it may be on purpose due to the common requirement for speedometers to never read lower than true speed. Indicated speed is required to be within -0% / +10% + 4km/h of actual speed in the EU. Technically we could correct this by doing two vehicle speed calculations on the Arduino, one for the odometer calculation using the proper scaling factors to keep it accurate and one for the displayed vehicle speed using a scaling factor which corrects this error. I do not intend to do this but I have found a scaling factor of 99 rather than 100 makes the speedometer match up if required.

As ever your mileage may vary, but hopefully it’ll closer than it was before! As I said earlier this is part of another major overhaul of the code and I’m intending to publish the final version as a complete code when I’m happy I’ve got everything working but that might take some time.

RX8 Project – Part 19, Canbus #4, The Comeback!

Lets be clear before we start – This will not allow you to start a car with a factory ECU with the wrong key or by bypassing the immobiliser. This is to do with making things like engine swaps work fully in the car without the factory ECU connected.

I’m going to apologise right now, there’s quite a lot of background about how I investigated the process of the ECU talking to the immobiliser in this one, if you don’t care and just want the CAN info scroll down a bit. I’ll write a complete update of all the codes when this phase of work is all done.

As some of you are probably aware my RX8 engine swap has been going on some time for a variety of reasons but specifically due to not having cover and so not easily being able to hook the car CANbus up to my computer to do live diagnostics I had hit something of a problem. I couldn’t generate data fast enough to fake all the devices on the bus reliably to test things on my desk away from the car but had no-where undercover to work with it connected to a PC so largely I’d planned to concentrate on organising a garage – something that should have happened more than a year ago now but due to the pandemic and related 2020 problems that not gone as well as hoped!

Anyway a few months ago on trying to find a CAN diagram for the car to aid answering a comment someone posted on here (yes I do try to answer them but I know sometimes it takes a while – I’m hoping to keep a better eye on it this year!) I came across a video from a guy called Dave Blackhurst (this one) which was rather interesting as he apparently had my two main issues from my previous code sorted, specifically the immobiliser system (the thing I want to look at here) and the power steering.

So to see how he was doing it I went to the linked Github and downloaded his Arduino code and on opening it I was largely very familiar code, specifically a whole set of variable declarations for the various dash instruments and a large section of code related to using a boolean variable to set the correct bit in the corresponding CAN packet so individual warning lights can be turned on or off and the speed/RPM etc to all be set easily on the cluster. So this was basically a development of my previous work

Now just to be clear this isn’t a complaint. This is just the first time I’d see my work go full circle and someone else actually develop it further which was quite exciting. If I hadn’t wanted it used and developed I wouldn’t have posted it online! Even better was it gave me a kick to have another go at it and at the very least try this new and improved code which said it fixed all the issues because if true Dave might have just solved my remaining problems!

So back to the immobiliser. I’d never managed to get the immobiliser light to go out despite trying all sorts of combinations of data from the logs I had but after seeing what Dave had done I realised I’d been missing a critical bit of information. The CAN logs I’d previously worked from were predominantly provided but someone else who contacted me via the blog and so were from two other cars and not my own. Additionally you can see in the early blog posts I actually built my own CANbus board several years ago which worked but had some speed issues with all the work it was doing. This was because when I started this project several years ago there was little else available for sensible money so it was the only real option. Long story short the immobiliser relies on a very short data exchange which occurs when the ignition key is first turned on and is never repeated and basically it had just been missed by the loggers that I had data from previously so I may never have figured it out!

Excited at the prospect of this just being a load the code and go I wondered if in the intervening years better hardware was available for this job than my old Arduino Nano based DIY job and there are now various Arduino expansion shields for CAN but to me these were all rather clunky solutions so I started looking at the “Feather” range which has a couple options but again these were a board and a piggback interface which isn’t what I wanted and there’s a new one which is the Adafruid Feather M4 CAN which looked pretty good but doesn’t seem to have ever actually been in stock anywhere so moving on.

Adafruit Feather M4 CAN

Following this I had a realisation – if if was going on the car it really didn’t need an integrated battery. Previously I’d started using Leonardo based modules for projects and these proved very quick for most tasks and have integrated USB meaning data throughput can be faster so I tried to find a Leonardo based CAN module. Eventually I found a company who I’ve used before for various neat modules do basically exactly what I was after for a reasonable price, enter Hobbytronics and their L-CANBUS board.

Leonardo CAN BUS board
Hobbytronics Leonardo Canbus

Looks just the job and even comes with the headers and 9 way connector unsoldered. and the board itself has pads for screw terminals to be soldered in place of the 9 way connector for bare wire connections. This time round I decided I wasn’t going to mess about with screw terminals while testing so I splashed out and bought a £10 OBD2 – 9 Way D-Sub CAN cable off eBay to go with it (unfortunately Hobbytronics were out of stock of the cable). This also had the advantage of including 12V and ground connections which are routed to the board regulator so the module is powered directly off the OBD2 port on the car making testing really easy.

I also decided being powered off the car that rather than risk shorting the module/car it needed a case and since I recently was given what I believe is still the cheapest 3d printer on eBay by a friend who got so annoyed with it he bought one that was actually good, so I designed a 3d printable one :

It’s pretty basic, the holes should be undersize for an M2.5 laptop screw so they basically thread cut it when you first put them in. Not ideal but it’s what I had. M2.5 sized plastic screws with a coarser thread would be better but either way it held fine. This case also leaves the USB accessible.

Anyway, back to the point we now have some nice neat hardware so I tweaked the code to run on this module (different CAN pins to the normal Adafruit CAN shields) and flashed it. After plugging it into the car…nothing happened. Once I’d reflashed the Leonardo with CLK_OUT enabled as per the instructions following a conversation with Hobbytronics who were very helpful (in their defence it says to do it right on the product page but I’d not read that bit!) I loaded it again and when hooked up to the car what I got was the basic warning lights went off, but the immobiliser and power steering that I’d hoped to resolve were still there. Time to delve a bit deeper!

So looking at Dave’s code here’s the bit to resolve the immobiliser:

 if(CAN_MSGAVAIL == CAN0.checkReceive()) { 
  // Check to see whether data is read
 }
    CAN0.readMsgBufID(&ID, &len, buf);    // Read data

        
    //Keyless Control Module and Immobiliser want to have a chat with the PCM, this deals with the conversation
    
    if(ID == 0x47) { //71 Dec is 47 Hex - Keyless Chat
      
      //***** Fixed Coding for Dave Blackhurst's Car *******
      if(buf[1] == 127 && buf[2] == 2) {      
        // Look for 0x 06 7F 02 00 00 00 00 00
      }
        CAN0.sendMsgBuf(0x041, 0, 8, send41a);// 0x041 = 65
        // send41a = 0x 07 0C 30 F2 17 00 00 00
      }
      if(buf[1] == 92 && buf[2] == 244) {     
        // Look for 0x 08 5C F4 65 22 01 00 00
      }
        CAN0.sendMsgBuf(0x041, 0, 8, send41b);
        // send41b = 0x 81 7F 00 00 00 00 00 00
      }

I’ve added in the codes being looked for or sent in each case which Dave identified from scanning the bus on his RX8 just to make it easier to see what’s going on. Breaking this down ID 0x47 is the immobiliser module sending data out which generally seems to just keep repeating 0x06 01 FF 00 00 00 00 00 when in normal use with the car running as factory I have that from my previous logs. So this first code starting 0x 06 7F 02 is something from the immobiliser which triggers the exchange. The code basically just reads any incoming data then checks the ID is 0x47 (i.e. it’s coming from the immobiliser) and that two bytes match the what he knows the CAN data should be (simpler than checking the whole code) , specifically byte 1 being 127 (7F) and byte 2 being 2. He then sends the recorded response to this (send41a – 0x 07 0C 30…) back to the immobiliser which would normally be done by the PCM (ECU) in the car when present. Then we look for the response from the immobiliser matches what we expect (0x 08 5C F4….) and sends a second reply to the immobiliser (send41b – 0x 81 7F 00….). I started thinking the module wasn’t talking to the CANbus right but after some fault finding and adding a diagnostic LED blink at critical points I found it was on the bus but just wasn’t seeing the right data coming from the immobiliser to respond to. Now I knew this exchange worked on Dave’s car but not on mine so clearly the codes we have aren’t universal in some way but I needed to work out what was going on but at least I knew what to look for.

Back when I was trying to find the code to disable the power steering light from Labview I bought a device called the USBtin which is a neat little PCB which is basically just a USB to CAN adapter but it has a built in protocol to control it so you can read the data via software like Putty or relative easily develop custom applications to connect to it. Now facing this problem I decided to give it a go and see if it was actually fast enough to catch this exchange in the first few fractions of a second of the ignition being on. I blew the dust of the original ECU for the car and hooked it back up to the bus (there’s no engine but I hoped that wouldn’t matter for this bit) loaded the basic USBtinViewer onto a tabled and hooked it up.

Ok it’s a photo of a tablet screen but anyway, the point is the USBtin is clearly fast enough to catch all the data because the monitor mode shows it’s caught the exchange because it’s logged packets to ID 0x41 and 0x47 and the last message to 0x41 matches the last one from Dave’s car (send41b – 0x 81 7F…). So it’s got the data, unfortunately to see what was sent both ways I had to trawl through the trace mode which just lists every CAN packet on the bus but after a bit of searching I found this:

So going through it first and ignoring all the extra data (there will be more to follow on this) there’s the default message from the immobiliser sending 06 01 FF… highlighted in yellow, then shortly afterward we see what looks very similar to Dave’s first message of the exchange but where his was 0x 06 7F 02, mine critically is 0x 06 7F 01. Looking back to Dave’s code for this we find that he was specifically looking for byte 2 = 2 and mine is 1, which is probably why it never triggered on my car. Now because that first packet we need to match starts 0x 06 7F … on both cars I can just change the check to look for that combination instead but at this point I also realised the outgoing data from the ECU (0x 07…) and return from the immobiliser (0x 08…) are totally different for my car so rather than mess about I just swapped out both to match what I’d logged for my car (assuming the codes may be car specific to stop PCM’s (ECU’s) being swapped between vehicles they’re not coded to or something) and tried it again, but this time…

Yes this time it cleared the security light! Definitely progress!

But for me making it work isn’t really enough and I like to understand why something works and hopefully make it better!

First off I tried again but this time with the matching done using the updated positions for the consistent bits of the code common to both cars. Specifically getting rid of the check for the byte 2 being any value because this appeared to change from car to car. What we can reasonably assume is fixed from this data is byte 0 because they always seem to indicate the step in the exchange with the exception of the initialisation state and first request state which both start “06” however byte 1 gives us if the immobiliser is still starting (0x 06 01…) and making a request to the PCM (0x 06 7F) and these match on both cars. We then send back one of the first response packets (0x 07….) and wait for the next request which byte comparing the data both cars start with byte 0 = 08 and based on the rest it’s reasonable to assume again this is the sequence step and so universal. Then Dave looks for a value of byte 2 which differs between our cars, however I have noticed that byte 5 for both cars is always 01 so this would work for both. So we end up with this :

      
      byte send41a[8] = {7,120,192,226,94,0,0,0};                      
      // Reply to 47 first  : 0x 07 78 C0 E2 5E 00 00 00 
      // Bytes 0 is the same, bytes 3 & 4 dont seem to matter, 
      // 5,6,7 are zero
      
      byte send41b[8] = {129,127,0,0,0,0,0,0};                         
      // Reply to 47 second : 0x 81 7F
      
      //***** Fixed Coding for Jon's Car *******
      // Some experimentation showed that on the initial request
      // for my car byte 2 was a 01 not a 02
      // however all codes so far begin 06 7F 
      // for either car so this was used.
      // Similarly in the second message from the 
      // immobiliser bytes 1-4 change but byte 5 
      // is always 01 on either vehicle

      if(buf[0] == 0x6 && buf[1] == 0x7F ) {                      
        // 0x 06 7F 01 00 00 00 00 32
        
        // printhex(buf,8);                                        
        // Transmit out received request on debug serial port 
        // - breaks timings on vehicle.
        
        CAN0.sendMsgBuf(0x041, 0, 8, send41a);                    
        // 0x 07 78 C0 E2 5E 00 00 00 
      }
      if(buf[0] == 0x8 && buf[5] == 0x1 ) {                        
        // 0x 08 94 29 BC 91 01 00 32
        
        CAN0.sendMsgBuf(0x041, 0, 8, send41b);                     
        // 0x 81 7F 00 00 00 00 00 00  
      }

I’ve included the notes I made at the time – the printhex is a function I wrote to dump these arrays out to the serial port easily as two digit hex pairs for monitoring what’s going on at different times. As noted here it breaks the timings of the exchange between the ECU and immobiliser but if we want to check something we just add it in and at least we can see what the data was. I’ll do a separate post for that as it might be useful to others. Not unexpectedly matching in this way worked fine but more interestingly I tried my car with Dave’s codes matching in this new way and interestingly it actually worked with no security light…

Well that raises even more questions because in theory I’d just swapped my ECU for his (in terms of the code exchange at least) and it authenticated!

So I went back to my car, reconnected the original ECU, powered it up with the USB logger again and noticed that each time I turned my ignition on the code exchange was different so clearly the idea of the code being fixed for a pair of ECU and immobiliser was wrong. After a number of goes and recording all the results a few things started to become apparent.

Firstly the initial request from the immobiliser had some variations on bytes 7 and 8 which always matched the byte 7 and 8 in the second request but the bytes we look for (byte 0 and 1 shown in green) are always 06 7F in every try.

Second, the first response given by the ECU indeed always starts 07 (light blue), but the next 4 bytes change each time the ignition is turned on (bright blue).

Third, bytes 0 and 5 in the second request are always 08 and 01 respectively (orange) however the 4 bytes between change each time the ignition is turned on (yellow).

Fourth, the second response is always the same (pink).

So what I think is going on here is actually something slightly different. If we assume for a moment the ECU knows the code or processing going on in the immobiliser we get a proper challenge/response interaction. I think the first message sent by the immobiliser is basically a “ready” message telling the ECU to send a block of data. The ECU then responds with a 4 byte block of data which is randomised each start. The immobiliser then performs some function we don’t know and sends the result back to the ECU where it checks the result against what it should be and gives a pass or fail back to the immobiliser so it updates the dash light. The last packet is always the same because we’re using everything from one car so its a pass so we don’t know what a mismatch fail looks like yet but I’m going to look into this at some point.

Now the interesting result of this outcome is with our Arduino we’re not checking if the code response actually matches and if my theory is right the outbound 4 bytes can be absolutely anything as it’s basically just a seed value, then the immobiliser will will reply with a coded version which we just ignore and so long as we reply with a pass message at that point (0x 81 7F 00 00 00 00 00 00)the immobiliser turns the dash light off.

To prove this out I set up the Arduino to send different random numbers in each of bytes 1-4 to the immobiliser in the initial response and indeed while the response from the immobiliser bytes 1-4 change as in response the immobiliser light went out on the dash every time.

My final theory is that the immobiliser module is reading the data from the chip in the key, and using that to transform the initial data from the ECU to create the response and since the ECU knows the key code and whatever this transformation is it knows if it’s the right key or not.

Now hopefully that problems solved for all RX8’s, I’m aware I haven’t posted a full, complete code like I have done previously but that’s because it has all sorts of other features going in this currently and I’ve not finished and tidied the rest of it yet. I’ve also considered the situation where there might be an RX8 out there that doesn’t match the code pattern found in my current sample of two vehicles so I’ve actually added a feature where if you jumper a wire onto a digital input and connect the Arduino to a car with the original ECU in place it will read out the entire code exchange and store all the codes for that car in EEPROM on the Arduino. If you then take the jumper off and pull out the ECU, when you turn the ignition on again the Arduino will use the codes it just stored instead of the defaults. Again I’ll write this up properly when it’s all finished.

Finally thanks to Dave Blackhurst for your work on this. While your solution didn’t work for my immobiliser it gave me the drive to have another go and enough information to go in the right direction and hopefully we’re a step closer to a universal engine/motor swap solution for everyone.

More to follow!

RX8 Project – Part 18, Resurfacing Cylinder Heads the Cheap Way!

As ever do this at your own risk. For most people you’re better off just getting heads machined by a specialist but if you’re reading this blog you’re probably already aware that’s not always the way I do it!

So this idea came from me wondering how I could easily clean up the cylinder heads on the V6 without additional machining. The heads were generally in good condition so I just wanted a fresh surface for the new head gaskets to seal well on rather than trying to remove any surface damage or warping. If you have this sort of damage this method is not for you.

When I came up against this problem I decided to do some research and found quite a few people online saying you could just do it with suitable abrasive paper and a sanding block. Now I get the idea but the engineer in me sees a good possibility of some part getting ground back more than another actually increasing the issues with the head that we’re trying to remove in the first place. Around this time I spoke with a few different people who have experience with engines and they all said much the same thing – machine skimming is safest and easiest but with enough care it should be possible to do a perfectly good job by hand, the problem is getting the whole thing completely flat which is very difficult by hand. Most people who had done this seemed to have done it on engines with small cylinder heads such as single cylinder machine engines which being small are easier to get flat by hand.

The problem was absolutely one of getting something suitably flat that would cover the whole head to get the whole thing even so I started looking into what might work. I was already aware of engineers surface tables which are used for checking flatness but these are large, heavy and very expensive as they’re often made of stone or tool steel. I then looked at getting some surface ground steel plate (where a thick steel place is ground to a precision flatness) but again this seemed to be expensive and awkward. After a bit of thought I had an idea…

£4 eBay coffee table


Ok, so at first glance this seems like a daft idea but stick with me! The cheapest and most rigid precisely flat surface I could find was a piece of toughened float glass. Specifically toughened because it is created in such as way as to pre-stress the surface which makes it both stronger and stiffer but also much more brittle – this is the glass that breaks down into granules when broken rather than shards. Initially my plan was to just order a decent sized bit but that seemed rather wasteful so I thought about it and realised second hand furniture included quite sizeable bits of the glass. I began searching eBay and Facebook marketplace to see if I could find something suitable as cheaply as possible and after a week or so found this coffee table. It was nearby and listed as local collection only with some damage to the wood veneer and scratches on top surface of the glass (so the price was unlikely to go high) and 99p no reserve starting. Couple days later I was the proud owner of a £4 coffee table!

Now you may be wondering why we aren’t bothered about the surface scratches on the glass which is likely to be a problem with any similar furniture. The reason is twofold, firstly due to this being toughened glass any scratches are likely to only be very minor and secondly the glass has a whole other side which is unlikely to have any scratches anyway so we’re going to use the underside.

I took the table apart carefully removing the top and to give additional support I placed it flat on a 19mm (3/4″) thick bit of chip board carefully screwing an section of baton at each end to stop the glass sliding about while we’re working. This assembly when then placed on my carpet which is just very hard office carpet tiles on concrete so shouldn’t allow any appreciable movement so hopefully with that stack of support the glass should be perfectly flat even with a cylinder head on it! The abrasive I will be using is wet and dry paper in a range of coarseness, get a pack of each grade you plan to use, it will take a lot of it! I made sure the wet and dry would stay in place by spraying the back of it with spray mount adhesive and putting it in place. Spray mount should also peel off relatively easily when we need to change the paper. I used 3 sheets to create an area larger than the head face in both length and width.

Glass coffee table refinishing rig


So now we have our setup we need to prepare the cylinder head for this. When it came off the engine it was quite grimy as you might expect so this needed addressing.

Head with worst of gasket scraped off


So here you can see how it was when it was (almost) fresh off the engine but with the residual head gasket material scraped off. You can see the amount of grime isn’t too bad, I have already wiped some off the top half but the bottom is a bit more representative. You can also clearly see the outline marks from the head gasket that we’re looking to remove later. This step basically involved soaking the mating face in a de-greaser then wiping it all off carefully.

Head during degreasing
Head after degreasing but before refinishing


It’s not perfect but it’s a huge improvement on where we started. The combustion chambers are considerably better. There’s some residual on the face but its more staining than anything else and will be removed by the refacing. So now we’re ready to go.

First cover the wet and dry with your chosen lubricant – water should work but I found WD40 seemed to work better as it helped the head ‘glide’ more. A light oil like 3in1 would probably be even better as it’s a little thicker again and WD40 tends to dissolve the spray adhesive as you work making the wet&dry come loose. Take the head and place it on the wet and dry (I started at 120 grit) holding both sides lightly start to slide it across the surface. There are different approaches to this where you can angle the head first one way then the other to give a crosshatch pattern. In my case I generally moved it in a long oval and this seemed to give a nice even finish but as ever your mileage may vary!

Cylinder head sat on DIY refinishing setup

You will find that as you work the oil and metal shavings will spread so I suggest doing it somewhere you don’t mind the mess!

This will take some time and effort. If the wet and dry wears down replace it. when you’re happy with the initial surface being clean of all the minor marks and debris you can go up to increasingly fine levels of grit for a better finish.

On the subject of finishes when I was doing this work I found the following information which relates the abrasive rating with the achieved resulting surface roughness – if anyone knows where this is from please let me know as I can’t seem to find out.

US GritUK Grit Ra µmRa µinch
 P1203125
 P180285
80 1.6570
 P2401.550
 P3200.7530
180 0.6225
240 0.4518
 P5000.415
320 0.2510
Comparison of grits vs achieved surface finish

So in the context of this I’m working in UK grit. Unfortunately the only information I could find on the required surface finishes for head gaskets came from the US so is in Ra µinch (Ra being the roughness average of the surface) but luckily this table equates everything. Generally normal gaskets seem to need a surface finish of about 50-60 Ra µinch, modern multi layer steel head gaskets require 30 Ra µinch or smoother so we need to finish at a minimum of P320. I actually went up to P400 to be safe.

Comparison between not touched and work in progress cylinder head


This is the comparison of the untouched head and the one with the first couple of grits done and so not quite finished but you can see the massive improvement made here.

Head surface reflection

I know judging by eye isn’t accurate but it’s clearly doing something good!

Keep going until you do all the grits you need and when you’re done then you need to check the flatness. I did this with an engineers straight edge (as opposed to a builders straight edge which is a big ruler) which cost £25 off ebay. This is a bit of steel that has been precision ground to be completely straight in one plane so is often only a couple mm thick but 70mm wide or more. You check the flatness by putting the straight edge perpendicular to the head (so it sticks up) and trying to slide a feeler gauge under the mid point (or as close as possible) of the area you’re checking. You need to check the width, length and both diagonals but also check across all the bores. The head should have no more than 0.075 mm off flat over the longest span on an iron head, or 0.05 mm off flat on an aluminium head on a V6. In my case the smallest feeler I have is 0.04mm so that proved it was good enough but to check it further I got some thin foil, checked the thickness with a digital micrometer which came out as 0.01mm and placed the foil on one of the central bridges of the head and put the straight edge on and it rocked on the foil. I then redid the test with the foil at the ends and the same again in other directions. Each time the straight edge was clearly resting on the foil first so the head must be flat to <0.01mm across the whole head. Unfortunately I neglected to take any photos of this stage but there’s plenty of information online.

That’s about as good as it gets so our £4 coffee table looks like a success. Plus I still own a coffee table – albeit with a few new scratches!

RX8 Project – Part 17, Changing to a concentric clutch slave.

To preface this I’ve not actually run the car with this setup yet so please make your own decision if you give it a go. This was done on the gearbox from a 2006 year RX8 5 speed box so may not be applicable to others. It looks like it should work but that’s only my opinion – your mileage may vary!

So this is a bit of an odd problem which depending on the engine you’re swapping in may not be and issue but in my case I decided a V6 was a good idea and unfortunately the standard clutch slave on the RX8 gearbox is on the top offset to one side which lines up perfectly with one of the cylinder heads on my V6. Add to this if you made the better decision mentioned earlier and made the adapter thicker you may be able to avoid this as well. But since I’m largely making this up as I go along here we are!

Now I did look into whether anyone offered a concentric slave conversion for this car but it seems that was never a thing anyone did so I set to work building my own. Luckily there was one thing I knew which would help this process quite a bit – the input shaft on the gearbox is the same diameter/spline as most Ford patterns and so a Ford part should be exactly the right clearance. Add to that I’m actually using a Ford clutch if I get the depth right everything should just match up ok.

So that’s the good news, the bad news is the RX8 gearbox was never intended to be used in this way so mounting a cylinder could be an issue. Now on the RX8 there’s a flanged sleeve mounted which the original release bearing slides on the outside of. This is held on by four bolts into the back of the bellhousing and so this appeared to be essentially the only option. The tube itself can’t stay because the new concentric slave is the same ID and so clashes with it but I thought why don’t I just unbolt the tube at the flange and bolt a suitable adapter there and we’re good to go? Well it’s never that easy is it. Under that flange is a location lip which not only keeps it concentric to the gearbox input shaft but it turns out it also the height of the shoulder accurately holds the input bearing in place behind it so if I just remove that whole part the bearing will move out of position and that will very likely result in it not having enough support and rapidly removing itself from the gearbox in small pieces.

3D model of the RX8 gearbox input bearing retainer
Unfortunately I can’t find a photo of it but the part looked like this!

Ok so I can’t just remove the flanged tube and stick an adapter plate on but how about cutting the tube down to the flange to leave a flat face above the bearing retainer and just using some longer bolts to keep it all in place. After some very careful trimming I was left with this:

Modified RX8 bearing retainer

Next was picking a suitable concentric slave from the Ford range. After a bit of poking about and trying to find something I could make fit I found the Teckmarx TMCS00047 which is a 3rd party part number for a 2001-2007 Mk3 Mondeo/Cougar among others which as you might have read earlier was also available with this same V6 engine I am using and this model has a few advantages firstly that both in and out hydraulics are in one direction so if I make that line up with the original position of the clutch fork I should have easy access and also that they’re threaded the standard M10x1 brake fitting thread so I can direct connect hoses or hardline as I need to make it work. another major advantage is they’re used on loads of versions of the car so they’re widely available and very cheap at under £25 delivered. It also seems that the RX8 also has almost same clutch master cylinder bore as the Mondeo (18mm vs 19mm) which should mean pedal travel is still sensible.

Mondeo mk3 concentric clutch slave

3D model of Mk3 Mondeo Clutch slave

Now with the clutch slave accurately 3D modelled I could measure the 4 bolt flange from the gearbox bearing retainer and by overlaying the two bolt patterns aligned on the centre of the input shaft I could design an adapter which I could index the relative rotational angle of the bolt patterns in the software until the fluid connections where in the right place for the hole in the bellhousing. The resulting first version was this :

3D design of first adapter design

Initially I transferred this to a bit of scrap plastic to make sure I hadn’t made any stupid mistakes before spending much more time cutting a proper steel adapter plate.

Plastic prototype RX8 clutch slave adapter

So with all that checked out and nothing apparently an issue I moved onto the steel one. I did make a mistake here if you can spot it…

To make the adapter I did the same as I had done with the plastic where I printed out the design at 100% scale, stuck it to the steel and then used a centre punch to mark the centre of all the drill positions. I admit this isn’t the most accurate method but it seems to work quite well!

Clutch slave adapter Mk1 in steel

This is the initial adapter, the four larger holes are M8 clearance holes. on the original RX8 flanged retainer they’re 9.4mm but I think I did them 8.5mm as that’s the drill I had available and tightening up the tolerance was probably a good thing. This actually turned out to be less of a problem in the end but that’s another story. The centre hole is larger than the original design to allow for the location feature I’d overlooked on the new slave (which is 42mm OD) to sit within it.

Clutch slave adapter trial fitted to the gearbox

So it fits, I called this good progress but it should come as absolute no surprise that it wasn’t quite that simple…

Clutch slave unit fitted to adapter plate

As soon as I tried to add the clutch slave all the issues become apparent as it just clashed with everything. This told me that I’d need to change the adapter to countersunk bolts so the slave didn’t foul them. I could have changed the rotation but I wanted to avoid having lengths of pipe in the bell housing if I could. Plus I’d already made this steel adapter and didn’t want to do it again!

The other thing I noticed is that the cast webs off the original pivot point actually clashed with the adapter plate preventing it from quite sitting flat so I decided to remove some of the plate to correct this minor issue.

Now the adapter sits flat and at the same time I countersunk all the adapter bolt holes and replaced the bolts.

It all fits more or less where I wanted it but when I tried to bolt up the gearbox I saw another problem. With the bearing retainer plate, a sensible thickness for an adapter plate and the height of the concentric slave itself the slave was already almost fully pressed down so that which it may have worked initially as the clutch wore the slave would prevent the clutch from fully re-engaging. Clearly not ideal so we need to get more radical. First off the back of the clutch slave had a lip similar to the one on the RX8 flanged plate which initially I was just going to leave on and sit on top of the bearing retainer plate as it was slightly thicker than the adapter plate but that just wasn’t an option any more. Below you can the way the slave is totally compressed. Also note how close the hydraulic connection point is to the original pivot point casting.

Stack height issues in the new clutch assembly

This lip was adding a couple mm of stack height we needed to remove so I proceeded to carefully file the lip off down on the slave such that it would sit full within the adapter plate and ideally totally flush to the back of the plate.

On trying to refit this in its new position I realised I’d created another problem that I glossed over earlier – that I’d need to remove some of the original gearbox casting to make the new slave sit flat in the orientation I needed as the original clutch fork pivot point clashed with the location where I wanted the hydraulic connections on the new slave. The best method I found was a drill bit larger than the feature and just drill the top of it away until it clears the new slave.

Around this time I realised really I needed to remove the original flanged bearing retainer plate as it alone added about 4mm to the stack height so I engaged in the type of butchery that makes engineers wince. I took the flanged retainer and trimmed the flange off it. Yes I specifically mean that – if you cut through the bearing retainer ring it will reduce the height such that the bearing is no longer held tightly so you need to carefully trim off just the flange plate leaving a ring the right height fill the gap between the bearing and where the retaining plate face would be. because the new slave retaining face was now flush with the adapter plate this ring will now be held in place by that. Removing this plate now meant I had to drill yet more out of the pivot casting to prevent it clashing but that’s easy.

Final fitment of the concentric slave conversion from the original fork position

Now everything is in place and the hydraulics are accessible through the original clutch fork hole.

RX8 gearbox refitted to the car

And all back in the car…

For anyone who may want it here’s the PDF drawing for the adapter :

RX8 Project – Part 16, Fitting Piston Cooling Oil Jets

These are something I hadn’t really come across until I started working on this project. While I was researching the work Noble had done developing their twin turbo engines I found the installation of piston cooling oil jets noted as one of the modifications undertaken. On the basis they found it was fine to use the stock pistons but did this mod I started doing research into what exactly they were and why they were used.

The usage of these jets seems to be almost exclusively related to turbocharged engines, both diesel and petrol due to the amount of energy released in these engines. This increased release of energy caused by burning more fuel in pressurised air generates much higher temperatures inside the engine and while the block and head are actively cooled most normal engines rely on incidental oil spray to keep the piston cool. Once you start getting the piston considerably hotter you have a couple options. Either use a piston material which will cope with much higher temperatures without degrading (either due to the temperature affecting the material properties or due to thermal expansion) or somehow cool the piston. Various materials have been used for high performance pistons to help negate the material strength and thermal expansion problems with varying degrees of success but these are generally very expensive made to order parts and well beyond the range of most. This is where the jets come in.

The jet is usually some sort of nozzle drilled into an oil gallery in the block which directs a stream of oil at the underside of each piston. This both cools and lubricates the piston and rod small end/pin.
The original Noble modification is known to have some issues but this was more of a problem with the implementation. Take a look at this : http://noblecars.org/engine.html

The basic problem of the original Noble method is that with such large drillings (probably about 4mm diameter) the cooling will be very effective because the flow rate will be high but the overall engine oil pressure will likely be very low, particularly around the main bearings because that is where they are drilled into the oil supply. Clearly the one place you don’t want low oil pressure!

So me being me I decided to improve on the situation! Firstly I found that most cars that have these fitted (unsurprisingly) use considerably smaller jets, the best example I found was a NASCAR engine using a jet of 0.75mm (I have since tried to find this page again with no luck). Not wanting to risk trying to drill a hole of such a small diameter freehand at the bottom of the cylinder bore from the top I took a slightly different approach and started looking for suitable nozzle inserts that I could use that were available easily and cheap. After a lengthy search trying to find something intended for the purpose (from either a suitable production vehicle or something) I gave up and started just trying to work out what I actually needed and realised that with the rise of home 3D printing small nozzles were actually easy to get – specifically the extruder nozzles used on these printers. These nozzles are usually brass, have an M6 thread and are available in a range of hole sizes, for me the 0.8mm version looked like a good match.

3d printer nozzle

I bought a pack of four nozzles off eBay for a few pounds and decided I should see what sort of spray I actually got from them – I wanted them to produce a fine jet at the normal engine oil pressure rather than a mist as this would assure the oil reached the piston rather than most of it just hitting the inside of the cylinder bore which would achieve nothing. Because I’d decided on the M6 thread it made a test jig quite simple, just a normal M6 nut welded on the end of a bit of 12mm tube. When welding anything threaded it’s a good idea (particularly on smaller threads) to put a suitable mating part in to prevent distortion if you can. In this case I used a standard M6 bolt. After welding the nut the bolt can simply be unscrewed again but if you don’t do this the heat will often distort the thread enough that it is unusable after welding. The 12mm tube just happened to be about right for the nut but also a good size to allow a normal garden hose to fit over it. Water pressure in the UK is nominally about 3 Bar which is at least in about the right area to represent an oil pressure. Also there is the question of viscosity but my logic told me that oil being more viscous than water should not form a mist as easily, so if it worked with water oil should be fine. The test showed a solid jet out to about a meter from the nozzle and beyond that a tight stream of droplets another meter or so. This should certainly be good enough for what I need!

After this test I decided to go for it, so I ordered another set of four nozzles and started trying to work out how to actually machine the block to make them fit. Due to the position the jets need to be installed the oil feeds need to be drilled from the crank bearing housing 60° either side of the centre line to match the cylinder bore angle and also at a slight angle forward or backward (depending on which cylinder it is) so they actually come out into the shoulder at the bottom of the bores rather than just continuing between the cylinders.
First off I marked up the 60° line for each bore so I had something to line the drill up with for the angle and the starting point for the drilling. Next I found a drill bit that nicely fitted into the groove in the bearing housing so as to avoid reducing the supporting area for the bearing which as it turns out is a 3.2mm. This is the area that apparently will crack on the Noble engines – they use a significantly larger drill hole here which breaks into the bearing support lands and I suspect this is part of the issue but that’s purely speculation. There is also no issue with restricting the flow to the jets here because the jets are now significantly smaller than drilling. The next important thing is this involves drilling quite a long, narrow diameter hole through aluminium and that can be quite problematic!

First off let me say this is next bit is a bad idea all round, you either have to be very confident in your abilities with a hand drill or not care if you ruin an engine block. Ideally you want to be both! If not you will want to talk to a machine shop to do this!

Before you start remember to remove the bearing shell itself and put it somewhere safe! Aluminium is a soft material and will stick to drill bits and tend to generate heat due to friction, if it gets hot enough it can actually seize onto the drill bit causing it to break. Firstly a normal length 3.2mm drill won’t be long enough for this job, it will work to an extent but the flutes will eventually be covered by the sides of the drilled hole when you get deeper and there’s nowhere for the chips of aluminium to go. My advice is to buy a long series drill bit and use it. Start the hole with a normal bit because long bits are more flexible and can be harder to get and accurate start with but once you have a dimple that will hold the bit in place swap to the long series. Use plenty of lubricant (go on, guess how I found that out!). You can use WD40 but it can get quite expensive if you have a few holes to do as it tends to vaporise off during cutting. Thicker oils tend to protect the cutting edge more but make cutting slower but in this case aluminium is soft and so drills quickly anyway plus we’re only making a small hole so it will make little difference. Personally I used 3in1 on mine with works well and helps flush the chips out but you will need to reapply the oil to the hole regularly during the process to make sure the drill is well lubricated. You could also use engine oil or even gearbox oil but these would probably slow the process a little more. Go slowly and let the tool do the work, if you push too hard there is a serious risk of flexing the drill bit which at best will give you a hole that wanders and at worst a serious risk of snapping the drill bit.
Once the 3.2mm hole comes through into the shoulder at the bottom of the bore we need to make the M6 nozzle fit, this means tapping a suitable thread into the bore end of the drilling. First clean out all the swarf (drilling debris) from the new hole. At this stage this is just to make sure we get a nice clean thread cut. Now we have the interesting bit, to tap M6 we need a 5mm pilot drill, so we have to drill out the cylinder end of the 3.2mm drilling to 5mm with enough depth for the nozzle to screw in but the only way to do this is to do it from the top of the bore with a really long drill! I went on eBay again and bought and extra long series 5mm drill for the job. This thing is 250mm long and looks absolutely ridiculous in a cordless hand drill.

Extra long Series Drill

It actually looks more like it should be used on masonry but these have the normal tip and are actually for metal. If the one you buy has a flat ceramic insert in the tip you’ve bought the wrong one! 5mm Drill Jet

I suggest you mark the depth you need to drill to accommodate the nozzle thread (with a little extra room for tapping) on the drill bit. The actual depth here isn’t critical as long as there’s enough depth for the nozzle threads at a minimum. Again plenty of lubricant and drill with slow speed and light pressure and be very careful to keep the drill loaded straight otherwise at best your hole will be at a funny angle but at worst you may snap the drill and damage the bore surface.

5mm Drilled hole

Next clean the swarf out again so we can get a good thread tapped. Tapping the holes is another slightly awkward problem for the same reason as drilling the pilot hole, we need to do it from the top of the bore. I suggest going on eBay (or any of a thousand other places online) again and looking for an extra long ratchet tap wrench. These are available under any number of brands but I suspect they’re largely all from the same place. They are available in a small version, which is 250mm long and will tap M3-M10 or a large version which is 300mm long but taps M5-M12. I went for the smaller one because the smaller chuck should allow tapping tighter to the cylinder wall without damaging it and this is likely to be tight for this task. Expect this to be about £10. While you’re at it buy an M6x1 plug (bottoming) tap!

Tapping the Jets

Again proceed slowly with a well lubricated tap, many people will say you need to use proper cutting compound but for a small hole in a soft material this isn’t necessary, 3in1 will be fine. Try to cut forward a bit (maybe a turn at a time or so) and then back the tool off until you feel it turn smoothly. This will help prevent the tap from clogging up and either seizing up or damaging the new thread by material being forced against it. It may be necessary to back the tap out entirely to clean the removed metal from the threads because this is effectively a blind hole. Be careful not to keep going once the tap bottoms out. If you aren’t careful it’s comparatively easy to strip the threads in the aluminium with such a small tap and then it would be awkward to repair. If you’re not confident this really isn’t an ideal job for anyone new to tapping because it relies on having a degree of ‘feel’ about what you need to do and when to stop.

Rinse and repeat five more times and congratulations you now have six neatly drilled and tapped jet positions! Before doing anything else clean everything again, I used a combination of brake clean, compressed air and a scribe. You need to make sure there is no swarf left in the drillings so you don’t risk that jet becoming clogged. Once clean you need to fit the jets. The jets I selected have an external hexagon and so can be tightened up with a socket wrench but you will need sufficient extension to reach the bottom of the cylinder bore with an appropriate sized socket. Clean all the jets with brake clean to degrease them – technically this is not necessary but it helps remove any other grime that has become stuck to the jets in manufacture/transit. Next I recommend you apply a small dab of a suitable thread locker to the jet threads, specifically I went for Loctite 243 which is a medium strength thread locker which will resist oil. You can use others but if you go for anything stronger you’ll need a blowtorch to get it out and trying to do that down a cylinder bore could be interesting! Once you have the dab of Loctite on the jet you need to screw it into the newly tapped hole – I found it easiest to do this carefully from the crank side of the block by fingertip but your mileage may vary! Once you have it in enough to keep it in place tighten it in with the socket wrench. The jets will only need to be nipped up for two important reasons; firstly they are thread locked and so will not vibrate loose and second they are small and made of brass so any more force will likely strip the hex.

Piston Jets Fitted
That’s it, one new set of shiny piston cooling oil jets! More on this project coming soon!

RX8 Project – Part 15, Engine Strip #2

So having removed the timing chain and tensioners (see part 1) next we need to start looking at removing some more major parts of the engine.

Having already removed the cam covers already you should be looking at something like this:

Jag Cams

Thanks to the Jag Motor Project for the image – hopefully they don’t mind me borrowing it! It seems I have misplaced my own photo of this!

You need to remove the cam bearing housings because the design of this engine has the head bolts directly under the cam making it impossible to remove the head with the cams still in place. This is worth remembering and is at least part of the reason stretch bolts are used for the head – it is impossible the re-torque them after an interval of use without removing all the timing gear. As you can see in the photo these are three smaller housings and one larger one at the front each held on with two small bolts. Basically you just need to carefully remove these bearing housings in order. I suggest marking the direction and its position on each one before removal. The position could be achieved by putting each into a small tub which is numbered. However you do this you need to know which is which and which way round they go. Remove them carefully and make sure you don’t drop any bits! Once you have removed the housings you’ll see this:

S-Type V6 Cams Removed

Now we have clear access to the head bolts which as you can see in the photo there are eight of. These are fairly easily removed except for one thing – the bolts are set well down into the head and there is very little room in the recess to put in a socket. You will need a 15mm socket for these bolts and a small breaker bar (or an impact gun) as they will be quite tight.

These bolts are not reusable – I mean you can but it’s a terrible idea particularly in such a critical location because odds are high it will not be up to the job. This is because “stretch” bolts rely on the material of the bolt reaching the yield point of the material at which it begins to exhibit a fairly constant elastic stretch. In effect once they start to deform they behave a bit like a very stiff spring and so if tightened correctly will hold a very accurate load without loosening and so do not need to be re-tightened after a run in period. That said hang onto them for now so you know what to order to replace them!

S-type V6 Head bolt removal

You can see how tight the casting is around the socket! Once all the bolts are gone you can lift the head away. It might take a little persuasion with a mallet. Make sure you have a suitable clear space to put it on once you remove it.

Now you should have this level of grime:

S-type V6 Head removed

Obviously you can just pull off the head gasket now to improve the situation quite a bit and you can have a good look at the state of the engine:

S-type V6 Factory Hone

Here you can see the cylinder bore actually looks in very good condition and even still has the factory honing marks on the bores which is a good sign it’s been working well and shouldn’t have suffered wear issues.

Now do all of that again for the other head and you should have something that looks a bit like this:

S-type V6 Heads Removed

Congratulations now you have an engine with no heads but since my plan was to upgrade the rods I still needed to remove more so flip the engine over and we can get to it.

S-type Oil Pump

In the picture you can see the oil pump is just held on by four small black bolts. I put the crank bolt back in place just so I didn’t lose it but you would have removed this a long time ago. Once the four small bolts are out the oil pump can just be slid off the crank and put aside.

S-type V6 Front Oil Pump Removed

 

Next we need to remove the con rod bolts and this is where having the crank bolt comes in because you can put it back in finger tight and once it snugs up a bit you can turn over the engine to get access to all the rod bolts. Mark up each rod with a cylinder number and arrow for the front of the engine. I put sharpie marks across the split line of the rod to make it easier to match them up later. I had to use something to knock the piston out of the bore use something non metallic otherwise you will likely damage a surface you don’t want to damage. I used a length of wooden dowel. Do these carefully unbolting and removing one at a time. When knocking the piston out don’t forget to catch it before it falls on the floor!

S-Type V6 Oil Pump Removed

So all we have left is the crank. If all you wanted to do was straight swap the rods this is as far as you need to get. Well I wanted to do a few other while I was at it (more on this in another post) so I carried on to remove the crank. This is actually pretty simple at this point, you just take out the 16  main bolts holding the lower block to the upper block along the bearings. The other thing you can see in the picture are the engine mounts, the rubbers here aren’t stock s-type, they’re actually from a V8 Land Rover (Discovery among many others). The reason for this is they’re very strong, extremely cheap (£7 a pair delivered from eBay) and have a stud each side which will fit straight onto the factory cast aluminium mounting arms and also make mounting onto the car really easy when we get to that stage!

S-type V6 Lower Block

It’s worth noting in the above picture not all the bolts are the same. This is because some have small studs on the top to allow the windage plate to be mounted (blue). Note which goes where so this can be put back later! Next you also need to remove the 6 outer bolts (red) before the block will separate.

S-Type V6 Lower Block Bolts

Once all the bolts are out again you might need a gentle tap with a mallet and/or a scraper to get the block apart. Don’t drop the crank bearings!

If you’ve done all of this you should have something a bit like this in front of you:

S-type Stripped 2.5 Block

And a heap of bits you just removed:

S-type Engine Parts

More to come on this project in my next post!

RX8 Project – Part 14, Engine Strip #1

After deciding to turbo the engine (see earlier posts) is became apparent I would have to upgrade the piston rods to make sure the engine wasn’t in danger of these failing and ruining the engine. This meant I needed to extract these from the engine Now bear in mind that this was the first time I’d ever taken the head off and engine before let alone removed a crank so it was likely to be quite a long and delicate process! Also accept that I was making this up as I went along, things may be in a strange order but it seemed to work!

First things first mount the engine to a suitable stand:

Here it is, it’s already upside down but that doesn’t matter! First off I took off the sump. On this engine it’s a cast alloy unit with a large front bulge which makes working around the front of the engine more awkward so I got it out the way early on.

V6 Windage tray

Take off the oil pick up pipe (2xM6 bolts) to get room for the windage tray. The tray is held on by 5 nuts on some special studs on this engine, these are M10 one side to hold the lower block to the upper block but i think M5 on the top just to hold the windage tray.

Duratec V6 Bottom

Now we have exposed the moving parts of the engine and get the first look at the bits we are replacing but there’s a lot more before we get them all out. An interesting thing to note here is the absence of crank bearing caps. On this engine the block is formed in two cast pieces which joint along the crank centre line so the crank bearings are held in place by the substantial cast ribs you can see in the picture and each bearing has four M10 bolts to keep it in place with additional bolts around the outside of the casting.

Next move to the front of the engine and disconnect the hose from the block to  the water pump then unbolt the water pump. On the Ford version of this engine the water pump is driven directly off one of the cams but on this Jaguar one it is a separate unit driven from the back side of the accessory belt and is held on by three small M6 bolts. Next up remove the crank bolt, there are a variety of ways to do this (the easiest probably being a decent impact gun but at this point in the project I’d not yet bought it) but the method I chose was to block the rotation of the crank using a block of wood. This is done by finding a suitable block that fits between the crank and the housing such that as the crank counterweight rotates round it is stopped by the wood. Just remember that the crank bolt undoes anticlockwise so make sure you put the block on the correct side(the bottom in the above image)!

S type V6 front

Now you can flip the engine back up the correct way because we’re moving on to the heads This is because the cam covers need removing to take off the front engine cover.

S-type V6 Black Cam Cover

This bit is again very simple, remove the bolts holding each coil unit in place. Again this being the Jaguar version of the engine is came from the factory with coil on plug. Next remove all the bolts around the cam cover and lift the cover away. Sometimes these get refitted with instant gasket to fix a failed cover gasket cheaply and quickly and so it may require some persuasion, I usually use a putty knife or a wallpaper scraper for this job but it can be easy to damage the faces if you’re not very careful. Alternatively plastic trim removal tools can work well. Obviously repeat the process for the other cover.

Next up we need to remove the front engine cover. This involves removing the bolts all the way round the edge, you can’t miss them, there’s loads and they’re all the same! Make sure you get them all, I think there’s 17 of them but don’t quote me on that, one is under the belt tensioner by the crank! This cover again might require a little help coming away due to the gasket but should be relatively easy. If it isn’t then you’ve missed a bolt so stop prying it!

S-Type V6 No Front Cover

It should look something like this! Now you can see the other feature these jag engines have – variable valve timing on the intake cams. An important point here is the crank timing wheel (the notched wheel on the crank). These have two key positions but only one is correct so carefully mark which position lines up with the key on the crank when you take it off. I recommend something permanent so when you clean all the oil residue off the mark is still visible, a centre punch mark should do it.

Next you need to remove the timing chain tensioners. These are small hydraulic cylinders that use engine oil pressure to maintain tension in the timing chain. They are held on by two bolts each. Just undo the bolts and carefully remove the tensioners from the tension arms.

S-type V6 Timing Tensioner

Once the tension cylinders have been removed the tension arms can be lifted off their dowels and removed as well and then the chains can be lifted off and you should have something that looks a bit like this:

S-type V6 removed tensioner

Now all that is clear the chain runners can be removed. These also hold the VVT solenoids and so are quite a complex bit of metal but are easily removed. I also took of the water hoses at this point just to simplicity.

Now you should be at this stage:

S-type timing gear removed

In the next part the engine strip will continue…

RX8 Project – Part 13, Canbus #3, Labview!

If you just want the CANbus ID for the RX8 PS light and not all the background work just skip to the end!

So it’s been quite a long time since I had chance to have another go at getting the CANbus on the cluster working and while previously I manged to get everything apart from the power steering warning light working I decided I really should find out why not. This is a simple lesson in why getting sufficient sleep is really important!

I was contacted a while ago buy a guy doing a similar conversion to mine who happened to have a second complete RX8 and a variety of diagnostic equipment that can talk CANbus who had send me a block of CANbus log data that I’ve done nothing like enough work on since I’ve had it! Anyway the key here is I knew that the car some of the logs had come from had the factory PCM (ECU) working as intended and as such the power steering light doesn’t illuminate. This meant that somewhere in that log file was the data that turned off the light, I just had to work out where it was!

Now first off I took the approach of taking the two sets of data logs I had, one from a car with a functioning PCM and one from a car that doesn’t. Then list out all the ID’s that occurred in each set of data. I’m going to assume for my purposes that any that occur in both sets are not required. The logic being that the data that turns off the light must be present in one set and not the other. I admit that this might not be the case if there’s something more complex going on like if with the PCM removed the power steering computer doesn’t get the required data and sends a different value on the same ID. But for now it’s a starting point!

The ID’s that remain are as follows:

201, 203, 215, 231, 240, 250, 420, 620, 630, 650

A couple of these we’ve already seen elsewhere, specifically 201, which is the RPM and speed to the dash, and 420 which control the cluster warning lights. So after setting up the arduino and canbus data to strobe all these remaining address and nothing happening I gave up!

Many weeks went by and I it was nagging at me why I couldn’t find the right code. Eventually I decided to try a different tack so I ordered a USBtin which is a really neat little USB to CAN adapter which appears as a virtual COM device in windows and can be controlled using a series of commands known as the LAWCIEL protocol (details of which can be found here). The kit version is really quite cheap and would probably be a good option for the budget conscious but on this occasion I just decided to be lazy and buy the prebuilt one.

Clearly I’ve decided to PC control it at this point! Next up I needed a way to stop it when the warning light went off. I ordered a very cheap optical detector off ebay which can be wired into an Arduino or something similar. These are the ones that vary around £1-2  so difficult to argue with. They offer a potentiometer to adjust the switching brightness so I can tune it to what I need and a digital output so I don’t need to mess about doing analog reads or calibrating things on a microcontroller. Yes i know it’s not the neatest or most efficient way of doing it but for my purposes it’s so cheap and easy it really doesn’t matter! So I need to make that talk to a PC in a way I can use and that’s where this whole thing starts to get more interesting.

I’d pondered ways of interfacing a microcontroller to a PC easily and while it’s not terribly hard to make it shout over serial when an input goes high I came across something much more interesting. There’s a company called National Instruments who make lots of very expensive software and equipment for recording data from experiments but fairly recently they started supporting hobbyists by producing the Labview Makerhub, and more specifically a package called LINX. LINX includes a series of drivers and firmwares to allow things like Arduinos, Beaglebones and even Raspberry Pi’s to be used as IO devices (the Raspberry Pi can actually have programs loaded to them as a full remote node). This is quite a major step because it suddenly allows hobbyists to use really good professional software without having the problem of only being able to use NI’s extremely expensive hardware! This gave me and idea – use labview as the core software then I can use the supplied LINX firmware to set up an arduino as IO. To make this deal even sweeter you can also download Labview for free from NI for home use. Take a look here

So after a quick bit of following the instructions we have a basic labview program that will read the arduino IO via serial:

Labview Lynx1

Basically what this does  is it starts by opening a serial connection via the LINX toolkit, this returns a device name to an on screen string display and passes a reference which identifies the connection to the read stage. The next bit the larger grey rectangle is how Labview handles a while loop so it’ll keep performing the enclosed functions constantly from left to right until the conditional term in the bottom right goes high – in this case it’s a stop button. So basically the loop just calls a LINX channel read of channel 2 where I connected the light sensor to the Arduino. The inner rectangle only executes when the read value is false (i.e. when the light goes off) and while there’s a lot of information recorded here from elsewhere in the program basically if it sees the light go off it records the current ID being tested, the time that has elapsed since the test started. This means we know when it’s right!

Labview is designed to capture data from lab instruments and so there’s a really handy thing called the VISA toolkit that allows blocks of data read and write via the serial port and basically you can just open a port with specified settings then make read and write requests and do things like crop the incoming data at a predefined character. In this case that character needed to be CR (Carriage Return) this is ASCIIcharacter 13 because LAWCIEL terminates everything with one.

Labview Lynx2

For the USBtin we open the correct COM port at 115200,8 Data bits, No parity, 1 stop bit and no flow control. The other thing to note is at the top right, this sets the termination character to the numeric value of CR, the benefit here is you can perform a read of any length and it will automatically break up the data in the buffer so a single read can vary in length but the start will always synchronise  with the read call. Opening the connection in a terminal program for the first time and you’ll see nothing actually happens as such, an OK is signified by a CR so all you see is the cursor move. At this stage we are only connected to the USBtin, not the CANbus. So next, configure the CAN connection, send a value of “S6\r” . The code is S6, this will set the USBtin to 500kbit correct for the dash, the \r is how you indicate a CR in a Labview string. Next I chose to send “v\r” which requests the version from the USBtin, we don’t need this but it gives a solid confirmation it’s talking to us. Next up Z1\r tells the USBtin to timestamp the incoming data, I thought this might be useful but never actually implemented it.

Labview Lynx3

With the setup complete we can start reading data by opening the CAN connection by sending O\r. On a terminal program (assuming you have the CANbus wired up) doing this would result in packets of can data from the cluster appearing. The initial read of length 1 byte reads just the confirmation from the USBtin that it has received the open request. Next is the main read, it’s worth noting the read length is set at 50 bytes but this will be cut short by the termination character set earlier so we can accept varying length CAN data. C\r closes the CAN connection and again another read 1 byte clears the acknowledge. Tacked on the end is a section to read the controller status looking for error states etc. The keen eyed amongst you will notice the majority of this code is conditional, this is because the code needs to insert send requests among the stream of reads. This is because if the data is not read from the USBtin constantly a buffer somewhere fills (I imagine on the USBtin itself but can’t confirm this) and the port crashes. I spent a lot of time finding this out the hard way!

Labview Lynx4This is the write data code, again very similar but it just opens the port, writes whatever string is in the buffer and closes the connection. Once the connection is confirmed closed it resets the Boolean that causes the ‘write’ condition so on the next loop it goes back to reading again to keep the buffer clear. The read loop runs at the maximum possible speed but it is slowed down because it waits for either a termination character or 50 characters to be received before it completes and loops again.

Beyond that the only other bits of code just generate the data for the write buffer using an increment counter for the ID field and toggling between either 8 bytes of FFFF or 0000 every 100ms for 20 cycles and setting the write flag high to send the data..

So after letting this run for a fair while it started spitting out values, specifically the ID 300 for the power steering light. Wait a minute that wasn’t in the list earlier. Yes I know that, that’s where getting enough sleep comes in. Originally I split the data based on whether or not the PCM was fitted and ignored the ones that occurred in both sets, the obvious mistake here is that of course the power steering light isn’t controlled by the PCM, quite logically it’s controlled by the power steering controller!

So there we go, ID 300, the first byte (leading) controls the light, values below 80 turn the light off. Unplugging the PCM causes the controller to send 80 on loop hence the the warning light.

Get data from ID: 4B1
0	0	0	0	0	0	0	0	
-----------------------------
Get data from ID: 81
43	6F	1	4B	
-----------------------------
Get data from ID: 300
80	
-----------------------------
Get data from ID: 231
F	0	FF	FF	0	
-----------------------------
Get data from ID: 430
95	5F	83	0	0	0	60	
-----------------------------
Get data from ID: 81
25	6F	1	4B	
-----------------------------
Get data from ID: 81
16	6F	1	4B	
-----------------------------
Get data from ID: 630
8	0	0	0	0	0	6A	6A

Looking at the log data again we see that ID 300 is getting a value of 80 – this is during the self test before the engine is started. I previously tried sending this data on the original Arduino CAN setup and go no result so what did I do wrong. Again this is based on another assumption, I though the logger was ignoring high order bytes with zero value (ie this value if could be 00-00-00-00-00-00-00-80) well it turns out that was totally wrong, it actually ignores trailing zeros, the value of the can data here should be 80-00-00-00-00-00-00-00.

So while all these hours of work told me one thing I should have already known it’s actually worked out Ok because it highlighted this other problem (read ‘incorrect assumption’ !). This means The odds of me working out all the other data from the logs (that I’d previously written off as not usable) is actually much higher!

 

 

RX8 Project – Part 11, Turbo’s #2 – Wastegates

So now the project is going in the turbo direction I need to be a bit wary with how I do it. The GT1549 turbo’s I chose had positives and negatives. They looked to be exactly the right size for the engine I had, they were fairly common in one form or another and importantly the price was spot on! I still don’t understand quite how but I managed to find someone on eBay with a matching pair of these turbos fully cleaned and rebuilt for £65 each delivered! So that’s the positives, now the negatives, firstly rather than the normal bracket bolted to rear of the compressor housing to hold the wastegate actuator. On these turbos it is actually cast into the housing and so it would make rotating the housing to fit the application considerably more difficult. The second problem is they have a factory fitted actuator which isn’t adjustable more than a small amount and I really didn’t want to start tweaking a completely untested engine with no idea what was going to happen with no way of keeping the boost below the 18 psi wastegate pressure!

So getting over these problems. Having looked at the rotation problem I came to the conclusion I should be able to make them both fit with no rotation changes needed. The backup plan here was to grind off the cast in mount and custom make a bracket using a bit of steel plate if it turned out I needed to later on. This takes us to the wastegate problem. I looked at a number of ways of providing a reduction in the actuator pressure including adding springs to the rod side of the actuator and even bolting the internal wastegate solid and fitting external wastegates to the manifolds I came to the conclusion the only real way of giving a wide but reliable range of adjustment while keeping the package as small as possible would be to replace the stock actuator with an aftermarket adjustable one.

Now this is where the plan goes a bit wrong about – after looking about for ages to find a sensible option at a half sensible price the best I could come up with was this : Kinugawa Actuator 

Kinugawa Actuator

I’m under no illusions here, this is a a cheapo unit! But I strongly object to spending the cost of the car on each wastegate. The problem is even though I got these for £68 each which really is very cheap they actually cost more then the pair of turbos! Considering all this it’s still a pretty good option because it is a ‘universal’ version. It comes with a range of springs for different pressures so I can start at just a few psi and swap the springs out as needed and also comes supplied with four different actuator rods.

So here we are – actuators!

Kinugawa Package

So at first glance they look ideal, but don’t let that fool you! There’s a couple engineering problems to overcome.

Actuator Flap clash

The first problem is this; the hole in the supplied rod end isn’t large enough for the flap actuator on the turbo. The solution is simply to drill this out to fit. I didn’t note the sizes, but it was a standard drill size.

Next up was that this ‘universal’ actuator was never really intended for a turbo this small and as such the shortest actuator rod is too long to allow the wastegate flapper to close so I had to modify that as well. The rods are nominally 6mm diameter but the end the rod end has a fine pitch thread meaning modifying that would need me to buy a fine pitch die to extend the thread. Luckily the end that goes into the actuator is a standard M6x1mm metric thread so that was the easier option.

Modified Actuator Rod

I measured how much I needed to shorten the rod to allow the flapper to just close at one end of the rod ends adjustment. The opening pressure of the actuator is set by preload so the more it is tightened greater the boost pressure. I then simply cut the thread down to the required point and then trimmed off the excess. The good news is if I made the rod too short I three more tries for each one!

Modified Actuator Rod

And here is the difference – it’s actually about 25mm less than it started out! Reassemble the whole thing and magically it now fits where it needs to!

GT15 Kinugawa actuator

The other thing you will need to do potentially at this point is change the spring. Once the actuator rod is in the actuator this is actually not too bad but be a bit fiddly. First of position the actuator so the rod is sticking downward between the jaws of a vice. Tighened the vice to hold the rod in place then undo all the housing screws. Lift off the top housing and carefully remove the diaphragm underneath. Next you need to carefully release the rod to take the load off the spring. then you just unscrew the rod and take the aluminium piston and the spring underneath out the housing. Reassembly is just the reverse but the key is to put tension on the rod again and clamp it in place again before refitting the diaphragm and cap otherwise it’s very difficult to get the diaphragm correctly positioned without any wrinkles that could cause damage or leakage.

So now we have two turbos with adjustable wastegate actuators with a potential working range covering something like 3-30psi!

 

RX8 Project – Part 10, Turbo!

So this is about the time this whole project started getting a bit out of hand, when I decided I was going to need more power…significantly more.

I looked into what options I had –

Option 1 – I could stay naturally aspirated and probably skim the head to increase compression a bit and get more out of it but tuning in this way can be very intricate and looked to be more involved than I wanted for the amount of power I could expect.

Option 2 – Supercharger, there are a few options here. Realistically the most common supercharger these days the Eaton M45 found on the modern Mini cooper S is just too small for this so sticking with the positive displacement type we can get an M62 from a mercedes CLK230 and with the right pulley ratio it would probably be ideal for moderate improvements. For real degrees of silliness an M90 might well be needed and these are a little harder to find.

Option 3 – Turbo, this gives a huge amount of options due to the prevalence of turbo engines at the moment and would give potential for significant power gains comparatively cheaply and without needing to align belts.

After debating for a very long time the best way to go for a road car I settled on option 3 primarily for the simplicity aspect – I know very little about the intricacies of high compression engines and I know superchargers require a level of alignment very difficult to achieve with DIY manifolds! The next obvious question is how much power? Well following finding out from Noble that the rods in the engine fold up at something a bit over 300bhp I decide that from a cost and complexity point of view I’d aim for about 280bhp as a limit so I could keep the amount of parts I needed to a minimum – famous last words!

Now there’s a huge online argument about whether two smaller turbos or a single larger one gives the best throttle response and performance. This isn’t an argument I want to get into but in my case I decided twin turbo was the way to go for two reasons. Firstly because I could close mount them under the engine to keep the overall engine package as small as possible and so simplify the pipework on the exhaust side. Secondly because due to the government publicising the benefits of diesel there are now loads of small cheap turbos about for very little money..

Getting into sizing most of the information is that Noble used two T25 turbos. Taking a look at http://www.boosttown.com/forced_induction/air_amount_calculator.php

We can see that for this engine at 6000 rpm and 0.7 bar of boost we need about 27 lbs/min of total airflow. Next we need the T25 Map for a common inducer size:

T25 Compressor map

Looking at the map for the normal T25 turbo we can see that with two turbos to share the load and so only needing about 13.5 lb/hr at 1.7 pressure ratio the turbo is right in its optimal zone. Not a bad choice all in all but these are old design turbos and as a twin turbo configuration the actual  amount of available exhaust will be limited so the turbo may not spool until a bit high up the rev range so I started looking at other options which would give a good improvement across a wider rev range. To achieve this a smaller exhaust housing was needed and this is where the diesel engines come in. Turbos used for diesel engines tend to have smaller exhaust housings for this very reason and they’re abundant. This led me to the GT1549, this is a manufacturer specific version of the GT1548 turbo, people have reported them to be good for 180-200bhp which is right in the area we want.

GT1548 Compressor Map

In many ways a similar map to the T25 but the spindle speeds are noticeably higher. The unit as a whole is much smaller but will have less weight in the rotating components and as a result of the smaller exhaust housing the turbo should generate boost at lower RPM. I used to have a map for the exducer which confirms this but have since misplaced it. Now before anyone tells me “you can’t use a diesel turbo on a petrol” consider this – this same turbo was used on both a huge range of diesel engines but also on the Saab 9-5 V6 petrol. That said there is also a VNT version of this turbo (GT15xxV), VNT turbos don’t last long on petrol engines by all accounts.

So here we are, the turbosGT1549 x2 :

So there you have it, a short post but a complete change in the direction of the project from where it started off and we’re only just getting started!