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
Пожалуйста, помогите! Это, безусловно, глупое решение!
@boki, 👍2
Обсуждение1 ответ
Таймер был слишком быстрым! Когда я уменьшил частоту, все заработало нормально.
Также помогает увеличение скорости передачи до значения выше 9600., @Gerben
Это может решить вашу проблему, однако это не лучшая практика для того, как вы используете прерывание. Вам следует прочитать [interrupt](http://gammon.com.au/interrupts) Ника Гэммона., @hcheung
- Попытка создать функцию задержки при выполнении других функций, используя библиотеки Timer.h. Ардуино уно
- Делать несколько вещей одновременно с функциями, объектами или прерываниями?
- Использование millis() и micros() внутри процедуры прерывания
- Как сделать очень долгую функцию delay(), несколько часов
- Разница между «time_t» и «DateTime»
- Получение BPM из данного кода
- Как считать время в секундах?
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
Я получаю hello world только в Serial. Я получил переполнение на MCU?, @boki
Хотя это может быть и не причиной вашей проблемы, помещаете ли вы печать матрицы в
loop()
в критическую секцию (с отключенными прерываниями)? В противном случае прерывание может произойти в середине печати. Пожалуйста, покажите полный пример скетча для прерывающей версии кода., @chrisl@chrisl Таймер был слишком быстрым! При снижении частоты все работало нормально., @boki
Обычно не рекомендуется использовать последовательный порт внутри прерывания., @Gerben
Даже Serial нельзя использовать в прерывании, если вы рискуете переполнить выходной буфер. Вы не можете записать более 63 символов (в обычные Arduino) из ISR., @DataFiddler