Qt UI to Arduino Serial connection. Setup called multiple times - c++

I have noticed that setup() is executed again and again. I receive the same messages from setup()
Here's the code:
enum flags{
RFID= 1,
LASER_ON= 2,
LASER_OFF= 4,
.
.
.
};
int inByte;
bool fcount = false;
unsigned int count=0;
long average_input=0;
bool cont = false;
int prev=-1;
/**
* Initialize.
*/
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
// while (!Serial);// Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
// Serial1.begin(19200);
// while (!Serial1);
// SPI.begin(); // Init SPI bus
// mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(laser, OUTPUT);
pinMode(13, OUTPUT);
// Prepare the key (used both as key A and as key B)
// using FFFFFFFFFFFFh which is the default at chip delivery from the factory
// for (byte i = 0; i < 6; i++) {
// key.keyByte[i] = 0xFF;
// }
Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
Serial.print(F("Using key (for A and B):"));
// dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
Serial.println();
Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
digitalWrite(laser, HIGH);
for(byte i =0; i<10 ; i++){
average_input += analogRead(photocell);
delay(10);
}
Serial.print("total sum=\t");Serial.println(average_input);
average_input /=10;
Serial.print("average=\t");Serial.println(average_input);
digitalWrite(laser, LOW);
}
/**
* Main loop.
*/
void loop() {
if(Serial.available()){
delay(2000);
Serial.println("Serial available");
int input = 0;
while (Serial.available()){
input = input*10 + (Serial.read()-48);
inByte = input;
}
Serial.println(inByte);
}
// if(Serial1.available()){
// delay(100);
// Serial.println("Serial1 available");
// int input = 0;
// while (Serial1.available()){
// input = input*10 + (Serial1.read()-48);
// inByte = input;
// }
// Serial.println(inByte);
// }
switch(inByte){
case RFID:
Serial.println("RFID CHOSEN");
// get_rfid();
break;
case LASER_ON:
digitalWrite(laser, HIGH);
fcount=true;
break;
case LASER_OFF:
digitalWrite(laser, LOW);
fcount=false;
break;
.
.
.
}
if (fcount){
.
.
.
}
As you can see I commented out a lot, just trying to make setup() run only once. As the general goal: I'm trying to connect my Qt UI through QSerialPort. I've found a good solution on similar topic and adopted it. Here's the Qt code:
.
.
.
QSerialPort serial;
QStringList ports;
for (QSerialPortInfo port : QSerialPortInfo::availablePorts()){
qDebug() << port.portName() << port.vendorIdentifier() << port.productIdentifier()
<< port.hasProductIdentifier() << port.hasVendorIdentifier() << port.isBusy();
ports += port.portName();
}
serial.setPortName("cu.usbmodem1471");
serial.open(QIODevice::ReadWrite);
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
qDebug()<<serial.isOpen()<<endl;
qDebug()<<serial.isWritable()<<endl;
if (serial.isOpen() && serial.isWritable())
{
QByteArray ba("2");
serial.write(ba);
//serial.flush();
qDebug() << "data has been send" << endl;
serial.close();
}
.
.
.
First of all, it shows false false on both isOpen() and isWritable() when the serial monitor is opened. My guess is that Qt is trying to connect/send data to the same Serial as PC getting data on. When the Serial monitor is closed the flags are set to true true and message is sent. However it goes through the same setup process (aka calibrating laser) and not receiving 2 as a flag to turn on laser. Please advice me on Serial communication between PC and Arduino.

The serial port is used exclusively by an application, either SerialMonitor or Qt.
Opening a COM port (both by SerialMonitor or Qt) usually triggers a reset of the Arduino. That's why setup() is running.
This is used to make uploading of new sketches easier.
It's achieved by toggling the Serial control signal DTR.
I'm not a Qt expert to know exactly how to disable this on the PC side. Some terminal programs give you control over that DTR signal.
Possible workarounds:
Open the Serial line only once and keep it open as long as your Qt app is active.
If you have a 10 µF capacitor or similar, plug it into the Arduino between GND and RESET. This should inhibit the automatic reset. (Remove it to upload new sketch)

Related

ESP32 Bluetooth connection status

I am running into some problems finding a solution when it comes to performing some form of Bluetooth connection check for my project that will allow me to have a connection status light.
My project consists of creating a Bluetooth speaker that has Led Strips controlled over Bluetooth serial (an app will be made to handle this) and audio stream over Bluetooth from a single ESP32.
I have found plenty of examples and had success with performing an spp callback event, however, of course this only works if I connect to the Bluetooth serial side of things through my 'Serial Bluetooth Terminal' app on my phone. If I just go into my phone Bluetooth list and connect to the audio side of things, nothing is registered, which isn't very useful for a Bluetooth speaker!
Basically I really need some help finding a way of registering that a device has connected to the Bluetooth audio so that I can have some form of indication light to tell the user that they are successfully connected to the speaker to play music.
Below is my code:
#include <btAudio.h> //<-------this is the library that I am using to handle Bluetooth audio to an external I2s DAC
#include "BluetoothSerial.h"
#include <FastLED.h>
TaskHandle_t Task1;
//POWER/BT-LIGHT-SETUP----------------------------------------
int powerPinR = 4;
int powerPinG = 16;
int powerPinB = 17;
bool BTisConnected;
//FAST-LED-STUFF----------------------------------------------
CRGB leds[NUM_STRIPS][NUM_LEDS];
CRGB leds_temp[NUM_STRIPS][NUM_LEDS/2];
//BLUETOOTH-SETUP---------------------------------------------
btAudio audio = btAudio("");
BluetoothSerial SerialBT;
//CONNECTION-CHECK--------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t*param){
if(event == ESP_SPP_SRV_OPEN_EVT){
Serial.println("Client Connected");
BTisConnected = true;
}
else {
BTisConnected = false;
}
}
//------------------------------------------------------------
void setup() {
//CORE-1-INITIALISE
xTaskCreatePinnedToCore(
codeForTask1, /* Task function. */
"Task_1", /* name of task. */
1000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* Core */
//POWER/BLUETOOTH-CONNECTION-LIGHT-SETUP
pinMode(powerPinR, OUTPUT);
pinMode(powerPinG, OUTPUT);
pinMode(powerPinB, OUTPUT);
digitalWrite (powerPinR, HIGH);
digitalWrite (powerPinG, HIGH);
digitalWrite (powerPinB, HIGH);
//COOLDOWN-DELAY
delay(3000);
//AUDIO-INITIALISE
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);
//LED-STRIP-SETUP-&-CLEAR-ALL
FastLED.addLeds<WS2812B,STRIP1PIN,GRB>(leds[0], NUM_LEDS);
FastLED.addLeds<WS2812B,STRIP2PIN,GRB>(leds[1], NUM_LEDS);
FastLED.clear();
FastLED.show();
//SERIAL-INITIALISE-&-CLIENT-CONNECTION-CHECK
Serial.begin(115200);
SerialBT.begin("Pilot"); //<-----BLUETOOTH NAME
SerialBT.register_callback(callback); //<-- SerialBT connection check works perfectly, but nothing for audio connection! :(
}
//CORE-0-VOID-LOOP--------------------------------------------
void codeForTask1( void * parameter )
{
for (;;) {
manageData();
delay(10);
}
}
//CORE-1-VOID-LOOP--------------------------------------------
void loop() {
BTconnectionCheck();
playScene();
}
//MANAGE-INCOMING-BLUETOOTH-SERIAL-DATA-----------------------------------------------
void manageData() {
//READ FROM SERIAL AND PARSE OUT ** READ FROM SERIAL AND PARSE OUT ** READ FROM SERIAL AND PARSE OUT **
char rawData[100] = "";
char keyword[] = "Mydata=";
if (SerialBT.available() > 0) {//new data in
size_t byteCount = SerialBT.readBytesUntil('\n', rawData, sizeof(rawData) - 1); //read in data to buffer
rawData[byteCount] = NULL;//put an end character on the data
const char delimiter[] = ",";
char parsedStrings[5][8]; //first number = how many bits of data - 2nd number = max size of eeach data
int dataCount = 0;
int dataPosition = 0;
char *token = strtok(&rawData[dataPosition], delimiter);//look for first piece of data after keyword until comma
if (token != NULL && strlen(token) < sizeof(parsedStrings[0])) {
strncpy(parsedStrings[0], token, sizeof(parsedStrings[0]));
dataCount++;
} else {
Serial.println("token to big");
strcpy(parsedStrings[0], NULL);
}
for (int i = 1; i < 5; i++) {
token = strtok(NULL, delimiter);
if (token != NULL && strlen(token) < sizeof(parsedStrings[i])) {
strncpy(parsedStrings[i], token, sizeof(parsedStrings[i]));
dataCount++;
} else {
Serial.println("token to big");
strcpy(parsedStrings[i], NULL);
}
}
if (dataCount == 5) {
scene = atoi (parsedStrings[0]);
hue = atoi(parsedStrings[1]);
saturation = atoi(parsedStrings[2]);
brightness = atoi(parsedStrings[3]);
eventInterval = atol (parsedStrings[4]);
}
}
}
//BLUETOOTH-CONNECTION-CHECK---------------------------------------------------------
void BTconnectionCheck(){
SerialBT.register_callback(callback);
if (BTisConnected == true){
bluetoothConnected();
}
else {
bluetoothSearch();
}
}
void bluetoothSearch(){
digitalWrite (powerPinR, LOW);
digitalWrite (powerPinG, LOW);
digitalWrite (powerPinB, HIGH);
}
void bluetoothConnected(){
digitalWrite (powerPinR, HIGH);
digitalWrite (powerPinG, LOW);
digitalWrite (powerPinB, HIGH);
}
I have cut lots of the code to do with the LEDs out but its still quite long, If it would help to have a more condensed version then I will chop it down further. Or if it helps to have the full code then I can also post it.
Any help would be greatly appreciated as I am well and truly stuck with this one and its a pretty important part of the project.
Thanks in advance!

How can I write on Arduino from PC with rs-485 and QSerialPort

I have linked my PC and my Arduino with a RS-485 line and a TTL/RS-485 converter. I receive the message from Arduino but when I want to send information from my PC, there is no receipt on Arduino.
My Arduino code is :
const int slavePin = 4 // link to RE and DE of converter module.
void setup(){
pinMode(slavePin, OUTPUT);
digitalWrite(slavePin, LOW);
}
c
void loop{
while(Serial.available()){
if(Serial.Read()){
digitalWrite(2, HIGH); // switch on a led.
}
}
}
In my C++ code i have all initialization parameter. I don't forget write in arduino->open(QSerialPort::ReadWrite); line. My function for write to arduino is call when i clicked on button.
void Dialog::serialWrite(){
quint8 bw = 0;
serialDataWrite = "1";
if(arduino !=NULL && arduino->isWritable()){ // arduino is my QSerialPort object.
bw = arduino->write(serialDataWrite);
qDebug() << bw << "bytes written | Value sent : " << serialDataWrite;
}
}
This function work when I use the rs-232 link but not with rs-485. Someone can help me ?

Arduino restarts after serial input from Raspberry Pi

I have this code running on the arduino:
#include <SoftwareSerial.h>
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// pins!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const int delayTime=10;
const int pin_yes_gate=3;
const int pin_no_gate=5;
int switchVal =0;
void setup()
{
Serial.begin(9600); // Initialize serial port to send and receive at 9600 baud
pinMode(pin_yes_gate, OUTPUT);
pinMode(pin_no_gate, OUTPUT);
}
void loop()
{
if (switchVal ==1 ){
allow();
}else{
prohibit();
}
if ( Serial.available())
{
String string = Serial.readString();
string.trim();
Serial.print("I received: ");
Serial.print(string);
Serial.print("\n");
if(string.equals("allowed"))
{
switchVal=1;
}else if(string.equals("error"))
{
switchVal=0;
}
}
}
void allow(){
digitalWrite(pin_yes_gate,HIGH);
digitalWrite(pin_no_gate,LOW);
delay(delayTime);
}
void prohibit(){
digitalWrite(pin_yes_gate,LOW);
digitalWrite(pin_no_gate,HIGH);
delay(delayTime);
}
and I'm writing echo allowed >> /dev/ttyACM0 which gives the reaction, but for less than a second, and then the arduino returns to the initial state. This is weird, as it works with the arduino IDE perfectly.
Am I missing something ?
Just solved it, apparently the problem is the
Serial.print("I received: ");
Serial.print(string);
Serial.print("\n");
It errors out if serial is not read. So either removing this, or as in my case I can't change anything on the arduino side run this command on raspi boot tail -f /dev/ttyACM0 & which opens a read port

Arduino doesn't receive data after reconnecting to USB

So, I've built a basic QT GUI where I want to establish communication with an Arduino Nano through USB. I send a number through the GUI and the Arduino receives the number and processes it.
The communication works fine when I upload the code to Arduino and right afterwards open the GUI and start the process. However, when I disconnect the Arduino from the USB (or restart my PC - I've tried both) and reconnect it to use it with the GUI, the Arduino behaves like it received nothing.
More specifically, in the first case Serial.available() returns "1" as it receives the number properly, but in the latter case it returns "0", so it does nothing.
I made the code as simple as I could trying to track down the issue and the problem continues.
So here is the main QT GUI code:
depth_ = insertDepthEdit->text().toInt(); // user input from GUI
myThread *mThread;
mThread = new myThread(this, depth_);
connect(mThread, SIGNAL(valueRead(QString)), this, SLOT(onTextChange(QString)));
//valueRead is the signal emitted from Arduino
//onTextChange the function that processes the received string
mThread->start();
mThread->wait(100);
mThread->quit();
The Arduino thread code (also QT):
void myThread::run() {
QSerialPort serial;
serial.setPortName("COM3");
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.open(QIODevice::ReadWrite);
if (serial.isOpen() && serial.isWritable()) {
qDebug() << "Ready to write..." << endl;
QByteArray ba(QString::number(depth_).toStdString().c_str());
qDebug() << ba << endl;
serial.write(ba);
if (serial.bytesToWrite() > 0) {
serial.flush();
if (serial.waitForBytesWritten(1000)) {
qDebug() << "data has been sent" << endl;
}
}
if (serial.flush()) {
qDebug() << "ok" << endl;
}
}
else {
qDebug() << "Error";
}
if (serial.isOpen() && serial.isReadable()) {
qDebug() << "Ready to read..." <<endl;
while (serial.waitForReadyRead(5000)) {
QByteArray inByteArray = serial.readLine();
input_ = QString(inByteArray);
qDebug() << input_;
qDebug() << "ok" << endl;
emit valueRead(input_);
}
}
serial.close();
}
And finally the Arduino code:
int c = 0;
const int ledPin = 13;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print(Serial.available());
while (Serial.available() > 0) {
digitalWrite(ledPin, HIGH);
delay(5);
c = Serial.read() - '0';
Serial.flush();
}
delay(1000);
digitalWrite(ledPin, LOW);
delay(500);
}
When I upload the code to Arduino, it functions properly no matter if I close the GUI and restart it. The problem happens only if Arduino loses power, e.g: when I disconnect it from USB or restart the PC.
~~~~~~~~~~~~~~~~~~~~~~~~~~EDIT~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
COM port remains the same after reconnecting and Arduino Rx LED flashes normally when I send data through the GUI.
~~~~~~~~~~~~~~~~~~~~~~~~~~EDIT 2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OK, so, I tried using the code from Arduino Serial documentation and the problem remains. When I upload the code the Arduino receives the character properly and turns the LED on, but once I disconnect it and then connect it back, it does nothing, the LED remains low as it never enters "if".
Here's the code I used:
int incomingByte = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
digitalWrite(13, HIGH);
incomingByte = Serial.read();
}
}
~~~~~~~~~~~~~~~~~~~~~~EDIT 3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So I have the following 3 scenarios:
Use Scenario A:
Upload code
Run GUI
Send data - It receives properly
Disconnect and reconnect
Run GUI again
Send data - RX blinks but Serial.available returns 0
Use Scenario B:
Upload code
Run Brays
Send data - It receives properly
Disconnect and reconnect
Run Brays again
Send data - It receives properly
Use Scenario C (the most interesting) :
Upload code
Run GUI
Send data - It receives properly
Disconnect and reconnect
Run Brays this time
Send data - It receives properly
Run GUI again after Brays
Send data - It receives properly
I also made the QT GUI code as simple as that but the problem persists:
void myThread::run()
{
QSerialPort *serial = new QSerialPort();
serial->setPortName("COM3");
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->open(QIODevice::WriteOnly);
if (serial->isOpen() && serial->isWritable())
{
QByteArray ba(QString::number(depth_).toStdString().c_str());
serial->write(ba);
serial->flush();
serial->close();
}
delete serial;
}
~~~~~~~~~~~~~~~~~~~~~~EDIT 4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So after much effort and curiosity, I realized that the source of the problem is not the Arduino code but something related to QT or Windows. I added the delays that Jeff recommended and noticed that each time it functioned properly Rx blinked and LED became high as indicated by the code. However, after reconnecting, the problem still remained but I noticed that, this time, immediately after clicking "Send" to send the characters, the LED blinked for some milliseconds (possibly indicating some error??) and then after the 1 second delay the Rx blinked indicating the receipt of data and LED remained LOW as Serial.available remained 0.
So, what I tried next, was to remove one line of code at a time to see what causes the problem. And I ended up with literally blank Arduino code, just empty setup and loop methods, and the following QT GUI code:
void myThread::run()
{
QSerialPort *serial1 = new QSerialPort();
serial1->setPortName("COM5");
serial1->open(QIODevice::WriteOnly);
serial1->close();
}
To summarize, what happens now is:
Upload code to Arduino
Run GUI
Send data
Nothing happens (normal behaviour)
Disconnect and reconnect Arduino to USB
Run GUI
Send data
Arduino LED momentarily blinks once (possibly indicating some kind of error)
OK, so, after hours of debugging I've found what caused the problem.
The root of it was that after reconnecting the Arduino, each time I called serial.open in QT, Arduino did a reset (indicated by the blink of the LED) and by the time it was after the bootloader stage and was running the code, the main program had already passed the serial.write QT command without receiving the data.
So, what I did to solve the problem was to just add a Sleep(uint(2000)); after serial.open in order to let Arduino finish booting and then start sending data.
Thank you all for your help and immediate answers!
In my experience, the issue is not the code in the Arduino. It is because the serial port gets a different name when it is plugged back in.
For example in Linux, originally the port is /dev/ARD0, but when it is disconnected and plugged back in with connections on ARD0, the new plugin is named /dev/ARD1. (In Windows, it might be COM17 then COM18.)
The only way I know to make it become the original port name is to close everything that is connected to it before plugging in again: Close the Arduino IDE, close all programs which have opened the port, etc.
If you use this example for the Arduino Serial documentation do you receive the chars you send?
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
Grasping at straws here, replace my comments below a one second delay. Editing on iPhone messed with the format a little, but I believe you can see my intent.
Edit: Also, I think you should not do serial->close inside your loop. I would also try sending a single character repeatedly until we have that working.
void myThread::run()
{
QSerialPort *serial = new QSerialPort();
serial->setPortName("COM3");
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->open(QIODevice::WriteOnly);
if (serial->isOpen() && serial->isWritable())
{
QByteArray ba(QString::number(depth_).toStdString().c_str());
serial->write("x");
delay 1 second here
serial->flush();
delay 1 second here
}
serial->close();
delay 1 second here
delete serial;
}

interfacing c++ to control motor stepper with arduino

I have tried to control motor stepper via arduino uno board with slider in visual C++.
but the servo didnot move at all.
here the program at PC side:
void CENVSConfigDlg::OnBnClickedButton1()
{
SetTimer(cTimer1,80,NULL);
}
void CENVSConfigDlg::OnTimer(UINT_PTR ID)
{
if(ID==cTimer1){
DWORD nbytes;
char buf[5];
sprintf(buf, "%d \n", val_test);
/* Open serial port. */
if(!WriteFile( hnd_serial, (void*)buf, 5, &nbytes, NULL )){MessageBox(L"Write Com Port fail!");return;}
}
and the program in arduino:
#include <Servo.h>
Servo servoMain;
int index=0;
String inputString;
void setup()
{
Serial.begin(9600);
servoMain.attach(9);
}
void loop()
{
int data;
while (Serial.available())
{
char inChar = (char)Serial.read();
if (inChar == '\n' || inChar == 'z')
{
data=stringToInt(inputString);
Serial.println(data); //
inputString="";
servoMain.write(data); //tambahannya
delay(50);
break;
}
if (inChar != 0)
{
inputString += inChar;
}
}
}
int stringToInt(String s)
{
char char_string[s.length()+1];
s.toCharArray(char_string, s.length()+1);
return atoi(char_string);
}
the pc i think is sending the data, but why the motor didnot working? any idea?
First off, does the serial link work at all? The number of ways that an RS232 link can not work, for both hardware and software reasons, is legendary. Unless you can show that the hardware can transfer data, it's pointless to look at your dedicated software. If you have a scope, use that to see if anything is being transmitted and then check that it arrives at the correct pin on the arduino input. If you have no access to a scope, a small LED and a 4.7K resistor can be used to indicate that there is data on the line - it will flicker with the data.