0

I'm making a project in which I have to control a mini car and get sensor information via bluetooth. I'd like to be able to control the mini car with the computers keyboard (w,a,s,d), but I was not able to find a library that could help with that, like the "keyboard" library does in python for example

Ex.

import keyboard

# when w is pressed, the car goes forward

If (keyboard.is_pressed("w"):

    Forward()

The "keyboard" library in arduino does not seem to work the same way. And I didn't find any other libraries nor tutorials about it online.

How to make it work?

0

1 Answer 1

2

In case someone is trying to do the same, I came up with a way to make it work. In ArduinoIDE, after the setup, the loop checks if the bluetooth serial is available and has received anything, if it receives the right variables for movement, it passes the instruction to the motors connected to the Arduino through an l298n module.

The code is as follows:

// variáveis para conexão bluetooth // variables for bluetooth connection
#include <SoftwareSerial.h>

SoftwareSerial SerialBT(8, 9);
char valorDoBluetooth;

//variáveis para o uso dos motores // variables for the use of motors
// motor 1
const byte in1 = 2;
const byte in2 = 4;
const byte enA = 3;
//motor 2
const byte in3 = 5;
const byte in4 = 7;
const byte enB = 6;

int velocidade = 100; // motor speed (up to 255)

int componentesOut[6] = { in1, in2, enA, in3, in4, enB }; // list created to setup the variables more easily


void setup() {
  SerialBT.begin(9600);
  Serial.begin(9600);

  // loop to set pins to Output
  for (int n = 0; n < 6; n++) {
    pinMode(componentesOut[n], OUTPUT);
  }
}


void loop() {
  // Read data from the Bluetooth module
  if (SerialBT.available()) {
    valorDoBluetooth = SerialBT.read(); // bluetooth Value

    if (valorDoBluetooth == 'F' || valorDoBluetooth == 'T' || valorDoBluetooth == 'D' || valorDoBluetooth == 'E' || valorDoBluetooth == 'P')  // if SerialBt recieved movement value
    {
      movimento(); // movement
    }
  }
}


void movimento() {
  if (valorDoBluetooth == 'F') {
    Serial.println("Frente");  // Forward
    frente();
  } else if (valorDoBluetooth == 'T') {
    Serial.println("Trás");  // Backwards
    tras();
  } else if (valorDoBluetooth == 'D') {
    Serial.println("Direita");  // Right
    direita();
  } else if (valorDoBluetooth == 'E') {
    Serial.println("Esquerda");  // Left
    esquerda();
  } else if (valorDoBluetooth == 'P') {
    Serial.println("Parar");  // Stop
    parar();
  }
  delay(1);
}


void frente() {
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  digitalWrite(enB, velocidade);
}
void tras() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}
void direita() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  digitalWrite(enB, velocidade);
}
void esquerda() {
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}
void parar() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}

To be able to control it via the PC keyboards, I connected the PC to the device through bluetooth, then see which COM it is connected to in bluetooth configurations of control panel, and use this the COM number on a Python code that's able to communicate with the device.

The Python code is as follows:

import serial
import time
import keyboard

# Replace 'COMX' with the actual COM port assigned to the HC-05 module / Esp device on your PC. More info at https://pyserial.readthedocs.io/en/latest/shortintro.html
ser = serial.Serial('COM8', 9600, timeout=1)

flagMovido = True # flag that checks if the motors are finished moving before changing directions


def controle(event):
    global flagMovido

    if event.event_type == keyboard.KEY_DOWN: # if a key is pressed:
        if (event.name == "w" or event.name == "a" or event.name == "s" or event.name == "d") and flagMovido: # if movement keys are pressed and motors are finished moving to any other direction:
            flagMovido = False # motors started moving

            if event.name == "w" and not flagMovido:
                ser.write(b'F')

                print('frente') # Forward

            elif event.name == "a" and not flagMovido:
                ser.write(b'E')

                print('esquerda') # Left

            elif event.name == "s" and not flagMovido:
                ser.write(b'T')

                print('trás') # Backwards

            elif event.name == "d" and not flagMovido:
                ser.write(b'D')

                print('direita') # Right

    elif event.event_type == keyboard.KEY_UP: # if a key is released:
        if (event.name == "w" or event.name == "a" or event.name == "s" or event.name == "d") and not flagMovido: # if movement keys are released and motors are moving to some direction

            flagMovido = True # motors are finished moving

            ser.write(b'P')

            print('parado') # Stop


print('START')


def main():
    while True:
        data = ser.readline().decode().strip()

        keyboard.hook(controle)
        time.sleep(.001)

        if data:
            print(f"Recebido: {data}") # prints data if any received. Used to print the sensor values received.


if __name__ == "__main__":
    main()

obs:

  • The code runs fine, but may present some problems if you press to many keys at a time, since it was made to handle one direction at a time. But the movement bools will help with that and prevents it from happening to certain extent. Though in specific cases is should be improved.
  • I ended up using a HC05 module with Arduino, but the code also woks for Esp. But if connecting to an Esp, the ser = serial.Serial('COM8', 9600, timeout=1) line should be changed to the way it connects to the Esp. More info at the link provided.
2
  • 1
    it is good to see that you were able to figure this out yourself ... the test of all values in loop() is somewhat redundant, just call movimento() without an if statement
    – jsotola
    Commented Aug 20, 2023 at 18:09
  • Thanks, and good point. I narrowed down the code to explain the logic here, but in the project I'm making this 'if' statement is actually necessary. That's true nonetheless, as it is, that's just a unnecessary 'if' statement. Commented Aug 21, 2023 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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