Read positive AND negative voltages via analog pin A0??

Thread Starter

A2X_

Joined Nov 9, 2016
10
Hi all,

I'm working on a project and I have a sinusoïdal signal (positive and negative voltages). I'd like to read it with an analog pin and print the results on an SD card. The problem is it is seams that the Arduino can only read positive values.

For example: I used a signal generator and injected in analog pin A0 a sinusoidal signal of 2V peak-to-peak. Which means the signal varies from -1V to 1V. When I read the analog pin, I get values somewhat like this: 0, 0.3, 0.6, 0.9, 1, 0.8, 0.6, 0.2, 0, 0, 0, 0, 0, 0, 0, 0.3, 0.5, 0.8 and it goes on. Obviously, the negative values are automatically put to 0. It's driving me crazy because I absolutely need those negative values!

Is there any way to get those values??? I'd appreciate some help. Thank you!

Here's the code I'm using:

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;
double Time = 0;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}


Serial.print("Initializing SD card...");

// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}

void loop() {
// make a string for assembling the data to log:
String dataString = "";
int X = 1; // Gain that can be varied
// read three sensors and append to the string:
for (int analogPin = 0; analogPin < 1; analogPin++) {
double sensor = analogRead(analogPin);
float voltage = sensor * (3.3 / 1023.0); // conversion factor to output voltages correctly
dataString += String(Time) + " ";
dataString += String(voltage*X);
}

// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);

// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
delay(1); // delay at which the values are taken
Time += 0.001;
}
 

ErnieM

Joined Apr 24, 2011
8,377
Don't assume your signal will be what you expect it to be. Don't assume +2 or -2 are the limits.

If your A2D can read say 0 to 5 volts offset the signal to half way in between for 2.5 volts... This is so you know a reading of zero or max means you have a problem, not just a max signal.
 

crutschow

Joined Mar 14, 2008
34,470
What is the frequency range of the signal?

You can provide a 2.5V offset by using two equal value resistors in series between +5V (or the A/D reference voltage) and ground, and connecting their junction to the A/D input.
Then use a series capacitor to couple the AC signal to the A/D input.
 

MrChips

Joined Oct 2, 2009
30,824
What is the frequency range of the signal?

You can provide a 2.5V offset by using two equal value resistors in series between +5V (or the A/D reference voltage) and ground, and connecting their junction to the A/D input.
Then use a series capacitor to couple the AC signal to the A/D input.
Only if you are only interested in the AC component of the input signal.
Otherwise, use a summing amplifier to offset the signal by the desired DC offset voltage.
 

Thread Starter

A2X_

Joined Nov 9, 2016
10
@MrChips/ErnieM: I taught about adding an offset voltage but what's the best way to do it without affecting the original signal? I take it that I'll have to use an op-amp for the offset? I don't want it to interfere with my original signal's frequency range : from 1Hz to around 10khz.

@nsaspook: Thanks! I will look into that solution even if it looks a bit more complex.

@crutschow schow: My signal's range goes from 1Hz to around 10khz. Would you have a little sketch for the circuit you're mentioning to help visualise? I'm only getting started with the arduino.

Thanks!
 

MrChips

Joined Oct 2, 2009
30,824
@MrChips/ErnieM: I taught about adding an offset voltage but what's the best way to do it without affecting the original signal? I take it that I'll have to use an op-amp for the offset? I don't want it to interfere with my original signal's frequency range : from 1Hz to around 10khz.

@nsaspook: Thanks! I will look into that solution even if it looks a bit more complex.

@crutschow schow: My signal's range goes from 1Hz to around 10khz. Would you have a little sketch for the circuit you're mentioning to help visualise? I'm only getting started with the arduino.

Thanks!
Do you know the impedance of the input source?
If you don't know, tell is where the signal is coming from.
 

MrChips

Joined Oct 2, 2009
30,824
Here is an example straight off the internet.
Use this if absolute DC values are not important to you.

Modify the values R1, R2 and C1 to suit your desired frequency range, DC offset and source impedance. For example, you will need C1 to be at least greater than 10μF to get down below 1Hz.

A DC summing amplifier would get you all the way down to 0Hz.

 

John P

Joined Oct 14, 2008
2,026
If the signal truly is a sinusoid, you only need to measure the positive half, and the negative half will be predictable. But maybe that's not sufficient.
 

Thread Starter

A2X_

Joined Nov 9, 2016
10
@MrChips : The signal is coming from an AC motor. I'm actually measuring the electromagnetic signal emitting from the motor (We're talking something around 100uV), amplifying it, than reading the voltage values using the arduino. I'm not sure about the impedance though... And thank you for the circuit, I'll look into it!

@John P: I've only used the sinusoidal signal as an example. The true signal I'm trying to measure is a lot more variable.

@dannyf: Yes, I think the level shift will be the way to go. Thanks.
 
Top