문자열에서 정수 문제까지

로봇 팔을 제어하는 데 사용할 컴퓨터 용 애플리케이션을 만듭니다. 먼저 모터가 아닌 다이오드에서 애플리케이션을 실행하고 슬라이더의 위치에 따라 밝기가 변경되는지 확인하고 싶었습니다. 나는 아두 이노로 끈을 보내는 Qt 애플리케이션을 작성했고 아두 이노는 읽고 int로 변환한다. 문제는 슬라이더가 0으로 설정되어 있지만 Arduino가 표시하지 않고 숫자가 너무 자주 일치하지 않는 경우 (종종 너무 작음), 갑자기 숫자 슬라이더를 항상 앞쪽으로 옮길 때 뒤로.

Arduino 코드 :

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 코드 :

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!"); } } 

여기에 이미지 설명 입력

댓글

  • Serial.readString ()은 심각한 결함이 있으므로 피해야합니다. 이 글을 읽어보세요 : majenko.co.uk/blog/reading-serial-arduino
  • 그리고 저는 확실합니다 다음과 같은 문제를 디버깅 할 때 n
  • 가 아닌 \n를 보내는 메시지에 추가하려고했습니다. Serial.println(br);analogWrite() 앞에 넣어 수신 내용을 확인하세요.

답변

Majenko가 의견에서 썼 듯이 문제는 Serial.readString()에 있습니다. 일반적으로 직렬 데이터를 처리하는 좋은 방법이 아닙니다. 시간 초과 (기본값 1s)가 발생할 때까지 직렬 인터페이스에서 데이터를 읽습니다. 따라서 슬라이더를 마지막으로 변경 한 후 1 초까지 읽고 전체 데이터를 하나의 문자열로 반환합니다. String.toInt()는 첫 번째 문자에서 문자열을 읽고 숫자가 아닌 문자를 읽을 때까지 정수로 변환하기 시작합니다 (n, 전송). 여기서 멈추고 이미 변환 된 값을 반환합니다.

이것은 Arduino로 전송 된 모든 데이터 중에서 첫 번째 값만 사용된다는 것을 의미합니다. 나머지는 버려집니다.

메시지 (귀하의 경우 숫자)를 올바르게 처리하는 비 차단 코드를 사용하는 것이 좋습니다. 이는 들어오는 직렬 데이터를 바이트 단위로 읽어서 수행됩니다. 특수 구분 문자가 수신 될 때까지 버퍼에 추가합니다. 그런 다음 메시지는 전체적으로 처리됩니다. 그 후에 다음 메시지를 읽고 처리 할 수 있습니다. 이렇게하면 전송 값을 놓치지 않습니다.

특수 구분 문자는 임의적입니다. 유효한 데이터에없는 모든 문자를 사용할 수 있습니다. 따라서 여기서 n 문자를 사용하는 것은 괜찮습니다. 그러나 대부분 개행 문자 \n가 사용되므로 영숫자로 메시지를 보낼 수도 있습니다. 이미 \n를 사용하려고했을 가능성이 높습니다.

이 시리얼 코드의 예로는 readline() 함수 Majenko의 블로그 게시물 :

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("<"); } } 

문자 버퍼를 변환 할 수 있습니다. void loop()의 if 문에서 atoi()가있는 int에 ´analogWrite ()`에 사용합니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다