Arduino Pro Mini에서 데이터를 수집하고이를 SPI를 사용하여 저장 용 라즈베리 파이에 보내는 프로젝트를 진행 중입니다.Arduino에서 Raspberry Pi 로의 신뢰할 수없는 SPI 바이트 배열 전송
Pro Mini는 아날로그 입력을 읽고 전압을 계산하고 (일단 완료되면) ISR을 사용하여 프롬프트 될 때 Pi에 값을 전달합니다.
두 플랫폼 모두 C/C++을 사용하여 일관되게 유지합니다. 슬레이브 코드는 Arduino IDE를 사용하여 함께 자르고 마스터 코드는 Pi의 BCM2835 SPI 라이브러리 예제를 기반으로합니다.
Arduino 코드는 float 값을 계산하고 float 값을 4 바이트/문자 배열로 사전 처리하기위한 것입니다 (이진 코드로 촬영하는 것이 최선의 방법이라고 생각하기 때문에). Pi에 의해 프롬프트가 표시되면 각 바이트가 보내지고 float로 다시 컴파일됩니다. 여기
내가 지금 무엇을 가지고 :
슬레이브
/*************************************************************
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;
}
내가 코드를 디버깅하는 고정 된 값을 사용하고 있습니다. 때로는 Pi의 SPI 출력이 정확하지만 그렇지 않으면 부분적으로 정확한 바이트 및/또는 임의의 바이트가 변경되어 출력됩니다.
내가 해결할 수없는 문제는 Pi 측면에서의 안정성입니다. 따라서 코드가 부정확하거나 하드웨어인지 여부를 평가하는 데 도움이 필요합니다.
감사 :
라즈베리 파이 GitHub의 사이트에서 이것의 좋은 예는있다. 나는 훨씬 더 솔직하기 때문에 spiDev로 파이썬을 사용하기로 바꿨다. 내가 C로 파이썬이 산업 표준에 대해 똑같이 받아 들일 수 있다고 생각하니? – giri
@giri 대답하기 어려운 질문입니다. 두 가지 모두 업계에서 사용되고 있으며, 이는 여러분에게 맞는 것보다 더 중요합니다. 하나의 언어로 유효한 작업 솔루션을 다른 언어보다 쉽게 만들 수 있다면, 그것은 당신을위한 언어입니다. – js441