8 bit communication between Arduino and Raspberry Pi

Context:
I am currently planning a curriculum to teach children about building with microcontrollers and coding. So far, they have learnt basic circuit building and simple coding (Enough to build a light following robot on their own). I want to teach them about how computers communicate by having them build an 8-bit communication connection between the Raspberry Pi and the Arduino.

Problem:
I have built a 2-bit communication connection by having the Raspberry Pi read 2 pins on the Arduino. Im using pins 8 and 9. The problem is the transition time of the pins. For example, if both pins were off and I want both pins to be on, since I turn them on one at a time, there will be a period when one pin is on and the other is off. This causes the information sent to the Pi to be wrong during this period. I wasn’t expecting this period to be as long as it is. My current solution is to have a 3rd pin that lets the Pi know that the configuration is ready. I use pin 2 for this. Basically immediately after digital write, I have a delay that lets the pins transition, then turn on pin 2, delay a little more, turn pin 2 off and delay a little more. But this solution inevitably slows down the communication speed by at least half a second. Is there a better solution that doesn’t slow down the communication speed as much?

2bitCommPi.PNG

You can change the values of 2 pins (on the same port) at the same time with direct port manipulation.

ClovisN:
Basically immediately after digital write, I have a delay that lets the pins transition, then turn on pin 2, delay a little more, turn pin 2 off and delay a little more.

There is absolutely no reason to wait for pins to transition, the will have changed long before digitalWrite returns.

Hi,
As you are using parallel communication, using one of the bits to confirm that the parallel word is loaded and ready to be read is a valid one.
Why 1/2 a second delay is a problem.

Port manipulation that @groundFungus has suggested is also a way to speed up port data changes.

  • Can you post the code you are using to transmit from the Arduino please?
  • What model Arduino are you using?
  • Have you got the gnds of the Pi and Arduino connected together.

Thanks.. Tom.. :slight_smile:

If you are using 2 pins anyway, why not (UART) serial?

ClovisN:
The problem is the transition time of the pins. For example, if both pins were off and I want both pins to be on, since I turn them on one at a time, there will be a period when one pin is on and the other is off. This causes the information sent to the Pi to be wrong during this period.

Then use a communication system which does not require simultaneous transitions. :astonished:

That is exactly the situation and problem for which all 2 pin protocols (as well as 8-bit parallel protocols) have been specifically designed. Research the I2C protocol to see how it works.

IMHO it would be more useful for your students to learn how to use Serial communication between the Arduino and the RPi.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

…R

@Robin2

Yes, I agree as well, and it is planned for them to learn this further down. But this particular project is to show students how much you can make simply having GPIOs.

@Paul__B

Thanks. Honestly I’m not at all well versed in how communication protocols work. Your suggestion might be a good starting point.

@TomGeorge

1/2 second delay isn’t really a problem, but the students are used to much quicker response times since so far they have only been working on a single system.

I’m using Arduino Mega 2560 rev 3. RPi model 3B+. I do have the grounds connected. In fact I’m powering the Arduino by connecting the 5V pin on the RPi to the Vin on the Arduino, so it won’t even power on until the grounds are connected. For the code attached, the Arduino code is written in mBlock ver 5 and the Pi’s code is written in Scratch 2.

@Whandall

I tried removing the delays but the communication just went haywire. My code is supposed to send 0,1,2,3 in that order from the Arduino to the Pi but without the delay the numbers just jump all over the place.

@groundFungus
That’s interesting. I didn’t know about that. Thanks. But the GPIO library in Scratch 2 doesn’t have that. I could write an extension for it, but for now I’ll try not to go there.

2bitCommPi.PNG

connecting the 5V pin on the RPi to the Vin on the Arduino,

That can cause problems. Vin is connected to the onboard 5V regulator. The regulator needs 7V minimum to regulate. If you have regulated 5V from the Pi, connect to the 5V of the Mega not Vin.

@groundFungus

Hmm, but I read that powering the Arduino via the 5V pin could damage the board. What could happen if I power my Arduino through Vin using only 5V? Would it simply turn off at times? So far I've been running it without any problems...

ClovisN:
@groundFungus

Hmm, but I read that powering the Arduino via the 5V pin could damage the board.

If the power you're feeding it isn't clean and goes above 5V it can be. Your Pi has a regulator giving you 5V doesn't it? That's OK then. Just don't plug unregulated power in there.

What could happen if I power my Arduino through Vin using only 5V? Would it simply turn off at times? So far I've been running it without any problems...

Then you're underpowering the chip. Any number of things could happen. Don't do this.

@Delta_G

Okay, I've switched it and it works. But I think I'll eventually switch back to powering the Arduino via USB. As a general rule of thumb I want students to follow officially recommended practices, at least until they learn about potentials. Thanks for the info though.

This causes the information sent to the Pi to be wrong during this period.

I think you are missing two important points here.

  1. the Arduino is running on 5V and the Raspberry Pi is running on 3V3. So you can’t simply connect the output of an Arduino into the input of a Pi, you will need at least a voltage divider on each pin.

  2. The Pi, while being capable of reading 32 inputs simultaneously, will not do this. No Pi library actually does this they only return a single bit. This is because virtually everyone writing Pi drivers is a software person with little understanding of hardware.

Therefore if two Arduino pins change at the same time it is possible that the Pi software will see only one pin change at a time.

@Grumpy_Mike

1.) The way I understand it, when a pin on the Arduino is written to HIGH, it's potential relative to the Arduino's ground is 5V. Similarly, when the pins on the Pi are written to HIGH, it's potential relative to the Pi's ground is 3.3V. By connecting the grounds of the 2 devices, they have a similar starting point of 0V. For inputs anything higher than half of the pin's max voltage is registered as high. As such the 3.3V of the Pi registers high on the Arduino and vice versa, which is what allows them to communicate. Am i misunderstanding something here?

2.) So the bottleneck lies in how fast the Pi can read the Arduino's pins and not the transition time of the pins on the Arduino? And there's not much I can do about unless I write a library to read the pins faster?

Update:

I added another pin for the Pi to acknowledge that the data has been received so that the Arduino doesn't keep sending new bits before the Pi has received the last set. It runs more stably now, but the response time is still about half a second.

ClovisN:
The way I understand it, when a pin on the Arduino is written to HIGH, it's potential relative to the Arduino's ground is 5V. Similarly, when the pins on the Pi are written to HIGH, it's potential relative to the Pi's ground is 3.3V. By connecting the grounds of the 2 devices, they have a similar starting point of 0V. For inputs anything higher than half of the pin's max voltage is registered as high. As such the 3.3V of the Pi registers high on the Arduino and vice versa, which is what allows them to communicate. Am i misunderstanding something here?

Yes. You are missing the fact that the 5V of the Arduino will damage the Pi.

Grumpy_Mike:

  1. the Arduino is running on 5V and the Raspberry Pi is running on 3V3. So you can’t simply connect the output of an Arduino into the input of a Pi, you will need at least a voltage divider on each pin.

On each pin that is output of the Arduino and input of the Pi (or any other non 5V tolerant device).

ClovisN:
I added another pin for the Pi to acknowledge that the data has been received so that the Arduino doesn’t keep sending new bits before the Pi has received the last set. It runs more stably now, but the response time is still about half a second.

Clearly both Arduino an Pi are capable of microsecond responses. Anything involving half a second is either a consequence of the multi-tasking and “nice” of the Pi Processes, or transferring many kilobytes of data.

I think you really need to look into I2C to understand what is necessary.

2.) So the bottleneck lies in how fast the Pi can read the Arduino's pins and not the transition time of the pins on the Arduino? And there's not much I can do about unless I write a library to read the pins faster?

No, you can read the Pi pins as fast as you like but there will always be some time on some occasion where you read only one input change when there has been two inputs changing. This problem is further compounded by the fact that it is not a real time operating system and any code is likely to be interrupted for the odd 300mS or so every now and then so two operations you perform one after the other could be a "long time" apart.

but the response time is still about half a second.

That is just silly, no way is it going to take that long.

I added another pin for the Pi to acknowledge that the data has been received so that the Arduino doesn't keep sending new bits before the Pi has received the last set.

This system is known as handshaking, and if it takes that long then you are doing it wrong. Normally you say "i have data for you", the receiving end then reads the data and replies with a "thanks I have got that". You would normally need two data lines to do this.

Am i misunderstanding something here?

Yes as pointed out by Whandall. Once an input to a device exceeds the voltage supply of that device the ESD protection diodes kick in and conduct the excess voltage into to power rails. These ESD diodes will burn out normally with a signal because they are not designed for the high current such as a signal produces.

A special form of ESD protection will allow some inputs to be designed to take more voltage than the maximum, these are called "tolerant" inputs. The Raspberry Pi, and most other processors do not have these. The exception is the Teensy 3.5, which is a 3V3 device with 5V tolerant inputs.

Paul__B:
I think you really need to look into I2C to understand what is necessary.

Correct, but what you probably don’t know is the I2C on a Pi can only ever be a master and that I2C on a Pi is a bit flaky and will fail at random and have to be restarted. The situation changes from OS build to build with it almost seems like alternating working / being flaky with alternate releases. You complain to the writers of the OS and they do the usual Linux thing of saying “we are only volunteers” and “if you think you can do better then write it yourself”, and other such typical comments you get from rank amateurs.

It is a PITA and to be avoided if you possibly can.

If the Pi (or the code thereon) is that flaky, you really have problems.

Thanks for the replies.

@Whandall

Oh, yea... So communication is only possible 1 direction... I mean I guess I could run the 3.3V pin on the Arduino to all pins on the Pi that I communicate with and control the logic via transistors... Seems a little convoluted but would that be a safe way of connecting the 2 devices?

@Paul__B

Yea, I get that. I've read up on it a little. But it seems a little complex for students who don't yet even understand the binary number system... Also, I tried making a serial communication system to test out whether it would be faster, but it wasn't much better.

@Grumpy_Mike

I'll go look up handshaking. Thanks.