Интерфейс Arduino SPI читает случайные значения? (Попытка использовать CAN Bus Shield) - PullRequest
0 голосов
/ 07 января 2020

У меня странная проблема при настройке Arduino CAN Bus Communication.

Ниже приведено описание, это видео показывает результат: https://www.youtube.com/watch?v=NnMyC23Fe9s&feature=youtu.be

(Примечание: Этот эффект встречается на каждой плате, которую я пробовал)

Аппаратное обеспечение:

  • Различные платы Arduino или Arduino-Equal (в настоящее время AZ-Delivery UNO, также пробовал с Arduino Mega и Arduino UNO.
  • Экран шины CAN (V1.2) от SeedStudio (см. https://github.com/Seeed-Studio/CAN_BUS_Shield)

Используемое программное обеспечение: https://github.com/Seeed-Studio/CAN_BUS_Shield/blob/master/examples/send/send.ino

Я начал с полной настройки с двумя моими Arduinos (не Mega, он не совместим) и двумя шинами CAN Bus, и мне было интересно, что инициализация не удалась и чем неожиданно это удалось. припаял контакты, так что я переделал это, но это не улучшилось.

После многих испытаний я получил результат, который вы видите на видео: мне даже не нужен CAN Bus Shield для инициализировать экран шины CAN O_o. Если я коснусь интерфейса SPI, он распознает меня как щит шины CAN.

Проходя через библиотеку шины CAN Я проверил функцию CAN.begin. Он использует контакты ISP (эти 6 контактов в 2 рядах) для:

  • Запись значений в адрес через SPI
  • Считывание двух значений из другого адреса через SPI

Код для чтения через SPI (у всех из библиотеки нет собственного кода!)

uint8_t MCP2515Class::readRegister(uint8_t address)
{
  uint8_t value;

  SPI.beginTransaction(_spiSettings);
  digitalWrite(_csPin, LOW);
  SPI.transfer(0x03);
  SPI.transfer(address);
  value = SPI.transfer(0x00);
  digitalWrite(_csPin, HIGH);
  SPI.endTransaction();

  return value;
}

И функция CAN.begin

int MCP2515Class::begin(long baudRate)
{
  CANControllerClass::begin(baudRate);

  pinMode(_csPin, OUTPUT);

  // start SPI
  SPI.begin();

  reset();

  writeRegister(REG_CANCTRL, 0x80);
  if (readRegister(REG_CANCTRL) != 0x80) {
    return 0;
  }

  const struct {
    long clockFrequency;
    long baudRate;
    uint8_t cnf[3];
  } CNF_MAPPER[] = {
    {  (long)8E6, (long)1000E3, { 0x00, 0x80, 0x00 } },
    {  (long)8E6,  (long)500E3, { 0x00, 0x90, 0x02 } },
    {  (long)8E6,  (long)250E3, { 0x00, 0xb1, 0x05 } },
    {  (long)8E6,  (long)200E3, { 0x00, 0xb4, 0x06 } },
    {  (long)8E6,  (long)125E3, { 0x01, 0xb1, 0x05 } },
    {  (long)8E6,  (long)100E3, { 0x01, 0xb4, 0x06 } },
    {  (long)8E6,   (long)80E3, { 0x01, 0xbf, 0x07 } },
    {  (long)8E6,   (long)50E3, { 0x03, 0xb4, 0x06 } },
    {  (long)8E6,   (long)40E3, { 0x03, 0xbf, 0x07 } },
    {  (long)8E6,   (long)20E3, { 0x07, 0xbf, 0x07 } },
    {  (long)8E6,   (long)10E3, { 0x0f, 0xbf, 0x07 } },
    {  (long)8E6,    (long)5E3, { 0x1f, 0xbf, 0x07 } },

    { (long)16E6, (long)1000E3, { 0x00, 0xd0, 0x82 } },
    { (long)16E6,  (long)500E3, { 0x00, 0xf0, 0x86 } },
    { (long)16E6,  (long)250E3, { 0x41, 0xf1, 0x85 } },
    { (long)16E6,  (long)200E3, { 0x01, 0xfa, 0x87 } },
    { (long)16E6,  (long)125E3, { 0x03, 0xf0, 0x86 } },
    { (long)16E6,  (long)100E3, { 0x03, 0xfa, 0x87 } },
    { (long)16E6,   (long)80E3, { 0x03, 0xff, 0x87 } },
    { (long)16E6,   (long)50E3, { 0x07, 0xfa, 0x87 } },
    { (long)16E6,   (long)40E3, { 0x07, 0xff, 0x87 } },
    { (long)16E6,   (long)20E3, { 0x0f, 0xff, 0x87 } },
    { (long)16E6,   (long)10E3, { 0x1f, 0xff, 0x87 } },
    { (long)16E6,    (long)5E3, { 0x3f, 0xff, 0x87 } },
  };

  const uint8_t* cnf = NULL;

  for (unsigned int i = 0; i < (sizeof(CNF_MAPPER) / sizeof(CNF_MAPPER[0])); i++) {
    if (CNF_MAPPER[i].clockFrequency == _clockFrequency && CNF_MAPPER[i].baudRate == baudRate) {
      cnf = CNF_MAPPER[i].cnf;
      break;
    }
  }

  if (cnf == NULL) {
    return 0;
  }

  writeRegister(REG_CNF1, cnf[0]);
  writeRegister(REG_CNF2, cnf[1]);
  writeRegister(REG_CNF3, cnf[2]);

  writeRegister(REG_CANINTE, FLAG_RXnIE(1) | FLAG_RXnIE(0));
  writeRegister(REG_BFPCTRL, 0x00);
  writeRegister(REG_TXRTSCTRL, 0x00);
  writeRegister(REG_RXBnCTRL(0), FLAG_RXM1 | FLAG_RXM0);
  writeRegister(REG_RXBnCTRL(1), FLAG_RXM1 | FLAG_RXM0);

  writeRegister(REG_CANCTRL, 0x00);
  if (readRegister(REG_CANCTRL) != 0x00) {
    return 0;
  }

  return 1;
}

2 вопроса:

  1. Как это вообще возможно, система должна различать чтение пропппера и простую ошибку, не так ли?
  2. Что я могу сделать, чтобы запустить эту вещь?

1 Ответ

0 голосов
/ 07 января 2020

Я подозреваю, что демонстрационная программа щита не работает, потому что вы не подключили экран к автобусу автомобиля.

Просмотр схемы c экрана на вкладке Документы на странице Seeedstudio на экране (https://www.seeedstudio.com/CAN-BUS-Shield-V2.html) это выглядит так, как будто экран является адаптером, без каких-либо аппаратных средств, чтобы сказать что-либо arduino. Я полагаю, что для работы его необходимо подключить к машине.

Как вы продемонстрировали, программное обнаружение шины шины не является надежным тестом для подключения щита к машине.

На вкладке «Обучение» для щита есть ссылка на демонстрацию. Хотя демонстрационное видео не на английском языке Engli sh, примерно на https://youtu.be/Y-1AFyOP-tk?t=565 видно, что плата подключена к автомобилю.

Желаем удачи в вашем проекте!

...