воскресенье, 16 февраля 2014 г.

Arduino+Arduino

Попробовал связать 2 Arduino по SPI протоколу. Я не нашел в сети официальной информации о максимальной длине кабеля, по которому можно передавать сигналы по SPI протоколу. Если у вас есть ссылочка на официальную документацию, буду благодарен. А у меня пока есть только мнения на форумах. В основном считают, что по SPI можно передавать информацию на совсем короткие расстояния. Но тут человек делится опытом, мол на 300 метров сигнал идёт, и можно использовать большую длину, если делить частоту.

Поэтому я решил проверить, как будет работать связь между платами по длинному кабелю.
И вот что получилось.

Сперва соединил 2 платы короткими проводками, чтобы отладить взаимодействие устройств.
С кодом как и раньше не заморачивался и сделал на основе этой статьи.
Код для Master
/*
MASTER При нажатии на кнопку зажигаем свой светодиод
  и отправляем 1 на ведомый контроллер
*/ #include <SPI.h> #define SS_PIN 10 void setup() { // LED pinMode(3, OUTPUT);
  // Button
pinMode(5, INPUT); pinMode(SS_PIN, OUTPUT); SPI.begin(); } void loop() { if (digitalRead(5)) {
    // Set the LED on
digitalWrite(3, HIGH);
    // Send 1 to Slave
digitalWrite(SS_PIN, LOW); SPI.transfer(1); digitalWrite(SS_PIN, HIGH); } else {
    // Set the LED off
digitalWrite(3, LOW);
    // Send 0 to Slave
digitalWrite(SS_PIN, LOW); SPI.transfer(0); digitalWrite(SS_PIN, HIGH); }
}

Код для Slave
/*
  SLAVE
  Принимаем сигнал по SPI
  и зажигаем светодиод, если сигнал = 1
 */

// Определяем пины SPI
#define MOSI_PIN 11 
#define MISO_PIN 12 
#define SCK_PIN  13
#define SS_PIN 10

byte recievedByte;

void setup() {
  // Обнуляем регистр управления SPI
  SPCR = B00000000;
  // Разрешаем работу SPI
  SPCR = (1<<SPE);

  // LED
  pinMode(3, OUTPUT);

  // Определяем пины для работы с SPI
  pinMode(MOSI_PIN, INPUT);
  pinMode(MISO_PIN, OUTPUT);
  pinMode(SCK_PIN, INPUT);
  pinMode(SS_PIN, INPUT);
}

void loop() {
  while (digitalRead(SS_PIN)==LOW) {
    // Принимаем байт
    recievedByte = spi_receive();
    if (recievedByte) {
      digitalWrite(3, HIGH);
    }
    else {
      digitalWrite(3, LOW);
    }
  }
}

// Приём байта
byte spi_receive()
{
  // Пока не выставлен флаг окончания передачи, принимаем биты
  while (!(SPSR & (1<<SPIF))){};
  // Возвращаем содержимое регистра данных SPI
  return SPDR;                    
}

Заработало с первого раза и без проблем. В Arduino просто напрямую соединил выводы 10 с 10, 11 с 11, 12 с 12 и 13 с 13 короткими проводками. Это видно на первом видео.

А потом решил опробовать реальный кабель. Взял обычный не экранированный Ethernet кабель длиной чуть больше 20 метров и точно так же соединил контакты. Не работает!!! Вернее то работает, то не работает, никакой стабильности. Сперва думал, что дело в контактах, так как при шевелении кабеля что-то улучшалось. А потом воткнул контакты кабеля в макетную плату, это видно на видео ниже, и начал замыкать контакты параллельно короткими кабелями.

В итоге оказалось вот что. Оказалось, что я наугад посадил одну витую пару на MOSI (11), MISO (12), а другую витую пару на SCK(13), SS (10) и это, как оказалось, не хорошо. Изменил порядок соединения. Одну витую пару посадил на SS(10), MOSI (11), а другую - на MISO(12), SCK (13). И всё заработало отлично! В спецификации к SPI не нашел информации о соединении по витой паре. Может быть плохо искал. Если есть ссылочка, буду благодарен.

Вот, длина кабеля чуть больше 20 метров:

UPD1: Пара ссылок
Extending the SPI bus for long-distance communication
Architecture, Design and Implementation of Embedded System for Real-Time Applications

UPD2: Информация от инструктора курса

See page 1355 of tm4c123gh6pm.pdf. The TM4C123 timing is rated for a maximum of 50 pF load. As the capacitance goes up, the signals rise and fall too slowly.


The simplest solution is RS232 or RS422 added to the UART in chapter 11.

CAN is a nice network for 20m and built into this processor.http://users.ece.utexas.edu/~valvano/EE345M/view23_CAN.pdf

1 комментарий:

  1. Вы пытаетесь модифицировать существующее зарядное устройство или разработать новое?

    Какой тип батареи вы заряжаете? Я предполагаю, что свинцово-кислотный, исходя из вашего упоминания о 14 вольтах.

    И при каком токе зарядки? Отчасти это зависит от нормальной емкости элемента.

    Зарядные устройства варьируются от быстрых и грязных, используемых для случайного использования в чрезвычайных ситуациях, до предназначенных для максимального увеличения срока службы батареи путем регулировки скорости заряда в зависимости от стадии зарядки, в некоторых случаях регулируя пороги в зависимости от температуры окружающей среды.

    А также является ли это зарядное устройство автономным или встроенным в оборудование. (В качестве примера последнего варианта можно привести оборудование, которое обычно работает от сети, но содержит и поддерживает зарядку батареи для резервного копирования во время перебоев в подаче электроэнергии. Если вы хотите заменить реле в существующем зарядном устройстве, вам нужно убедиться, что вы понимаете, для чего используется реле. Возможные варианты (в зависимости от ответов на вышеприведенные вопросы) включают автоотключение, переключение между струйной и полной зарядкой, а также переключение нагрузки с питания от сети на резервное питание от батареи. Большинство автономных зарядных устройств, которые я видел, не имеют реле.

    Для примера проблем оптимальной зарядки свинцово-кислотных батарей посмотрите на микросхему BQ24450 и на то, как она их решает: https://www.ichome.com/goods_details/stmicroelectronics-stm32f429bit6.

    ОтветитьУдалить