Raspberry Pi сайт

Русский сайт по микрокомпьютеру




Вход








Регистрация | Забыли пароль?

Поиск



По всему сайту
По тэгам
По тэгам и заголовкам

Рубрики

  • Проекты и статьи
  • Модели
  • Новости
  • Мысли
  • Рейтинг

  • 1. Хакеры могут атаковать устройства Apple через Bluetooth и Raspberry Pi
  • 2. Новая операционная система для государства Российского!
  • 3. Настройка приёма цифрового телевещания dvb-t2 на компьютере Raspberry PI
  • 4. Собираем ваш новый роутер с тотальной защитой в интернете на Raspberry Pi.
  • 5. Используем старую кассету в качестве корпуса под Raspberry Pi
  • Облако тэгов

    windows, raspberry pi 3, raspbian, умный дом, gpio, ubuntu, osmc, windows 10, linux, игры, python, установка ос, raspberry pi 2, raspberry pi zero, raspberry pi zero w, слежение, самолёт, http, diy, 1c-битрикс, нейросеть, сеть, кластер, бесперебойник, акустика

    Боковое меню

  • RSS-канал
  • Карта сайта
  • Обратная связь
  • Пользователи
  • Статистика посещений

  • Обмен данными по SPI между Raspberry Pi и Arduino

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



    Первое, о чем пришлось позаботиться - это согласование логических уровней двух устройств. Arduino работает на 5V, Raspberry на 3.3V. Для этого используется устройство LogicLevelConverter на 4 канала.



    Порты для подключения на устройствах строго определены
    Arduino Uno(Nano):

    13 - SCK - тактовые импульсы для работы протокола SPI

    12 - MISO (Master Input Slave Output) - передача данных от ведомого устройства (Arduino) к ведущему (Raspberry)

    11 - MOSI (Master Output Slave Input) - передача данных от ведущего устройства (Raspberry) к ведомому (Arduino)

    10 - CS или SS (Chip Select или Slave Select) - выбор устройства для работы. Raspberry может работать с 2 устройствами SPI сразу, и этот порт используется для указания, с каким идет обмен данными



    Arduino Mega:

    52 - SCK - тактовые импульсы для работы протокола SPI

    50 - MISO (Master Input Slave Output) - передача данных от ведомого устройства (Arduino) к ведущему (Raspberry)

    51 - MOSI (Master Output Slave Input) - передача данных от ведущего устройства (Raspberry) к ведомому (Arduino)

    53 - CS или SS (Chip Select или Slave Select) - выбор устройства для работы. Raspberry может работать с 2 устройствами SPI сразу, и этот порт используется для указания, с каким идет обмен данными



    Raspberry PI:

    23 - SCK - тактовые импульсы для работы протокола SPI

    21 - MISO (Master Input Slave Output) - передача данных от ведомого устройства (Arduino) к ведущему (Raspberry)

    19 - MOSI (Master Output Slave Input) - передача данных от ведущего устройства (Raspberry) к ведомому (Arduino)

    24 - CS или SS (Chip Select или Slave Select) - выбор устройства для работы. Raspberry может работать с 2 устройствами SPI сразу, и этот порт используется для указания, с каким идет обмен данными



    Также к Logic level converter подключается рабочее напряжение каждого устройства и земля

    Теперь к коду:

    На Raspberry Pi необходимо включить SPI:

    sudo raspi-config

    Interfacing options - SPI



    Включаем SPI



    Далее устанавливаем библиотеку spidev

    pip3 install spidev

    И используем заготовку кода для передачи данных


    import spidev
    import time
    from camer2 import getCherry

    def list_int_to_bytes(input_list):
    # Split list int values to list ready for transfer by SPI
    # every value from -32768 to 32767
    # will be replaced two values from -255 to 255
    # Original values must be collected by Arduino after transmission
    output_list = []
    for int_data in input_list:
    output_list.append(int_data >> 8)
    output_list.append(int_data & 255)
    return output_list


    def spi_send(txData):
    # Send and recieve 40 bytes
    N = 40
    spi = spidev.SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    txData = list_int_to_bytes(txData)
    txData = txData+[0]*(N-len(txData))
    rxData = []
    _ = spi.xfer2([240]) # 240 - b11110000 - start byte
    for i in range(40):
    rxData.append(spi.xfer2([txData[i]])[0])
    spi.close()
    return rxData

    recieved_data = spi_send([1,2,3,4,5,6])


    Функция spi_send принимает на вход список до 20 значений от -32768 до 32767, которые разбиваются в 40 байт и передаются в Arduino. В ответ функция возвращает 40 байт, полученных из Arduino

    Код для Arduino:


    #include

    #define DATA_SIZE 40
    byte data[DATA_SIZE];//массив, в которые получаем исходные данные
    int int_data[DATA_SIZE / 2];//массив в котором будут значения, полученные от Raspberry
    byte sendData[DATA_SIZE];//массив, значения которого будут переданы на Raspberry
    volatile byte counter = 0;
    volatile byte in_byte = 0;
    volatile byte spiTranferEnd = 0;
    volatile byte spiTranferStarted = 0;

    void fillSendData() {//заполняем массив числами, чтобы проверить корректность передачи
    for (byte i = 1; i < 40; i++) {
    sendData[i] = i;
    }
    }

    void setup() {
    Serial.begin(9600);
    pinMode(MISO, OUTPUT);
    SPCR |= _BV(SPE);//переводим SPI в режим Slave
    SPI.attachInterrupt();//включаем прерывания по SPI
    fillSendData();
    }

    ISR (SPI_STC_vect)//обработка прерывания, получение и передача данных
    {
    in_byte = SPDR;
    if (in_byte == 240 and !spiTranferStarted) {
    spiTranferStarted = 1;
    counter = 0;
    SPDR = sendData[counter];
    }
    if (spiTranferStarted and counter > 0) {
    data[counter - 1] = in_byte;
    SPDR = sendData[counter];
    }
    counter++;

    if (counter == DATA_SIZE) {
    SPDR = sendData[counter - 1];
    counter = 0;
    spiTranferStarted = 0;
    spiTranferEnd = 1;
    }
    }

    void joinRecievedBytes() {//функция, которая собирает 40 байт в 20 значений, которые передавались
    for (int i = 0; i < DATA_SIZE; i += 2) {
    int_data[i / 2] = data[i] << 8 | data[i + 1];
    }
    spiTranferEnd = 0;
    }

    void printSpiData() {//вывод в монитор порта полученных значений
    for (int i = 0; i < DATA_SIZE / 2; i++) {
    Serial.print(int_data[i]);
    Serial.print(" ");
    }
    Serial.println();
    }

    void loop () {
    if (spiTranferEnd) {//если эта переменная стала равна true, значит мы получили все 40 байт
    joinRecievedBytes();//собираем из 40 байт 20 значений

    // Тут можно написать действия с массивом int_data
    // if (int_data[0]==1) {
    // что-то делаем
    //}
    printSpiData();//выводим данные в монитор порта. Только для тестов!
    //ПОТОМ ОТКЛЮЧИТЬ, Т.К. ЗАМЕДЛЯЕТ РАБОТУ ПРОГРАММЫ
    }
    }


    Такие дела! Успехов!
    Источник

    08.01.2023 в 00:40, Просмотров: 503
    Опубликовал: ak167

    spi

    ID: 99