Help identifying signal.

What I am trying to do is build a digital speedometer for my car.

There is a sensor in the diff, which sends a pulse 6 times every rotation, the signal then goes into a chip in the gauge cluster which i presume converts the pulses to a signal to drive the speedo.

I tried mesuring the signal with my digital multimeter but still not sure what kind of signal it may be.

With the multimeter set to DC, and the car not moving it reads about 4.98V when i start driving the voltage decreases ( i think i got the voltage down to about 3.7v doing 130kph)

With the multimeter set to AC I get a 0V reading which increases as I speed up, but seems to jump around alot and not be very accurate.

With the multimeter set to Hz, I get 0Hz when the car is not moving and it increases with car speed although it is not linear the signal seems to be stable (136Hz~ = 100kph, 64Hz~ = 50kph, or there abouts. Actually after reading that, it could be linear?) When I come to a stop it reads approx 4.67Hz for about 2 or 3 seconds then drops to 0Hz, but this could just be my multimeter.

Any idea what kind of signal this is? I thought maybe PWM/Squareware signal. Also, what would the best way to read this signal with the arduino?

Should I use a optoisolator or somthing like that to protect the arduino?

A PWM squarewave sounds likely.

If you could get access to an oscilloscope that would be really helpfull in finding out exactly what the signal is. You would probably need some kind of inverter to power it from the car though :-)

I used to have a oscilloscope when I was about 10 but I didnt know how to use it so my mum made me throw it in the rubbish :(

I have a 150w inverter, that should be enough to run a small scope I think.

If it is a PWM squarewave signal, how would I read this with arduino? Interrupts, or pulsein() or maybe somthing else?

You can try a PC sound card Oscilloscope. There are many software on the net. They have low resolution and low frequency range, comparing to real equipment, but it would be useful in your case.

If you need to know the pulsewidt i think pulsein() is the way to go, but maybe someone with more experience in this area can chip in.

You could just filter it and use analogread.

Or just hook up the sensor in the diff to a interrupt as well.

It really depends on how fast the signal is coming in. For decoding many protocols I use a slightly modified version of the code that I found in the playground, I think. Here it is:

/*
 *  File....... IRanalyzer.pde 
 *  Purpose.... Records up to 128 signal changes
 *  Author..... Walter Anderson 
 *  E-mail..... wandrson@walteranderson.us 
 *  Started.... 18 May 2007 
 *  Updated.... 18 May 2007 
 * 
 *
 */
 
#include <avr/interrupt.h>
#include <avr/io.h>

#define TIMER_RESET  TCNT1 = 0
#define SAMPLE_SIZE  128

int IRpin = 2;
unsigned int TimerValue[SAMPLE_SIZE];
char direction[SAMPLE_SIZE];
byte change_count;
long time, time2;

void setup() {
  Serial.begin(115200);
  Serial.println("Analyze IR Remote");
  TCCR1A = 0x00;          // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
  // ICNC1=0 => Capture Noise Canceler disabled -- ICES1=0 => Input Capture Edge Select (not used) -- CTC1=0 => Clear Timer/Counter 1 o Compare/Match
    // CS12=0 CS11=1 CS10=1 => Set prescaler to clock/64
  TCCR1B = 0x03;          // 16MHz clock with prescaler means TCNT1 increments every 4uS
  // ICIE1=0 => Timer/Counter 1, Input Capture Interrupt Enable -- OCIE1A=0 => Output Compare A Match Interrupt Enable -- OCIE1B=0 => Otput Compare B Match Interrupt Enable
    // TOIE1=0 => Timer 1 Overflow Interrupt Enable
  TIMSK1 = 0x00;          
  pinMode(IRpin, INPUT);
  Serial.println("Waiting...");
}

void loop()
{
  change_count = 0;
  while(digitalRead(IRpin) == HIGH) {}                                 
  TIMER_RESET;
  TimerValue[change_count] = TCNT1;
  direction[change_count++] = '0';
  while (change_count < SAMPLE_SIZE) {
    if (direction[change_count-1] == '0') {
      while(digitalRead(IRpin) == LOW) {}
      TimerValue[change_count] = TCNT1;
      TimerValue[change_count] = TCNT1;
      direction[change_count++] = '1';
    } 
    else {
      while(digitalRead(IRpin) == HIGH) {}
      TimerValue[change_count] = TCNT1;
      direction[change_count++] = '0';
    }
  }

  if (change_count > 1) {
    Serial.println("Bit stream found!");
    change_count = 1;
    while (change_count < SAMPLE_SIZE) {
      time  = (long) TimerValue[change_count-1] * 4;
      time2 = (long) TimerValue[change_count] * 4;
      Serial.print(time2 - time);
      Serial.print("\t");
      Serial.println(direction[change_count++]);   
    }
    Serial.println("Bit stream end!");
    delay(2000);
    Serial.println("Waiting...");
  }
}

This code spits out the time in micro-seconds with a resolution of 4 micro-seconds. The resolution can be fairly easily bumped up to a finer grain, if needed (0.5 us, or even higher) but the danger here would be a very very short window before the timer rolled over. Anyhow, good luck!