On an Arduino Mega board I am getting interference with reading pin input while PWM is running. It seems to affect both analogRead and digitalRead, and I have tried multiple pins.
I have also tried a 9 volt power source for the board in place of the USB.
My very simple circuit is attached as a picture, and my code and a serial output example is included as well. The code triggers a 2 second tone every 5 seconds.
In the output example, the first several lines reading pin A7 are happening while the PWM is NOT ocurring -- it reads "682."
Then, you can see the reading begin to jump around while PWM is running.
When the PWM stops, the reading again stabilizes. (I did not paste all of these line of output, however.)
I would appreciate help and input about what is causing this, and how it is to be fixed.
Thank you very much!
CODE BELOW:
void setup()
{
pinMode(3, OUTPUT);
pinMode(A7, INPUT);
Serial.begin(9600);
}
void loop()
{
if (millis() % 5000 < 100 )
tone(3, 1000, 2000);
Serial.print("Analog read on pin A7: ");
Serial.println(analogRead(A7));
}
SERIAL OUTPUT BELOW:
(The analog read is stable EXCEPT
while the pwm is running via tone().
During PWM output, the reading flutters.)
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 681
Analog read on pin A7: 681
Analog read on pin A7: 684
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 679
Analog read on pin A7: 681
Analog read on pin A7: 681
Analog read on pin A7: 684
Analog read on pin A7: 682
Analog read on pin A7: 682
Analog read on pin A7: 680
Analog read on pin A7: 681
Analog read on pin A7: 682
Analog read on pin A7: 683
Not unusual. A low pass filter, in hardware or software, should quell it. Unless, of course, your PWM is loading down the 5V rail, which is also used for the ADC, in which case you might want to switch to an internal VREF instead of the 5V. An oscilloscope might be useful to sort this out.
I reconnected the potentiometer just for the picture, and at that time I did switch the wires around.
However, when actually running the circuit and taking analog readings, it was wired correctly and functioned normally.
Thank you for checking the potentiometer wiring -- but in any case, this is not the cause of my problem.
About the low pass filter (hardware) - can you point me in the direction of some information about doing this?
I would like to understand what you mean about "loading down the 5V rail," and using the internal VREF instead. What is this all about, and how to do it?
Thing is, the proper solution depends upon the source of the (very small) transient. For example, telling you how to implement a hardware filter is useless, if the transient is real, and affecting the ADC reference.
Here's a few thoughts:
If speed of change for the analog input is NOT critical, then filter that conversion output by averaging values in software. This is likely your best approach, though it depends on the nature of the PWM disturbance - an oscilloscope would inform.
by loading the rail, I mean, if your PWM output is driving something like a motor load, you may be inducing quite a transient on the 5V rail of the Arduino; since it's used in the ADC, a disturbance on the 5V will affect the conversion result.
If you want to dig deeper, you'll find in the Arduino information a bit about alternative references, instead of the 5V normally used. Not sure if, in your case, that reference voltage is available for application to the potentiometer, though.
Right now the pwm is driving a piezo.
In other tests I have used it to drive a 3.7W class D amp with two small speakers attached.
The speakers and tones work perfectly well, but the problem with the analog read is the same.
I appreciate the help! I thought it would be nice to fix the jitter in the analog read rather than averaging values in my program. The latter option is simple and straightforward, but it would be nice to fix it anyway. I am posting because I want to learn about what is causing the problem and how to fix it.