@Override
    protected void internal_connect() throws MyException, InterruptedException {
      // try 3 times to get answare:
      for (int t = 0; t < 3; t++) {
        internal_reset();

        // Send M110 to reset checksum
        internal_send("M110");
        doSendEvent("M110");

        // 5 secound Timout for answer
        for (int i = 0; i < 50; i++) {
          Communication.class.wait(100); // give data the possibility  to enter internal_receive!
          if (!core.isConnected()) {
            throw new MyException("Lost connection! (" + status + ")");
          }
          if (receiveCount > 0) {
            break;
          }
        }

        if (receiveCount > 0) {
          break;
        }
        Communication.doChangedEvent("Printer not answering to M110! Retrying ...");
      }

      // Printer not answered!
      if (receiveCount == 0) {
        throw new MyException("Printer did not respond! Try to replug USB cable.");
      }

      // SET absolute
      internal_send("G90");
      doSendEvent("G90");

      // 2 secound Timout for answer
      synchronized (Communication.class) {
        for (int i = 0; i < 20; i++) {
          Communication.class.wait(100); // give data the possibility to enter internal_receive!
          if (!core.isConnected()) {
            throw new MyException("Lost connection!");
          }
          if (!internal_isbusy()) {
            break;
          }
        }
      }
      if (internal_isbusy()) {
        throw new MyException("Printer did not answer to G90!");
      }
    }
  public static synchronized void send(String command) throws ComInterruptException {
    if (!isConnected()) {
      disconnect();
      throw new ComInterruptException("Not connected !");
    }
    // No command
    if (command.trim().equals("")) {
      return;
    }

    while ((I().internal_isbusy() || initThread.isAlive()) && isConnected()) {
      try {
        Communication.class.wait();
      } catch (InterruptedException ex) {
        throw new ComInterruptException("Interrupt!");
      }
    }
    if (!isConnected()) {
      throw new ComInterruptException("Not connected !");
    }

    doSendEvent(command);

    try {
      I().internal_send(command);
    } catch (MyException ex) {
      Logger.getLogger(Communication.class.getName()).log(Level.SEVERE, null, ex);
      resetAll();
      doChangedEvent(ex.getMessage());
      throw new ComInterruptException(ex.getMessage());
    }
  }
    @Override
    protected void internal_connect() throws MyException, InterruptedException {
      internal_reset();

      // Wait for GRBL to reset (1 secound)
      Communication.doChangedEvent("Wait for GRBL Reset ...");
      Communication.class.wait(3000);

      // SET absolute
      internal_send("$X");
      doSendEvent("$X");

      // 2 secound Timout for answer
      synchronized (Communication.class) {
        for (int i = 0; i < 20; i++) {
          Communication.class.wait(100); // give data the possibility to enter internal_receive!
          if (!core.isConnected()) {
            throw new MyException("Lost connection!");
          }
          if (!internal_isbusy()) {
            break;
          }
        }
      }
      if (internal_isbusy()) {
        throw new MyException("Printer did not answer to $I!");
      }
    }
    private void resend(int rs) throws MyException {
      // Cecksum:
      if (rs > cmdHistroy.size()) {
        throw new MyException("Resend bigger than send history!");
      }

      String command = cmdHistroy.get(rs - 1);
      command = "N" + cmdHistroy.size() + " " + command + " *";
      byte cs = 0;
      byte[] b = command.getBytes();
      for (int i = 0; b[i] != '*' && i < b.length; i++) {
        cs = (byte) (cs ^ b[i]);
      }
      command += "" + cs;

      doSendEvent("   " + rs + "=>[" + command + "]");
      core.send(command);
    }