2016-08-31 2 views
0

Я работаю над проектом, который собирает данные из Arduino Pro Mini и отправляет его с помощью SPI в малину Pi для хранения.Ненадежный перенос массива SPI от Arduino до Raspberry Pi

Pro Mini будет считывать аналоговый вход и вычислять напряжение (после завершения) и передавать значения Pi при запросе с использованием ISR.

Я использую C/C++ для обеих платформ, чтобы сохранить его равномерным. Ведомый код сбрасывается вместе с использованием Arduino IDE, а основной код основан на примере библиотеки BCI2835 SPI для Pi.

Arduino код предназначен для расчета поплавка значения и предобработать значение с плавающей точкой в ​​массив 4 байт/символы (я стреляю для двоичного, потому что я думаю, что это лучший способ пойти). После запроса Pi каждый байт отправляется и будет перекомпилирован в поплавок.

Вот что я сейчас:

Ведомый

/************************************************************* 
ARDUINO BREAKER READ/SPI PRE-PROC/TRANSMIT CASES 
****************************************************************/ 

/*************************************************************** 
Global Variables 
***************************************************************/ 

byte command = 0; //command from PI 
byte bytes[4]; // 

int sensorVoltage, sensorCurrent; //eventual live reading vars 
float Voltage, Current, RealCurrent, RealVoltage, Power; 

/*************************************************************** 
Set Up 
    -designate arudino as slave 
    -turn on interrupts 
***************************************************************/ 

void setup (void) 
{ 
    //debugging with serial monitor 
    Serial.begin(9600); 

    // Set up arduino as slave 
    pinMode(MOSI, INPUT); 
    pinMode(SCK, INPUT); 
    pinMode(SS, INPUT); 
    pinMode(MISO, OUTPUT); 

    // turn on SPI in slave mode 
    SPCR |= _BV(SPE); 

    // turn on interrupts 
    SPCR |= _BV(SPIE); 

} // end of setup 

/************************************************************* 
Interrupt Service Routine 
************************************************************/ 

// SPI interrupt routine 
ISR (SPI_STC_vect) 
{ 
    delay(500); //for errors 

    // Create union of shared memory space 
    union 
    { 
    float f_var; 
    unsigned char bytes[4]; 
    } u; 

    // Overwrite bytes of union with float variable 
    u.f_var = RealVoltage; 

    // Assign bytes to input array 
    memcpy(bytes, u.bytes, 4); 

    byte c = SPDR; 
    command = c; 

    switch (command) 
    { 
    // null command zeroes register 
    case 0: 

    SPDR = 0; 
    break; 

    // case a - d reserved for voltage 
    case 'a': 
    SPDR = bytes[3]; 
    break; 

    // incoming byte, return byte result 
    case 'b': 

    SPDR = bytes[2]; 
    break; 

    // incoming byte, return byte result  
    case 'c': 

    SPDR = bytes[1]; 
    break; 


    // incoming byte, return byte result  
    case 'd': 

    SPDR = bytes[0]; 
    break; 

/** // case e -h reserved for current 
    case 'e': 

    SPDR = amps.b[0]; 
    break; 

    // incoming byte, return byte result 
    case 'f': 

    SPDR = amps.b[1]; 
    break; 

    // incoming byte, return byte result  
    case 'g': 

    SPDR = amps.b[2]; 
    break; 

    // incoming byte, return byte result  
    case 'h': 

    SPDR = amps.b[3]; 
    break; 

    // case i - l reserved for wattage 
    case 'i': 

    SPDR = watts.b[0]; 
    break; 

    // incoming byte, return byte result 
    case 'j': 

    SPDR = watts.b[1]; 
    break; 

    // incoming byte, return byte result  
    case 'k': 

    SPDR = watts.b[2]; 
    break; 

    // incoming byte, return byte result  
    case 'l': 

    SPDR = watts.b[3]; 
    break;**/ 

    } // end of switch 

} // end of interrupt service routine (ISR) SPI_STC_vect 

/*************************************************************** 
Loop until slave is enabled by Pi. 
****************************************************************/ 
void loop (void) 
{ 
/************************************************************* 
Read and Calculate 
****************************************************************/ 

    /** 
    sensorVoltage = analogRead(A2); 
    sensorCurrent = analogRead(A3); 
    Voltage = sensorVoltage*(5.0/1023.0); 
    Current = sensorCurrent*(5.0/1023.0); 
    RealCurrent = Current/0.204545; 
    RealVoltage = (Voltage/0.022005); 
    Power = RealVoltage*RealCurrent; 
**/ 
    RealVoltage = 1.234; 
/************************************************************* 
Loop Check for SS activation 
****************************************************************/ 

    // if SPI not active, clear current command, else preproc floats and pass to SPI 
    if (digitalRead (SS) == HIGH){ 
    command = 0; 
    } 
/************************************************************* 
Debug with serial monitor 
****************************************************************/ 
/* 
    Serial.print("Byte 3: "); 
    Serial.println(bytes[3],BIN); 
    delay(500); 
    Serial.print("Byte 2: "); 
    Serial.println(bytes[2],BIN); 
    delay(500); 
    Serial.print("Byte 1: "); 
    Serial.println(bytes[1],BIN); 
    delay(500); 
    Serial.print("Byte 0: "); 
    Serial.println(bytes[0],BIN); 
    delay(1000); 
    Serial.println();*/ 
} 

Мастер

#include <bcm2835.h> 
#include <stdio.h> 


void setup() 
{ 
    bcm2835_spi_begin(); 
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST);  // The default 
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);     // The default 
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default 
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);  // the default 
} 

char getByte(const char command){ 

    char read_data = bcm2835_spi_transfer(command); 
    delay(100); 
    return read_data; 
} 

int main(int argc, char **argv) 
{ 
//If you call this, it will not actually access the GPIO 
//Use for testing 
//bcm2835_set_debug(1); 

    if (!bcm2835_init()) 
     return 1; 
    setup(); 

//Start communication  
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);// Enable 0 

    //voltage 1-4 
    char read_data = getByte('a'); 
    printf("byte is %02d\n", read_data); 

    read_data = getByte('b'); 
    printf("byte is %02d\n", read_data); 

    read_data = getByte('c'); 
    printf("byte is %02d\n", read_data); 

    read_data = getByte('d'); 
    printf("byte is %02d\n", read_data);  

    /** voltage = volts.f; 
    printf("%.6f", voltage); 
    printf("\n"); 
    **/ 
    delay(1000); 

    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, HIGH); 
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);// Disable 0 
    bcm2835_spi_end(); 
    bcm2835_close(); 

    return 0; 
} 

Я использую фиксированное значение для отладки кода. Иногда вывод SPI на Pi является точным, но в остальном он меняет и выводит частично точные и/или случайные байты.

Проблема, с которой я не мог справиться, - это стабильность на стороне Pi, поэтому я ищу помощь в оценке того, что мой код вызывает неточности или если это мое оборудование.

ответ

0

Полагаю, что это вопрос синхронизации между отправителем и получателем. Попробуйте просмотреть биты данных, которые вы получаете, и посмотреть, смещены ли они вперед или назад. Это может указывать на то, что pi ждет слишком много времени, чтобы начать получать или не дожидаться достаточно долго для всех данных. Я думаю, что проблемы, вероятно, вокруг задержки:

delay(500); //for errors 

на Arduino и

delay(1000); 

на ресивере. Почему вы их используете? 500 мс - это долгое время, чтобы держать pi ожидающим ответа на данные SPI.

Просто примечание: теперь есть драйвер ядра SPI (spidev) для pi - это гораздо более стандартный подход к стандартизации, и это потенциально более надежный метод.

Там хороший пример этого на пи GitHub сайте малиновым: https://github.com/raspberrypi/linux/blob/rpi-4.4.y/Documentation/spi/spidev_test.c

+0

спасибо за ответ js441. Я переключился на использование python с spiDev, потому что он намного более прямолинейный. Позвольте мне спросить вас, вы думаете, что python над C одинаково приемлемо в отношении отраслевого стандарта? – giri

+0

@giri Это сложный вопрос. Оба используются в промышленности, это скорее случай того, что работает для вас. Если вы можете сделать допустимое рабочее решение на одном языке проще другого, то это язык для вас. – js441

Смежные вопросы