Pages: [1]   Go Down
Author Topic: arduino-to-arduino communication using differential Manchester encoding  (Read 419 times)
0 Members and 1 Guest are viewing this topic.
Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would like to communicate between two Arduinos, connected pin to pin by only a wire at relatively low speeds (e.g. 9600 baud or less). I am interested in using differential Manchester encoding to do this, because it includes both the clock and the data. I've figured out how the protocol works, but I haven't found any existing code to implement it. I am aware of mchr3k's Manchester communication library and VirtualWire, but these don't seem to be the same kind of animal. They don't seem to use differential Manchester encoding at least.

Apart from communication between Arduinos I want to try and implement this protocol on some RF analog wireless systems that I have.

I'd like to write some code for this, and create a library so that multiple "links" could be invoked, for instance between a "main" Arduino and several "satellite" Arduinos that need to communicate data back to the main unit. I probably need to write it as a class, but I will need some input on how to get this done and make a library out of the code.

In the meantime, I will follow up with some info on differential Manchester encoding, which I think is pretty cool, just in case this is of use to someone else.

-Charlie

Edit: OK, I just read a great tutorial on how to make an Arduino library. I've written and used classes in C++ before, so this part seems to be no problem for me.

I will take a stab at it and then post some code, or where I get stuck (now that is more likely!).
« Last Edit: July 30, 2014, 12:59:05 am by charlielaub » Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is a rundown of what I have learned about differential Manchester encoding. Much of this information was adapted from this source: http://www.pcbheaven.com/wikipages/manchester_coding/ but I have tweaked and added to the material. Hopefully this will make all of this clear to those interested in reading about it.

In the following figure, we define:
Clock period = elapsed time between two numbered red lines.
End of the Nth clock period is indicated by the number next to the red line.
The end of one clock period and the beginning of the next clock period occurs at the same time.



In the image above, the level of the differential Manchester encoded signal is kept HIGH when no data is being sent (before Start and after End). There are 2 encoding methods: The first is the "Transition on LOW" and the second is the "Transition on HIGH". Both methods use similar logic to determine when a transition should take place:
In the middle of each clock period a transition in the differential Manchester encoded signal always occurs. Data is sent when the clock transitions at the end of each clock period. If the data bit to be encoded is 0, then a polarity transition also occurs at this time, otherwise the line remains unchanged.

For example consider the “0 = Transition” (on LOW) sequence in the figure. The data that is transmitted is the binary '10011101' (starting from left to right). Each data bit is transmitted during negative transition at the end of each clock period - these are indicated with the red lines (additionally shown in red are the start and end of the transmission). You can see that between each bit transmission (halfway between pairs of red lines) the encoded signal changes polarity.

Note that the clock, or a good estimate of it, can be recovered by the receiver from the first two transitions in the differential Manchester encoded signal. This is because the line is held in one state before the transmission begins (the standby state). Which signal level is used for the standby state does not matter. In the example above, the standby signal level = HIGH). Because the signal polarity may change during transmission (which would also change the standby state level), the property that the standby state is unimportant is very useful in practice. Once the clock frequency has been estimated from the first two transitions, subsequent transitions are used by the receiver to receive data bits and/or to update the estimate of the clock. All transitions should occur at multiples of the time between the first two transitions, and a kind of running average can be used to update the clock estimate. This can be useful when the timing of the transitions is not precise.




To decode the differential Manchester signal, we can use a micro (such as an Arduino) digital input pin with an interrupt that is called when there is a level transition on the pin.

The code waits in “standby mode” for the interrupt to trigger. In the figure above, this would happen at "Start" with the first HIGH to LOW transition of the differential Manchester encoded signal. The time at which the first transition occurs is stored as the start time of the transmission. The code then waits for the interrupt to be triggered a second time. This will happen at the middle of the clock period, because differential Manchester encoding always has a transition there. The code then calculates the first clock period estimate as twice the time difference between the two initial transitions.

The code then enters the “receive incoming signal” mode and now actively checks for the level of the pin at each half period of the clock. The transition at the half period is used to update the estimate of the clock period and the transition at the end of each clock period is used to receive data, using the following scheme:

  • TRANSITION IF LOW: add a 0 to the received bit stream if there is a transition at the end of the clock period. Add a 1 to the received bit stream if there is no transition at the end of the clock period.
  • TRANSITION IF HIGH: add a 1 to the received bit stream if there is a transition at the end of the clock period. Add a 0 to the received bit stream if there is no transition at the end of the clock period.
  • When there is no longer a transition at the half period of the clock, the transmission has ended and the code returns to the standby mode.
« Last Edit: July 30, 2014, 12:25:42 am by charlielaub » Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here are some first thoughts on coding these routines:

In order to support moderate data rates I need to be able to set and read pins at time intervals that are in the tens of microseconds. My current Arduino platform is the Uno, and this definitely seems doable with a little care. Also, to leave open the possibility of multiple satellite boards sending data back to a single mothership board I need to be able to receive on multiple pins but only need to send from one pin. In order to make this possible, I plan to use the following programming libraries/functions:


RECEIVER:

PinChangeInt library: PinChangeInt is used for getting input (reading the incoming data stream). PinChangeInt allows hardware (external) interrupts to be used on all pins, and can be triggered by a state CHANGE. Because of the differential nature of the encoded signal, an interrupt on CHANGE is necessary for proper receive operation.

The time when when the pin change occurs must be determined with precision of single microseconds. The PinChangeInt library can only interrupt every 30-40us, so knowing the number of elapsed microseconds to a couple of microseconds should be sufficient.

Paul Stoffregen's EllapsedMicros function can be used to test when the data stream has timed out and avoids the overflow problem of micros(). Once data is flowing, if there is no longer a transition at the half clock period the transmission has ended. EllapsedMicros can be called in the main loop to test for stream stop. During each call of the function called by the PinChangeInt interrupt the elapsed time counter used by EllapsedMicros is reset.


GENERATOR:

Timing of generator pin changes - for transmission, a timer or polled function call that can execute a pin state change on intervals of 30us or more is needed. If the main loop() is fast then ElapsedMicros can be used to test whether the pin change should be performed. If there are other things going on in loop() then a timer driven pin change would be better.

TimerOne library - available on at least two pins for a variety of Arduino boards. These pins are pin 9 and 10 for the Uno. See:
https://www.pjrc.com/teensy/td_libs_TimerOne.html



It seems that I can implement the functionality for both the generator and receiver of the differential Manchester signal using the code elements listed above.

Are there any inherent problems with this approach? Suggestions for changes/improvements?

Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am going to need a FIFO or circular bit buffer that is interrupt safe for the receiver code. I want to be able to populate the buffer as the data comes in and then process it in the main loop(). This would give me some options on how to process it, do error or parity checking if that is used, etc.

I have found a couple of these kind of things out there, but I can't convince myself that there won't be problems if I am using PinChangeInt. For instance...
how about one of these:
http://playground.arduino.cc/Code/QueueList
http://playground.arduino.cc/Code/QueueArray

...or this circular buffer:
https://code.google.com/p/bytebuffer-cpp/source/browse/trunk/src/ByteBuffer.h?r=8

This may have potential (the author made an attempt to make it interrupt safe):
https://github.com/rambo/SimpleFIFO

Can anyone who is at all familiar with interrupt safe code look at these and give me an opinion on which might be best?


Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Update: I have managed to code up transmitter and receiver routines. I've tried to keep things general and allow a variable number of TX or RX channels. The RX code can service as many channels as there are digital pins available. The transmitter side uses the TimerOne library, and as a result there are either 2 or 3 pins available for TX channels, depending on the type of board. I have used compiler directives to skip over unneeded code whenever possible (especially in the TX module) so that transmission speed can be maximized.

The TX and RX routines both compile without errors. I will try to test out the code in the next couple of days and post a follow up.
Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code is finally working!!!!   smiley-cool

After about two days of debugging, I have two Arduino boards talking to each other. I can queue and send a message, and receive it on the other end of the wire in the other board. I'm sending the data at a clock rate of 1kHz, which is 125 8-bit characters per second. I will eventually try to see how high I can push this rate, but for now this is fine for testing purposes.

There are still a couple of buggy issues. The PCintPort::arduinoPin pin identifier that is returned by the PinChangeInt library is not working correctly for some reason. This is needed to identify which pin triggered the interrupt when multiple RXs are used. At the moment I am just using a single RX so I have replaced that variable with a constant.

Can someone suggest a forum where people would actually be interested in this kind of thing? The response here has been rather, um,  underwhelming...   smiley-sad
Logged

Sacramento CA, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Update: I seem to have ironed out all the bugs now. Everything is working for a single TX and a single RX. I don't have the setup that would be needed to test out multiple TXs feeding an RX, so that will have to wait for another day.

I did some speed testing. The fastest clock that I could use was 5kHz. Keep in mind that there are two transitions per clock cycle, so with a 5kHz clock there is a transition every 100 microseconds. At this speed one can send 625 8-bit characters per second. Because we are not just toggling a pin back and forth and there is other code that executes in between each transition, this seems to be about right given the limitations of some of the libraries that I am using.

Now that the code is working, I will focus on investigating different ways to make the physical connection between boards. For instance, I want to try using optical fiber, or sending the data over an analog wireless link. Some of these require a little extra hardware to be added to the project, but seems doable. This might be an interesting way for someone to set up a sensor network or distributed system that relays info back to a main "home base".
Logged

Pages: [1]   Go Up
Jump to: