Beaglebone is getting very popular day by day. With this cheap single board computer you can create such
amazing things. Probably this things need communicate other things to progress something. In the video
I just simply show the required diagrams and connections. You will learn how to communicate BBB and Arduino via SPI. Therefore, I do not write much about SPI, you can find for more in my other tutorials.
First, in BBB you need to activate the SPI device. To do that, you need to create a dts file, after then compile. But If you use latest debian image for you BBB , it is not needed these steps. To understand the situation
root@beaglebone:/# ls
bin dev home lost+found mnt proc run selinux sys usr
boot etc lib media opt root sbin srv tmp var
root@beaglebone:/# cd /lib/firmware/
root@beaglebone:/lib/firmware# ls *SP*
ADAFRUIT-SPI0-00A0.dtbo ADAFRUIT-SPI1-00A0.dtbo
above, In firmware file, dtbo (device tree blob object) file is available. To activate the SPI the following command line is copied in the uEnv.txt ( under boot file for mine ) then reboot the BBB, so SPI is ready
for use.
optargs=quiet drm.debug=7 capemgr.enable_partno=BB-SPIDEV0
root@beaglebone:/# ls -al /dev/spidev*
crw-rw---T 1 root spi 153, 1 Jan 1 2000 /dev/spidev1.0
crw-rw---T 1 root spi 153, 0 Jan 1 2000 /dev/spidev1.1
also you should see under /sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups using any editor (like nano )
group: pinmux_bb_spi0_pins
pin 84 (44e10950)
pin 85 (44e10954)
pin 86 (44e10958)
pin 87 (44e1095c)
Second, lets see how the code looks like for BBB. For this tutorial C++ is used. You need gcc compiler, probably you already have. First code send only data with write command , second code is sent data also wait for the coming data at the same time. As it is known for the SPI interface that at the same time you can send data and get data.
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<stdint.h>
#include<linux/spi/spidev.h>
#define SPI_PATH "/dev/spidev1.0"
int main(){
unsigned int fd, i=0; // file handle and loop counter
char a=112;
uint8_t bits = 8, mode = 0; // 8-bits per word, SPI mode 3
uint32_t speed = 10000; // Speed is 1 MHz
// The following calls set up the SPI bus properties
fd = open(SPI_PATH, O_RDWR);
ioctl(fd, SPI_IOC_WR_MODE, &mode);
ioctl(fd, SPI_IOC_RD_MODE, &mode);
ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
write(fd,&a,1); // write a single a character
fflush(stdout); // need to flush the output, as no
close(fd); // close the file
return 0;
}
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<stdint.h>
#include<linux/spi/spidev.h>
#define SPI_PATH "/dev/spidev1.0"
int transfer(int fd, unsigned char send[], unsigned char receive[], int length){
struct spi_ioc_transfer transfer; // the transfer structure
transfer.tx_buf = (unsigned long) send; // the buffer for sending data
transfer.rx_buf = (unsigned long) receive; // the buffer for receiving data
transfer.len = length; // the length of buffer
transfer.speed_hz = 1000000; // the speed in Hz
transfer.bits_per_word = 8; // bits per word
transfer.delay_usecs = 0; // delay in us
// send the SPI message (all of the above fields, inc. buffers)
int status = ioctl(fd, SPI_IOC_MESSAGE(1), &transfer);
if (status < 0) {
perror("SPI: SPI_IOC_MESSAGE Failed");
return -1;
}
return status;
}
int main(){
unsigned int fd, i=0,b,a=112; // file handle and loop counter
unsigned char value, null=0x00; // sending only a single char
uint8_t bits = 8, mode = 0; // 8-bits per word, SPI mode 3
uint32_t speed = 10000; // Speed is 1 MHz
// The following calls set up the SPI bus properties
fd = open(SPI_PATH, O_RDWR);
ioctl(fd, SPI_IOC_WR_MODE, &mode);
ioctl(fd, SPI_IOC_RD_MODE, &mode);
ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
for (i=33; i<124; i++)
{
transfer(fd, (unsigned char*) &i,(unsigned char*) &b, 1);
printf(" %c
",b);
fflush(stdout); // need to flush the output, as no
usleep(100000); // sleep for 100ms each loop
}
close(fd); // close the file
return 0;
}
Third, we make ready Arduino pro mini for SPI. Unlike BBB we do not have to do nothing. Just connections as in the video. I use here Arduino pro mini, because beaglebone is working with 3.3v , for compability , Arduino pro mini 3.3v is good for me. You can, also make you arduino uno working with 3.3v but you need to change
on board physical things. It takes time. there is another trick to communicate with different voltage levels, using voltage level converters.If you as how arduino pro mini program, you can use arduino uno board. to do that just remove the Microcontroller on the board then choose arduino pro mini and specify it is 3.3v in arduino ide. It is simple. Then make connections like in the video, before the send the code press the reset button on the arduino pro mini, then send the code, when tx or rx pin is blinking, release the reset button, so after you will see pro mini will be programmed.
The code is here, I search much in the internet about spı for arduino. There are good examples, therefore I could not find what I need. Some use libraries some use not. Some make different algorithms that I do not understand. In such a communications, I mean, here BBB is master, arduino is slave. Arduino waits data and when data came it writes back to the BBB, interrupts are the painless solutions. That is why I used interrupt service routine in the code. For configuration I read a little bit datasheet of atmega328p to use special
function registers. You can see in the code.
char c;
void setup (void)
{
// turn on SPI in slave mode
SPCR |= (1<<SPE)|(1<<SPIE);
SPSR |= (1<<SPIF);
sei(); // enable global interrupts
// have to send on master in, *slave out*
pinMode (MISO, OUTPUT);
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
c = SPDR; // grab byte from SPI Data Register
while(!SPIF){};
Serial.println(c);
} // end of interrupt routine SPI_STC_vect
// main loop - wait for flag set in interrupt routine
void loop (void)
{
} // end of loop
when arduino takes the byte from MOSI line it writes automatically to the MISO line. I hope this tutorial gives you some idea. Thanks..
30/04/2016