Analog input - positive/negative voltage

Hi, new on Arduino.
Are analog input pins of Arduino UNO sensing only positive voltages (0V to+5V) or can -5V to+5V signals be input - and A/D converted with sign - ?

If the former, would a negative voltage damage an input pin?
Is a silicon diode (0.6V) from input pin to GND enough to protect the input pin?

thanks in advance

Sandro

The Arduino should only be exposed to positive voltages. A negative voltage will mos likely make toast of Your controller.
Protective diode….. Check the data sheets for the controller, section Absolute Maximum Ratings. Maybe it works, maybe not.

Sandro36:
Are analog input pins of Arduino UNO sensing only positive voltages (0V to+5V) or can -5V to+5V signals be input - and A/D converted with sign - ?

The pin itself can only measure positive voltages, but a voltage divider with pull up to VCC can be used to measure -5volt to +5volt.
Try 10k from pin to VCC (5volt pin) and 10k from pin to the voltage to measure.
That will result in a bias of 2.5volt (A/D value of 512) on the pin with 0volt on the source.
Subtract 512 from the returned A/D value to get positive and negative values (voltages)

Sandro36:
If the former, would a negative voltage damage an input pin?

Depends on the current into (out of) the pin.
If you keep it low (the above voltage divider), then the pin will survive.

Sandro36:
Is a silicon diode (0.6V) from input pin to GND enough to protect the input pin?

No, useless.
A common diode can have 1volt across with sufficient current.
A schottky diode might be ok, but it's leakage can introduce errors.
Better make sure you never exceed voltage (or current) ratings of the pin.
Leo..

Thank you Wawa,
I'll try the voltage divider idea. It will also simplify the downstream signal dealing.
Sandro

I worked out the V divider solution.
I don’t know if a schematics image can be posted here. I shall explain by words.

A shunt measuring resistor (100mV/500A) is inserted in series between ground and negative pole of a batterie. The maximum expected current is 250 A.
Purpose is measuring the -/+ current

The ground side of the shunt (small terminal) is the Arduino UNO GND.
The batterie side of the shunt(small terminal) is the current signal(-50 mV to +50 mV).

1k from this terminal to input pin. 100k from input pin and +5V.
Input pin signal = 0V (-200A), 50mV (0A), 100mV (+200A).

Pin AREF kept at 60 mV.
In the sketch: analogReference(50)
Digital current value: 0 to 512 = -200A to 0A, 512 to 1024 = 0A to +200A

Is all this correct?
If yes more questions later on.

Thanks
Sandro

I wouldn't use that low a reference voltage - better use the built-in 1.1V reference (and calibrate the actual value as it's got a 10% tolerance).

Then take your signal, apply an offset, and amplify 10x through an OpAmp.

Or use an external ADC such as the ADS1115 which has a 256 mV reference available. Again offset your signal to something positive. You use only part of the range but it's a 16-bit ADC so still better resolution than the Arduino.

Minimum useable Aref voltage for the Arduino is 1volt (see Atmel datasheet).
You should have mentioned that this was for a shunt.
Ignore all the advice I gave you.

A shunt is better measured with a chip meant for those low shunt voltages.
Try something like an INA219 or INA229 breakout board.
Leo..

I made The voltage divider suggested by Wawa and the op ampl by wvmarle.

After a good deal of trial and error, the voltage divider is 9k and 1M and the gain of the non inverting op amp (741) is 10k and 500k.
The op ampl feed voltage is supplied by the battery under observation; the input voltage divider is supplied by the 5V pin of the Arduino.

Lacking a big battery and the shunt, I mocked up the shunt voltage drop with an 1.3V battery, a potentiometer and two resistors to pick up the centre (my 0V).
In this way to an input of -45 mV to +45 mV an output of 0 to 5 V corresponds. No AREF needed.
Settled the hardware, now the software starts.
I began the sketch but, being new to this, I am sure I'll need further help in the near future. I'll search the forum before asking directly.

The program should:
read the analog input,
convert it in positive/negative Amps.
sample the input value every a given amount (100 ?) of millis (interval)
average between the current values of interval start and end.
multiply this by the interval legth and and sort units [Ah]
add (+/-) this to the battery charge value
send the charge value to an LCD display
an input (push button) sets the charge value to a preset known value to start from (e.g. fully charged)

ancillary preset values needed:
the shunt current range
the starting charge loaded by the push button
an offset (very small) for accurately adjust the zero
a gain factor ( very near to 1) for accurately adjust the 5V to the shunt range

The charge display could be better shown as a percentage of the full charge instead than in Ah.
in this case the capacity of the battery would also be input as a preset.

I'll report the outcome
Thanks

Sandro

Better post a circuit diagram.
We don't know if you understand "common mode range".

The 741 is a dinosaur compared to todays opamps.
Leo..

Good luck.
And indeed that's an old OpAmp - get a modern rail to rail one, so you can actually measure 0-5V and not 0.5-4.5V or so.

One other issue to overcome: remember the battery charge over a power outage.
One way to do this is by writing it to EEPROM - but you have a limited number of writes, rated 100,000. Doing this 10 times a second wears it out quickly.
An alternative is to get an RTC chip with NVRAM, some 64 bytes of RAM that are kept by its back-up battery. That can be written to unlimited times, just like regular RAM.

Only now I read again in the forum, apologies for the delay.

I’ll try and post the diagram. It is on two sheets because my printer can only print A4.
I have around a small 6V 14Ah lead acid battery with which test the project.

Please make clear for me the “common mode range”.
Please suggest a better op amp. I used 741 perhaps because I am also myself a dinosaur…

Everything is fed by the battery monitored, so there should not be power failures, anyway it is a good thing to store the variable C (currentl charge) in EEPROM or other permanent memory.
The sampling interval could be increased to a few seconds but it would be not enough.
I plan to sort out this later.

I began the sketch. I get in many lines the error message: “variable” was not declared in this scope.
I don’t understand where should I declare the variable. It is in the void set up.

Thanks for your assistance

Sandro

Carica1l.pdf (9.19 KB)

Carica2l.pdf (15.9 KB)

Sandro36:
Please make clear for me the "common mode range".

The voltage window in which both inputs have to stay for the opamp to work.
Typically ±13volt on a ±15volt supply. Meaning they must be at least 2volts away from ground or supply.
An LM741 is designed for a bipolar 15volt supply, common in the seventies, and won't do well on a single 5volt rail.
The LM358 has a common mode range that includes ground (not VCC), but doesn't have rail2rail outputs.
Frequently used, because it works on 5volt and is cheap.
Maybe an INA219 breakout board (with high-side shunts) is better suited for what you're trying to do.

Voltage range of an Uno's DC socket starts at ~7volt.
If you only have 6volt, then use the V-in pin.

Global variables are declared outside setup() and loop().
Post your sketch if you want help with that.
Read the forum guidelines about using code tags first.
Leo..

Thank you very much.
I 'll shift to LM358. I won't use INA219 because I have not got a real project to make. My purpose is just to practise with Arduino and I think that this is a good project to start with.

If I don't manage to write a working sketch I shall surely post what I did and beg for help, but before giving up I shall try to overcome the snags myself, just for better learning.

When all is finished and tested I shall post diagram and sketch, but I am sure I'll need further help in the meanwhile.

Sandro

Here I am after a long delay doing else.

Beginning to learn/exercise coding for managing the display.

I sent to the display several constant values of the code: everything OK.
Then I sent to the display the voltage from the shunt ( of course rectified and amplified).
This caused the arising of a problem I had not foreseen and that I am afraid could doom the project.

When showing the current from the battery the figures were steady; when showing the current from the battery charger the figures were flickering in a range between different values

The charger is an old and rough one: a transformer and a rectifier bridge. Instant value of voltage, current and shunt voltage have a deep ripple at 50 or 100 Hertz.
The measured and displayed figure depends on the time of the period when the code cycle samples the voltage.
A smart charger supplying a PWM output voltage would feature the same problem.

How can the signal voltage be kept on a constant (actually slowly changing) average value?
I wonder if just a large capacitor would flatten the variable voltage at about peak value. Not what is wanted.

Any comment and/or suggestion is the welcome.

Sandro

That would be 100 Hz (double the AC frequency).

Probably your best solution is to filter the values in software. Either use a moving average of the past n values, or use the maximum number you get.

That failing, maybe you can add an envelope detection circuit at the output of your OpAmp, and read that on your Arduino's input.

I think that it is not possible to filter or average the voltage values in software.
The instant value varies from zero to peack value. It is read at random moments by the cycling code.
In a while most readings can happen near zero, or can happen near peack. The software average of these readings would have no connection with the average of the real voltage.

With the rough charger it could work if the code cycling period were much shorter than 10 ms, with a smart PWM charger things would be worst yet.

What is an envelope detecting circuit?

By the way, which is the working cycle time of a 300 lines sketch in Arduino?
Is there any sotware trick for reading (watching) an input more frequently than once a cycle?

Thank you
Sandro

Sandro36:
I think that it is not possible to filter or average the voltage values in software.
The instant value varies from zero to peack value. It is read at random moments by the cycling code.
In a while most readings can happen near zero, or can happen near peack. The software average of these readings would have no connection with the average of the real voltage.

[…]

By the way, which is the working cycle time of a 300 lines sketch in Arduino?
Is there any sotware trick for reading (watching) an input more frequently than once a cycle?

Connect a timer interrupt to the ADC trigger, and use a 50 Hz and/or 100 Hz notch filter.

If you don’t mind some distortion at other frequencies, you can use a very simple FIR notch filter like this one:
Simple Finite Impulse Response Notch Filter

Don’t worry if you don’t understand the theory behind it, just use the formulas to calculate the normalized frequency ωc,d and the transfer function formula. Also have a look at the magnitude response of the Bode plot. This graph tells you how much each frequency is attenuated by the filter. In the example, you can clearly see that frequencies around 50 Hz are attenuated really well. You can also see the problem of the FIR notch: other frequencies around 50 Hz are attenuated as well, and it’s not symmetric, higher frequencies are amplified.

Here’s an example on how to use the notch filter on Arduino. It uses a timer using micros, but you can also use it in the ADC ISR (without the printing, of course).

Arduino 50Hz Notch Filter example

Pieter

Sandro36:
I think that it is not possible to filter or average the voltage values in software.

Why not? You ran out of memory already or so?

What is an envelope detecting circuit?

This.
When you encounter an unknown term, open your favourite search engine, copy/paste it into the search field, and start reading.

By the way, which is the working cycle time of a 300 lines sketch in Arduino?

Anything from a few microseconds to infinite time, depending on the program itself.

Is there any sotware trick for reading (watching) an input more frequently than once a cycle?

You can of course read it a second time during that same cycle... but whether that's useful is hard to say.