Leonardo board --Keyboard press

Hello, everyone!
I'm trying to use the Leonardo board to connect the ultrasonic distance sensor, after detecting the value, then simulate the keyboard key input. And I want it not to print when the same value can be sensed until the next time a different distance is detected. So now I try to use the method of setting two variables, when the comparison is different from the previous variable, do Keyboard. press action. But now, it still often prints the same values repeat echo like 1, 1, 1, so I can't find where the program is going wrong.

If you have a solution, please tell me how to solve it, thank you!

#include <Keyboard.h>           
int trig=A4;
int echo=A5;
float echotime=0;
int pre_distance;
int distance;
void setup() 
{ 
  Serial.begin(9600);
  pinMode(trig,OUTPUT);
  pinMode(echo,INPUT);
}
void loop () { 
    pre_distance = distance;
    digitalWrite(trig,LOW);delay(1);
    digitalWrite(trig,HIGH);delay(5);
    digitalWrite(trig,LOW);
    echotime=pulseIn(echo,HIGH);
    distance=echotime*0.0172;
    distance=distance/10;distance=distance*10;
    Serial.print("pre_distance:");Serial.print(pre_distance);Serial.print("/");
    Serial.print("distance:");Serial.println(distance);delay(1); 
    pre_distance=pre_distance/10;pre_distance=pre_distance*10;
    
      if (distance != pre_distance) 
  {
    if(distance<=10){Keyboard.press('1');Keyboard.releaseAll();delay( 1 );}
    if(distance>10 and distance<=20){Keyboard.press('2');Keyboard.releaseAll();delay( 1 );}
    if(distance>20 and distance<=30){Keyboard.press('3');Keyboard.releaseAll();delay( 1 );}
    if(distance>30 and distance<=40){Keyboard.press('4');Keyboard.releaseAll();delay( 1 );}
    if(distance>40 and distance<=50){Keyboard.press('5');Keyboard.releaseAll();delay( 1 );}
    if(distance>50 and distance<=60){Keyboard.press('6');Keyboard.releaseAll();delay( 1 );}
    if(distance>60){Keyboard.releaseAll();delay( 1 );}
  }
}
1 Like

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use [color = red]code tags[/color] (the </> icon above the compose window) to make it easier to read and copy for examination

2 Likes

Five milliseconds (5000 microseconds) may be too long. The usual value is 10 microseconds.

    digitalWrite(trig,HIGH);
    delayMicroseconds(10);
    digitalWrite(trig,LOW);

Because the default timeout of the pulseIn() function is 1,000,000 microseconds (1 second) you can get better responsiveness without losing range by setting a time limit of 30000 (about 6 meters):
echotime = pulseIn(echo, HIGH, 30000);

There is no reason to put a 1 millisecond delay after a print. If you want to make sure the serial output is complete, use "Serial.flush();"

If you use 'write' instead of 'press' there is no need for a separate 'release'. If you use 'else' there is no need to re-test for all the previous conditions.

  if (distance != pre_distance)
  {
    if (distance < 10)
      Keyboard.write('1');
    else if (distance < 20)
      Keyboard.write('2');
    else if (distance < 30)
      Keyboard.write('3');
    else if (distance < 40)
      Keyboard.press('4');
    else if (distance < 50)
      Keyboard.press('5');
    else if (distance < 60)
      Keyboard.press('6');
  }
2 Likes

Thanks for the idea, now it works! :laughing:
But when I move, the board press 1,2,1,2,1,2 when I stand 19-20 cm. So when I play the game I designed, the player vibrates back and forth constantly.

Can you tell me how to solve it?
Thank you!

#include <Keyboard.h>           
int trig=A4;
int echo=A5;
float echotime=0;
int pre_distance;
int distance;
void setup() 
{ 
  Serial.begin(9600);
  pinMode(trig,OUTPUT);
  pinMode(echo,INPUT);
}
void loop () { 
    pre_distance = distance;
    digitalWrite(trig,LOW);delay(1);
    digitalWrite(trig,HIGH);delayMicroseconds(10);
    digitalWrite(trig,LOW);
    echotime=pulseIn(echo,HIGH,30000);
    distance=echotime*0.0172;
    distance=distance/10;distance=distance*10;
    Serial.print("pre_distance:");Serial.print(pre_distance);Serial.print("/");
    Serial.print("distance:");Serial.println(distance);
    pre_distance=pre_distance/10;pre_distance=pre_distance*10;
    
      if (distance != pre_distance) 
  {
    if(distance<10){Keyboard.write('1');}
    else if(distance<20){Keyboard.write('2');}
    else if(distance<30){Keyboard.write('3');}
    else if(distance<40){Keyboard.write('4');}
    else if(distance<50){Keyboard.write('5');}
    else if(distance<60){Keyboard.write('6');}
    else if(distance<70){Keyboard.write('7');}
    else if(distance<80){Keyboard.write('8');}
    else if(distance<90){Keyboard.write('9');}
    else if(distance<100){Keyboard.write('0');}
    else if(distance<110){Keyboard.write('A');}
    else if(distance<120){Keyboard.write('B');}
    else if(distance<130){Keyboard.write('C');}
    else if(distance<140){Keyboard.write('D');}
    else if(distance<150){Keyboard.write('E');}
    else if(distance<160){Keyboard.write('F');}
    else if(distance<170){Keyboard.write('G');}
    else if(distance<180){Keyboard.write('H');}
    else if(distance<190){Keyboard.write('I');}
    else if(distance<200){Keyboard.write('J');}
  }
}
1 Like

You are looking for a change in the second decimal place. If the actual distance is between 19 and 20 cm then the noise in the measurement will cause the measured distance to switch between 10 and 20, outputting 1 or 2 each time it switches.

You could reduce the noise by averaging several readings.

You could avoid the super-sensitive boundary conditions by ignoring readings that are less than 5 cm from the previous reading. If you were at 19 cm you would ignore readings in the range 14 to 24 cm. This has to be done BEFORE you throw out the low-order digit.

2 Likes

Thank you. I'll try your advice :smiley:

1 Like

I do not really know your meaning, so I try to set some variables to make it work.
I set it when the distance was equal to 9,19,29......, next value shouldn't be 14~24cm.
If the next value was 14~24cm, it won't do the Keyboard press.
But it still moves like1,2,1,2,1,2,3,4,3,4. :disappointed_relieved:
Can you just tell me the code? Thank you.

1 Like

I can give it a try.

#include <Keyboard.h>
const byte TriggerPin = A4;
const byte EchoPin = A5;

unsigned PreviousDistance = 0;
const unsigned DistanceBuffer = 5; // Increase until the noise doesn't cause output

// Speed of sound:
// 343 meters per second
// == 0.002915452 seconds per meter
// == 2915.452 microseconds per meter
const float MicrosecondsPerCM = 29.15452;
const float MicrosecondsPerRoundTripCM = MicrosecondsPerCM * 2;  // ~58.3

void setup()
{
  Serial.begin(9600);
  pinMode(TriggerPin, OUTPUT);
  pinMode(EchoPin, INPUT);
}

void loop ()
{
  static unsigned long pingTimer = 0;

  // Don't ping too often or you will catch older echoes.
  if (millis() - pingTimer > 50)
  {
    pingTimer = millis();

    digitalWrite(TriggerPin, LOW);
    delay(1);
    digitalWrite(TriggerPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(TriggerPin, LOW);
    unsigned long echoTime = pulseIn(EchoPin, HIGH, 30000);

    // Did we get an echo? Returns 0 on timeout.
    if (echoTime != 0)
    {
      // An echo was received
      unsigned distance = echoTime / MicrosecondsPerRoundTripCM;

      // Is the change in distance enough to report?
      if (distance > (PreviousDistance + DistanceBuffer) ||
          (PreviousDistance > DistanceBuffer && distance < (PreviousDistance - DistanceBuffer)))
      {
        Serial.print("new distance:");
        Serial.println(distance); Serial.print("/");

        PreviousDistance = distance;
        Keyboard.write('1' + (PreviousDistance / 10));
      } // End: Distance has changed
    } // End: got an echo
  } // End: pingTimer
}
2 Likes

I have tried your advice, but it can't work after all. :worried:
Your code seems a little bit hard, but now I can know what your code's meaning is.
I just copied your code, but when I uploaded it, it just kept running like1,1,1,2,2,3,3,3.
So I add some of my original code, then it repeats like 1,2,1,2,1,2,1,2.

Does it seem like we can't use this solution to prove it?
if you have some ideas,please tell me, thanks!

1 Like

I think there must be something terribly wrong with your distance sensor. If you open up Serial Monitor, what are you receiving when there is an object at a fixed distance?

2 Likes

I open the Serial Monitor and receive 20 when I put a box on 20cm, and I require to push it 6 cm back or forward, it will receive a new distance.
But I had switched 3 sensors, it appears like all have the same trouble. :cry:
And the board occasionally presses like 2,2,2,3,4, which causes me can't play the game. :anguished:

1 Like

That is what I thought you wanted. I'm sorry that I did not (and still do not) understand how you want your device to behave.

2 Likes

@johnwasser
Thank you for answering so many questions, although I didn't find the final answer, I learned a lot about this program. :laughing:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.