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!).
Here is a rundown of what I have learned about differential Manchester encoding. Much of this information was adapted from this source: Manchester and Differential Manchester Code 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.
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.
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?
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.
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.
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...
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".
Intersting development. I'm using the mchr3k's Manchester communication library now, to have a wireless connection between 2 cheap ASK modules. I can now send 11 packets of data ( 2 bytes) per second, but would actually like to get this to 40 packets (of 2 or 3 bytes) per second, as the data is driving an RC servo.
I was surprised to see there was almost no interest in this topic. I am extremely interested. I would love to get your working code. I have a similar need but want to use BMC encoding and also need to send individual bits instead of bytes. Instead of starting from scratch it would be great to have what you have written. Please post your code of let me know how to get it. I want to use this on a teensy 3.1 so hoprfully there is not a lot of board specific stuff that i would need to convert. i am not very good with this.
@ spencoid
My code is written for attiny85
It is a wireless throttle control for vintage control-line model airplanes. It had to be very small size as it needs to fit inside the grip.
Transmitter
/*
Pinlayout of the ATTINY 85
+-------+
(PCINT5/RESET/ADC0/dW) PB5 -| 1 8 |- VCC
PIN 3 (PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3 -| 2 7 |- PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2) PIN 2
PIN 4 (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 -| 3 6 |- PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1) PIN 1 PWM
GND -| 4 5 |- PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0) PIN 0 PWM
+-------+
*/
#include <Manchester.h> // additional libray to install for Manchester code datatransmission
uint8_t data[3] = {0,0};
void setup(){
pinMode(0, INPUT_PULLUP); //PB0 pin where Landing Gear Switch is connected (leading to ground)
pinMode(1, INPUT_PULLUP); //PB1 pin where Throttle engage/kill Switch is connected (leading to ground)
pinMode(A1,INPUT); //PB2 pin where Throttle speed potentiometer is connected (A1 = PB2)
pinMode(3, OUTPUT); //PB3 pin where Transmitter datasignal is connected
pinMode(4, OUTPUT); //PB4 pin where Transmitter + voltage is delivered through ATTiny85
digitalWrite(4, HIGH);
man.setupTransmit(3, MAN_1200);
}
void loop(){
data[0] = map(analogRead(A1), 0, 1023, 0, 255);
bitWrite(data[1], 0 , digitalRead(0));
bitWrite(data[1], 1 , digitalRead(1));
man.transmitArray(3, data);
}
Receiver
/*
Pinlayout of the ATTINY 85
+-------+
(PCINT5/RESET/ADC0/dW) PB5 -| 1 8 |- VCC
PIN 3 (PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3 -| 2 7 |- PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2) PIN 2
PIN 4 (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 -| 3 6 |- PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1) PIN 1 PWM
GND -| 4 5 |- PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0) PIN 0 PWM
+-------+
*/
#include <Manchester.h>
#define RX_PIN 3
#define LL_PIN 2
#define R0_PIN 4 // reverse throttle channel if pin connected to ground
#define THROTTLE 0
#define GEAR 1
#define BUFFER_SIZE 3
uint8_t buffer[BUFFER_SIZE];
int servopwm;
long currentMillis; // time the system is on since power-up
long previousMillis = 0; // will store last time correct data received
long interval = 20000; // Safety threshold duration for no signal received
#include <TinyServo.h>
const byte SERVOS = 2; // how many servos do you have? up to 5 on ATTiny85 and 8 on ATtiny84/2313
const byte servoPin[SERVOS] = {0, 1}; // what pins are your servos on?
void setup() {
setupServos();
pinMode(LL_PIN, OUTPUT);
pinMode(RX_PIN, INPUT);
pinMode(R0_PIN, INPUT_PULLUP);
man.setupReceive(RX_PIN, MAN_1200);
man.beginReceiveArray(BUFFER_SIZE, buffer);
currentMillis = previousMillis = millis();
}
void loop() {
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
if (digitalRead(R0_PIN)) servoPos[THROTTLE]=10;
else servoPos[THROTTLE]=47;
}
if (man.receiveComplete()) {
uint8_t receivedSize = 0;
previousMillis = currentMillis;
if (bitRead(buffer[1],0)){
servoPos[GEAR]=10;
digitalWrite(LL_PIN,LOW);
}
else{
servoPos[GEAR]=47;
digitalWrite(LL_PIN,HIGH);
}
servopwm=buffer[0];
if (bitRead(buffer[1],1)) servopwm=0;
if (digitalRead(R0_PIN)) servoPos[THROTTLE]=map(servopwm, 0, 255, 10, 47);
else servoPos[THROTTLE]=map(servopwm, 0, 255, 47, 10);
man.beginReceiveArray(BUFFER_SIZE, buffer);
}
}
Transmitter HW (potentiometer is optional and can be omitted)
look great but i need something for a teensy 3.1 with a different processor. the Mchr3k - Arduino Manchester Encoding library does not support this. i am looking more for some generic encoding and decoding code that i can learn from to be able to write my own simple functions.
I realize this is an old thread, but I am just about to do the exact same thing. Code for Differential Manchester, in order to hook the Arduino up on an already existing bus using differential manchester.
So I too is very interested in this, and to hear if there is any possibility to have the code shared?