What I want is using visual studio to read and write to arduino UNO using a bluetooth device HC-05. In the previous step, I am able to communicate using visual studio c++ and Arduino directly through usb port. The code I am using is basically same as arduino and visual studio c++, 2 way serial communication. In arduino, I have command as:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available() > 0) {
char c = Serial.read();
if (c == '1')
Serial.write("FORW");
else if (c == '2')
Serial.write("LEFT");
else if (c == '3')
Serial.write("RIGTH");
else if (c == '4')
Serial.write("BACK");
else if (c == '5')
Serial.write("STOP");
else
Serial.write("Invalid");
}
and my/output is (using arduino usb directly):
Connection established!!!
Enter your command: 1
arduino: FORW
Enter your command: 2
arduino: LEFT
Enter your command: 3
arduino: RIGTH
Enter your command: 6
arduino: Invalid
Enter your command:
When I added a bluetooth Module HC-05 with it. Using serial monitor can get same output, but when I used visual studio, the first input never gives back a output, while for the following output, it always gives a previous output not a current one, as following:
Connection established!!!
Enter your command: 1
arduino:
Enter your command: 2
arduino: FORW
Enter your command: 1
arduino: LEFT
Enter your command: 4
arduino: FORW
Enter your command: 6
arduino: BACK
Enter your command: 2
arduino: Invalid
Enter your command:
I don't know if following steps may give error:
bluetooth is supplied with 5v
I cross connected bluetooth TX RX with Arduino Uno
bluetooth HC-05 is in default mode, I didn't change anything about it.
When bluetooth is connected with PC, it shows two ports: COM4 'DEV-B' & COM5,so I just changed the code in visual studio to make it connect to COM4.
Bound rate is set to be 9600 on Arduino also indicated in visual studio.
So any idea why this would happen?
Most probably the problem is that in 10ms the previous communication can't reach you.
Now, I don't have much experience in programming with plain C++ and visual studio (I usually use the managed C++ extensions and the event loop) but when I have to deal with serial ports I usually use either events or parallel threads.
When using events, I use the SerialPort class and its DataReceived event. Since you are using Visual C++ this is the method I suggest you to use. Just let VS create a base skeleton for you by creating a managed console application instead of an empty one and see how events work.
If you want to use multiple threads, just use one thread to check for the input and the other to check for the serial. I'm afraid I can't help you on how to start and handle the threads (you have to use some OS or library functions, maybe pthread's ones), but the two threads functions can be something like this:
void thread1()
{
while (1)
{
std::cout << "Enter your command: ";
std::cin.get(command, 2); //input command
int msglen = strlen(command);
if (port->WriteData(command, msglen)); //write to arduino
printf("\n(writing success)\n");
}
}
void thread2()
{
while (1)
{
int n = port->ReadData(data, 4);
if (n != -1){
data[n] = 0;
cout <<"arduino: " data << endl;
}
Sleep(10);
}
}
The third solution is to check the input and the serial only when some data is there:
std::cout << "Enter your command: ";
while(1)
{
if (_kbhit())
{
std::cin.get(command, 2); //input command
int msglen = strlen(command);
if (port->WriteData(command, msglen)); //write to arduino
printf("\n(writing success)\n");
std::cout << "Enter your command: ";
}
//read from arduino output
n = port->ReadData(data, 4);
if (n != -1)
{
data[n] = 0;
cout <<"arduino: " data << endl;
}
Sleep(10);
}
These are the solutions if you want to send multiple commands (i.e. make the program wait for the input, send it and then wait for another input).
If you want to just use it for one command and then exit, just wait for some data:
std::cout << "Enter your command: ";
std::cin.get(command, 2); //input command
int msglen = strlen(command);
if (port->WriteData(command, msglen)); //write to arduino
printf("\n(writing success)\n");
while ((n = port->ReadData(data, 4)) <= 0)
Sleep(10);
data[n] = 0;
cout <<"arduino: " data << endl;
The easiest but most unsuggested solution is to just increase the sleep period (e.g. to 50 ms) to allow the packets to be sent and received.
One more thing, since sooner or later you will face this problem. Usually with communication (be it serial, ethernet, ...) you don't have control on how often the driver tells you when it received the data. When you receive "FORW", you usually receive it as a block, but sometimes you receive a block with "FOR" and another with "W", or "FO" "RW", or "F" "ORW". Or you can receive two consecutive messages, for instance "FORWLEFT". Consequently you should either
decide a "terminator" character, for instance #. The sending function sends FORW#, the receiving tests each received character until it finds the terminator and then processes all it received till that moment. For instance, it receives "FO". Append to the buffer (FO). No terminator, no processing. Then it receives "RW". Append to the buffer (FORW). No terminator, no processing. Then it receives "#LEFT#". Append to the buffer (FORW#LEFT#). The first terminator is at position 5, so analyze the first 5 bytes (FORW#) and remove them from the buffer (which now contains LEFT#). Still a terminator, analyze. If you don't like #, you can use a carriage return (\n), a space, a string terminator (\0); every character you are NOT using in the strings is fine.
make each command exactly the same length (for instance 4 chars). Then read every byte until the buffer is longer or equal to 4 chars, and process the first n bytes.
Related
I just start to using Clion as my IDE and I'm struggling with EOF inputed from keyboard.
If I execute this simple c++ code
#include <iostream>
int main(){
int sum = 0, value = 0;
//read until EOF, calculating a running total of all values read
while(std::cin >> value){
sum += value;
}
std::cout << "Sum is " << sum << std::endl;
return 0;
}
In the Run window of Clion, after I input from keyboard
1 2 cmd+d I get this
1 2 ^D
Process finished with exit code 0
In MacOS the EOF(with keyboard) is Cmd+D.
In CLion is in settable in:
File -> Preferences -> KeyMap -> search EOF and set Cmd+D.
However, I suggest you to use in your code a Terminating Character such as zero that in this case doesn't change the result.
Example of execution in CLion
This is some known issue with CLion on Windows. Disabling the run.processes.with.pty in Registry (open via Find Action) usually helps.
In some environments the EOF emulation is performed using Ctrl+Z combination not Ctrl+D
To avoid such problems - create file with contents you want to enter "1 2"
and run your program from terminal redirecting the standard input to read from file. In this case the EOF event will always happen at the end of the input.
$./test < myinputfile.txt
I am currently working on a project that involves serial communication between a Arduino and a laptop. I know the Arduino is indeed sending the data that I need, see this picture: http://s1.postimg.org/w5wisaetr/Help.png
Now on the other end my laptop is connected to the Arduino and running a program that I made using QT Creator. However, when reading data from the serial Port I can't get the program to display this information.
I connected my readData() function to be executed when data is received like this:
connect(m_serialPort, SIGNAL(readyRead()), m_dataGathering, SLOT(newData()));
This works and the newData() function is called whenever something in transmitted from the Arduino. However the function newData() does not display the data that I need.
newData():
void DataGathering::newData()
{
QByteArray rMsg = m_serial->readAll();
qDebug() << rMsg.constData();
}
This only sends empty message to the display. Like this: http://s2.postimg.org/dkcyip2u1/empty.png
The following code however works:
void DataGathering::newData()
{
QByteArray rMsg("\nTest...");// = m_serial->readAll();
qDebug() << rMsg.constData();
}
This code display the message like it should.
However, another difference in the output display is that when the working code is executed my console also displays a lot of Framing errors, I assumed this is because the baudrate of the unwanted characters differs from the data that I need.
That is why i started questioning the readAll() function.
It is also obvious that the Arduino is not only sending the data that I need but also some unwanted characters (see image in first link), but I don't see this as a problem since I will filter this out later.
All help is very much appreciated.
Update: I found out that the readAll() function is returning QByteArrays with size() equals to 0.
Looks like the serial port QIODevice does not implement bytesAvailable, if it returns 0. This may also be why readAll() fails, depending on how it is implemented. But at least readAll() has the problem of not being able to report error.
Try using read method instead for better diagnostics, like this (untested):
void DataGathering::newData()
{
QByteArray rMsg;
for(;;) {
char buf[256]; // read data in this size chunks
qint64 len = m_serial->read(buf, sizeof buf);
if (len <= 0) {
if (len < 0) {
qDebug() << "newData() read error" << m_serial->errorString();
}
break; // for(;;)
}
rMsg.append(buf, len);
}
qDebug() << "newData() got byte array" << rMsg.size() << ":" << rMsg;
}
It may not solve your problem, but with luck it will give you error message.
I have 2 threads: one of them is constantly cout'ing to the console some value, let's say increments an int value every second - so every second on the console is 1,2,3... and so on.
Another thread is waiting for user input - with the command cin.
Here is my problem: when I start typing something, when the time comes to cout the int value, my input gets erased from the input field, and put into the console with the int value. So when I want to type in "hello" it looks something like this:
1
2
3
he4
l5
lo6
7
8
Is there a way to prevent my input from getting put to the console, while other thread is writing to the console?
FYI this is needed for a chat app at client side - one thread is listening for messages and outputs this message as soon as it comes in, and the other thread is listening for user input to be sent to a server app.
Usually the terminal itself echos the keys typed. You can turn this off and get your program to echo it. This question will give you pointers on how to do it Hide password input on terminal
You can then just get the one thread to handle output.
If you are a slow typer, then the solution to your problem can be, as I said, making it a single thread, but that may make the app to receive only after it sends.
Another way is to increase your receiving thread's sleep time, which would provide you some more time to type (without interruption)
You could make a GUI (or use ncurses if you really want to work in the console). This way you avoid having std::cout shared by the threads.
I think you could solve this problem with a semaphore. When you have an incoming message you check to see if the user is writing something. If he does you wait until he finishes to print the message.
Is there a way to prevent my input from getting put to the console, while other thread is writing to the console?
It is the other way around. The other thread shouldn't interrupt the display of what you are typing.
Say you have typed "Hel" and then a new message comes in from the other thread. What do you do? How should it be displayed?
Totally disable echoing of what you type and only display it after you hit enter. In this way you can display messages from the different threads properly, in an atomic fashion. The big drawback is that you cannot see what you have typed already... :(
You immediately echo what you type. When the new message comes in, you undo the "Hel", print the new message and print again "Hel" on a new line and you can continue typing. Doable but a bit ugly.
You echo what you type in a separate place. That is, you split somehow the display. In one place you display the posted/received messages in order; and in another place you display what you are typing. You either need a GUI or at least some console library to do this. This would be the nicest solution but perhaps the most difficult to port to another OS due to the library dependencies.
In any case, you need a (preferably internally) synchronized stream that you can safely call from different threads and can write strings into it atomically. That is, you need to write your own synchronized stream class.
Hope this helps.
Well i recently solved this same issue with a basic workaround. This might not be the #1 solution but worked like a charm for me, as a newbie;
#include <iostream> // I/O
#include <Windows.h> // Sleep();
#include <conio.h> // _getch();
#include <string> // MessageBuffer
#include <thread> // Thread
using namespace std;
void ThreadedOutput();
string MessageBuffer; // or make it static
void main()
{
thread output(ThreadedOutput); // Attach the output thread
int count = 0;
char cur = 'a'; // Temporary at start
while (cur != '\r')
{
cur = _getch(); // Take 1 input
if (cur >= 32 && cur <= 126) // Check if input lies in alphanumeric and special keys
{
MessageBuffer += cur; // Store input in buffer
cout << cur; // Output the value user entered
count++;
}
else if (cur == 8) // If input key was backspace
{
cout << "\b \b"; // Move cursor 1 step back, overwrite previous character with space, move cursor 1 step back
MessageBuffer = MessageBuffer.substr(0, MessageBuffer.size() - 1); // Remove last character from buffer
count--;
}
else if (cur == 13) // If input was 'return' key
{
for (int i = 0; i < (signed)MessageBuffer.length(); i++) // Remove the written input
cout << "\b \b";
// "MessageBuffer" has your input, use it somewhere
MessageBuffer = ""; // Clear the buffer
}
}
output.join(); // Join the thread
}
void ThreadedOutput()
{
int i = 0;
while (true)
{
for (int i = 0; i < (signed)MessageBuffer.length(); i++) // Remove the written input
cout << "\b \b";
cout << ++i << endl; // Give parallel output with input
cout << MessageBuffer; // Rewrite the stored buffer
Sleep(1000); // Prevent this example spam
}
}
I'm working on some code that will be used to test other executables. For convenience I'll refer to my code as the tester and the code being tested as the client. The tester will spawn the client and send commands to the client's stdin and receive results from the client's stdout.
I wanted to do some performance testing first so I wrote a very simple example tester and client. The tester waits for the client to write "READY" to its stdout and in response it sends "GO" to the client's stdin. The client then writes some number of bytes to stdout, configured via a command line flag, and then writes "\nREADY\n" at which point the tester will again write "GO". This repeats 10,000 times after which I calculate the time it took to complete the test and the "throughput", the 10,000 divided by the time to complete.
I ran the above test having the client send 0, 10, 100, 1000, 10000, and 100000 bytes of data before it sends "READY". For each byte size I repeated the test 10 times and took the average. When run on my laptop in an Ubuntu VMWare instance I got a throughput of about 100k GO/READY pairs per second. The performance was fairly stable and had virtually no dependence on the number of binary bytes the client sends to the tester. I then repeated the test on a very fast, 24 core server running CentOS. With a 0 byte payload I observed only about 55k GO/READY pairs per second and the performance degraded noticably as the number of bytes the client sent increased. When the client sends 100k bytes between "GO" and "READY" the throughput was only about 6k operations per second.
So I have three questions
Why would the same code run much more slowly on a faster machine
Why would the performance in the virtual machine be independent of payload size but the performance on the fast server be heavily dependent on payload size?
Is there anything I can do to make things faster on the server
One possible explanation is that I recompiled the code on the fast server and it is using a different version of the C++ libraries. The VMWare machine is running Ubuntu 11.10 and the fast sever is running CentOS 6. Both are 64 bit machines.
The relevant tester code is as follows:
ios_base::sync_with_stdio(false);
const int BUFFER_SIZE = 2 << 20;
char buffer[BUFFER_SIZE];
process_stdout->rdbuf()->pubsetbuf(buffer, BUFFER_SIZE);
Timer timer;
// Wait until the process is ready
string line;
line.reserve(2 << 20);
getline(*process_stdout, line);
CHECK(line == "READY");
timer.Start();
for (int i = 0; i < num_trials; ++i) {
*process_stdin << "GO\n";
process_stdin->flush();
line = "";
while (line != "READY") {
getline(*process_stdout, line);
}
}
double elapsed = timer.Elapsed();
cout << "Done. Did " << num_trials << " iterations in "
<< elapsed << " seconds. Throughput: "
<< double(num_trials) / elapsed << " per second." << endl;
I also tried versions using read() calls (from unistd.h) into a 1MB buffer and calls to memchr to find the "\n" characters and look for READY but got the same performance results.
The relevant client code is as follows:
// Create a vector of binary data. Some portion of the data will be sent
// to stdout each time a "GO" is received before sending "READY"
vector<char> byte_source;
const int MAX_BYTES = 1 << 20;
for (int i = 0; i < MAX_BYTES; ++i) {
byte_source.push_back(i % 256);
}
cout << "READY" << endl;
while (cin.good()) {
string line;
getline(cin, line);
if (line == "GO") {
// The value of response_bytes comes from a command line flag
OutputData(response_bytes, byte_source);
cout << "READY" << endl;
}
}
// write bytes worth of data from byte_source to stdout
void OutputData(unsigned int bytes,
const vector<char>& byte_source) {
if (bytes == 0) {
return;
}
cout.write(&byte_source[0], bytes);
cout << "\n";
}
Any help would be greatly appreciated!
The fact that the speed in VM is independent of the payload size indicates that you're doing something wrong. These are not complete programs so it's hard to pinpoint what. Use strace to see what's going on, i.e., whether the client actually does send all data you believe it is (and also check that the tester is receiving all data it should be).
100k READY/GO pairs is way too much; it's basically near the upper limit of the number of context switches per second, without doing anything else.
Does anyone know how to make an event loop in c++ without a library? It doesn't have to be cross-platform, I'm on a Mac. Basically, I want the program to run and do nothing until the user presses the up arrow key, then the program will output "You pressed up" or something. All i can think of is having an infinite while or for loop and get input with cin, but I don't think cin can detect arrow keys and I believe it pauses the program until it reaches a '\n';
I would want it to look like this:
void RUN()
{
while(true)
{
// poll events and do something if needed
}
}
int main()
{
RUN();
}
I'm kinda sure it's possible without threads, and I've heard that this can be accomplished with fd_set or something, but I'm not sure how.
Any help would be really appreciated.
EDIT:
The program has to run in the background when there aren't any events. For example, Microsoft Word doesn't stop until the user presses a button, it keeps running. I want something like that, but command-line not GUI.
Since you're talking keyboard input, and not looking for a Mac look and feel, what you want is the UNIX way of doing it. And that is,
1) set the terminal in either raw or cbrk mode (I forget which).
2) now use read() to read single characters at a time.
3) temporarily echo the character read (as an int) so you can find what the up arrow key gives you.
As for the more general event loop question, where the only input device is the keyboard, you sit in a loop, and whenever a key is typed (in raw mode?) you call a routine with the value of the key typed. If you had more input devices, you would need multiple threads each could listen to a different device, putting what they find on a queues (with appropriate locking). The main loop would then check the queue and call a routine appropriately everytime something appears in it.
You can use ncurses and enable cbreak to get the raw input stream.
I've used a while loop with signal handlers. Like this incomplete snippet.
void getSomething()
{
std::cout << "Enter new step size: "; std::cout.flush();
std::cin >> globalVariable;
std::getchar(); // consume enter key.
}
void printCommands()
{
std::cout << "1: do something\n"
<< "q: quit\n"
<< "h: help\n"
<< std::endl;
}
void getCommand()
{
// Output prompt
std::cout << "Enter command ('h' for help): "; std::cout.flush();
// Set terminal to raw mode
int ret = system("stty raw");
// Wait for single character
char input = std::getchar();
// Reset terminal to normal "cooked" mode
ret = system("stty cooked");
std::cout << std::endl;
if (input == 'h') printCommands();
else if (input == '1') getSomething();
else if (input == 'q') {
g_next = true;
g_quit = true;
}
}
void
signalHandler(int signo)
{
if (signo == SIGINT) {
g_next = true;
} else if (signo == SIGQUIT) {
getCommand();
}
}
int main(int argc, char* argv[])
{
signal(SIGINT, signalHandler);
signal(SIGUSR1, signalHandler);
signal(SIGQUIT, signalHandler);
do {
// Stuff
} while (!g_quit);
exit(0);
}
The question has been updated to say "The program has to run in the background ... but command-line not GUI."
All traditional; *NIX shells that can put a program into the background also disconnect the program's standard input from the terminal, so AFAIK, this has become impossible.
This does not need to be Mac specific. The Mac supports *NIX mechanisms for reading characters from a keyboard.
AFAICT all the program is doing is waiting for a character, so it might as well block.
Normally the terminal device, tty (teletype!), is interpreting characters typed on the keyboard before your program can read them from standard input. Specifically the tty device normally buffers an entire line of text, and intercepts the rubout character (and a few others like CTRL+w) to edit the line of text. This pre-processing of characters is called a 'line discipline'
You need to set the tty device driver to stop doing that! Then you can get all of the characters the user types.
You change the device using ioctl or termios on the file descriptor.
Search for e.g. "ioctl tty line discipline raw" to understand the details, and find program examples.
You can set the terminal to 'raw' using the command line program stty.
Please read the stty man page because setting it back can be slightly tricky (NB: if you make a mistake it is often easier to kill the terminal, than try to fix it, because there is not echoing of anything you type)
It is possible that the up-arrow is not a single char, so it will require some byte-at-a-time decoding to avoid blocking at the wrong point in the input stream, i.e. if some input sequences are one character, and others two, or three characters, the decoding needs to happen at each byte to decide if there is a pending byte, or one too many read's might get issued, which would cause the program to block.