The arduino should be reading different values as the signal is a sine wave. Tried using different signal frequency as well as different delay(), still shows a constant value. Any help is highly appreciated! Thanks!!
You are printing the value of A2 while you should be reading the pin itself.
Look for analogRead() to start with and if you intend to use much higher frequencies and perhaps need more precise information then consider using an interrupt.
You are not sending the actual reading of analog input. Your code should be something like
void loop(){
int adcRead = analogRead(A2);
Serial.println(adcRead);
delay(2);
}
Related
I'm using ADC pin in ESP32 WROOM to determine the voltage reading from them (GPIO34, GPIO35, GPIO36, GPIO39) but the reading is not accurate aka non-linear.
What I have done is:
I take the actual reading using a multimeter and compare to what the ESP32 reads on those pins by using a potentiometer by varying the voltage on that pin (from 0.1V -> 3.3V based on the ADC reading)
I put those numbers into an excel sheet to plot the error in the following columns :
ADC_READING_VOLTAGE | MULTIMETER_READING | ERROR (MULTIMETER_READING - ADC_READING_VOLTAGE)
Then I get a trendline equation from the error plot and add the error margin to the ADC_READING_VOLTAGE so that I could actually get the real value of the reading (MULTIMETER_READING)
voltage_reading = analogRead(adc_pin)/4095 *3.3V // to get the actual reading
The method that I've tried though gives a slightly better result, but still not good enough (the reading is still off by +- 0.2V)
Has anyone deal with this before? Any suggestions are welcomed.
I'll need your header files to give you a clear solution.
I also came across this issue when I used the WiFi.h everything seems to work fine without WiFi.h, for some reason the ESP32 analog pins(13,12,14,4..) are HIGH while using WiFi.h that's why when you connect the sensors to these pins the value returned is 4095 which is the highest value, I got around this by changing the pins to pin 32, 34, 35, 36 & 39.
I figured it out by plotting 3 piecewise equation to solve the problem on excel, reduced the error margin around +-0.02V (although region >3.1V around +-0.05V).
I was working on this project : http://elm-chan.org/works/sd8p/report.html
and I failed in every possible way from the start. Now that the .Hex files have been uploaded, and the fuses written, when I plugged the SD card in, nothing happened. Nothing at all. Directly asking for a solution might be impossible here as I have no idea what went wrong. So instead I tested the speaker's positive connection with the arduino serial plotter, and I found some interesting results. The output gave some cool irregular pattern of waves,similar to what I would expect from a sound output. But there was no sound, and I suspect that it was because of the output size being too small.(60/1023 is around 0.06 volts, 200/1023 is around 0.2 volts and the bigger output at 500++ levels out, so it shouldn't produce a sound.)
So now I would like to ask whether I can change the fuses of the .hex file(or the hex file itself, but its big.) to produce a larger output. I have not much understanding in hex files or even AVR devices, so any hep at all would be useful.
Thanks in advance.
the graphs
Please let me know if any other information is needed.
Your voltage output on a GPIO pin is limited to your supply voltage, so no you probably can't fix your problem by changing the software or the fuse bits. Depending on your current supply voltage, you might be able to crank that higher, which would increase your voltage output of the PWM, but the supply voltage can only go so high without damaging the chip.
That being said, you need to disconnect the amp and speaker from the AVR and probe the output pin of the PWM and make sure that it is actually producing a signal on that pin. The plots that you posted with that amplitude look like they are nothing but random electrical noise to me.
We are simulating an oven. The potentiometer sets the desired temp and the sensor reads the current temperature of a little copper plate that is "the oven."
Both the temp sensor are connected to their own analog input pin on my arduino uno. Individually, I have gotten values for both the potentiometer and the temp sensor that make sense (I am monitoring the values on the serial window). However, when I adjust the potentiometer it significantly alters the sensor reading.
For example:
The potentiometer is at its 0 position, and the sensor is in the room temperature air. The serial shows TempSensor = 22 C, TSet = 0 C. This is normal.
Then when I turn the pot up: TempSensor= 40 C, TSet=55 C. -But the temperature sensor is still in the room temp air! So the pot value, TSet, goes up like it should, but also affects the sensor reading even though the temperature hasn't really changed.
Any advice would be greatly appreciated. Thanks!
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A3);
float tsens = map(sensorValue, 0, 1023, 0, 500);
int sensorValue2 = analogRead(A1);
float tset = map(sensorValue2, 0, 1023, 0, 70);
Serial.println(tsens);
Serial.println(tset);
}
I've recently bumped into a similar problem and my searches suggest that inserting a delay between the reads can help. On this question, I found this answer and this answer particularly helpful.
The idea is that you need to let some time pass after making a reading, then make another reading after the ADC has stabilized. Here's a function I have been using:
int safeAnalogRead(int pin)
{
int x = analogRead(pin); // make an initial reading to set up the ADC
delay(10); // let the ADC stabilize
x = analogRead(pin); // toss the first reading and take one we will keep
delay(10); // delay again to be friendly to future readings
return x;
}
I'm still having trouble getting an accurate reading of several potentiometers connected to the analog pins configured as a voltage dividers between vcc and ground, but at least now the values are stable.
BTW, it could be argued that since you have a delay after the first reading, it isn't necessary to have the second delay. This might matter if you call safeAnalogRead() twice in quick succession on two different pins.
You most likely have a ungrounded or miswired grounding on your temperature sensor. The pin configurations on the analog pins in Arduinos are layed out very close to each other such that floating voltages will move up or down when nearby pins have an applied voltage. If your ground connection (or power, though if it's correct at the beginning it's probably ground) for the sensor is disconnected or fixed to a high impedance line the analog voltages will move all over the place as other normally minuscule voltage sources will dominate the signal pathing. It probably fluctuates heavily if you put your finger near the A3 pin as well.
Is it noise or a bad value? I did a little test routine that looks at a pin and checks it against previous max and min values. I printed it to the serial monitor whenever a new boundary value showed up. If the wrong value is stable, check the circuit. If its noisey around a valid value, a digital low pass filter works pretty well. Take 34 readings of the pot. Find the highest and lowest values and discard those. Then take the average of the remaining 32 readings. I saw a 90% improvement in my setup (40 count error down to 3). 36 readings with 2 high and 2 low discarded would probably improve things further. If you have the time, you can do a double pass filter. Do this same process 34 times, then throw away the high and low and average it again. All together this is 34 x 34 readings, so noise should go away, but you are taking a long time to get a sample and a pot change will take awhile to get detected. To help with the time, I read the pot every pass through the main loop and save each value in a circular buffer. When I need to read a pot, I look at the historical 33 readings along with a 34th new one.
I have run into this issue before when reading multiple analog sensors in rapid succession. One possible cause(and the one I experienced) is the fact that the arduino only has 1 ADC and it charges a capacitor to take that reading. That capacitor can remain charged between readings thus skewing them.
Introducing a delay could potentially help with this as another user has pointed out, however the cleanest solution I was able to come up with was to "Reset" and discharge the ADC capacitor by taking an analog read of a third pin that is connected directly to ground.
int sensorValue;
int sensorValue2;
float tsens;
float tset;
int resetADC;
void setup()
{
Serial.begin(9600);
pinMode(A0,input);
pinMode(A1,input);
pinMode(A3,input);
}
void loop()
{
resetADC = analogRead(A0);
sensorValue = analogRead(A3);
tsens = map(sensorValue, 0, 1023, 0, 500);
resetADC = analogRead(A0);
sensorValue2 = analogRead(A1);
tset = map(sensorValue2, 0, 1023, 0, 70);
Serial.println(tsens);
Serial.println(tset);
}
I'm new to microcontrollers and I need help reading voltages and printing them in the serial monitor. I have done this using a potentiometer, but I was wondering if I could do the same with just voltages. Below is the code that I used when I read the potentiometer values:
I have tried reading voltages but when I input a voltage smaller than between 3-5V in pin A0 I get 0s in the serial monitor
int potPin = 0; // select the input pin
int val = 0; // variable to store the value coming from the function generator
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
val = analogRead(potPin); // read the value from the function generator
Serial.println(val);
delay(1000); //Sampling rate for the signal
}
as Udo Klein said, this looks like a hardware issue. try setting up your circuit like this: http://imgur.com/PYbeqLq
note that the grounds are shared between the function generator and the arduino - this is important for ensuring that voltages are measured correctly. remember that voltage is actually a difference in electric potential, so you need a common reference point to measure from.
To answer your question, yes you can read voltages from another piece of hardware.
As gearbot tells you it is important to keep a common ground between the arduino and the other piece of hardware.
Also be carefull, the arduino can only measure voltages between 0 and 5 Volts. Don't try to measure higher voltages without adjusting the circuitry as you might destroy your arduino board.
If you're unsure measure the voltages before attaching to the arduino with a multimeter.
The Uno has 6 analog inputs, labeled A0 through A5, each of which provide 10 bits of resolution (i.e. 1024 different values). By default they measure from ground to 5 volts, though is it possible to change the upper end of their range using the AREF pin and the analogReference() function.
edit:
I didn't see the added comment at the bottom of your post. This indicates indeed a hardware problem (probably in your circuitry)
To be sure the arduino does the right thing, measure the voltage with your multimeter between pin A0 and GND while your hardware is attached and working. You should be able to read the correct voltage there.
I suspect it will give the same values as the Arduino.
Then trace back your circuitry with your multimeter (keeping GND attached) to find where something is going wrong.
Try scaling your 0 to 5 or 1-5v input
using map function.
int setValue = map(ana1Value, 0, 1023, 0, 100);
could be a help for you.
the analogue input voltage is the scaled 0-100 then you can work with that
I've just hooked up a electret microphone to an Arduino, and I'd like to sample between the ranges of 1 kHz and 4 kHz.
I understand this is limited to the machine code and the ADC, so I'm trying to keep the sketch simple.
Is it possible to sample between these frequencies with the sketch below?
const int analogPin = 0;
int ledPin = 13;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
int mn = 1024;
int mx = 0;
for (int i = 0; i < 5; ++i) {
int val = analogRead(analogPin);
mn = min(mn, val);
mx = max(mx, val);
}
if (mx-mn >= 50) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}
Arduino is a prototyping platform consisting of a number of hardware boards plus a software abstraction layer. For a question like this, it is useful to consider the capabilities of the underlying hardware, as these provide the ultimate limits. I'll assume you are using Arduino Uno/Nano, the story is different for Due.
According to the datasheet, each ADC reading (beyond the first one) takes 13 ADC clock cycles. ADC clock (different from the MCU) clock is derived by dividing the system clock by some factor, at least 2. So at 16Mhz board this amounts to 0.6 million samples per second. So far so good. However, that's not the end of the story, you still need to read the data. If you use interrupts, even if you do something very simple, experience suggests that you will lose about 100 clock to interrupt processing. Now you are down to 126K samples/second. But this is a theoretical maximum.
The datasheet states that for maximum accuracy for the ADC requires 50kHz - 200kHz ADC clock. In the Arduino code (in wiring.c), a division factor of 128 is chosen:
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
This means that each conversion takes 128*13 = 1764 clocks, which yields a theoretical maximum of 10K samples per second. It is a little bit worse than that given that the readAnalog() function does something beyond just starting the ADC conversion and waiting for it to finish, but it shouldn't be too much worse. This doesn't involve your code of course: any processing you do on the results of readAnalog() will make it more difficult to capture more samples. But yes, to capture at 4Khz you will need to make sure that you code spends less than 1.5k clock cycles/sample, which should be doable. Note that if you are doing five readings like you are doing in the code you posted, the maximum capture rate will be 2kHz if your code does very little.
As far as how to capture the data, you need to make deal with the fact that microphones without amplification will not give you 0-5V readings that you might expect if you are using analogRead(). In fact, microphone output voltages swing from positive to negative, however, the negative voltages will not be picked up by the ADC, and show up as just zeros, unless you give your microphone a voltage offset.
I am not exactly sure what your code that compares minimum amplitude to maximum amplitude is supposed to be doing. Are you wanting to digitize the audio? In this case you need to save all the amplitude readings collected from analogRead(), and then you can run FFTs on them on another computer: Arduino is most likely not going to be fast enough to do frequency analysis on the data.
I have heard, or rather remember reading, that the ADC could handle up to 10k-samples per second, so it should be OK up to 5 kHz. However, I have not tried this nor do I have a link to back it up at the moment.
Just try and see.
Now I know some of the Arduino library functions are slow, notably the DigitalRead/Write that has overhead of hundreds of cycles. Most of this is the sanity checking that allows people to just perform DigitalRead/Write without thinking much about setting everything up.
However, to squeeze out the maximum performance you could look into writing your own AnalogRead that is optimized for your use case.
At least some links on the subject:
Pin I/O performance (JeeLabs)
C++ Template method for faster access (JeeLabs)
I happen to have just tried this using an Arduino Uno and similar code to yours and I've been able to sample an average of 8000 times a second. That is the Nyquist frequency for 4 kHz so you're good but not much margin for error.