necessity to give delay to adc - arduino

I was trying to send analog signals from arduino to the computer by the serial port.For getting the maximum samples of my input analog signals,I put my baudrate to the maximum limit.The code is as given
void setup()
{
Serial.begin(115200);
}
void loop()
{
int a=analogRead(A0);
Serial.println(a);
delay(1);
}
This program works well for my signals with very low frequency.but at higher frequency signals,there is still arising a problem of aliasing.I tried decreasing the delay.i got more samples When i did this but some of my digital values that I got could not be used,that is,some of the wrong digital values were like 353?12 and so on.Is it manda to give minimum delay of 1 ms to the ADC??Or is there any way that i can Increase my samplestory

You are running into an issue with the default prescaler setting in arduino. The default setup will only get less than 10 samples per millisecond.
You can certainly get faster reads from your ADC if you want to play with some of the underlying settings:
www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/
has a good write up on the subject. They got it running at 50 samples per millisecond with some tweaking.
The other option is to get an ADC chip which will run faster for you. Search sparkfun for "mcp3002". No tweaking of your arduino required since it uses spi input.

Related

Serial print slowing down execution of code. Arduino Due

We are using an Arduino Due to send serial data via usb to a piece of software produced in visual studio.
The problem we are having lies with the Due. We have a section of code that is time critical
PumpCycleTime = millis();
// Loop this until the pumpHIGH duration has expired
do
{
digitalWrite(Pump, HIGH);
SendSerialData();
}
while (millis() - PumpCycleTime < PumpHIGH);
// Record the pump cycle LOW start time
PumpCycleTime = millis();
// Loop this until the pumpLOW duration has expired
do
{
digitalWrite(Pump, LOW);
SendSerialData();
}
while (millis() - PumpCycleTime < 1);
Initially we were controlling the frequency of the pump using delays. Which gave us reliable frequencies when measure on an oscilloscope. However this of course compromised the plotting of the graphs as there was gaps in the data.
With millis() we are unable to produce the same frequency. Obviously we could compensate to achieve a single frequency however we need to be able to use a range frequencies reliably.
It seems the SendSerialData(), which is a function with around 15 serial.print's, is effecting the timings as without it the frequency is as expected.
Does anyone know of any solutions? Data logging and plotting to a graph in real time is essential and cannot be compromised.
Thanks in advance
If the time is so critical DON'T use delay(), use Finite State Machine.
More then this, what is your baud rate? if it's 9600 there is a big chance that is your slowing down because the println();, try to use a bigger baud (like 115200).
Hope it's help.
Yoav

How do I read serial between interrupts on Arduino?

I have steppers stepping during an interrupt timer at 50 and have all my code working between the interrupts until I tried reading serial commands more than one character long.
I'm getting dropped bytes so my strings are missing a letter every 4-5 chars. I researched all day to try and figure out a solution but have come up with nothing. If I don't use an interrupt my stepper stops for 2 seconds reading a one char serial input as a string.
My goal is to have a remote control app sending speed commands. I need help working this problem out.
https://sourceforge.net/p/open-slider/code/ci/master/tree/OpenSliderFirmware/
String incomingString = "";
if (Serial.available() > 0) {
incomingString = Serial.readString();
Serial.println(incomingString);
}
Using Accelstepper library
interrupt:
//Interrupt Timer1
void ISR_stepperManager() {
Slide.runSpeed();
Xaxis.runSpeed();
Yaxis.runSpeed();
}
Quick answer: you don't if the interrupt timer is cutting in too often.
I resolved the problem by using a variable interrupt timer and a step multiplier. Basically the steps are called every time the timer interrupts instead of checking millis inside the interrupt function. This solved many issues. The speed of the stepper is now controlled by the interrupt timer. This gave me more free cycles to fully read the incoming serial without corruption and improved efficiency. Calling more steps per cycle when doing over 4k steps/s also improved efficiency requiring less cycles for a high rate of steps.
The serial is processed one char per cycle to prevent blocking.
Overall, if you are using serial and an interrupt timer, any interrupt happening < 100us you should be cautious how much code you are running during the interrupt. It will cause issues with incoming serial and user inputs. A few lines of code in a 25us timer interrupt, incoming serial will not function.
i'm not sure if it will help to your problem, but i saw along the time that the String type is not safe to use when other things need to happened.
i prefer to use char array and read one char at a time.
while(Serial.available())
{
data[x] = Serial.read();
x++;
}
i'm finding it much more reliable.
hope it's help!

Arduino: Using analogRead() on Photoresistor to read LED with PWM

I have been working on a project with Arduino and have come across something that I find fascinating/confusing. So, I had to test something before constructing this project. I built a simple circuit that consists of just an LED and photoresistor. What I had to test was whether the photoresistor was capable of determining the brightness of an LED that was being dimmed through PWM. My initial expectation was that this would not work (the photoresistor would either read 1023 or 0 because PWM is achieved digitally). To my surprise, the photoresistor was able to accurately read the brightness of the LED (accurately to an extent -- this is simply based off of comparing the apparent brightness of the PWM LED with an LED placed in series with a certain resistor)! This is exactly what I wanted, but I am just curious as to why this works. I am not sure if my original doubt was due to a misunderstanding of photoresistors or PWM. Any help would be much appreciated. Thank you!
Here is the code I am running (I am not using the analogWrite() function because the project I am working on requires me to have a certain level of control over the PWM):
const int LED_PIN = 9;
const int PHOTO_PIN = 0;
//These values have been altered and tested
const int HIGH_TIME = 250;
const int LOW_TIME = 2750;
void setup()
{
pinMode(LED_PIN, OUTPUT);
pinMode(PHOTO_PIN, INPUT);
Serial.begin(9600);
}
void loop()
{
digitalWrite(LED_PIN, HIGH);
delayMicroseconds(HIGH_TIME);
digitalWrite(LED_PIN, LOW);
delayMicroseconds(LOW_TIME);
Serial.println(analogRead(PHOTO_PIN));
}
A "photoresistor" is a variable resistor. That is the simplest way to say it.
Just imagine your potentiometer, you can control its resistance by turning the little knob and then analogRead it. The photoresistor on the other side, changes it resistance depending on the light intensity. Because of that, the resistance will go up and down depending on your LED.
For "HOW" it actually works, see here.
Now, there are a couple of factors to consider:
1 - The ambient light of your room.
2 - The distance between your LED
So hope I helped you learn a little more about photoresistors!
The response time of the photo resistor is much slower than the PWM frequencies you are using. So it averages the on and off times of the LED and gives a resistance proportional to the average light. If you were using a photodiode with a fast response time, it would be able to "see" the LED go on and off.
I suggest that you don't try to write to the Serial port every time through the loop since it will quickly fall behind at 9600 baud. Perhaps write every 500 times through the loop.

Unable to get Data from Serial Device using Arduino

I am trying to read the data from a Ultra Sonic Fuel Sensor(the link).The Baud rate of this device is 9600.The device basically sends data at regular time intervals.I am able to read the output in the PC using Terminal software.Given below is a sample.
Eg:*XD,205B,00,0000,0031,0000,0000,null#
I am trying to connect this device to Arduino through serial port provided in the device and when I see the Serial Monitor,the output is not correct.Given below is the sample.
5320215115451166102572432302302432302302302302432303816623024323023023023024323023023023051822281141463
String incoming_char; // Will hold the incoming character from the Serial Port.
void setup()
{
//Initialize serial ports for communication.
Serial.begin(9600);
Serial1.begin(9600);
Serial.println("Starting Communication with Fuel Sensor");
}
void loop()
{
//If a character comes in from the cellular module...
if(Serial1.available() >0)
{
incoming_char=String(Serial1.read()); // Get the character from the cellular serial port.
Serial.print(incoming_char); // Print the incoming character to the terminal.
}
}
The Arduino is powered from USB and the Device from a 12V supply.
The voltage levels from the device Tx-GND=-5.44V,Rx-GND=-8.22V.
I initially thought the the issue might be because of the voltage range and made a voltage divider circuit and fed Arduino the proportionate voltage.Even that is not working.
So,what is the thing which is going wrong ?Please guide me.
Since you are using Serial1 I am assuming you are using an Arduino Mega?
From your question I would say the issue isn't voltage etc. but more likely to be how you are reading the data. You are assuming that the sensor will be returning char values. Are there any specifications on what is being returned?
I created a similar project using an Arduino. Except my Ultrasonic device was used as a range finder. There are details here. As you can see in the code the range is returned from the sensor as a two byte integer.
You will need to find out what the what the Ultra Sonic Fuel Sensor is returning and read in a similar fashion.
allright i would start by suggesting that you connect this to an analog pin to read. you will have to find the ratio between the fuel hight and voltage by measuring and dividing. then insert the multiplication in the code and you are set it will look like the hight instead of just a voltage
This is just a wild guess since I don't own an Arduino Mega (I have Duemilanove and Uno), but I've worked on projects wherein I've encountered issues similar to what you have. Sometimes adding a delay() on your void loop() block helps and gives it enough time for the arduino to read the bytes from the buffer. For 9600 baud rate, it usually takes about 1 ms to read 1 byte so adding a delay is necessary.
void loop()
{
//If a character comes in from the cellular module...
if(Serial1.available() >0)
{
incoming_char=String(Serial1.read()); // Get the character from the cellular serial port.
Serial.print(incoming_char); // Print the incoming character to the terminal.
}
delay(100);
}
Thank you all ! for your Value inputs.The problem was, I was trying to connect RS232 Serial(Works with Negative Voltages) to TTL serial interface(Works with 0 to some Positive Voltages) used in Arduino. Apparently,I was supplying negative voltages to Arduino whereas it was expected to give Positive voltages. So, got a RS232-to-TTL connector and it worked,finally.

Two port receive using software serial on Arduino

i am having trouble getting data from two sensors using two software serial ports with an arduino board. I noticed a similar question might have been asked before but the answers suggest it can't be done and I know fully well it can based on the example here (http://arduino.cc/en/Tutorial/TwoPortReceive)!
I am using an arduino ethernet. The devices I am trying to get data from include a GPS and an IMU both from sparkfun.
I can get data from either devices using just on software serial port but as soon as I add the second software serial port, neither ports will work. I can't use the hardware serial port because that is being used byt another device.
My code is exactly similar to the example:
#include <SoftwareSerial.h>
SoftwareSerial portOne(7,8);
SoftwareSerial portTwo(5,6);
void setup()
{
Serial.begin(9600);
portOne.begin(9600);
portTwo.begin(9600);
}
void loop()
{
portOne.listen();
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
}
delay(500);
portTwo.listen();
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
}
Serial.println();
}
Anyone with any ideas?
This code will not work, or will work poorly if it works at all. SoftwareSerial only has one internal buffer. Yes, you can have multiple SoftwareSerial objects in existence, but only one of them controls the internal buffer. When any RX pin gets asserted, that generates an interrupt, but only the listen()ing RX pin gets checked for a start bit.
What's really needed is the ability to check on multiple pins when an interrupt comes along from the start bit. Then you'd have to set up pointers to the appropriate data structures. It would be complicated, but possible.
Or maybe just give up on interrupt-driven reception, and spin on checking both/all of the RX pins, and start the receive based on the pin you see. Be forwarned that this code has much hair, and you WILL need an oscilloscope to make it work.
I'm having a similar problem, which is why I found your sensor. After talking it over with my co-workers, we've decided to read our sensors in rotating order. Our sensors report the current state of the sensor, and not specific events, so it's okay if we lose some reports. So we'll read from port 1, then read from port 2, then port 1, etc. Our sensors spit out lines of text, so we know when to switch to the next sensor.
The referenced example only actively listens to one port at a time. The recommended solution would be to upgrade to an Arduino Mega (https://www.sparkfun.com/products/11061) which has 4 hardware serial ports.
In order to simultaneously support two software serial ports is going to require a lot of the CPU resources. It also be a difficult design and excessive programming time far outweighing the cost of $58 + shipping.
Looking at you code again it occurs to me that you are immediately checking for characters after your portOne.listen command. At 9600 baud it will take approximately 1ms for the first character to arrive, your while test will have been completed and the portTwo.listen command executed long before the first character arrives.
For testing purposes try adding a 1-2 ms delay after the portOne.listen command and see if you get a character.
As an example (untested and note, if port one is sending characters with no intercharacter gaps, the first while will never fail, preventing reading portTwo characters):
void loop()
{
portOne.listen();
delay(2);
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
delay(1);
}
portTwo.listen();
delay(2);
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
delay(1);
}
Serial.println();
}
Don't use while ......
Use:
{ portOne.listen();
if (PortOne.available() ) {
ricevo = myPort1.read(); }
// delay(2); // ridiculos waiting time
// delay(1); // extra ridiculos waiting time
Than 500 ms is a too big time for switching, no time.....

Resources