Serial не работает при вызове функции из таймера

Вы можете попробовать код на своей Arduino UNO, чтобы лучше понять, что происходит в последовательном мониторе!

Я хочу вычислить матрицу Якобиана из матрицы вращения!

float jakMATB[3][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}
     };
float POKUS = 0;
float k = 0.000001;
float dt = 0.001;
float b = 90 * (PI / 180);
float vnB[3] = {0, 1, 0}, vpB[3] = {0, 1, 1};
float nB[3] = {0, 1, 0};
float nBplus[3] = {0 , 1, 0};
float nBminus[3] = {0, 1, 0};
void setup() {
Serial.begin(9600);
Serial.print("init ok");
cli();//останавливаем прерывания
TCCR1A = 0;// устанавливаем весь регистр TCCR1A в 0
TCCR1B = 0;// то же самое для TCCR1B
TCNT1  = 0;//инициализировать значение счетчика до 0
// установить регистр совпадения для сравнения с шагом 1 Гц
OCR1A = (16000000) / ((1 / dt) * 1024) - 1; // 15624 = (16*10^6) / ((1)*1024) - 1 (должно быть <65536)
// включаем режим CTC
TCCR1B |= (1 << WGM12);
// Установите биты CS12 и CS10 для прескалера 1024
TCCR1B |= (1 << CS12) | (1 << CS10);
// включить прерывание сравнения таймера
TIMSK1 |= (1 << OCIE1A);
sei();//разрешить прерывания
}

когда я вызываю функцию в цикле, все работает нормально, и я получаю 1 2 1 в последовательном мониторе

 void loop() {
 izracunJAKOB();
 for (int j = 0; j <= 2; j++) {
for (int i = 0; i <= 2; i++) {
  Serial.print(jakMATB[j][i]);
  Serial.print(" ");
}
Serial.println("");
}
}

когда я вызываю izracunJAKOB() с прерыванием таймера Последовательный монитор перестает работать и не пишет событие "init ok"

ISR(TIMER1_COMPA_vect) {
  //izracunJAKOB();
 }
void izracunJAKOB() {
for (int j = 0; j <= 2; j++) {
for (int i = 0; i <= 2; i++) {
  nBplus[j] = nB[j] + k;
  nBminus[j] = nB[j] - k;
  float matricaBplus[3][3] = {
    {cos(b) + nBplus[0]*nBplus[0]*(1 - cos(b)), nBplus[1]*nBplus[0]*(1 - cos(b)) - nBplus[2]*sin(b), nBplus[0]*nBplus[2]*(1 - cos(b)) + nBplus[1]*sin(b)},
    {nBplus[1]*nBplus[0]*(1 - cos(b)) + nBplus[2]*sin(b), cos(b) + nBplus[1]*nBplus[1]*(1 - cos(b)), nBplus[1]*nBplus[2]*(1 - cos(b)) - nBplus[0]*sin(b)},
    {nBplus[0]*nBplus[2]*(1 - cos(b)) - nBplus[1]*sin(b), nBplus[1]*nBplus[2]*(1 - cos(b)) + nBplus[0]*sin(b), nBplus[2]*nBplus[2]*(1 - cos(b)) + cos(b)}
  };
  float matricaBminus[3][3] = {
    {cos(b) + nBminus[0]*nBminus[0]*(1 - cos(b)), nBminus[1]*nBminus[0]*(1 - cos(b)) - nBminus[2]*sin(b), nBminus[0]*nBminus[2]*(1 - cos(b)) + nBminus[1]*sin(b)},
    {nBminus[1]*nBminus[0]*(1 - cos(b)) + nBminus[2]*sin(b), cos(b) + nBminus[1]*nBminus[1]*(1 - cos(b)), nBminus[1]*nBminus[2]*(1 - cos(b)) - nBminus[0]*sin(b)},
    {nBminus[0]*nBminus[2]*(1 - cos(b)) - nBminus[1]*sin(b), nBminus[1]*nBminus[2]*(1 - cos(b)) + nBminus[0]*sin(b), nBminus[2]*nBminus[2]*(1 - cos(b)) + cos(b)}
  };
  jakMATB[i][j] = (matricaBplus[i][j] - matricaBminus[i][j]) / (2 * k);
  nBplus[0] = 0;
  nBplus[1] = 1;
  nBplus[2] = 0;
  nBminus[0] = 0;
  nBminus[1] = 1;
  nBminus[2] = 0;
}
}
}

/////////////////////////////// когда я выйду

   nBplus[j] = nB[j] + k;
   nBminus[j] = nB[j] - k;

и

   nBplus[0] = 0;
   nBplus[1] = 1;
   nBplus[2] = 0;
   nBminus[0] = 0;
   nBminus[1] = 1;
   nBminus[2] = 0;

Serial работает отлично

когда я закомментирую, нормально работают только серийные номера matricaBminus и matricaBplus

Пожалуйста, помогите! Это, безусловно, глупое решение!

, 👍2

Обсуждение

Я получаю hello world только в Serial. Я получил переполнение на MCU?, @boki

Хотя это может быть и не причиной вашей проблемы, помещаете ли вы печать матрицы в loop() в критическую секцию (с отключенными прерываниями)? В противном случае прерывание может произойти в середине печати. Пожалуйста, покажите полный пример скетча для прерывающей версии кода., @chrisl

@chrisl Таймер был слишком быстрым! При снижении частоты все работало нормально., @boki

Обычно не рекомендуется использовать последовательный порт внутри прерывания., @Gerben

Даже Serial нельзя использовать в прерывании, если вы рискуете переполнить выходной буфер. Вы не можете записать более 63 символов (в обычные Arduino) из ISR., @DataFiddler


1 ответ


1

Таймер был слишком быстрым! Когда я уменьшил частоту, все заработало нормально.

,

Также помогает увеличение скорости передачи до значения выше 9600., @Gerben

Это может решить вашу проблему, однако это не лучшая практика для того, как вы используете прерывание. Вам следует прочитать [interrupt](http://gammon.com.au/interrupts) Ника Гэммона., @hcheung