Срабатывание ложного прерывания Arduino Mega
Я использую Arduino mega с 4 прерываниями, чтобы найти скорость вращения 4 двигателей . Для этого я использовал INT2, INT3, INT4, INT5, и код для этого приведен ниже
struct Pulse {
uint32_t last_toggle;
uint32_t width;
bool stateHigh;
uint32_t get_width() {
noInterrupts();
uint32_t width_copy = width;
interrupts();
return width_copy;
}
};
Pulse ch1, ch2, ch3, ch4;
void pin_initialization() {
// Four engine configuration
pinMode(19, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
}
volatile uint32_t ovfCount = 0;
ISR(TIMER3_OVF_vect) {
ovfCount++;
}
void timer3_initialization() {
TCCR3A = 0x00;
TCNT3 = 0x1FF; // из таблицы данных
TIFR3 = _BV(TOV3);
TIMSK3 = _BV(TOIE3); // включить переполнение
TCCR3B = B00000011; // 64 предварительная настройка
}
void pulseWidthCalculator(Pulse *channel){
unsigned char sreg;
sreg = SREG;
cli();
uint16_t tcnt3 = TCNT3;
SREG = sreg;
uint32_t ovf_count = ovfCount;
if (bit_is_set(TIFR3, TOV3) && tcnt3 < 32768) {
ovf_count++;
}
uint32_t time = ovf_count << 16 | tcnt3;
if (!channel->stateHigh) { // первый максимум
channel->stateHigh = true;
} else if ( channel->stateHigh) { // вторая высота
channel->width = time - channel->last_toggle;
channel->stateHigh = false;
}
channel->last_toggle = time;
}
ISR(INT2_vect) {
pulseWidthCalculator(&ch1);
}
ISR(INT3_vect) {
pulseWidthCalculator(&ch2);
}
ISR(INT4_vect) {
pulseWidthCalculator(&ch3);
}
ISR(INT5_vect) {
pulseWidthCalculator(&ch4);
}
void externalInterrputInitialization() {
EIFR = _BV(INTF2) | _BV(INTF3) | _BV(INTF4) | _BV(INTF5);
EICRA = 0; EICRB = 0;
EICRA = B10100000;
EICRB = B00001010;
EIMSK = B00111100;
}
void setup() {
Serial.begin(115200);
pin_initialization();
delayMicroseconds(10);
externalInterrputInitialization();
delayMicroseconds(10);
timer3_initialization();
delayMicroseconds(10);
}
void loop() {
String a = String(15e6/ch1.get_width());
a += " ";
a += String(15e6/ch2.get_width());
a += " ";
a += String(15e6/ch3.get_width());
a += " ";
a += String(15e6/ch4.get_width());
Serial.println(a);
}
Проблема , с которой я сталкиваюсь, заключается в том, что всякий раз, когда я даю сигнал INT2, INT3 также срабатывает, то же самое с INT4, INT5 также срабатывает без сигнала .
Чего мне здесь не хватает, ?
Должен ли я сделать свои каналы ch1, ch2 , ch3, ch4 изменчивыми или нет? Нравится
летучий импульс сн1, сн2, сн3, сн4
- Все, что не так с
OUTPUT_PULLUP
@Lawliet, 👍3
Обсуждение1 ответ
Лучший ответ:
У вас есть правильная идея, чтобы атомарно получить копию данных, обновляемых прерыванием:
unsigned char sreg;
sreg = SREG;
cli();
uint16_t tcnt3 = TCNT3;
SREG = sreg;
uint32_t ovf_count = ovfCount;
...но последние две строки следует поменять местами, чтобы сохранить операцию копирования в разделе без прерываний:
unsigned char sreg;
sreg = SREG; // Сохранить состояние прерывания.
cli(); // Отключить прерывания.
uint16_t tcnt3 = TCNT3; // Атомарные операции.
uint32_t ovf_count = количество овалов;
SREG = sreg; // Восстановить состояние прерывания.
Хотя я заметил, что вы вызываете этот код из служебной процедуры прерывания, поэтому прерывания уже должны быть отключены, если вы не собираетесь использовать вложенные прерывания.
Ложное прерывание может быть вызвано перекрестными помехами между номерами INT2 и INT3. Вы можете подтвердить это с помощью осциллографа. Держите сигнальные провода отдельно, чтобы избежать перекрестных помех.
Вы также можете попробовать более сильные внешние подтягивания, такие как 10 К или 1 К. Внутренние подтягивания Arduino слабее примерно на 20-50 Ком.
Спасибо Тиму , из осциллографа я понял, что это проблема INPUT_PULLUP, я буду выполнять внешние подтягивания., @Lawliet
используется резистор 1K и его работа. Есть ли какие-либо проблемы с использованием внешнего подтягивания вместе с INPUT_PULLUP.?, @Lawliet
- Считать данные датчика повторно через указанное время?
- Arduino mega PinChangeInterrupt с 16 битным таймером
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Сбой Arduino во время последовательной печати без очевидной причины
- Будет ли адаптер питания 12В постоянного тока, 1А подавать слишком большую мощность и повредит Arduino Mega 2560?
- Возникла проблема с переобъявлением символа другого типа
- Как запрограммировать Robotdyn Mega 2560 PRO MINI?
- Отключите автоматический сброс Mega 2560 на последовательном мониторе, открытом с помощью резистора 60 Ом.
изменчивость
необходима для того, чтобы убедиться, что вносимые изменения заметны между контекстами ISR и не-ISR. Тем не менее, не похоже, что это полностью объясняет то, что вы видите. Вы должны сделать их "изменчивыми" и сообщить нам, каково поведение в этом случае., @timemageпочему вы считаете, что это проблема программирования?, @jsotola
@timemage, переход на volatile не помогает., @Lawliet
В этом случае, вероятно, было бы хорошей идеей просто сделать переменные "изменчивыми" в вашем коде и удалить ту часть, где спрашивают об этом, чтобы отвлечь внимание от основного вопроса., @timemage
Это не имеет никакого отношения к вашему вопросу как таковому, но ваш "последовательный" поток объединяет вещи для вас как нечто само собой разумеющееся. Все ваши назначения и добавления к "Строке a" являются неэффективной и подверженной ошибкам альтернативой серии вызовов "печать" /`println"., @timemage