Arduino Uno R3 - After ~5 seconds the serial complete freezes, chip not

Hi, I am playing little with DC brushed motor and encoders, so I glued together some code:

/*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent

#define pin 9

int readInt() { //dirty
  if (Serial.available() > 0) {   // something came across serial
    int integerValue = 0;         // throw away previous integerValue
    while(1) {            // force into a loop until 'n' is received
      char incomingByte = Serial.read();
      if (incomingByte == '\n') break;   // exit the while(1), we're done receiving
      if (incomingByte == -1) continue;  // if no characters are in the buffer read() returns -1
      integerValue *= 10;  // shift left 1 decimal place
      // convert ASCII to integer, add, and shift left 1 decimal place
      integerValue = ((incomingByte - 48) + integerValue);
    }
    return integerValue;
  }
  return -1;
}

void setup() {
  pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pin, OUTPUT);
  attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
  Serial.begin(74880); // start the serial monitor link
}

void PinA(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos --; //decrement the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void PinB(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos ++; //increment the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void loop(){
  if(oldEncPos != encoderPos) {
    Serial.println(encoderPos);
    oldEncPos = encoderPos;
  }
  int val = readInt();
  if(val != -1) {
    Serial.println(val);
    analogWrite(pin, val);
  }
}

The problem is however that when I plug in the Arduino, open serial and write any number, i got messages for like 3 seconds and then it freezes. When I write something, serial just kind of waits. But the chip is working and generating PWM. I tried initializing serial to 9600, 74880 and 115200 bauds, but it didn't helped. If you could help me, I would be very grateful. Thanks

in addition to receiving digits and '\n' could the Serial.read() be receiving other characters (e.g.'\r') which could be causing problems
try inserting the following test

      if((incomminByte <'0') || (incommingByte > '9'))continue; 
      integerValue *= 10;  // shift left 1 decimal place

to discard any other characters

Your system for receiving data is not robust. For one thing, you are assuming the data will be there when you expect it.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

...R

I know that the integer parsing is quick-and-dirty code, but that does not matter. The problem is in both input / output. In whole serial. I send number 100, it is received and printed and the movement begin. As I am receiving the position from arduino, it just freezes and thats it.

can you tell if the host program freezes or the arduino?
what host program are you using?

are you sure the host is sending a '\n' at the of the line?
if I use teraterm the following works

     if (incomingByte == '\r') break;   // exit the while(1), we're done receiving

I am using Arduino serial monitor. Here is video. The serial freezes (sometimes in one sec, sometimes in 5 sec; I tried it like 20 times and the longest 2 periods were ~40seconds and ~15seconds - video) but the arduino keeps outputing signal. I tried 3 different usb cables and different ports (and even second computer), but it just does not work. Serial freezes while receiving position data from arduino - YouTube
The motor is driven with 5V 2A (usb charger) through mosfet with push-pull transistors. Is there any chance that this is caused by bad grounding or any oscilations or whatever electrical?

when I used the Arduino serial monitor it sends the digits OK but no '\n' or '\r' so the code hangs waiting for the line terminator

I do send the \n.
EDIT: I little edited the receiving, but still the serial freezes.

//#include <PID_v1.h>

/*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent

#define pin 9

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
    if (Serial.available() > 0) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

int readInt() {
    if (newData == true) {
        return atoi(receivedChars);   // new for this version
    }
    return -1;
}

void PinA(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos --; //decrement the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void PinB(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos ++; //increment the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

//input cur temp, output last temp, setpoint settmp
double input, output, setpoint;

//PID pid(&input, &output, &setpoint, 1, 0.05, 0.25, DIRECT);

void setup() {
  pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pin, OUTPUT);
  attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
  Serial.begin(115200); // start the serial monitor link
  //pid.SetMode(AUTOMATIC);
}

void loop(){
  /*input = output = encoderPos;
  setpoint = 100;
  if(input > setpoint) input = setpoint;
  analogWrite(pin, (int) input);
  pid.Compute(); */
  recvWithEndMarker();
  if(oldEncPos != encoderPos) {
    Serial.println(encoderPos);
    oldEncPos = encoderPos;
  }
  int val = readInt();
  if(val != -1) {
    //Serial.println(val);
    analogWrite(pin, val);
  }
}

if I run your code it works OK accepting numeric input from the PC without problems
I would suspect that the motor is causing problems - possibly a reduction in voltage as it starts
try a more powerful power supply?

Arduino is connected to the PC, the motor (mosfet) is connected to battery usb charger 5V@2Amps.

you could try some large capacitors on the power supply lines
I tend to drive motors, heaters, etc via opto isolators

ok thanks, I will put there optoisolars laters. Looks like I have to not to use the serial for a while.

try commenting out the statement which switches on the motor

analogWrite(pin, val);

if that is the problem the rest of the code should work as expected

It has to be problem with electrical noise, when I move the motor manually the serial works just fine.

try some large capacitors across the motor power lines - it may reduce the noise
or even a power supply with a larger current output

Sure, I will post results probably on Sunday. Dont have equipment here right now.