Serial.readString keyboard

Hi, im new to arduino. im making a code for controlling an engine with keyboard and i would like to know what does arduino reads from Serial.readStringUntil when i keep pressing "W" for example. here is the code i did:

void loop() {

wheel_speed_L_fun();
wheel_speed_R_fun();
while(!Serial.available()>0);
str = Serial.readStringUntil('\n');
if(str=="-1")
str=str_last;
while(str!="r"){
while(str == "w")
{
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==1))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==0 || dir_R==0)
{
move(0,dir_L,0,dir_R);
break;
}
}

//IF S BACKWARD
while(str.compareTo("s") == 0) {
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==0 && dir_R==0))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==1 || dir_R==1)
{
move(0,dir_L,0,dir_R);
break;
}
}

//IF D RIGHT
while(str.compareTo("d") == 0) {
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==0))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==0 || dir_R==1)
{
move(0,dir_L,0,dir_R);
break;
}
}
//IF A LEFT
while(str.compareTo("a") == 0){
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==0 && dir_R==1))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==1 || dir_R==0)
{
move(0,dir_L,0,dir_R);
break;
}
}

}
if(str.compareTo("r") == 0){
move(0,dir_L,0,dir_R);
}

str_last=str;

}

  1. Use [ code ] tags
  2. Post your whole sketch, not just one function.

Are you using the Arduino serial monitor and pressing enter or send after each command? Are you using capital-S Strings?

Read Serial Input Basics before doing any more programming.

while(str == "w")
{   
  if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==1))
           {
             move(0.09,dir_L,0.09,dir_R);
             break;
           }
           if(dir_L==0 || dir_R==0)
           {
             move(0,dir_L,0,dir_R);
             break;
           }
}

If str ever IS “w”, that while loop will never end.

Your sending program needs to be smarter. It should send ONE character when a key becomes pressed, and another when it becomes released. Typically, this is done be sending upper and lower case values for the pressed/released key. Press the x key; the ‘x’ character is sent. Release the x key, ‘X’ gets sent.

The Arduino reads one character, not needing to piss away resources on the String class, as it arrives, and makes a change accordingly.

julimen5:
i would like to know what does arduino reads from Serial.readStringUntil when

As well as what @MorganS has said you should not use Serial.readStringUntil() because it blocks the Arduino from doing anything else.

The examples in serial input basics are non-blocking.

...R

@MorganS now, im pressing enter. thats why i used **Serial.ReadStringUntil(" /n").**but , as you said , i need to be smarter .So, how can i separate W of that / n without using Serial.ReadStringUntil (.... )
@PaulS that is what i want, while i keep pressing W, that loop should never end, then when i press R it should brake.
i read that when i keep pressing w, the Serial reads -1, so thats why i used str and str_last, so there im transforming that -1 into a W/S/D/A.

Hi, im new to arduino. im making a code for controlling an engine with keyboard and i would like to know what does arduino reads from Serial.readStringUntil when i keep pressing "W" for example. here is the code i did:

What serial application are you using to send the keyboard characters to the arduino via the serial port?

julimen5:
@PaulS that is what i want, while i keep pressing W, that loop should never end, then when i press R it should brake.

You misunderstood the comment. If str is w it will run that loop and keep running that loop and nothing but that loop. There is no attempt made inside that loop to read anything from the Serial interface. So it doesn't matter how many 'r' you send, if you never read them and assign to str then str will still be w and that loop will never end.

Both of the two previous replies deal with parts of the problem.

Your sending application needs to be able to deal with both the key press and key release events. If yours can't, you'll need a different one.

The Arduino must NOT expect a steady stream of characters to keep doing something. There is NO way to assure that the sending application sends them at the same rate as the Arduino can (and does) read them. Therefore, the Arduino code should have NO while loops.

i understood everything you tell me, but what i really dont know is how arduino knows when i release a key.
i know arduino sends a -1 when i keep pressing a key. so, when i want to release i press R, but as @pauls told me, im not leaving the while loop.

julimen5:
i understood everything you tell me, but what i really dont know is how arduino knows when i release a key.

You can't really control an Arduino that way from the Serial Monitor (or any other terminal).

You could control it with one character to start something and a different character to to stop it. After it receives a single start character the Arduino should keep doing stuff until it receives a stop character. And I agree that this is not a very convenient system.

If you write a program for your PC (perhaps with Python) it can detect the keyDown and keyUp (or mouseDown and mouseUp) events and send the start and stop characters to the Arduino as appropriate. This provides a much more intuitive system for the user.

...R

i have a JAVA doing that already, but we want to prove the code before start using that one.
i think i might start using java.

If your Java program sends different characters to the Arduino for start and stop you can easily try that by sending those characters from the Serial Monitor.

...R

what I see is that if I do not send other characters , the loop is locked in while ( Serial.available ) ....
what I need is to skip that step until I enter something else.

what I see is that if I do not send other characters , the loop is locked in while ( Serial.available ) ....

Nonsense. You can read serial data far faster than it arrives. The while loop will read all the data very, very, quickly and then end.

PaulS:
Nonsense. You can read serial data far faster than it arrives. The while loop will read all the data very, very, quickly and then end.

i already know that, but it is getting locked by my code.
what i dont know is how to skip that step

what i dont know is how to skip that step

Highlight the code. Hit delete.

Obviously, that isn’t the real solution, but I have no idea what you are sending now, from what application, under what circumstances, or what your Arduino code now looks like, so I can’t offer any other advice.

void loop() {

wheel_speed_L_fun();
wheel_speed_R_fun();
while(!Serial.available()>0);
str = Serial.readStringUntil('\n');
if(str=="-1")
str=str_last;
while(str!="r"){
while(str == "w")
{
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==1))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==0 || dir_R==0)
{
move(0,dir_L,0,dir_R);
break;
}
}

//IF S BACKWARD
while(str.compareTo("s") == 0) {
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==0 && dir_R==0))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==1 || dir_R==1)
{
move(0,dir_L,0,dir_R);
break;
}
}

//IF D RIGHT
while(str.compareTo("d") == 0) {
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==0))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==0 || dir_R==1)
{
move(0,dir_L,0,dir_R);
break;
}
}
//IF A LEFT
while(str.compareTo("a") == 0){
if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==0 && dir_R==1))
{
move(0.09,dir_L,0.09,dir_R);
break;
}
if(dir_L==1 || dir_R==0)
{
move(0,dir_L,0,dir_R);
break;
}
}

}
if(str.compareTo("r") == 0){
move(0,dir_L,0,dir_R);
}

str_last=str;

}

look, lets do an example.

i start the arduino, y send a W. when the hole LOOP finish, the arduino is waiting for another character.
what i want is to simulate that W is holding down

My first guess is that the problem is Serial.readStringUntil() which is a blocking function.

Have you experimented with the examples in Serial Input Basics - they are simple, reliable and non-blocking.

Another guess is that you should not use WHILE in (for example)

while(str!="r"){
while(str == "w")

Use IF in place of WHILE - which may mean other changes to your code.

...R

while(!Serial.available()>0);

This is ass-backwards. Rather than doing nothing until a byte of data arrives, you need to do everything else until there is data to read.

while(str == "w")
{   
  if((wheel_speed_L==0 && wheel_speed_R==0 ) || (dir_L==1 && dir_R==1))
           {
             move(0.09,dir_L,0.09,dir_R);
             break;
           }
           if(dir_L==0 || dir_R==0)
           {
             move(0,dir_L,0,dir_R);
             break;
           }
}

Suppose that you send a w. str will equal "w", so this loop will start. It will NEVER end, because the value of str does not change anywhere in the while loop.

This is still completely wrong.

You need to structure your code like this:

void loop()
{
   if(Serial.available() > 0)
   {
       char whatToDo = Serial.read();
       switch(whatToDo)
       {
          case 'w':
             // Do whatever w means ONCE
             break;
          // Other cases
       }
   }
}

You need to make the sender send ONE value to indicate that an action should start, and another to indicate that the action should end. You do NOT, under any circumstances whatsoever, send a continuous stream of data to indicate that an action should continue.