#include <HCPCA9685.h>
#include <Wire.h>
#define I2CAdd 0x40
HCPCA9685 HCPCA9685(I2CAdd);
String state = "";
int servo5Pos;
int servo5PPos;
void setup() {
Wire.begin();
Serial.begin(4800);
HCPCA9685.Init(SERVO_MODE);
HCPCA9685.Sleep(false);
servo5PPos = 63;
}
void loop(){
if (Serial.available() > 0){
state = Serial.readString(); // Read the data as string
Serial.print(state + "\n");
// If "Waist" slider has changed value - Move Servo 5 to position
if (state.startsWith("s5")){
String stateS = state.substring(2, state.length()); // Extract only the number. E.g. from "s1120" to "120"
servo5Pos = stateS.toInt(); // Convert the string into integer
// We use for loops so we can control the speed of the servo
// If previous position is bigger then current position
Serial.print(servo5Pos);
if (servo5PPos > servo5Pos){
for (int pos = servo5PPos; pos >= servo5Pos; pos--) {
HCPCA9685.Servo(5, pos);
delay(20);
}
}
if (servo5PPos < servo5Pos){
for (int pos = servo5PPos; pos <= servo5Pos; pos++) {
HCPCA9685.Servo(5, pos);
delay(20);
}
}
servo5PPos = servo5Pos;
}
}
}
I'm trying to communicate my MIT Block Code to this Arduino Code, to control a servo via slider. By giving it a ''s5'' text to move the servo. However, I get this output instead when I'm printing the data received. Below is the code output and MIT block code.
1 Answer 1
Do not use Serial.readString()
Your main issue here is that you seem to assume that the serial port transmits messages from your computer to your Arduino. It doesn't. It only transmits a stream of bytes (ASCII characters here), which is what the Arduino gets ate the other end.
Serial.readString()
has no way of knowing where one message ends and
the next one begins. Instead, it relies on a very simple heuristic: if
one full second has elapsed with no byte being received, then it assumes
whatever has been received so far is a complete message. This works
reasonably well for messages manually typed at the serial monitor,
because you are unlikely to type two messages within one second.
When you move the slider, however, your block code sends messages in
quick succession: "s539.7", then "s540.8", then "s543"... The Arduino
then receives a string of characters: 's'
, '5'
, '3'
, '9'
, '.'
,
'7'
, 's'
, '5'
, '4'
, '0'
, '.'
, '8'
, 's'
, '5'
, '4'
,
'3'
, ... This is interpreted as a single message by
Serial.readString()
.
Solution: Use an "end of message" indicator instead of (or in
addition to) the "start of message" indicator. The characters CR (\r
)
and LF (\n
) are popular choices. You can then use
Serial.readStringUntil()
to get a full message.
Or, better yet, do not use the String
class at all. See
Reading Serial on the Arduino.
\n
?