Перестает работать скетч после 5-10 минут работы. В чем может быть проблема? Скетч внутри

acces969
Offline
Зарегистрирован: 22.01.2017

Здравствуйте. Весь код перечитываю - проблем не нахожу. Что может приводить к остановке работы? Mega 2560 
 

// d - провернуть двигатель против часовой стрелки (по движению джойстика).
//      при этом varres_in увеличивается, а палка натягивается от себя. u - наоборот

boolean oscill       = false;
boolean messages     = false;
boolean usemove     = true;
const int ffb_min  = 22;       // уровень сигнала ффб мин.
const int ffb_max  = 57;       // уровень сигнала ффб макс. (33 - середина 25-33-55)
const int varresMin  = 560;       // пружина от себя
const int varresMax  = 640;       // пружина на себя
const uint8_t ffbpin = A15;       // сигнал ффб
const uint8_t EN     = A2;        // № вывода Arduino к которому подключены входы драйвера L_EN и R_EN. Можно указать любой вывод Arduino поддерживающий ШИМ.
const uint8_t L_PWM  = A1;        // № вывода Arduino к которому подключён  вход  драйвера L_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
const uint8_t R_PWM  = A0;        // № вывода Arduino к которому подключён  вход  драйвера R_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
const uint8_t varres_in    = A4;  // считывание резистора переменного.
int varres_value;                 // значение емкости потенциометра (текущее положение)
int ffb_current = (ffb_min + ffb_max) / 2;             // среднее значение ффб за последний промежуток времени
int ffb_percent = 50;             // среднее значение ффб за последний промежуток времени
int CurrentPosition = 0;
int ToPosition = 50;
int Array[4] = {30, 50, 70, 100};
unsigned long prev_millis = 0;
volatile unsigned long start_time = 0;
volatile long ffblength = 0;
volatile int ffbcount = 0;

void setup() {
  Serial.begin(9600);          // Последовательное соединение
  pinMode(EN,    OUTPUT);      // EN как выход (выход Arduino, вход драйвера)
  pinMode(L_PWM, OUTPUT);      // L_PWM как выход (выход Arduino, вход драйвера)
  pinMode(R_PWM, OUTPUT);      // R_PWM как выход (выход Arduino, вход драйвера)
  pinMode(A3, OUTPUT);         // Выход питания потенциометра позиции двигателя
  pinMode(A5, OUTPUT);         // Выход питания позиции двигателя
  pinMode(13, OUTPUT);         // Светодиод
  pinMode(varres_in, INPUT);   // пин приема сигнала с потенциометра позиции двигателя
  pinMode(ffbpin, INPUT);      // пин приема сигнала с FFB
  digitalWrite(A3,   LOW);     // Питание потенциометра позиции двигателя
  digitalWrite(A5,   HIGH);    // Питание потенциометра позиции двигателя

  prev_millis = millis();
  attachInterrupt(0, rising, RISING);
}

void loop() {
  if (millis() >= prev_millis + 30) {
    detachInterrupt(0);

    ffb_current = ffblength / (ffbcount / 2);
    ffb_current = constrain(ffb_current, ffb_min, ffb_max);

    // Обработка сигнала FFB
    ffb_current = constrain(ffb_current, ffb_min, ffb_max);
    ffb_percent = map(ffb_current, ffb_min, ffb_max, 0, 100);
    if (usemove) {
    ToPosition = ffb_percent;
    if (ffb_percent <= 25) {
      ToPosition = map(ffb_percent, 0, 25, 0, Array[0]);
    } else if (ffb_percent <= 50) {
      ToPosition = map(ffb_percent, 26, 50, Array[0] + 1, Array[1]);
    } else if (ffb_percent <= 75) {
      ToPosition = map(ffb_percent, 51, 75, Array[1] + 1, Array[2]);
    } else {
      ToPosition = map(ffb_percent, 76, 100, Array[2] + 1, Array[3]);
    }
    ToPosition = constrain(ToPosition, 0, 100);
    }

    if (messages) {
      Serial.print(ffb_current); Serial.print(" - "); Serial.println(ToPosition);
    }

    prev_millis = millis();
    ffblength = 0;
    ffbcount = 0;

    attachInterrupt(0, rising, RISING);
  } else {
    delay(5);
  }

  varres_value = analogRead(varres_in);
  Serial.println(varres_value);
  // Остановка при выходе за рамки
  if (varres_value <= varresMin - 10 || varres_value >= varresMax + 10) {
    //moveto(0, 255);
    if (messages) {
      Serial.print("error: ");
      Serial.println(varres_value);
    }
    //error(2);
  }

  // Перемещение на позицию
  if (usemove) {
    varres_value = constrain(varres_value, varresMin, varresMax);
    CurrentPosition = map(varres_value, varresMin, varresMax, 0, 100);
    if (CurrentPosition - 4 > ToPosition) {
      if (messages) {
        Serial.print("move min - "); Serial.print(CurrentPosition); Serial.print(" - "); Serial.println(ToPosition);
      }
      moveto(2, 255);
    } else if (CurrentPosition + 4 < ToPosition) {
      if (messages) {
        Serial.print("move max - "); Serial.print(CurrentPosition); Serial.print(" - "); Serial.println(ToPosition);
      }
      moveto(1, 255);
    } else {
      if (messages) {
        Serial.print("STOPPED: "); Serial.print(ToPosition); Serial.print(" - "); Serial.println(ffb_percent);
      }
      moveto(0, 255);
    }
  }

  // Перестановка по командам из COM
  while (Serial.available() > 0) {
    // messages = true;
    int incomingByte = Serial.read();
    if (incomingByte >= 48 && incomingByte <= 57) {
      Serial.print("command move to - ");  Serial.print(ToPosition);
      ToPosition = (incomingByte - 48) * 10;
      Serial.print(" - "); Serial.println(ToPosition);
    }
    else if (incomingByte == 100) {
      Serial.print("command move max - ");  Serial.print(analogRead(varres_in));
      moveto(1, 160);
      delay(60);
      moveto(0, 160);
      Serial.print(" - "); Serial.println(analogRead(varres_in));
    }
    else if (incomingByte == 117) {
      Serial.print("command move min - ");  Serial.print(analogRead(varres_in));
      moveto(2, 160);
      delay(60);
      moveto(0, 160);
      Serial.print(" - "); Serial.println(analogRead(varres_in));

    }
    else {
      Serial.print("command not found - ");  Serial.print(incomingByte);
    }
  }

  // Вывод данных
  if (oscill) {

    // Осциллограф - значение FFB
    // Serial.write( 0xff );
    // Serial.write( (ToPosition * 10 >> 8) & 0xff );
    // Serial.write( ToPosition * 10 & 0xff );

    // Осциллограф - сглаженное значение FFB
    //Serial.write( 0xff );
    //Serial.write( (map(ffb_average, 300, 700, 0, 100) * 10 >> 8) & 0xff );
    //Serial.write( map(ffb_average, 300, 700, 0, 100) * 10 & 0xff );

    // тест
    //Serial.write( 0xff );
    //Serial.write( (50 * 10 >> 8) & 0xff );
    //Serial.write( 50 * 10 & 0xff );

    // Осциллограф - Процент для двигателя
    //Serial.write( 0xff );
    //Serial.write( ((CurrentPosition * 10) + 1000 >> 8) & 0xff );
    //Serial.write( (CurrentPosition * 10) + 1000 & 0xff );

    // Осциллограф - Текущее значение FFB
    //Serial.write( 0xff );
    //Serial.write( ((map(constrain(ffb_average, ffb_min, ffb_max), ffb_min, ffb_max, 0, 100) * 10) >> 8) & 0xff );
    //Serial.write( (map(constrain(ffb_average, ffb_min, ffb_max), ffb_min, ffb_max, 0, 100) * 10) & 0xff );

    Serial.write( 0xff );
    Serial.write( ((map(ffb_current, 10, 80, 0, 100) * 10) >> 8) & 0xff );
    Serial.write( (map(ffb_current, 10, 80, 0, 100) * 10) & 0xff );

  };

}

void rising() {
  start_time = micros();
  attachInterrupt(0, falling, FALLING);
}

void falling() {
  ffblength = micros() - start_time + ffblength;
  ffbcount++;
  attachInterrupt(0, rising, RISING);
}

// 1 - натянуть, 2 - ослабить пружины
void moveto(byte mode, byte power) {
  if (mode == 1) {
    digitalWrite(L_PWM, 0 );   // Устанавливаем логический 0 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S-
    digitalWrite(R_PWM, 255);   // Устанавливаем логическую 1 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S+
    analogWrite (EN,    power );   // Устанавливаем 50% ШИМ на входах драйвера L_EN и R_EN, это скорость, можно установить от 0 (0%) до 255 (100%).
  }
  else if (mode == 2) {
    digitalWrite(L_PWM, 255);   // Устанавливаем логическую 1 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S+
    digitalWrite(R_PWM, 0 );   // Устанавливаем логический 0 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S-
    analogWrite (EN,    power );   // Устанавливаем ШИМ
  } else {
    digitalWrite(L_PWM, 0 );// Остановка и торможение
    digitalWrite(R_PWM, 0);
    analogWrite (EN,    power);
  }
}

void error(int code) {
  detachInterrupt(0);
  while (true) {
    for (int i = 1; i <= code; i++) {
      digitalWrite(13, HIGH);
      delay(700);
      digitalWrite(13, LOW);
      delay(500);
    }
    delay(1500);
  }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Как именно "перестает работать"? Зависает, сваливается в ошибку или еще как? На каком именно действии останавливается - всегда на одном или на разных?

acces969
Offline
Зарегистрирован: 22.01.2017

Дополню

1. Reset на плате восстанавливает работоспособность меги. 
2. Зависание происходит через несколько минут во время игры. В периоде ожидания (когда данные не меняются, цикл крутится вхолостую) зависания не происходит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

acces969, Вам же залаи вопрос "как именно и в каком месте останавливается". 

У Вас там много вывода в монитор порта. Выложите протокол от начала и до зависания, это помогло б тому, кто захочет разбираться.

acces969
Offline
Зарегистрирован: 22.01.2017

Сообщения ничего не дают = просто поток сообщений прекращается и все. Остановится может в любой момент. Последнее сообщение всегда "stopped ...". 
Но вот что заметил - если закрыть окно монитора порта и вновь открыть его, то иногда мега "оживает" и начинает работать, в т.ч. отправлять сообщения. Но это не всегда

 

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Поставьте скорость порта 115200.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Что я вижу из недоработок: переменные, меняющиеся в прерывании, объявлены volatile - это хорошо. Однако, вне прерывания, в loop - работа с ними идёт неатомарно. Думаю, в этом и причина странного поведения.

Что надо сделать:

1. Сейчас в loop:

ffb_current = ffblength / (ffbcount / 2);

Надо:

noInterrupts();
long this_ffblength = ffblength;
int this_ffbcount = ffbcount;
interrupts();

ffb_current = this_ffblength/ (this_ffbcount/ 2);

Надеюсь, мысль понятна ;)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

acces969 пишет:

Сообщения ничего не дают

Сообщения - они как бабы - одному дают,  другому - нет. Тебе по-русски сказали: "это помогло б", но если ты лучше знаешь, кто кому и что даёт, то разбирайся сам.

Чечако
Offline
Зарегистрирован: 15.06.2018

Я бы проверил, не кончается ли свободная память - погуглите функцию FreeRAM, она даже тут на форуме пробегала. И проследите за числом. Она может как уменьшаться, если есть утечка, так и увеличиваться резко, что говорит о проблемах с работой с памятью.