Here’s a picture of my circuit.
Very simple. All it does is analogRead() the value of a potentiometer and serial.Print() it out. This is the sketch program.
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.print(analogRead(0));
Serial.print(byte(26)); //prints an end of file character. you’ll see why.
}
When you open up the serial monitor in the Arduino IDE, you can easily see the potentiometer values streaming with no errors. What I wanted to do was get that potentiometer value into a C program as easily as possible. So I wrote this program :
include
include <stdio.h>
FILE *arduino;
char tempf[64];
int main() {
system(“mode com3:115200,n,8,1”);
arduino=fopen(“COM3:”,“r”);
while(1) {
fscanf(arduino,"%s",tempf);
printf("%s\n",tempf);
}
fclose(arduino);
return 0;
}
I know the baud rate is really high, but that doesn’t really seem to matter. The program works… sort of.
What will happen is that suppose the potentiometer is set at 712. In the Arduino IDE, I can see it streaming into the serial monitor at that value. I can twist it and watch the values change. Everything works. Here is the problem with pulling the data from the Arduino as a “copy” command or file copy. By file copy I mean that you can do this :
- USB plug in the Arduino board.
- Open the command line
- Type in “mode com3:115200,n,8,1” without the quotes, where com3 is whichever port the USB is plugged into and 115200 has to match the baud rate set by Serial.begin() in the Arduino program.
- Now type in “copy COM3: testfile.txt”
- Open testfile.txt in notepad and you’ll see that the contents are a single line with 712, which is the potentiometer value. Remember that Serial.print(byte(26)) line? That made sure that the copy command would stop. If you didn’t have Serial.print(byte(26)) in the program, the copy command would run indefintely. You could open testfile.txt while it was copying and see a stream of data. If you cancel the copy command, it deletes testfile.txt. You can copy testfile.txt before canceling, but thats a pain in the neck. Just put at Serial.print(byte(26)) in there and that makes the copy command recognize an end of file and stop.
Here’s where it all gets messy. Run that copy command a few times.
copy command 1 - testfile.txt shows 712 - everything is good.
copy command 2 - testfile.txt shows 712 - everything still good.
copy command 3 - testfile.txt shows 12 - it missed the 7.
copy command 4 - testfile.txt shows 712 - everything is good again.
copy command 5 - testfile.txt is empty - not good.
copy command 6 - testfile.txt shows 2 - it misse the 7 and the 1.
This doesn’t happen in this order. It may get 712 twenty times in a row, then it will pull a 12, a 2 or nothing. I think what is happening is that since the Arduino is streaming out information which is not synchronized with the copy command, it’s only picking up a character and then everything to the right.
At this point, if you turn the potentiometer, suppose to 286, the copy command will still pickup the change and show 286… but sometimes 86, sometimes 6 and sometimes nothing.
So I tried writing a C program which reads COM3: like a file. It works in the same manner as the serial monitor in the Arduino IDE. You can see the potentiometer values streaming along just fine. Twist the knob and watch the values change. You can see that the tempf variable is now very simply filled with data supplied by the Arduino.
But that didn’t fix it.
If the potentiometer is stable, the streaming display in the C program shows it fairly stable. I made it output to a file and saw that when a potentiometer is stable, it only messes up the value about 1% of the time. If the value is 863, it will show 863 about a hundred times before it shows 63, 3 or nothing.
It gets worse when you turn the knob. Turning the knob when the C program is running makes all kinds of weird errors. It still does the catch-only-characters-to-the-right problem, but it is more like 50% this time. About half the potentiometer values are junk during a transient, when the knob is turned.
Any thoughts on how to fix this? I tried changing the baud rate, which didn’t fix it. I tried slowing down the while(1) loop in the C program to only read the COM3: file once a second rather than 100 times a second, which didn’t fix it.
I think it all comes down to the fact that the Arduino output data is not synchronized with the “copy” command or fscanf() in the C program.
I know there are all sorts of libraries out there I could install. The problem with that is that it seems silly to me to have to fill out 50 lines of code just to read from a serial port in a barebones simple ANSI C program. I’m doing it in two lines of code… but it’s not quite right yet.
There is bound to be some guy to tell me to learn python, C# or some other stupid idea. That is overkill. I’m able to do everything I want in plain C without having to learn 5 other programming languages.
I think there is something very simple that I am missing. I thought about writing a function to do some sort of idiot check of the potentiometer value, but that would be the equivalent of programming duct tape. I also thought about writing this code :
Serial.print(0);Serial.print(" “);Serial.print(0);Serial.print(” ");Serial.print(0);Serial.print(byte(26));
Which would, suppose the potentiometer value is 473, look like this :
473 473 473
473 473 473
473 473 473
73 473 473
473 473 473
3 473 473
473 473 473
473 473
473 473 473
Which means that the fscanf() or “copy” commands might still miss a few characters, but it will still have the chance of getting some good ones.
Another idea might be that if I have 3 potentiometers set up on a board, I could make identifiers for each of them and stream that data out, where the C program could parse through and recognize what is what. Arduino code of :
Serial.print(“potlabel0”);Serial.print(" “);Serial.print(“potlabel0”);Serial.print(” “);Serial.println(0);
Serial.print(“potlabel1”);Serial.print(” “);Serial.print(“potlabel1”);Serial.print(” “);Serial.println(1);
Serial.print(“potlabel2”);Serial.print(” “);Serial.print(“potlabel2”);Serial.print(” ");Serial.println(2);
Supposing potlabel0 was set at 473, potlabel1=395, potlabel2=832 would have an output like this
potlabel0 potlabel0 473
potlabel1 potlabel1 395
potlabel2 potlabel2 832
would allow little bits of text to be cut off on the left side of each line, then the C program could read the string, match it to potlabel0 in the C program and assign 473 to a variable in the C program. This is another kind of programming duct tape, but it’s a little more clever.
I’d rather not do this with duct tape, and I really don’t want to install some library or worse, learn a completely new programming language. That’s not the point. There has to be a way to make this very simple arrangement of two lines of code work. It’s simple, it’s quick, but it doesn’t work quite perfectly yet. There has to be a way to get it working.
Any thoughts?