Arduino Master and Slave Using Manual SPI Alternative

Hi,

First post here, so let me know if I'm doing something wrong.

I'm in a dilemma, I have three custom PCB boards using the ATMEGA328, two of which are 'sensor boards' which use SPI to communicate to a thermocouple IC and DAC on the board (atmega reads the thermocouple digitally and sends data to DAC), the third board ('bluetooth board') reads the data on both 'sensor boards' and transmitts the data via bluetooth (for speed and modularity, I separated the bluetooth from the sensor boards).

Currently I'm using Nick Gammons (Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino) to communicate between the two 'sensor boards' and 'bluetooth board'. I am trying to avoid using the same SPI bus for both communicating between both the components and the boards so I'm currently investigating modulating the clock signals on reading/writing SPI data on alternative pins. I'm currently still debugging, but my read function looks something like this...

int readByte(int pin, int bits) {
int Rdata = 0;
digitalWrite(cs,LOW); //Select component
for (int i = 0; i < bits; i++) {
digitalWrite(ck, HIGH); //Send clock high, data out changes on rising edge
int Dbit = digitalRead(dataPin); //read data out
digitalWrite(ck, LOW); // Send clock low
Rdata = Rdata << 1; // bitwise shift
Out |= Rdata; // Compound bitwise or (tacks on most recent Read as LSB
}
return Out;
}

Has anyone tried this? I'm curious if there is a better way to approach all together or if there is a better way without using digitalWrite/Read.

Thanks! Any direction will be appreciated.

TLDR: Need arduino to act as Master and Slave using SPI while maintaining high speed capabilities you can't get with I2C.

I am trying to avoid using the same SPI bus for both communicating between both the components

Why? The data is all going over the same bus internally. Processor can thus only send data to 1 place at a time anyway, so you're not gaining any processor time by bit-banging SPI out to one of them. Each device gets a unique chip select line, so just need to connect SCK, MOSI, MISO to all pins in parallel. The only time it's an issue is if you need to change SPI modes for devices, or if they need different speeds, and you can change those on the fly as far as I know.

I realized the code was wrong anyway...

int readByte(int pin, int bits) {
int Out = 0;
for (int i = 0; i < bits; i++) {
digitalWrite(ck, HIGH);
int Dbit = digitalRead(dataPin);
Serial.println(Rdata);
digitalWrite(ck, LOW);
Out = Out << 1;
Out |= Dbit;
}
return Out;
}

Thanks for the explanation CrossRoads. Since the board to board SPI communication used an SPI interrupt routine ISR (SPI_STC_vect), I was deterred from using SPI for the sensor component communication because I don't exactly how the interrupt routine works. I thought it would just be safer to split the lines. You don't think this would be an issue?

Just remembered the main reason I split them into two buses, for increased speed I wanted the sensor boards to constantly read the sensor IC and output an analog voltage on the DAC. So as the bluetooth board is sending/receiving data from one sensor board the other sensor board is reading it's on-board sensor in parallel. For this to work, we need separate MISO,MOSI, SCKs.

I think there is some confusion here - the 328P chip on a board can only do 1 thing at a time - read the sensor, send the data to DAC, and do a Bluetooth thing to another board.
With SPI, it can read the sensor on MISO while it writes to the DAC on MOSI:
incomingByte[1] = SPI.transfer(dacByte[0]);
Maybe what it sends out is the data from the prior read ,using a couple of arrays.
Where does Bluetooth come in? And isn't Bluetooth typically serial comm's?

My bad. Maybe I wasn't explaining well. I meant that the three ATMEGAs, which periodically use SPI in parallel with one another, not that there are multiple processes going on the same ATMEGA.

The setup:
There are three boards each with their own ATMEGA. One master board (bluetooth board), and two slaves (more in the future).

The sensor boards continuously communicates via SPI to their on-board components (Read Sensor IC, interpret, and write to DAC). This happens continuously until an interrupt from the master board prompts the slave boards to send a few bytes of data to the master.

The sole purpose of the master board is to read data from slave A and slave B and then send it via bluetooth to an external device. Continuously looping in that order.

1)Master reads most recent data from slave A while slave B reads, processes, and writes most recent data to DAC
2)Master reads most recent data from slave B while slave A reads, processes, and writes most recent data to DAC
3)Master sends data via bluetooth while slave A & B read, process, and write most recent data to DAC
4)Repeat

So for instance in step (1) , in order for slave B to read and write to the DAC while the data is being sent from the Slave A to the master board, there would need to be separate SPI buses.

You made a good point about the bluetooth using serial comms though, I was approaching it wrong. I originally had the mentality that I needed to use the SPI bus to send data from the slave/sensor boards to the master board in order to interpret then send it via bluetooth, but I should be able to just tie both slave/sensor boards' TX and RX pins together and alternate sending data directly from the multiple slave/sensor boards to a single bluetooth and skip the step of using an ATMEGA on the masterboard all together.

Thanks for talking it out with me CrossRoads

So you're reading sensors digitally then outputting the data as an analog voltage so that a third board can read that via an analogRead()?

SPI can be fast. Very fast. It can actually be faster to read from an SPI device than the built-in analogRead(). It's certainly more accurate.

I would try to do this without the first two boards at all. MOSI, MISO and SCK go to all the sensors and the bluetooth module. Then each has a CS line from any of the spare Arduino pins. Unless there's some special processing in the first two boards you aren't telling us?

Thanks for the response Morgan. I should really draw a schematic or something. Communication is all digital between the boards, the DAC is just another SPI component on the slave/sensor board. I have it there just in case I wanted to use a data acquisition device to pull the voltage straight from multiple sensor boards for debugging or increased data acquisition rates.

Using Nick's arduino to arduino SPI communication, I was able to get communication rates of 12,000-24,000 bytes per second which is pretty nice.

As you dabbled on, there is special processing going on. The sensor boards have a molecularity factor to them, so I will be able to switch out a thermocouple sensor board with a barometer sensor board, strain gauge amplifier board, ect... without having to update the program on the master board. So basically the sensor board, ATMEGA interprets and packages the data as a standard 24 bit package that the master board can understand.

However, after CrossRoads response I think I'm diverging from that concept slightly and eliminating the ATMEGA on the master board completely. Instead I'm going to send the 24 bit packets from the sensor boards to the bluetooth directly via serial comm.

I'll let you guys know how it goes...

It's difficult to have two boards sending data over one serial line. There's no way of ensuring that both don't talk at once. You do unfortunately have to have a master which sits in that position to receive data separately and combine it for transmission.