0

I create applications for a computer that is to be used to control the robot arm. I wanted to make the first attempt to run the application not on the motor, but on the diode and check if it will change its brightness depending on the position of the slider. I wrote an application in Qt that sends thongs to Arduino, and Arduino I read and converts to int. The problem is that although the slider is set to 0, the Arduino does not show it, often the figures do not agree too often (often too small), also when I suddenly move the number slider all the time count towards the front instead of back.

Arduino code:

String br;

void setup()
{
  Serial.begin(9600);
  pinMode(9, OUTPUT);
}

void loop() 
{ 
   while (Serial.available()>0)
 {
    br = Serial.readString();     
    analogWrite(9, br.toInt());
    Serial.println(br.toInt());
 }
} 

Qt code:

void MainWindow::on_horizontalSliderGrip_sliderMoved(int position)
{
   this->sendMessageToDevice(QString::number(position) + "n");
   qDebug() << "Grip: " << QString::number(position);
}


void MainWindow::sendMessageToDevice(QString message)
{
   if(this->device->isOpen() && this->device->isWritable())
   {
       //this->addToLogs("Sending information to the device " + message);
       this->device->write(message.toStdString().c_str());
   }
   else
   {
       this->addToLogs("I can not send a message. The port is not open!");
   }
}

enter image description here

  • 1
    Serial.readString() is deeply flawed and should be avoided. Read this: majenko.co.uk/blog/reading-serial-arduino – Majenko Jul 7 '19 at 10:08
  • And I am sure you meant to add \n to your outgoing messages, not n... – Majenko Jul 7 '19 at 11:48
  • when debugging a problem such as yours put Serial.println(br); before the analogWrite() to see what is being received – jsotola Jul 7 '19 at 19:04
1

As Majenko wrote in his comment, your problem lies with Serial.readString(). It is generally not a good way to handle Serial data. It reads data from the Serial interface, until the timeout (default 1s) occurs. So it will try to read until 1 second after your last change of the slider and return the whole data as one string. String.toInt() will then start to read the string from the first character and convert them to an integer, until it reads a non-digit character (meaning the n, that you send). It stops there and returns the already converted value.

This means, that out of all the data, that was send to the Arduino, only the first value will be used. The rest get's thrown away.

Better you should use a non-blocking code, that handles the messages (numbers in your case) correctly. This is done by reading the incoming serial data byte by byte, adding them into a buffer, until a special delimiter character get's received. Then the message get's processed as a whole. After that, the next message can be read and processed. This way you don't miss any of the send values.

The special delimiter character is arbitrary; you can use any character, that does not occur in the valid data. So using the character n is ok here. But mostly the newline character \n is used, so that you can also send messages with alphanumeric characters. Most likely you already meant to use \n.

As an example of this serial code, you can take the readline() function from Majenko's blog post:

char buf[80];

int readline(int readch, char *buffer, int len) {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
        switch (readch) {
            case '\r': // Ignore CR
                break;
            case '\n': // Return on new-line
                rpos = pos;
                pos = 0;  // Reset position index ready for next time
                return rpos;
            default:
                if (pos < len-1) {
                    buffer[pos++] = readch;
                    buffer[pos] = 0;
                }
        }
    }
    return 0;
}

void setup() {
    Serial.begin(115200);
}

void loop() {
    if (readline(Serial.read(), buf, 80) > 0) {
        Serial.print("You entered: >");
        Serial.print(buf);
        Serial.println("<");
    }
}

You can convert the character buffer to an int with atoi() in the if statement in void loop() and use it for ´analogWrite()`.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.