C++ Serial Communication Issue - c++

I am trying to make a Console C++ program that will be able to communicate through the serial port with my Arduino microcontroller, however I am having a problem with the ReadFile() function:
This is the ReadFile() function code from my C++ Console Program:
if(ReadFile(myPortHandle, &szBuf, 1, &dwIncommingReadSize, NULL) != 0)
{
cout<<"FOUND IT!"<<endl;
Sleep(100);
}
else
{
cout<<".";
Sleep(100);
}
The ReadFile function is consistently returning the "False" value, meaning it is not finding anything in the serial port. On the other side of the serial port, I have my Arduino Hooked up with the following code:
int switchPin = 4; // Switch connected to pin 4
void setup() {
pinMode(switchPin, INPUT); // Set pin 0 as an input
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
if (digitalRead(switchPin) == HIGH) { // If switch is ON,
Serial.write(1); // send 1 to Processing
} else { // If the switch is not ON,
Serial.write(0); // send 0 to Processing
}
delay(100); // Wait 100 milliseconds
}
And every time I press a push button, I would send a "1" value to the serial port, and a "0" every time I don't press a push button. Basically, I got the Arduino code from a tutorial I watched on how to do serial communication with the program Processing (which worked perfectly), though I am unable to do the same with a simple Console Application I made with C++ because for some reason the ReadFile() function isn't finding any information in the serial port.
Anyone happen to know why?
P.S.: The complete code in the C++ Console Program can be found here:
https://stackoverflow.com/questions/27844956/c-console-program-serial-communication-arduino

The ReadFile function is consistently returning the "False" value, meaning it is not finding anything
No, that is not what it means. A FALSE return value indicates that it failed. That is never normal, you must implement error reporting code so you can diagnose the reason. And end the program since there is little reason to continue running. Unless you setup the serial port to intentionally fail by setting a read timeout.
Use GetLastError() to obtain the underlying Windows error code.

You look to use MS Windows so try to catch the arduino output using portmon first, then you can debug your C++ code.

Related

How can I wait for all data to be written before the serial port connection is terminated

I need to send data from my QT application via serial port. I am trying to send data in this way.
void productDetail::on_detailSaveBtn_clicked()
{
if (!serial.isOpen())
{
if (serial.begin(QString("COM3"), 9600, 8, 0, 1, 0, false))
{
serial.send(ui->productDesp->text().toLatin1());
serial.end();
}
}
}
As I understand it, serial connection closes without writing all data. I think closing the serial port after waiting for all the data to be written can solve my problem. How can I verify that all data is written before the serial port close?
QT 5.15.2
Windows
Try to wait a few time so a portion of data can be written. Check if any left with while loop and repeat the process.
serial.send(ui->productDesp->text().toLatin1());
while(serial.bytesToWrite()){
serial.waitForBytesWritten(20);
}
serial.end();

ESP32 attempt reconnect to when network drops without halting loop (Arduino)

I have an ESP 32 collect data from a moisture sensor, which it then serves on our network. Our WiFi turns off between 1am and 6 am (because no one is using it). The ESP does not automatically try to reconnect, so it gathered data all night which I straight up can not access now.
For obvious reasons I do not want it to halt data collection when it looses connection to our network, so I can not have a loop try to reconnect. I tried this code:
void loop() {
sensor_value = analogRead(sensor_pin);
Serial.println(sensor_value);
push_value(float(sensor_value)/2047.0);
//============
//RELEVANT BIT
//============
if( WiFi.status() != WL_CONNECTED ){
//Try to recconect if connection is lost....
WiFi.disconnect();
WiFi.begin(ssid, pwd);
}
delay(second_delay*1000);
}
I've seen everyone run Wifi.disconnect() before attempting reconnecting. Is that necessary. Also does WiFi.begin() pause execution? I can't test my code right now unfortunately.
I am using the Arduino IDE and Wifi.h
And before you ask: Yes, 2047 is correct. I am running the sensor on the wrong voltage which results in about this max value.
Given that you've tagged esp8266 wifi, I'm assuming you're using that library. If so, then wifi.begin will not block execution. The library sets autoreconnect by default, so it'll automatically reconnect to the last access point when available. Any client functions will simply return an error code while disconnected. I do not know of any reason that wifi.disconnect should be called before begin.

C++ Boost::asio serial communcation with Arduino can't write

I tried to communicate with my Arduino Uno using the Boost Asio library. Somehow I can't send data to my Arduino, and I have no idea what i'm doing wrong. Reading works fine, but writing only works when i open a terminal and say:
cat /dev/ttyACM0
When this terminal window is open, and I run my C++ application it works otherwise it doesn't work.
Code of the test application (C++):
#include <iostream>
#include <boost/asio.hpp>
char* message;
int main()
{
boost::asio::io_service ioservice;
boost::asio::serial_port serial(ioservice, "/dev/ttyACM0");
serial.set_option(boost::asio::serial_port_base::baud_rate(115200));
serial.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none));
serial.set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none));
serial.set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one));
serial.set_option(boost::asio::serial_port::character_size(boost::asio::serial_port::character_size(8)));
std::string s = "u";
boost::asio::streambuf b;
std::ostream os(&b);
os << s;
boost::asio::write(serial, b.data());
if (serial.is_open()) {
serial.close();
}
return 0;
}
Code of my Arduino application:
#include "Servo.h"
Servo servo;
void setup() {
Serial.begin(115200);
servo.attach(9);
servo.write(0);
}
void loop() {
if(Serial.available()) {
char c = Serial.read();
if(c == 'u') {
servo.write(180);
} else if (c == 'v') {
servo.write(0);
}
}
}
I tried this both on my Ubuntu 18.04 and Debian 10 installation to rule out a permission issue, so I think there is something wrong with my code.
Update:
I found the issue, the Arduino is restarting when making a serial connection. When I add a thread sleep for for example 5 seconds and after that resent the data it works (because then it keeps the serial connection alive). I'm still looking for a permanent solution, so that I don't have to do a write before I really want to write something.
Update 2:
Apparently I don't even have to do a write, but where must be a small delay before I can start writing, because when after opening the port the Arduino is still restarting.
I fixed it with adding a small delay before writing to the serial port. As I also wrote in my comment above, the Arduino is restarting when you start a serial communication.
This can be disabled on several ways: https://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection/
Another option is to send a "ready" signal from the Arduino to know in your application that the Arduino is rebooted. So then start in your application with reading, and when you received that message, you can start writing.

Send a signed integer as a byte via serial in c++ and Arduino read it

I could send a String via serial, but Arduino reads String very slow. Therefore, I use reading byte in Arduino, but the problem is I don't know how to send a number (<256) as a byte via Serial Port in C++.
If you open up the Arduino IDE, under the menu, look at:
File > Examples > 08.Strings > CharacterAnalysis
Here I think you'll find something very close what you're looking for. To sum up, it opens a Serial connection (USB) and reads input from the computer. (You'll need to make sure you match the baud rate and use the "send" button.) It's up to you do program the Arduino as you'd like. In the example's case, it simply sends feedback back to the the Serial Monitor. Run it for yourself and see what happens :)
A [MCVE] snippet from the example:
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// send an intro:
Serial.println("send any byte and I'll tell you everything I can about it");
Serial.println();
}
void loop() {
// get any incoming bytes:
if (Serial.available() > 0) {
int thisChar = Serial.read();
// say what was sent:
Serial.print("You sent me: \'");
Serial.write(thisChar);
}

QSerialPort proper sending of many lines

I am trying to write really big files to serialport using QSerialPort (QT 5.3.1). The problem is - I keep sending more than device can handle.
Programm works like this (this function is called once in 50ms):
void MainWindow::sendNext()
{
if(sending && !paused && port.isWritable())
{
if(currentLine >= gcode.size()) //check if we are at the end of array
{
sending = false;
currentLine = 0;
ui->sendBtn->setText("Send");
ui->pauseBtn->setDisabled("true");
return;
}
if(sendLine(gcode.at(currentLine))) currentLine++; //check if this was written to a serial port
ui->filelines->setText(QString::number(gcode.size()) + QString("/") + QString::number(currentLine) + QString(" Lines"));
ui->progressBar->setValue(((float)currentLine/gcode.size()) * 100);
}
}
But it eventually gets flawed and hangs (on the device, not on the PC). If only I could check somehow if the device is ready or not for next line, but I cant find anything like it in the QSerial docs.
Any ideas?
You can use QSerialPort::waitForBytesWritten to ensure that the bytes are written. However this function would block the thread and it's recommended to use it in a new thread, otherwise your main thread would be blocked and your application freezes periodically.
The RS232 does have some flow control capabilities.
Check if Your device uses RTS/CTS and if so change the connection properties to use hardware flow control.
The QSerialPort also allows for checking the flow control lines manually with dataTerminalReady or requestToSend