Protect from Car Battery Voltage

I know this probably got answered somewhere else before, but my Google skills apparently aren't up to the task.

I have a Pro Mini, and in my car I have a +5v supply to run the board. There is a wire I would like to monitor. When my car is in neutral the wire has no voltage, but when the car is in gear the wire has battery voltage. I want the arduino to tell me if there's voltage or if there's not. I don't need the arduino to know what the voltage is, I just need to know if it's higher than 0. But I don't want to fry the board, I don't think it's meant to handle 12 volts, and I've seen my battery as high as 14.7 volts before.

I do have a small voltage regulator thing, but could this be solved in a more simple manner?

I thought about a resistor, because according to Ohm's law, Amps = Volts / Ohms So then you multiply by Ohms to get Amps * Ohms = Volts But in this situation I don't know what the current is, so I'm not sure what to do.

Just use a pair of resistors as a voltage divider.

12V interface.JPG

The threshold for a HIGH is 3.0V with an ATMega328P running on 5V, so the above values should work fine.

Edit: And the same question was actually answered in this another section yesterday.

You were halfway there with the resistor idea. You would need two resistors in series and take your output from the connection point between them, creating a voltage divider.

You could also use a zener diode across the Arduino input with a current limiting resistor in series with the car's voltage.

saximus:
You could also use a zener diode across the Arduino input with a current limiting resistor in series with the car's voltage.

A zener diode is useless if the Arduino happens to be off.
A voltage divider IS already "a current limiting resistor in series with the car's voltage".

OldSteve is right. Just a voltage divider will do.
If you consider a fault current through the internal pin clamping diodes a safe value, than the resistor values given by OldSteve will protect the pin to more than 40volt.
Leo..

Wawa:
A zener diode is useless if the Arduino happens to be off.

Why is that? I thought it would just provide a more stable voltage for the input pin to read.

saximus:
Why is that? I thought it would just provide a more stable voltage for the input pin to read.

Stability isn't an issue. Anything above 3.0V will register as HIGH anyway, and the input voltage is 12V. It simply needs to be scaled to an appropriate range.

Bottom line - why pay more to use a Zener if a pair of resistors does the job properly?

I agree that your way is better but I simply offered another alternative and now am genuinely curious as to what makes it useless if the Arduino is turned off? Isn't the whole thing useless if it is turned off?

Maximum (positive) voltage on an Arduino input is not 5volt+0.5volt. It's VCC+0.5volt.

If the Arduino is ON, a 4.7volt or 5.1volt zener could limit input voltage.
But if the Arduino is OFF, voltage has to be limited to 0.5volt.
Then a 4.7volt zener does nothing.
Leo..

Natalya:
There is a wire I would like to monitor. When my car is in neutral the wire has no voltage, but when the car is in gear the wire has battery voltage. I want the arduino to tell me if there's voltage or if there's not. I don't need the arduino to know what the voltage is, I just need to know if it's higher than 0.

Is that the entire purpose? Or is the Arduino supposed to do something based on that information?
Because using an Arduino simply to tell if a wire has a current is quite overkill.

Use optocoupler, i think is a better option besides, you are protecting your arduino with that solution.

Visionario:
Use optocoupler, i think is a better option besides, you are protecting your arduino with that solution.

The 27K resistor in the voltage divider that I showed should be more than enough protection.

OldSteve:
The 27K resistor in the voltage divider that I showed should be more than enough protection.

You don't even need a divider, just a large enough series resistor and the input diodes will clamp the voltage.

Atmel has an App Note with a zero-cross detection method involving nothing more than a digital pin connected to mains voltage with just a 1 Meg series resistor.

Natalya:
When my car is in neutral the wire has no voltage, but when the car is in gear the wire has battery voltage. I want the arduino to tell me if there's voltage or if there's not.

That tells me it could be a switch.
If so, just a series resistor and an open switch is a "floating" pin.
That's never good. The extreme high impedance of a pin could pick up anything.
Better calculate to only use the internal clamping diodes as a safety net.
I would stick with the values of OldSteve.
Leo..

Okay I have the resistors OldSteve spec'd, so I'll go with those and his setup.

Wawa brings up the floating pin problem. If I recall correctly, all I need to do to solve that is put a small capacitor between the pin and the arduino ground, right?

@INTP:
The Arduino is going to constantly read the voltage and use it as as boolean. It's also going to be reading the voltage of another 0V or 12V wire (brakes) from the car and store that as a boolean also.

It's also going to read a third wire (VSS) probably on the receive pin and repeat it on the transmit pin (to ECM), until it sees the first boolean as false (neutral) and the second one as true (brakes activated) at which point it will start broadcasting a 2Hz square wave to the ECM, until the car is put back into gear or the brakes are pressed 4 times in a row.

There is a question I just thought of. This is the square wave function:

void loop()
{
 digitalWrite(out_a, HIGH);
 delay(250);
 digitalWrite(out_a, LOW);
 delay(250);
}

Is there a way to do that without delaying any other operations I might want in the loop() by 500ms? Like maybe I put it inside another bracket...

void loop()
{
 // Do Stuff
 squareWave();
}
void squareWave()
{
 digitalWrite(out_a, HIGH);
 delay(250);
 digitalWrite(out_a, LOW);
 delay(250);
}

Or will that still put 500ms between each iteration of the loop?

Natalya:
Wawa brings up the floating pin problem. If I recall correctly, all I need to do to solve that is put a small capacitor between the pin and the arduino ground, right?

No, the 12k resistor already takes care of the "floating pin" problem.
A 10n or 100n cap from pin to ground is optional, and could take care of unexpected spikes/noise.

digitalWrite(out_a, HIGH);
delay(250);
digitalWrite(out_a, LOW);
delay(250);

Not a good idea.
You basically "freeze" everything untill the delay finishes.

Take a look at "blink without delay" in the examples that comes with the IDE.
Leo..

Okay I got some code from a very old post on the forum. I looked at Blink Without Delay but I don't think it's going to be sufficient. I need to generate a 2hz square wave, and I also need to pass through a wave which I figured I'd do using PWM. So the first step is get Timer1 working as a 2hz generator. Second step will be to spoof the incoming wave.

I'm having trouble outputting a square wave using PWM. I think this is because of board differences between the Mega which the following code was written for, and the Pro Mini.

In the example below I set OCRValue to 3096 to get an approximately 2hz wave. The Pro Mini pinout I looked at shows that OC1A is on pin 9. The Atmel .pdf which explains the processor says, "However, note that the Data Direction Register (DDR) bit corresponding to the OC1A or OC1B pin must be set in order to enable the output driver." I'm guessing my problem has something to do with this, but I'm having difficulty figuring out where the bit is or how to activate it or whatever.

/* The following sketch replicates the classic blink program that most users try as their first example  but also blinks led 11 using Timer/Counter 1. The Timer/Counter led uses no processor resources except for the setup  however the standard blink code oocupies the processor completely
*/

int ledPin = 13;
int blinkPin = 11;

void TimerOne_setPeriod(long OCRValue)
// It would be possible to develop a program to take the required frequency, assign an apporopriate prescale option
// and then determine the OCR frequency. This has not been done in this case as the process usually done once
// and the thought process to determine the optimum prescaler option is of value

{
 TCCR1B = _BV(WGM12)|_BV(CS12)|_BV(CS10);   //  or use TCCR1B = 0x0d;            // CTC mode - 1024 prescale
 TCCR1A = _BV(COM1A0);                      //  or use TCCR1A = 0x40;            // Toggle mode 0C1A  
 OCR1A = OCRValue;                          // set the counter
}

void setup()
{
 pinMode(ledPin, OUTPUT);                   // ledPin is output
 pinMode(blinkPin, OUTPUT);                 // alternately use DDRB = 0xa0;      // turn on the timer ouput pin;
 TimerOne_setPeriod(15625);                 // set up and start Timer1 to blink at the same rate as the blink sketch
}

void loop()
{
 digitalWrite(ledPin, LOW);                 // set the LED on
 delay(1000);                               // wait for a second
 digitalWrite(ledPin, HIGH);                // set the LED off
 delay(1000);                               // wait for a second
}

Blink without delay will work great for 2Hz, that is sooo sloooow, just an edge change every 250mS.

I used blink without delay here to make piano (well, organ) tones, for up to 13 notes at one time (with a '1284P, which has 12 more IO pins than an Uno)
http://forum.arduino.cc/index.php?topic=179761.0
Demo with 8 notes (all the buttons I had):

Yeah so the 2hz wave is easy using that method, but I also have to pass through the VSS signal from the car which varies wildly -- 2hz corresponds to only 1mph -- and I'm going to need PWM to do that.