Перестает работать скетч после 5-10 минут работы. В чем может быть проблема? Скетч внутри
- Войдите на сайт для отправки комментариев
Вс, 21/06/2020 - 10:42
Здравствуйте. Весь код перечитываю - проблем не нахожу. Что может приводить к остановке работы? 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);
}
}
Как именно "перестает работать"? Зависает, сваливается в ошибку или еще как? На каком именно действии останавливается - всегда на одном или на разных?
Дополню
1. Reset на плате восстанавливает работоспособность меги.
2. Зависание происходит через несколько минут во время игры. В периоде ожидания (когда данные не меняются, цикл крутится вхолостую) зависания не происходит.
acces969, Вам же залаи вопрос "как именно и в каком месте останавливается".
У Вас там много вывода в монитор порта. Выложите протокол от начала и до зависания, это помогло б тому, кто захочет разбираться.
Сообщения ничего не дают = просто поток сообщений прекращается и все. Остановится может в любой момент. Последнее сообщение всегда "stopped ...".
Но вот что заметил - если закрыть окно монитора порта и вновь открыть его, то иногда мега "оживает" и начинает работать, в т.ч. отправлять сообщения. Но это не всегда
Поставьте скорость порта 115200.
Что я вижу из недоработок: переменные, меняющиеся в прерывании, объявлены volatile - это хорошо. Однако, вне прерывания, в loop - работа с ними идёт неатомарно. Думаю, в этом и причина странного поведения.
Что надо сделать:
1. Сейчас в loop:
Надо:
Надеюсь, мысль понятна ;)
Сообщения ничего не дают
Сообщения - они как бабы - одному дают, другому - нет. Тебе по-русски сказали: "это помогло б", но если ты лучше знаешь, кто кому и что даёт, то разбирайся сам.
Я бы проверил, не кончается ли свободная память - погуглите функцию FreeRAM, она даже тут на форуме пробегала. И проследите за числом. Она может как уменьшаться, если есть утечка, так и увеличиваться резко, что говорит о проблемах с работой с памятью.