reading analog 0 to 5v to a file in PC

Hello I am about to buy an ARDUINO UNO but want to be sure it can do what I need. I have two transducers each producing a 0 to 5v signal. I want to capture the two outputs so I can make an X-Y plot. When the value at one port (say the x) has increased by a given amount ( say 0.05 volts) I want to read the value at the other port, thus giving an x,y data point. I can program the PC to open the com ports and input the data. Can the ARDUINO UNO convert the analog voltage and send it to the serial port. I believe can keep reading the port in a loop fast enough to monitor the change from the transducer as it will be fairly slow ( from 0 to 5v over a period of 1 to 3 seconds). When the data representing the .050 volt change is detected it will read the other port fed by another ARDUINO UNO, save the data and get back to the loop.

What do you think Thanks

What you describe sounds easily achievable.

Thanks so much I'll probably have detailed questions when I get going........

You might find PLX-DAQ useful. This is a freebie macro for Excel that can put Arduino data directly to Excel and provide a real-time on-screen graph. It is usually triggered by time but I imagine it works just as well triggered by events, like you propose.

HI All I have an ARDUINO UNO reading analog input 0 to 5v dc and sending it to the serial output port and attached to my PC with the USB cable. I am running the ARDUINO UNO with a program I got from the "examples" (attached below). I am reading it with a simple program written in "JustBasic" that plots a graph of the values it reads. I have fooled around with delays, and lof parameters and it is working pretty well but I want to be positive about capturing all the data reliably. I am occasionally missing data or reading partial messages. How can I find out the following?

At what frequency are the messages sent to the port? Are they fixed length or variable? Does it add an end sentinel to mark the end of the message? Is there a better way to reliably capture the data?

Thanks Rob

AnalogReadSerial Reads an analog input on pin 0, prints the result to the serial monitor. Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground. This example code is in the public domain. */ // the setup routine runs once when you press reset: void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); } // the loop routine runs over and over again forever: void loop() { // read the input on analog pin 0: int sensorValue = analogRead(A0); // print out the value you read: Serial.println(sensorValue); delay(75); // delay in between reads for stability}

Please use code tags.

Read this before posting a programming question

At what frequency are the messages sent to the port?

Approximately every 75 mS because of the delay. The serial printing takes a bit of extra time too.

Are they fixed length or variable?

Variable as you would see if you tried it. For example "0" is shorter than "1023".

Does it add an end sentinel to mark the end of the message?

A carriage-return + linefeed (because of the Serial.println).

Is there a better way to reliably capture the data?

Better in what sense?

Thank you so very much. I understand now that the frequency is controlled by the delay value in the program.

I am getting numbers from 2 to 1050 as seen on the ARDUINO monitor.

Am I to understand that the analog pin is read then converted to a digital number and sent to the serial port where it sits for the delay period (75 ms) until it is "over written" by the next Serial.println. So there is only one value at a time in the buffer. Not a bunch of readings stacked up in a queue waiting to be read. If I read the port while it is being written to I will get erroneous numbers. If this is true how do I assure that I am getting the whole current value of the last written data?

I assume I need to specify the word length when I read the port. I can use a Lof() function to determine the length but how do I know it is the full word and not a partial if the word length is a variable.

I hope this makes sense... Thanks Rob

rhfland1: I understand now that the frequency is controlled by the delay value in the program.

If you use millis() instead of delay(), you can more easily control the frequency of reading/sending the values See the Blink Without Delay example that came with the Arduino IDE

I am getting numbers from 2 to 1050 as seen on the ARDUINO monitor.

Sounds right.

Am I to understand that the analog pin is read then converted to a digital number and sent to the serial port where it sits for the delay period (75 ms) until it is "over written" by the next Serial.println. So there is only one value at a time in the buffer. Not a bunch of readings stacked up in a queue waiting to be read. If I read the port while it is being written to I will get erroneous numbers. If this is true how do I assure that I am getting the whole current value of the last written data?

No. It is sent to the serial port, and if buffered there until it is read by the other end of the line (the PC in your case). You will not get erroneous numbers or dropped characters unless you overrun the buffer (64 bytes). You can read the port any time, whether it is being written to or not. Bear in mind that if you just read a character from the PC, it will have to be ready to read. I am not familiar with JustBasic, but there should be some way to tell if the PC's serial buffer has anything in it, and qhat quantity it has. If not, I would suggest VB.Net Express Edition. It's free. You should read until you get a CR or LF or both. You could always do away with Serial.println() and only use Serial.print(), and add sentinel characters to the beginning and end of your data. Or, just send the data and add a single LF or CR.

I assume I need to specify the word length when I read the port. I can use a Lof() function to determine the length but how do I know it is the full word and not a partial if the word length is a variable.

No, you don't have to specify length. See above regarding end of line or sentinel characters.

Thanks Nick

A quick description of what I am trying to do: I have two ARDUINOs. One reading a linear transducer (0 to 5v) to measure distance. The other is reading a force transducer (0 to 5v) to measure the force. The transducers are connected and actuated together so that I can determine the force generated at a particular distance. I then generate a Force vs Distance graph.

I am reading the distance port in a loop. When it has traveled a known amount, say 1 inch, which corresponds to an increase in the output of 20, I then want the value of the force at the other port. If I then read it, I will be reading "old" data that has been stacked up in the buffer. I want the value that corresponds to the position read from the distance transducer.

Because of this I put the Force read in the same loop as the Distance so they were both constantly reading and updating at the same time. Then when the value of the distance changed by at least 20 I jump out to the plotting routine. This seems to help. I still get erroneous small values as I believe I am reading partial words.

I still do not understand how to read the buffer until I get to a LF or CR. To read the port I use a command: t$=input$(#comm,10)

Any words of wisdom? Thanks Rob

That was lar3ry that responded, and I agree with what he said.

The data doesn't "queue up" in the output port for 75 mS. At the rate you are sending (9600 baud) and a reading every 75 mS it should flow smoothly out the serial port. What happens to it then is up to whatever-it-is you have connected to the serial port on your computer.

To read the port I use a command: t$=input$(#comm,10)

You want some sort of "read line" function on the PC. Something that reads until it gets a newline. This is pretty standard stuff, because that is how you normally read user input.

Thanks to you both

I will look into read line commands

Thanks again Rob

rhfland1: I have two ARDUINOs. One reading a linear transducer (0 to 5v) to measure distance. The other is reading a force transducer (0 to 5v) to measure the force. The transducers are connected and actuated together so that I can determine the force generated at a particular distance. I then generate a Force vs Distance graph.

I am reading the distance port in a loop. When it has traveled a known amount, say 1 inch, which corresponds to an increase in the output of 20, I then want the value of the force at the other port. If I then read it, I will be reading "old" data that has been stacked up in the buffer. I want the value that corresponds to the position read from the distance transducer.

Well, the answer to that is simple. Don't send anything out the Serial port unless it's the data you want. You read the distance sensor and the force sensor, store the values, and check to see if the distance has increased to 1 inch. If it has, send the values at that time. There's no sense in sending in data that you aren't interested in.

Because of this I put the Force read in the same loop as the Distance so they were both constantly reading and updating at the same time. Then when the value of the distance changed by at least 20 I jump out to the plotting routine. This seems to help. I still get erroneous small values as I believe I am reading partial words.

If you have the values you are interested in, just send them with something like:

   Serial.print (distance);
   Serial.print ("\n");  // or "\r" or "\r\n"
   Serial.print (force);
   Serial.print ("\n");

I still do not understand how to read the buffer until I get to a LF or CR. To read the port I use a command: t$=input$(#comm,10)

input$() should input an entire line, though I don't know if it requires a CR, LF, or both. See the snippet above for how to send them.

Thanks Lar3ry I will be away from the lab until Monday and will try these things then and let you know. Question: What exactly does the message to the serial port, as the ARDUINO sends, look like? How many bytes? Would an 8bit byte look like this? 0,0,1,0,1,0,1,0,LF,CR

If this is true, I can see how I could read until I get to the LF,CR but how do I know that I have started at the beginning of the byte and not in the middle?

Thanks Rob

No, if you send 42 using Serial.println you will get:

0x34 0x32 0x0D 0x0A

Or in other words:

4,2,CR,LF

rhfland1: ... how do I know that I have started at the beginning of the byte and not in the middle?

You don't, but after a linefeed the next thing should be the start of the next number.

Thank you........ this is very helpful.

My distance transducer is traveling a distance of 20 inches in approximately 2 seconds. For a resolution of 1/4 inch I need to be sampling at about .025 seconds. Is this to fast for the ARDUINO to read the analog pin, convert to digital, send to the port, and then sample again?

Thanks

The sampling takes around 104 µS.

Sending a 4 digit number plus CR/LF at 9600 baud will take:

 1/960 * 6 = 0.00625 S = 6.25 mS

So sampling at 25 mS should be achievable, however if you increased the baud rate to 115200 baud the transmission time would decrease to:

 1/11520 * 6 = 0.000521 S = 521 µS

So at 115200 baud the sampling plus transmission should be achievable in around 1 mS.

Thank you , thank you. You have been so helpful and a wealth of information. I think I am on my way now. Rob

UGH ! Another question after all.

Why is the sampling time calculated by 1/960 rather than 1/9600 ?

Rob

9600 baud is 9600 bits per second, and there are 8 bits per byte, plus a start bit and a stop bit, giving 10 in total.