open : Resource busy when trying to communicate to arduino - c++

I have a very simple question but for some reason I can't find any answer. I'm a total beginner with arduino and c++. I just want to be able to send an angle from xcode to a servo motor. I'm on macos 10.9.5.
So my arduino is connected to the serial port "/dev/cu.usbmodem1411". My c++ code connects to this port and send a number. Then my arduino should receive it and control the servo. It's pretty simple but apparently my c++ code can't access the serial port when my arduino is connected. How am I supposed to make them communicate ?
If I run my c++ code first, I get a timeout error on arduino.
Here is my arduino code :
#include <AFMotor.h>
#include <Servo.h>
Servo servo1;
void setup() {
Serial.begin(9600);
servo1.attach(9);
}
void loop() {
if (Serial.available()>0){
int x;
x = Serial.read()
servo1.write(x);
}
And my c++ code :
using namespace std;
int main()
{
unsigned int angle;
fstream arduino;
arduino.open("/dev/cu.usbmodem1411");
if(arduino.is_open())
{
do
{
cout<<"\n\nangle ?";
cin>>angle;
arduino<<angle;
}while(angle <= 360);
arduino.close();
}
else
{
cout<<"error";
}
}
I tried another c++ code using the boost library and received the error "open: Resource busy". I have no problem if I try to connect to another port like "/dev/tty.usbmodem1411" but it's not proposed in the arduino tool menu.
My problem is very similar to this one that didn't have a convincing solution.

Related

How to set low latency in serial port open by QSerialPort

I have already developed an application and it performs serial communication with sensors.
For an unknown reason, my received data is slow with QT C++ Framework.
I have tested the sample code (https://www.pjrc.com/tmp/host_software/receive_test.c). I received data in the appropriate time with this sample code.
Here i found that low latency mode is set ASYNC_LOW_LATENCY.
I have read (https://doc.qt.io/qt-5/qserialport.html) but didn't get any idea about how to set low latency with QSerialPort
Q1: Please give a sample code in qt c++ with QSerialPort on how to set low latency.
Please don't suggest writing c code inside qt c++ this is not the right approach to solve this probleam.
QSerialPort *pUsbSerialPort;
pUsbSerialPort = new QSerialPort();
if(IS_VALID_OBJ(pUsbSerialPort))
{
pUsbSerialPort->setPortName(sSerialPort);
pUsbSerialPort->setBaudRate(BaudRate);
pUsbSerialPort->setDataBits(QSerialPort::Data8);
pUsbSerialPort->setParity(QSerialPort::NoParity);
pUsbSerialPort->setStopBits(QSerialPort::OneStop);
pUsbSerialPort->setFlowControl(QSerialPort::NoFlowControl);
if(pUsbSerialPort->open(QIODevice::ReadWrite))
{
connect(pUsbSerialPort, &QSerialPort::readyRead,this , &Laser::LaserReadyRead);
PRINT_INFO("Serial port successfully initialized" + sSerialPort);
bIsServeropen = true;
}
else
{
PRINT_INFO("Serial port initialization failed" + sSerialPort);
return;
}
}
else
{
PRINT_INFO(" Failed to assign memory to pUsbSerialPort" + sSerialPort);
return;
}
The descriptor is the Handle of the QSerialPort:
#include <sys/ioctl.h>
#include <linux/serial.h>
// ...
pUsbSerialPort->open(QIODevice::ReadOnly);
int fd = pUsbSerialPort->handle();
struct serial_struct kernel_serial_settings;
::ioctl(fd, TIOCGSERIAL, &kernel_serial_settings);
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
::ioctl(fd, TIOCSSERIAL, &kernel_serial_settings);

Why is the Serial communication via BLE failing on the first run of the code but working fine for consecutive runs?

I'm trying to communicate with the STM32 microcontroller via serial communication. Before I was using the USB cable and the communication worked flawlessly. However when I switched the same serial mode from USB to BLE (HM-10), the microcontroller fails to respond correctly for the first try, but it is okay after that. What could be a problem?
I tried searching if it was something to do with buffers or start/stop bits. But it didn't help me much because I had no clue about how to implement them through code. I'm using the MbedOS to program my dev board.
CODE:
#include "mbed.h"
DigitalOut led1(LED1);
#define MAX_INPUT_LENGTH 2
int code[MAX_INPUT_LENGTH];
Serial bt(PD_5, PD_6);
//Serial pc(USBTX, USBRX);
int main()
{
while(1)
{
while(bt.readable()==1)
{
volatile char str[2];
bt.scanf("%2s",str);
int index = 0;
while(index<=MAX_INPUT_LENGTH)
{
code[index] = str[index] - '0'; // convert to an int.
index++; // increase the index.
}
if(code[0]==0 && code[1]==1)
{
bt.printf("\n01 RECIEVED.");
for(int x=0;x<15;x++)
{
led1 = 1;
wait(0.25);
led1 = 0;
wait(0.25);
}
}
else
bt.printf("\nINCORRECT VALUE RECIEVED.");
}
}
}
I expected the output from ble serial to work the same way as the usb serial, but it failed for the first run.

Issue with Serial and Arduino Servo Library

today I tried to setup a servo motor running along with this sketch on Arduino. For some reason, when I add the setup lines for the servo, the software serial port doesn't receive data normally. I tried to change the software serial to the normal Serial port on Arduino but the same thing happens.
#include<SoftwareSerial.h>
#include<Servo.h>
Servo myServo;
SoftwareSerial BT1(3,2); // TX, RX
int val;
int servoPin = 7;
int ledPin = 10;
void setup() {
pinMode(ledPin,OUTPUT);
BT1.begin(9600);
myServo.attach(servoPin);
myServo.writeMicroseconds(2000); //2 ms for Tower Pro SG 90 Servo
myServo.write(90); //Initialize at servo's middle point
}
void loop() {
if (BT1.available()) {
int i = (int)BT1.read();
setIntensity(i);
}
}
void setIntensity(int value) {
if (value >= 0 && value <= 110) {
analogWrite(ledPin, value);
}
}
When I comment out the setup lines for myServo, the Arduino works like a charm. How can I solve this? I'm using an Arduino Duemilanove.
NeoSWSerial is a suitable replacement for SoftwareSerial. NeoSWSerial won't interfere with Servo, because it doesn't use any extra resources, and it doesn't block interrupts for long periods of time.
It's also available from the IDE Library Manager, under the menu Sketch -> Include Library -> ManageLibraries.

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;
}

Why is no serial data available on my Arduino?

I've run the simple serial program on my Arduino Uno, which just echos whatever you type to it. This works perfectly when run in the Arduino Sketch IDE (v22).
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(115200); // opens serial port, sets data rate
}
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);
}
}
(Code taken from http://arduino.cc/en/Serial/Available)
However, I prefer not to use the Arduino IDE and would rather compile my C++ code with avr-g++, so I wrote this, which should function exactly the same as above:
extern "C" {
#include <avr/io.h>
}
#include <HardwareSerial.h>
extern "C" void __cxa_pure_virtual() { while(1); }
int main (void)
{
int incomingByte = 0;
Serial.begin(115200);
while (1) {
if (Serial.available() > 0) {
incomingByte = Serial.read();
//print as an ASCII character
Serial.print("received: ");
Serial.println(incomingByte, DEC);
}
}
return 1;
}
I compile and run it, but it doesn't work. I never see my text echoed back to me. I tried printing out the value of Serial.available() in the while(1) loop, and it's always zero. Whenever I type on the keyboard, I see the RX LED light up, but nothing happens after that. I can edit my code to successfully call Serial.println() as long as it's outside the Serial.available() conditional.
I've confirmed that my baud rate in my serial software is also set to 115200. And yes, my serial software is pointing to the right serial port.
What am I missing?
Arduino's original glue code looks like this:
#include <WProgram.h>
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}
The init() stuff is missing in your code. init() is defined in $ARDUINO_HOME/hardware/arduino/cores/arduino/wiring.c, you can either link against it directly or just copy the code of init() into your code.
You probably have not properly initialized the UART port on the chip. This has to be done manually for microcontrollers, and the Arduino IDE was probably doing it for you. Check the AVR datasheet for your chip, specifically the serial port section.
Found the answer to my own question:
It turns out the HardwareSerial.h library relies on interrupts. This is something that is automagically taken care of for you when building with the Arduino IDE. If you aren't using the Arduino IDE (like me), then you must remember to enable interrupts on your own.
Just #include <avr/interrupt.h>, and call sei(); to turn on interrupts before you try to use the Serial Library.
cheers!