# [Solved] Wierd data range from ADC on Arduino Due

I’ve been trying to read samples from a microphone with my Arduino Due. Somehow the samples are wrong in amplitude and I can’t figure out how they end up that way.

Setup is as follows:

Microphone → filter to make sure the signal is in the range 0-3.3 V → Arduino Due ADC.

I play a sine with frequency of 1000 Hz to the microphone and measure the output on my oscilloscope. The picture below shows the signal before (yellow) and after (green) my filter. The filter is not the best but that is not important here.

The sampled signal on my Arduino Due is sampled with 48 kHz. In the end my Arduino will take input from 8 different microphones. For now I just feed the same signal (the green one from the picture) to all 8 ADC channels.

This picture below this paragraph shows 1024 samples on channel0 and channel7 (red and blue) that I’ve sent from the Arduino Due to MATLAB using a USB serial connection. (The figure also shows the difference between the signals in green.) As seen the signals are not completely identical but that’s not important to the main problem, although not ideal for the end goal.

There is obviously something wrong here. According to my calculations the green signal on the oscilloscope has a peak-to-peak 0.470-0.313 V (readings from the Measurements tab down right on the oscilloscope) which is 0.157 V.

In my sketch I set the analog read resolution to 8 bits using

``````analogReadResolution(8);
``````

1 bit then corresponds to 3.3/256 = 0,0129 V/bit. Since signal peak-to-peak is 0.157 V it would correspond to a very small signal, read by the ADCs, fluctuating with 0.157/0,0129 = 12 bits in the lower region of the plot. This is not the case as seen in the picture above, the signal amplitude covers almost the whole 256 value range and is overflowing resulting in going from 255->0 over all periods. Is there something I missed?

To be clear, the period of the recorded signal is very satisfying. I’ve counted the number of samples in the period of the signal in the plot. They are (on average taken over all the displayed periods) almost exactly 48. Since sampling frequency is 48 000 we get the frequency of the recorded signal to 1/(48/48 000) = 1000 Hz.

I’ve done this test with a lot of different frequencies and its the same type of result.

I attached the images together with the source code. It’s 2 sketches, one for the Arduino Due that is sampling the signal, one for the Arduino Due that send’s the 48 kHz interrupt-sampling-signal, and the MATLAB code, RecordSamples.m file and a SerialSetup.m script (uploaded as .pdfs here).

The way the sampling works is that one Arduino sends an interrupt signal at 48 kHz to the sampling Arduino, that is because in the end I will have 8 Arduinos recording on 8 channels, that is 64 different microphones. And they all need to record at the same time (± the time for all 8 channels to take a sample within one Arduino). The sampling needs to be very quick that’s why I’ve had to use register calls rather than normal Arduino wrapping code.

The way I see it it could be 2 things going wrong here

1. Some data type conversion is made wrong somewhere, overflowing the uint8 type, resulting in a weird amplitude but correct period. If so I’d be happy if someone could point to where.

2. Maybe the ADC doesn’t read 8-bit, but some larger value that will overflow the 8-bit conversion again resulting in a weird amplitude but correct period. If so maybe someone could explain why, and how to correct it.

I hope the problem is understandable and I hope you will want help me pinpoint the problem or suggest a solution I’ve spent the better part of the day searching for an answer.

Here is the code for the sampling Arduino in text format as well:

``````volatile int sampleCount = 0;   //count samples so we don't get more than 1024
volatile bool measure = false;  //flag to decied if we want to sample or not

const byte interruptPin = 2;    //the interruptsignal comes to this pin

const int channels = 8;                         //the number of analog channels to record on
const int sampleMax = 1024;                     //length of the sample array
uint8_t recordedSamples[channels][sampleMax];   //2D array to store the sampled signals in

void setup() {
//set interrupt pin
pinMode(interruptPin, INPUT_PULLUP);

analogReadResolution(8); //<---- this seems to be ignored

//serial setup and send ready message to MATLAB
Serial.begin(250000);
}

void loop() {
//In the main loop there is a while loop that checks for serial commands
while (Serial.available() > 0) {
//reads a byte from Serial. This byte is a "command" byte telling us  what to do
if(ans=='r')
{//In this case MATLAB wants us to begin reading samples
//and listen to interrupts, 'a' is confirmation char in this case
sampleCount = 0;
Serial.write('a');
measure = true;   //sets the flag to begin listen to interrupts
}else if(ans == 'd')
{ //In this case MATLAB wants us to send the recorded signals on channel 0 and 7
Serial.write(recordedSamples[0], sampleMax);
Serial.write(recordedSamples[7], sampleMax);
}
}

}

//This is the interrupt function
if (!measure) return;           //if this flag is false we dont want to begin sampling yet
if (sampleCount >= sampleMax){  //if we've reached the end of sampling array we dont want to sample anymore
measure = false;
Serial.write('r');
return;
}

for(int i=0; i<channels; i++){                     //goes through the channels
}

sampleCount++;                                     //increment what sample we are taking next time
}
``````

clock_generator.ino (1.72 KB)

RecordSample.ino (2.27 KB)

RecordSamples.pdf (7.86 KB)

serialsetup.pdf (6.61 KB)

What microphone, how is it amplified and how is it connected?
What is the "filter"?

Please post a hand drawn circuit diagram, not Fritzing.

jremington:
What microphone, how is it amplified and how is it connected?

It is a custom built Loudspeaker/Microphone unit supplied with +-12 volts. When in microphone mode it outputs a signal that is greater than what the Arduino can handle, therefore..

jremington:
What is the "filter"?
Please post a hand drawn circuit diagram, not Fritzing.

.. there is a simple circuit after the microphone that converts the signal down to a range of 0-3.3 V. maybe filter is the wrong word, it's kind of an op-amp with gain less than 1.

Surely I can supply you with diagrams of this, although I don't think it is relevant to the subject. Everything before the signal to the Arduino can be abstracted away, can't it? Since the signal I'm trying to sample is shown on the oscilloscope we can work from that, no?

although I don't think it is relevant to the subject.

You are quite wrong.

You are quite wrong.

jremington:
You are quite wrong.

Pardon me and pardon my hand writing. Here is a block diagram of the setup. Should you want a component level schematics I can provide that as well, although I still don’t think that is relevant. The input to the Arduino will just be a signal between 0 and 3.3 V.

EDIT: on the drawing it says 3-3.3 V, it should be 0-3.3 V, its quite late at the moment…

It is also attached as a .jpg

That diagram seems sufficient to me. It clearly shows that you are measuring with the scope at the right point.

Just make sure you have the scope set to "DC" and it really is measuring what you think you're measuring. Check the divider switch on the probe (if any) and the other scope settings. I suspect that you still don't have the appropriate DC offset and it's clipping the signal at 0V or 3.3V.

It appears that the mysterious "filter" is the problem.

MorganS:
Just make sure you have the scope set to "DC"

It is DC as shown on the picture, and the oscilloscope is on the same ground as everything else!

MorganS:
Check the divider switch on the probe

This is a mistake I did earlier this week and it was the first thing a checked, it's set to 1 as it should be!

jremington:
It appears that the mysterious "filter" is the problem.

The signals looks like they should when viewing them on the oscilloscope. If the "filter" is the problem, then the oscilloscope settings are too. I will check this first thing when I'm back in the lab!

analogReadResolution(eight) do not exist with the Arduino DUE ! You can choose between 12 or 10 bits resolution.
Do not use magic numbers to program ADC registers, it is very painful to debug.

You will find numerous example sketches of ADC conversions thru registers programming in the Arduino DUE sub forum of this forum.

A 1 KHz sampling can't be an issue.

The A/D should return half of the A/D range (512 or 2048) without signal, not clamped to ground as in your graph.

You must use a 1:1 voltage divider from VCC to ground, with center connected to the A/D, to float the input mid-voltage. And a DC blocking capacitor between filter and A/D.
Without those components, audio will be clamped (distorted) to ground by the pin clamping diodes.
Post a diagram of that filter.
Leo..

Judging from the green oscilloscope trace, the "filter" is oscillating at relatively high frequency. That is why the trace looks so thick.

Yes, the filter is definitely oscillating, we need to see its schematic.

You don't need an amplifer to attentuate, and in fact its clearly a bad idea here as there is unwanted
oscillation.

ard_newbie:
analogReadResolution(eight) do not exist with the Arduino DUE ! You can choose between 12 or 10 bits resolution.

Really? According to what I found here it seems it should work. Atleast it will automatically convert it to 8 bits by disregarding the LSBits.

ard_newbie:
Do not use magic numbers to program ADC registers, it is very painful to debug.

Hard to debug, yes. But I didn't find another way of getting the desired results in terms of speed. If you have a suggestion on another approach I will gladly take advice from you

ard_newbie:
A 1 KHz sampling can't be an issue.

1 kHz signals is not a problem. However, it should work for 24 kHz (48 kHz sample rate) baseband audio signals.

Wawa:
The A/D should return half of the A/D range (512 or 2048) without signal, not clamped to ground as in your graph.

I'm not sure what you mean here. Do you mean that the yellow signal on the oscilloscope is centered at ground? It should be.

Wawa:
You must use a 1:1 voltage divider from VCC to ground, with center connected to the A/D, to float the input mid-voltage. And a DC blocking capacitor between filter and A/D.

With a capacitor between filter and A/D the signal will be centered around ground, and the range of the A/D is 0-3.3 so surely it has to be centered at 3.3/2?

Wawa:
Without those components, audio will be clamped (distorted) to ground by the pin clamping diodes.
Post a diagram of that filter.
Leo..

Yes, a lowpass filter you mean? As I said the current thing is not very good and is just put together of things we happened to have laying around in the lab. We will most probably put a lowpass filter there due to the high frequency oscillation displayed on the scope.

jremington:
Judging from the green oscilloscope trace, the "filter" is oscillating at relatively high frequency. That is why the trace looks so thick.

Yes, I completely agree but it's not the point here. The point is that the signal is not displayed correctly in MATLAB.

ViktorWingqvist:
I'm not sure what you mean here. Do you mean that the yellow signal on the oscilloscope is centered at ground? It should be.

With a capacitor between filter and A/D the signal will be centered around ground, and the range of the A/D is 0-3.3 so surely it has to be centered at 3.3/2?

Yes, a lowpass filter you mean?

As I said the current thing is not very good and is just put together of things we happened to have laying around in the lab. We will most probably put a lowpass filter there due to the high frequency oscillation displayed on the scope.

The Arduino you're using can only process positive voltages (0-3.3volt for a Due).
You can't just shove an AC signal in there, because half of the AC wave is negative.
That negative part of the wave will be cut off by the input pin protection/clamping diodes (if you're lucky).
Too much current from your preamp, and you could fry the pin.

Yes, VCC/2.
You're using a Due that runs on 3.3volt, so VCC is 3.3volt.

No, a high-pass filter that blocks DC.

Again, post a diagram and pictures.
Leo..

Wawa:
The Arduino you’re using can only process positive voltages (0-3.3volt for a Due).
You can’t just shove an AC signal in there, because half of the AC wave is negative.
That negative part of the wave will be cut off by the input pin protection/clamping diodes (if you’re lucky).
Too much current from your preamp, and you could fry the pin.

I am aware of this and that is why I convert the signal from [-5, +5] to [0, 3.3], that’s the whole point with the converting “filter”. I thought I was clear on that, apparently not. If you have a look at the oscilloscope you can clearly see that the green signal is above ground. I didn’t state it explicitly but of course the whole system is on the same ground.

Wawa:
Again, post a diagram and pictures.

Here you go. In this case RX_DOWN_IN is grounded.

ViktorWingqvist:
I am aware of this and that is why I convert the signal from [-5, +5] to [0, 3.3], that's the whole point with the converting "filter".

How?

The output if this preamp can theoretically deliver 10volt peak/peak with a +5volt -5volt supply, regardless of the 1.65volt offset. Non rail2rail opamps might reduce that to 8volt, but still way too high for the A/D of a Due.
Leo..