1
votes


I'm trying to make an arduino project today that can "replicate" or emulate a keyboard based on a serial communication handled then by a Java app.
So, I'm trying to code a Java application that interfaces itself with my Arduino Mega to "replicate" a keyboard and I need the Java app to "convert" the serial bytes received to the keystrokes to send to the OS itself. The problem is that whatever I try to keep the key pressed while the serial read byte doesn't change, I get stuck in a single key pressed situation or in an infinite loop of keystrokes sent in a little to no time situation (game I'm currently doing this project for, where the idea came from, expected behaviour, current behaviour...)
I would also like to say that I know I could reprogram the Arduino firmware to be recognized as the other "bridge" chip to get the keyboard library working but I would like to be able to use this board for other projects too and having it just to recompile and upload the sketch I need every time and switch project in the matter of a minute is a must for me that I don't have more than a single board around just bought saving some mum's school budget with cheap gear instead of "Fabriano's" one (known, good and not cheap brand here where I live)...

Here's my Arduino code (if needed, but works perfectly for what it needs to do):

const int SECOND = 1000;
const int Hz = 2; // change to 250Hz~1000Hz when ready to use
const int firstPin = A6;
const int secondPin = A7;

void setup() {
  pinMode(13, OUTPUT);
  pinMode(firstPin, INPUT);
  pinMode(secondPin, INPUT);
  analogWrite(firstPin, LOW); // initialize to LOW both pins to overcome
  analogWrite(secondPin, LOW); // incorrect read values in the future
}

void sendData() {
  if (analogRead(firstPin) > 300) {
    Serial.write(0b00001011);
  }
  else {
    Serial.write(0b00001010);
  }
  if (analogRead(secondPin) > 300) {
    Serial.write(0b00010101);
  }
  else {
    Serial.write(0b00010100);
  }
}

int connectionSetup() {
  Serial.begin(9600);
  while(!Serial.available()) {
    ;
  }
  if(Serial.read()==0b10101010) {
    Serial.write(0b10101010);
    Serial.write(0b01010101);
    while(!Serial.available()) {
      ;
    }
    if(Serial.read()==0b01010101) {
      return 0;
    }
  }
  return -1;
}

void loop() {
  if(connectionSetup() == 0) {
    while(true) {
      sendData();
      delay (SECOND / Hz);
    }
  }
}


And here's my buggy Java code:

package ArduinoSerialKeyboard;
import com.fazecast.jSerialComm.*;
import java.awt.AWTException;
import java.io.IOException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
/**
 *
 * @author BJPGameVideosITA
 */
public class Startup {
    private static SerialPort sp = SerialPort.getCommPort("COM5"); // device name, change it if needed
    private static int key1 = KeyEvent.VK_Q, key2 = KeyEvent.VK_W; // change if needed
    private static boolean key1state = false, key2state = false;
    private static Thread t;

    private static int setup() throws IOException, InterruptedException {
        sp.setComPortParameters(9600, 8, 1, 0); // default connection settings for Arduino
        sp.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 0, 0); // block until bytes can be read
        t = new Thread(new Runnable() {
            @Override
            public void run() {
                pressKey.setup(key1, key2);
            }
        });
        t.start();
        if (sp.openPort()) {
            System.out.println("Port opened!");
            Thread.sleep(1000); // waits for the serial connection to be established and ready
            sp.getOutputStream().write(0b10101010);
            sp.getOutputStream().flush();
            while(sp.getInputStream().available() < 1) {
                ;
            }
            if(sp.getInputStream().read()==0b10101010) {
                while(sp.getInputStream().available() < 1) {
                    ;
                }
                if(sp.getInputStream().read()==0b01010101) {
                    sp.getOutputStream().write(0b01010101);
                    sp.getOutputStream().flush();
                    return 0;
                }
            }
            System.out.println("Error in synchronization!");
            return -1;
        }
        else {
            System.out.println("Error in opening port!");
            return -1;
        }
    }

    private static int read() throws IOException {
        while(sp.getInputStream().available() < 1) {
            ;
        }
        int b = sp.getInputStream().read();
        return b;
    }

    private static void keyboard() throws IOException {
        boolean exit = false;
        do {
            int read = read();
            if(read == -1) {
                break;
            }
            switch (read) {
                case 10: if(!key1state) {pressKey.stop(1); key1state=!key1state;} break;
                case 11: if(key1state) {pressKey.start(1); key1state=!key1state;} break;
                case 20: if(!key2state) {pressKey.stop(2); key2state=!key2state;} break;
                case 21: if(key2state) {pressKey.start(2); key2state=!key2state;} break;
                case 0: exit = true; break;
            }
        } while (!exit);
    }

    private static int close() {
        if (sp.closePort()) {
            System.out.println("Port closed!");
        }
        else {
            System.out.println("Error in closing port!");
            return -1;
        }
        return 0;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        setup();
        keyboard();
        close();
    }
}

class pressKey {
    private static boolean toPress[] = {false, false};
    private static int key1, key2;

    public static void setup(int k1, int k2) {
        key1 = k1;
        key2 = k2;
    }

    private static void run(int key) {
        try {
            Robot robot = new Robot();
            if(key == key1) {
                while (toPress[0]) {
                    robot.keyPress(key1);
                }
                robot.keyRelease(key1);
            }
            if(key == key2) {
                while (toPress[1]) {
                    robot.keyPress(key2);
                }
                robot.keyRelease(key2);
            }
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    public static void start(int key) {
        toPress[key-1] = true;
        if(key == 1)
            run(key1);
        if(key == 2)
            run(key2);
    }

    public static void stop(int key) {
        toPress[key-1] = false;
    }
}


Thanks everyone in advance, any help is appreciated.

PS: I found other StackOverflow questions but they were all related to keeping the key down no matter how, I need instead to keep it down as if it was by the user and let the OS handle it (meaning that it has to stop for a little after the first press and then press every TimeoutSetByTheOperatingSystem seconds and not just smash over9000 times as shown in the video because that game previously mentioned needs the key down and not a smash of keys to hold the "sliders" as shown in the "where the idea came from" video... more informations of the game itself here.) and I have already tried them all without success... thanks!