Controlling Arduino Uno from NetBeans

Hello!
I’m controlling my Arduino Uno from NetBeans using JSerialComm, making two servo motors move in a pan-tilt mechanism.
Controlling the servo motors from the application works like a charm, but it seems to fill up the SRAM, I also need to control the servo motors with a joystick, which fills up the SRAM even faster. In my app, upon selecting a checkbox, I send byte value 6 to the Uno, which switches to the case 6 in the code provided below.
After approximetely 10 seconds of controlling the servos with the joystick, they seem to freeze up, and you can’t control them at all.
I send information to the arduino every 35 milliseconds using the method that controls the cases 1-5, every 20 milliseconds using the method that switches to the joystick controls. The first 4 cases work while the Arduino receives the appropriate byte to trigger the servo. The 5th one needs only one triggering byte to work, the 6th one works consantly until a checkbox is unselected.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
Servo myservo2; //MAKSIMSMADE
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position


// Arduino pin numbers
const int BTN_pin = 13; // digital pin connected to button output
const int SERVO_pin = 3; // digital pin connected to button output
const int SERVO_pin2 = 6; // MAKSIMSMADE
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

int flagBtnPressedOnce = 0;

int x, y = 0; // for joystick readings
int xDeg, yDeg = 0; // for servo angle control
int xSpeed, ySpeed = 0; // for servo speed control

void setup() {

  pinMode(BTN_pin, INPUT); // INPUT is Sensor (e.g. button, motion sensor, mic, etc.)
  pinMode(SERVO_pin, OUTPUT); // OUTPUT is Actuator (e.g. any motor, LED bulb, etc.)
  pinMode(SERVO_pin2, OUTPUT); //MAKSIMSMADE
  digitalWrite(BTN_pin, HIGH); // default state

  myservo.attach(SERVO_pin);  // attaches the servo on pin 9 to the servo object
  myservo2.attach(SERVO_pin2); //MAKSIMSMADE
  //myservo.write(90);  // default position 90 degrees
  //myservo2.write(90); //MAKSIMSMADE
  Serial.begin(9600);
}

void loop() {

  //Trying to communicate with NetBeans
  //myservo - vertical
  //myservo2 - horizontal
  byte incomingByte;
  incomingByte = Serial.read();
  if (incomingByte != -1) {
    switch (incomingByte) {
      case 1: {
          int testY = myservo.read();
          myservo.write(testY + 1);
        }
        break;
      case 2: {
          int testY = myservo.read();
          myservo.write(testY - 1);
        }
        break;
      case 3: {
          int testX = myservo2.read();
          myservo2.write(testX + 1);
        }
        break;
      case 4: {
          int testX = myservo2.read();
          myservo2.write(testX - 1);
        }
        break;
      case 5: {
          if (myservo2.read() > 91) {
            while (myservo2.read() != 90) {
              myservo2.write(myservo2.read() - 1);
              delay(15);
            }
          }
          if (myservo2.read() < 89) {
            while (myservo2.read() != 90) {
              myservo2.write(myservo2.read() + 1);
              delay(15);
            }
          }
          if (myservo.read() > 91) {
            while (myservo.read() != 90) {
              myservo.write(myservo.read() - 1);
              delay(15);
            }
          }
          if (myservo.read() < 89) {
            while (myservo.read() != 90) {
              myservo.write(myservo.read() + 1);
              delay(15);
            }
          }
        }
        break;
      case 6: {
          //Izvadam X,Y koordinātes:
          x = analogRead(X_pin); //nolasām joystika X vērtību
          Serial.print("X: ");
          Serial.print(x);

          y = analogRead(Y_pin); //nolasām joystika Yvērtību
          Serial.print(", Y: ");
          Serial.print(analogRead(Y_pin));

          xDeg = map(x, 0, 1023, 0, 180); // remapping values of joystick reading to servo angles (https://www.arduino.cc/reference/en/language/functions/math/map/)
          yDeg = map(y, 0, 1023, 0, 180);

          xSpeed = map(x, 0, 1023, -100, 100); // remapping values of joystick reading to servo speed (https://www.arduino.cc/reference/en/language/functions/math/map/)
          ySpeed = map(y, 0, 1023, -100, 100);

          Serial.print(", xDeg: ");
          Serial.print(xDeg);
          Serial.print(", yDeg: ");
          Serial.print(yDeg);

          Serial.print(", xSpeed: ");
          Serial.print(xSpeed / 20);
          Serial.print(", ySpeed: ");
          Serial.print(ySpeed / 20);

          // palielinām / samazinām servo leņķi ar xSpeed (kad būs otrais servo - tad tam ySpeed jāizmanto)
          if (xSpeed < - 1 || xSpeed > 1) {
            int oldPosition = myservo.read();
            myservo.write(oldPosition + (xSpeed / 20));          // tell servo to go to position in variable 'pos'
            delay(15);
          }

          //MAKSIMSMADE
          if (ySpeed < - 1 || ySpeed > 1) {
            int oldPositionY = myservo2.read();
            myservo2.write(oldPositionY + (ySpeed / 20));          // tell servo to go to position in variable 'pos'
            delay(15);
          }

          delay(5); // 1ms aizkave starp mērījumiem
        }

        break;
      default: {

        }
        break;
    }
  }


}

After looking at some similar topics, I found that other people had SRAM issues too, and someone used client.flush();
client.stop();
because the Serial buffer was filled up, not accepting any more values. Would this help in my situation?
I can provide the NetBeans code which is responsible for sending the values to Arduino if needed.
I would be appreciate any help!

i'm curious how you know SRAM got filled?

why aren't you using Serial.available() to determine if there's a byte to read from Serial?

gciurpita:
i'm curious how you know SRAM got filled?

why aren't you using Serial.available() to determine if there's a byte to read from Serial?

I can only use one port, to connect my Java application to Arduino, so I cannot access the console, nor do I have any other peripherals to use as debugging (for example, a LED lighting up if SRAM is almost full, if it's even possible to determine that).
I think SRAM is being filled up, because after reading some other threads, people have said that sending too much data to Serial is bad, since it is slow at both reading and writing, but as I am fairly new to Arduino, I could be wrong.

i understand that you're using the Serial interface to send commands and therefore have limited ability to use it for debugging.

but my point about using Serial.available() is that it can be used to determine when to read the port instead of always reading it seeing if the value is valid. in other words

if (! Serial.available())
     return;

and there's no need to test
if incoming Byte != -1)

It looks like your external application is filling up the serial buffer with commands and your sketch is not consuming these fast enough.

How long can the sketch be waiting here because, while it is in here, you are not taking data from the serial buffer (which has a limit, say 63 characters)

      case 5: {
          if (myservo2.read() > 91) {
            while (myservo2.read() != 90) {
              myservo2.write(myservo2.read() - 1);
              delay(15);
            }
          }
          if (myservo2.read() < 89) {
            while (myservo2.read() != 90) {
              myservo2.write(myservo2.read() + 1);
              delay(15);
            }
          }
          if (myservo.read() > 91) {
            while (myservo.read() != 90) {
              myservo.write(myservo.read() - 1);
              delay(15);
            }
          }
          if (myservo.read() < 89) {
            while (myservo.read() != 90) {
              myservo.write(myservo.read() + 1);
              delay(15);
            }
          }
        }

gciurpita:
i understand that you're using the Serial interface to send commands and therefore have limited ability to use it for debugging.

but my point about using Serial.available() is that it can be used to determine when to read the port instead of always reading it seeing if the value is valid. in other words

if (! Serial.available())

return;



and there's no need to test
` if incoming Byte != -1)`

Unless I'm misunderstanding, all it would do is either only go to the switch case if the value is "valid" or only read valid inputs, which is every single input? My problem, as far as I understand, is that I send too much information for the Serial port to handle, so the buffer fills up, not accepting any more values, but I need to send this amount of information, so the servo motors work both smootly and quickly.
I read this thread, and maybe I need to try and empty out the buffer faster than it can be filled up?

what about minimizing processing time. 9600 bps is roughly 1 char/msec.

can you minimize prints?

6v6gt:
It looks like your external application is filling up the serial buffer with commands and your sketch is not consuming these fast enough.

How long can the sketch be waiting here because, while it is in here, you are not taking data from the serial buffer (which has a limit, say 63 characters)

      case 5: {

if (myservo2.read() > 91) {
           while (myservo2.read() != 90) {
             myservo2.write(myservo2.read() - 1);
             delay(15);
           }
         }
         if (myservo2.read() < 89) {
           while (myservo2.read() != 90) {
             myservo2.write(myservo2.read() + 1);
             delay(15);
           }
         }
         if (myservo.read() > 91) {
           while (myservo.read() != 90) {
             myservo.write(myservo.read() - 1);
             delay(15);
           }
         }
         if (myservo.read() < 89) {
           while (myservo.read() != 90) {
             myservo.write(myservo.read() + 1);
             delay(15);
           }
         }
       }

In the 5th case, I just have the motors rotate back into the default position, which is 90 for both of them, so the maximum amount of time I need to wait is about ~2 seconds for it to complete (If i understood your question correctly).
To “trigger” the 5th case, I just press the button, and the servo motors reset. If i want, say, the first servo to go up (move towards 180 degrees), then I hold down the Up button in my interface, which sends the Integer 1 as a byte to the Arduino very quickly, ensuring that the second (the 35th millisecond to be precise) the button is let go, the servo stops rotating.
Do I need to try something else in stead of switch? I remember working with if statements, but they didn’t perform well at all, the current situation works, although briefly.

gciurpita:
what about minimizing processing time. 9600 bps is roughly 1 char/msec.

can you minimize prints?

I set the baud rate to 2400, which made the motors fairly jerky, when using the joystick, and they lasted a bit longer (I guess the buffer didn't fill up as fast) than with the baud rate of 9600.
Minimizing prints is definitely possible, but it makes the movement of the servos either jerky or delayed, so it's something I'd only consider as the last resort.

Here:

I send information to the arduino every 35 milliseconds using the method that controls the cases 1-5, every 20 milliseconds using the method that switches to the joystick controls.

Does this mean that you are sending a continuous stream of bytes, 1 byte each 35mS (20mS in the case of the joy stick) or do you send data only when something changes.

A 2 second wait is a long time is data is coming at one byte at 20mS or 35mS.

As ever, use of delay is killing you. You'll need to restructure your code to use millis for your timing instead.

wildbill:
As ever, use of delay is killing you. You'll need to restructure your code to use millis for your timing instead.

Delays in arduino code are there so the servo doesn't instantly snap into the required position, but slowly moves towards it. In the 5th case if I remove the delay, it moves there insantly, and the platform it'll be mounted on could be unstable because of it.
In the 6th case, delays make sure that the joystick input doesnt make the servos snap into place as well.

6v6gt:
Here:

Does this mean that you are sending a continuous stream of bytes, 1 byte each 35mS (20mS in the case of the joy stick) or do you send data only when something changes.

A 2 second wait is a long time is data is coming at one byte at 20mS or 35mS.

Using this Java code, i constantly send data while the Up/Down/Left/Right buttons are pressed down.

do {
                                Integer selection;
                                if (jButton.getName().equalsIgnoreCase("upButton")) {
                                    selection = 1;
                                } else if (jButton.getName().equalsIgnoreCase("downButton")) {
                                    selection = 2;
                                } else if (jButton.getName().equalsIgnoreCase("rightButton")) {
                                    selection = 3;
                                } else if (jButton.getName().equalsIgnoreCase("leftButton")) {
                                    selection = 4;
                                } else if (jButton.getName().equalsIgnoreCase("Reset")) {
                                    selection = 5;
                                } else {
                                    selection = 0;
                                }

                                System.out.println("selection " + selection);

                                try {
                                    chosenPort.getOutputStream().write(selection.byteValue());
                                } catch (IOException ex) {
                                    Logger.getLogger(GrabberShow.class.getName()).log(Level.SEVERE, null, ex);
                                }

                                try {
                                    chosenPort.getOutputStream().flush();
                                } catch (IOException ex) {
                                    Logger.getLogger(GrabberShow.class.getName()).log(Level.SEVERE, null, ex);
                                }
                                try {
                                    Thread.sleep(35);
                                } catch (Exception ex) {
                                }
                            } while (mouseDown);

To trigger the Reset button, i only need to click it, then it sends 5 as a byte value once to the Arduino, which triggers the 5th case, resetting the servos from their current position to 90.

Indeed, but there are other ways to control the timing on your servos without using the delay function. Take a look at the IDE example blink without delay.

You might need to slow down the data feed from the netbean setup, as servos can only move so fast. What does a sent data packet look like? You probably can get rid of the delay(15) in your code as it probably just slows your code loop down. You may want to try the simple serial capture like below that allows 3ms for a new character to arrive. That may be the only delay needed in your code, and it should empty the serial buffer faster than your code does with all the delays.

  while (Serial.available()) {

    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
      delay(3);
    } 
  }

wildbill:
Indeed, but there are other ways to control the timing on your servos without using the delay function. Take a look at the IDE example blink without delay.

But isn't my case sort of the opposite? I can't do two things at once. On pressing down one button, i execute only one case, moving only one servo motor. Using the joystick i can move both of them at once, but that works fine. As I understood, the milis() approach would be good if i wanted to control one servo, while doing something else, which isn't needed for me.
Do you think the delay() is the problem, not the SRAM issue?

It depends on what your PC code is sending on serial. If it's sending a continuous stream of bytes that you're not reading for two seconds as mentioned earlier, you have a problem with delay.

What are you seeing that makes you think you have an SRAM issue?

zoomkat:
You might need to slow down the data feed from the netbean setup, as servos can only move so fast. What does a sent data packet look like? You probably can get rid of the delay(15) in your code as it probably just slows your code loop down. You may want to try the simple serial capture like below that allows 3ms for a new character to arrive. That may be the only delay needed in your code, and it should empty the serial buffer faster than your code does with all the delays.

  while (Serial.available()) {

if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
      delay(3);
    }
  }

Slowing it down is possible, but that means that when I press down the Up button, the servo moves up by one degree, then it waits for the next input, so the servo will move in a jerky or just slow manner. The servo movement can be almost instant, if there is no delay they snap into place, but that's not at all what I want.
Where exactly would I put that snippet of code? Place my entire switch in the while loop before the if statement?

wildbill:
It depends on what your PC code is sending on serial. If it’s sending a continuous stream of bytes that you’re not reading for two seconds as mentioned earlier, you have a problem with delay.

What are you seeing that makes you think you have an SRAM issue?

I’m not seeing anything, as I do not have access to the Serial Monitor, since my port is used, I just think that’s the only possiblity - I do send a lot of data.
I’m sending the Integer 1, 2, 3, 4 for up/down/left/right, which is converted to a byte value (the output of 1.byteValue() from java is 1, so I guess it sends the byte 1) The program doesn’t send anything until i either hold down a button or press it. I have to hold down Up/Down/Left/Right for the servos to move, press Reset once for the servos to go into default position, and check the checkbox to swap to joystick controls, which sends the byte 6 every 20ms.
In the attachment is the fairly basic user interface, which is how i control the servos.

I suggest that you remove all delays from your code.

Keep a variable for each servo that keeps the position you would like that servo to be at. Adjust these variables accordingly as you get commands from the serial port.

Using the blink without delay technique, every 30mS check to see if each servo isn't where it's supposed to be according to its corresponding variable. If it isn't, move it a small step towards the new position.

That's it.

Oh, and whatever you do, don't use String objects. I can't see that you have any RAM issues now - any surplus serial input that you don't get to in time is just thrown away, but if you would like some RAM problems, String objects can provide them for you.