Go Down

Topic: Sending data from C++ app to Arduino via Serial Port? (Read 626 times) previous topic - next topic

techniqueOne

Hello.  New here.  Been struggling with an issue and hope this is the right place to get help.  So here goes.

I'm trying to get a C++ application running on a computer to send data, eg. simple string, to arduino via the serial port.  The host computer running the C++ program is Linux.  I don't know if this is the proper way to 'talk' to Arduino from an external program, but I am writing to the Arduino device file :  /dev/ttyACM0 as referenced in this post: https://salilkapur.wordpress.com/2013/03/08/communicating-with-arduino-using-c/


I have my Arduino wired up with a LCD (non serial) display and it works fine as a standalone.  I am trying to get the C++ program to send a string of text to the Arduino which will display the text on the LCD screen when it recieves it.  Example:  The C++ program writes "Hello World!" to device file /dev/ttyACM0.  Arduino reads the Serial Port and displays "Hello World!" to the lcd. 

This works fine, but only when the serial monitor on the IDE is open?  I don't know why, but for some reason I have to have the serial monitor from the Arduino IDE open for this to work.  If I have the serial monitor closed/not opened.  It doesn't work.

I poked around and found out there are some issues with the permissions of /dev/ttyACM0 and who can use it.  I tried changing permissions, adding myself to the dialout group, etc.  but nothing seems to work.

Obviously, I would like the program to work without the need of having the Arduino IDE and it's serial monitor opened and running in the background.  In an actual deployment, I wouldn't tell the customer they have to install the Arduino IDE and launch the serial monitor for it to work.

I've concluded there is something about the serial monitor that makes this whole thing work.  What is it?  I'm not skilled enough to check out the Arduino IDE source code, but obviously, something is triggered when the serial monitor is opened.  eg.  changes permissions to /dev/ttyACM0 or something like that.


note:  If I just write to /dev/ttyACM0 directly via the command line, eg. sudo echo "hello world" > /dev/ttyACM0, w/o the arduino IDE or serial monitor running, it works.  This command does prompt for my password and after I type it in, the string appears in the lcd (keep in mind, w/o the ide or serial monitor running).   If I don't use sudo, eg.  echo hello > /dev/ttyACM0, nothing happens.  No output.

Another thing to note is that when I try to send data to the arduino via the C++ program or just writing directly to /dev/ttyACM0 without the IDE & serial monitor running is that I notice the RX led is blinking.  Still no output on the lcd, but the RX led does blink, suggesting it is getting something.

Any help would be greatly appreciated. 


Robin2

You need to post both your PC program and your Arduino program.

A common problem is that people familiar with PC programming open the serial port, send the message and then close the port. Everytime the serial port is opened the Arduino will reset so the PC code must open the serial port and keep it open until it is completely finished with the Arduino.

This Python - Arduino demo illustrates the idea and should be easily implemented in C++.

This more recent Thread Serial Input Basics illustrates a few different ways to receive data reliably on an Arduino.

...R

Two or three hours spent thinking and reading documentation solves most programming problems.

techniqueOne

wow.  Didn't think it would be that complicated, but I guess nothing is easy.  Well, here's my c++ code.  Probably very amatuerish programming which is why it doesn't work:

C++ program running on host computer:

Code: [Select]
#include <iostream>
#include <fstream>

int main(int argc, char* argv[])
{
//open arduino device file (linux)
        std::ofstream arduino;
arduino.open( "/dev/ttyACM0");

//write to it
        arduino << "Hello from C++!";
arduino.close();

return 0;
}


It's probably missing all that opening port stuff you mentioned.  I have no idea how to go about that.  Is there a serial library for C++ similar to python?  Would it really be necessary?  Isn't the device file enough?  I thought that was the beauty of linux?  You could just write/read to "files".


arduino sketch:
Code: [Select]
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

char buffer[256];

void setup() {
    Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
}

void loop() {

// send data only when you receive data:
if (Serial.available() > 0) {

// read the data
        Serial.readBytes(buffer, 256);
               
// say what you got:
        lcd.print(buffer);

}

}


Again, this works fine as long as the serial monitor from the ide is open.  I don't print anything to the serial monitor, it just has to be opened.  But the string still gets to the lcd.

I had no idea the Arduino resets when the serial port opens.  Also, didn't know you had to wait for it to be ready.  Again, harder than I thought.  I''ll try to study the python examples and see if I could get it to work in C++.  Any suggestions appreciated.  thanks.

Robin2

Again, this works fine as long as the serial monitor from the ide is open.  I don't print anything to the serial monitor, it just has to be opened.  But the string still gets to the lcd.
Are you saying that, with the Arduino Serial Monitor open on /dev/ttyACM0 your C program can send data to the Arduino?

I did not think that could work because I thought the Serial Monitor would have exclusive use of the serial port. But I am certainly no expert on Linux even though I use it every day.

Why not just use Python and save yourself a lot of trouble?
I only use C/C++ on the Arduino because I have no choice.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

techniqueOne

Are you saying that, with the Arduino Serial Monitor open on /dev/ttyACM0 your C program can send data to the Arduino?
yup.  I don't know why/how, but that is the case.  As a matter of fact, I can send strings from both my c++ program as well as by typing in the serial monitor text field.  Both will appear on the lcd.

I guess I could use Python, but I want to try to do it in C/C++ if possible for speed considerations.  I still can't believe this is that hard.  No one has ever tried to make a C/C++ program talk to arduino?  Really?

Robin2

I guess I could use Python, but I want to try to do it in C/C++ if possible for speed considerations.?
Python can work very much faster than the serial interface. I don't think you will experience any speed difference.

Quote
No one has ever tried to make a C/C++ program talk to arduino?
There is no certainty that such people will notice your Thread

Have you tried asking Google or asking on some other PC programming Forum - what about Stakoverflow?

As a general comment, the reason people use Python (etc) rather than C/C++ is because programmer time is more costly than CPU time.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PaulS

Quote
I did not think that could work because I thought the Serial Monitor would have exclusive use of the serial port.
Windows enforces the restriction that only one application at a time can access a COM port. Other operating systems do not.

OP: The problem with your C++ code is that you are NOT setting any of the properties of the serial port - the baud rate, the parity, etc. You are ASSuming that the default setting will work. Clearly, they do not. Opening the Serial Monitor application sets all the serial port properties correctly, so that your application can then communicate with the Arduino. Set the properties correctly in your application, and you won't have to open the Serial Monitor application first.

Opening the port resets the Arduino. Without waiting for the Arduino to reset, it is pointless to send it anything.

techniqueOne

pauls:  I think you're right.  I suspected my client C++ was far too simple to be interacting with the serial port in that manner.  I definitley need to use some serial library abstraction to set such properties eg. baud rate, etc.

Giving the Arduino time to reset was the key missing ingridient.  I literally used sleep( 2 seconds) and everything worked (without even using any serial object code).  So I was sending the data too fast before the Arduino had a chance to set up.

Well I guess the takeaway when trying to communicate with the Arduino via a user program on a pc is 1) use serial code abstraction to access the serial port (even on linux) and  2) at the very least,  give time (~2-3s) for the Arduino to reset before interacting! 

thanks all!

Robin2

I suspect 2 to 3 seconds is at the low end of what will work. I think 5 to 7 secs might be more reliable.

It is possible to disable the auto-reset, but that can make it difficult to upload programs.

Also, the Leonardo and Micro which use the Atmega 32U4 MCU do not reset when the serial port is opened - which could be useful in your case but can be a PITA in other circumstances.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy