Я собираюсь прочитать изменение ввода кнопки, используя 2 отдельных Arduino, подключенных через шину CAN (MP2515). Передатчик подключается к кнопке с внутренним подтягивающим резистором, этот контакт будет действовать как внешнее прерывание. Моя ссылка исходит от здесь. Не присваивая какое-либо значение фрейму данных (canMsg1 и canMsg2 в приведенном ниже коде), достаточно ли этого для получателя, чтобы понять состояние входного контакта?
Исходный код, использующий digitalRead(pin)
для чтения и последующей записи состояния кнопки одним Arduino.
передатчик CAN массажа
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
int incPin(2);
int decPin(3);
unsigned long current_time = 0;
unsigned long previous_time = 0;
void setup() {
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
canMsg1.can_id = 0xAA;
canMsg1.can_dlc = 1;
canMsg2.can_id = 0xBB
canMsg2.can_dlc = 1;
pinMode(incPin, INPUT_PULLUP);
pinMode(decnPin, INPUT_PULLUP);
attachInterrupt(incpPin, inc, FALLING);
attachInterrupt(decPin, dec, FALLING);
}
void loop() {}
void inc() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.sendMessage(&canMsg1);
}
previous_time = current_time;
}
void dec() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.sendMessage(&canMsg2);
}
previous_time = current_time;
}
приемник/считыватель CAN-сообщений
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
int pos = 0;
int up;
int down;
void setup() {
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
void loop() {
if (mcp2515.readMessage(&canMsg1) == MCP2515::ERROR_OK) { //read CAN increment button message
if (canMsg1.can_id==0xAA) {
up = canMsg1.data[0];
if (up == LOW) {
pos++;
} else {}
}
}
if (mcp2515.readMessage(&canMsg2) == MCP2515::ERROR_OK) { //read CAN decrement button message
if (canMsg2.can_id==0xBB) {
down = canMsg2.data[0];
if (down == LOW) {
pos--;
} else {}
}
}
}
Вместо настройки аппаратного обеспечения, могу ли я просто вместо этого вызвать другую функцию из прерывания для устранения дребезга и отправить canMsg? Я предполагаю, что ISR должны быть как можно короче (?)
Вы получите прерывание за отскок, что является проблемой. Вот пример того, как это можно сделать: stackoverflow.com/a/32647699/584518 . Но это излишне сложно и, следовательно, плохой дизайн. Профессиональные разработки используют периодические таймеры, которые считывают GPIO, например: stackoverflow.com/a/54900591/584518. Опционально с цифровыми фильтрами (медианные фильтры и т.д.).
Вы правы, ваши события CAN не требуют никаких данных. Но тогда почему вы устанавливаете can_dlc в 1? Нет данных 0 байт.
Вы можете попробовать это:
Избавляться от:
struct can_frame canMsg1; // these only hog global memory for no practical use.
struct can_frame canMsg2;
Измените свои процедуры прерывания на:
void inc() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.beginPacket(0xAA);
mcp2515.endPacket();
}
previous_time = current_time;
}
void dec() {
current_time = millis();
if (current_time - previous_time > 200) { //debouncing for 0.2s
mcp2515.beginPacket(0xBB);
mcp2515.endPacket();
}
previous_time = current_time;
}
Я не мог понять, что такое canMsg7 и canMsg8. И почему вам нужно несколько структур сообщений в глобальной памяти для получения одного сообщения CAN за раз ... Я действительно не думаю, что это необходимо. Поскольку в ваших пакетах нет данных, получение также упрощается:
int loop() {
if (mcp2515.parsePacket() != 0) { // != 0 => we have fully received a packet.
switch (mcp2515.packetId()) {
case 0xAA:
// inc switch was pressed
// ...
break;
case 0xBB:
// dec switch was pressed
// ...
break;
}
}
}
Спасибо за указание на canMsg7 и canMsg8, это должно быть canMsg1/2, мой плохой лол. Кроме того, я немного потерялся здесь, особенно beginPacket
и endPacked
. Не могли бы вы обратиться к какой-нибудь ссылке об этом?
Документация по API находится здесь: github.com/sandeepmistry/arduino-CAN/blob/master/API.md. Это API, который я использовал. Он прост в использовании: beginPacket(id); write();
по мере необходимости, затем endPacket();
отправляет все это.
Что касается части кнопки, это не рекомендуется. Устранение дребезга кнопки с помощью прерывания является более сложным, чем обычное устранение дребезга (если у вас нет внешних аппаратных фильтров).