SPI alternative with (pseudo)master- and slaves

Hello fellow creators,

as this is my first time posting please point out any missing information, I'd be glad to give information wherever I can.

I have been working on a Data-Transfer project lately with the following setup:

PC <- Raspberry Pi <- Master Arduino (nano, 1 piece) <- Slave Arduinos (nano, 4 pieces) <- Capacitive Sensors (7 Pieces per Slave, 28 total)

The reason why I use an Arduino as a master is because I want to later Expand this setup and occupy all usb slots on the rpi without significant loss of transfer speeds.

The slaves should gather relevant Data (with the help of the capsense library) and send that Data directly to the master. The master on the other hand will route the data-packets over serial to a rpi, which will process that data further. The master will also append a letter to discern from what slave that data came from.

This process has to be fast and the code for the master should itterate at least 10 times a second.

The data package sent from the slaves to the master are packaged as follows:
aa100-100-100-100-100-100-100bb

aa and bb is used in order to check if the package is sent correctly, the values inbetween correspond to the sensor values in percent. The dash is used to later on discern from which sensor that data came from.

The Slaves are connected on digital pin 10, 11, 12 and 13 with the master. Pin 13 is used as SS.
I have attached a schematic of the Slave and Master below.

The problem I currently have with SPI is that it is in my oppinion is too unstable to call an interrupt and send an array like the one mentioned above, which is why I am trying to work out a better alternative.

I have decided that a good solution would be for the slave to convert the String "aa100-100-100-100-100-100-100bb" to Bytes and send one Bit at a time with digitalWrite() and then disconnect to tell the master that the byte has been transferred. The Master should listen to the incoming traffic while also pulsing the slave to act as a clock.

I have included all codes of both the master and the slave below.

When telling the master to listen to a slave however I get something lie this:

01100001
01100001
00110000
10001111
10000001
10000000
00101101
00110001
11001111
00000011
00000000
00110001
10100110
00001001
11100000
00110000
00010110
10011111
11000100
00110000
00110000
00000011
11101101
11110011
10001000
00110000
00110000
00011110
11010011
00010000
00110000
00011111
10000000
00101101
00110000
10011110
00000110
00000011
11100010
00000110
00000000
01000000

Converted to Ascii this gives aa0€-1Ï1¦ à0ŸÄ00íóˆ00Ó0€-0žâ@
indicating that probably only the first two bytes were correctly transferred. :cold_sweat:

I suspect that this may be because of clock differences between the arduinos, but I am not sure how to solve this. I have tried out different microsecond delays and some seem to work better than others, but when changing the overall length of the sent string the previously used delays are now useless.

I'd really appreciate any input as I am eager to better myself in this topic.

Also I feel like I've just reinvented the wheel :sob:

Master.ino (898 Bytes)

Slave.ino (1.23 KB)

SPI is that it is in my oppinion is too unstable to call an interrupt and send an array

What is the basis for this opinion? I/O should never be performed within an interrupt routine.

SPI communication is an industry standard, and if used properly, is perfectly stable. It has been so for decades.

It sounds to me like you do not understand how SPI works, so let forum members help solve the real problems you are having, rather than invent a new set of problems.

Note that SPI is not designed for long distance communication between boards. There are better communication standards for that.

Thank you!

The biggest problem I have with SPI is that I really can't get it running. I tried an example code from Wie benutzt man SPI auf einem Arduino? (Exact code is at the bottom of the page) but I can't seem to get any communication between the two, and to be honest with how the code looks like I thought it'd be easier to write a similar protocol from scratch. I tried to read up on it, but as I stand currently I beleive that I do not have the knowledge I need yet.

I do not know if it's worth continuing with this protocoll as of now and focus on some easier ones.

SPI is superb chip to chip protocol much more performant and with better data integrity than I2C and Serial. You can safely transfer data at many Mbits/s.

I had a quick look at your software, and it is no joy to read. It is likely not doing what you expect it to do.

Just a few examples:

bytes = digitalRead(11);

  • bytes is an int variable so the name is misleading
  • digitalRead gives you a bit it can be HIGH or LOW
  • you use number in your code instead of declaring a name e.g. #define RX_PIN 11 and then digitalRead(RX_PIN)

val_10 = digitalRead(10);

  • mostly as above
  • what is val_10 where are val_9, 8 ....

int Binary [8];

  • an array of integer numbers called Binary
  • 8 another number, if you want to read your code or have others read it use #defines and give them good names

You have a tiny 8-bit microcontroller and use Strings everywhere without the need for them.

byte bytes = bitRead(myChar,Data_byte);

  • a variable of type byte called bytes (multiple bytes)
  • have a look at the definition of that bitRead funcion the first parameter is a number the second is a bit position
  • the result returns 0 or 1 not a byte or bytes

https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitread/

I think you need to go back to the basics. Draw a schematic of the SPI connection. No fritzing pictures. You can use pen and paper and draw a schematic and take a photo of it.

The Arduino has a SPI module. That will handle the physical layer. You push one byte in on one side and a byte comes out at the other. If you do something by hand you have to send each bit individually, define a relationship between data and clock and other stuff.

Referring to the Original Post (for some reason the quote button won't work)

This does not make sense

The Slaves are connected on digital pin 10, 11, 12 and 13 with the master. Pin 13 is used as SS.

On an Atmega 328 pin 13 is the SPI CLK signal and pin 10 (or any other pin) is used for SS. Also the master needs to use a different SS pin for every slave. It is only MOSI MISO and CLK (11, 12 and 13) that are shared with all the slaves.

Before starting an SPI message the master must set the appropriate SS pin for the particular slave it wishes to talk to.

...R

Thank you all for writing!

Thanks to Robin2 I figured out the reason why it didn't work for me, I accidentally mixed up the SS and SCK pins and always pulled pin13 low when it should've been pin10.
I'll start from scratch and scrap the code I've written above, I think that's my best bet.

noiasca:
well, why is there an Arduino as SPI Master? Why not simple connect your SPI devices to the Raspberry via SPI? Using levelshifter if necessary? Reduce complexity?

That is a good point, I'll definitely look into it.