Whilst working on my radio-controlled car, I developed my own versions of Manchester encoding and decoding libraries.
The sending library is here:
http://www.gammon.com.au/Arduino/ManchesterSend.zip
It uses a hardware timer (Timer 2) to clock out pulses at exactly 500 uS intervals. That is, 1000 bps (since it takes two pulses for a data bit).
Example code:
#include <ManchesterSend.h>
void setup ()
{
ManchesterSend::begin (8); // send on pin D8
} // end of setup
void sendString (const char * s)
{
while (*s)
ManchesterSend::write (*s++);
} // end of sendString
void loop ()
{
sendString ("hello, world\n");
} // end of loop
The receiving library is here:
http://www.gammon.com.au/Arduino/ManchesterInterrupts.zip
That uses interrupts (you can choose which ones you want) to clock in bits.
Example code:
#include <ManchesterInterrupts.h>
void setup ()
{
// incoming on pin D2
ManchesterInterrupts::dataPin = 2;
// need a change interrupt to detect incoming data
attachInterrupt (0, ManchesterInterrupts::isr, CHANGE);
Serial.begin (115200);
} // end of setup
void loop ()
{
if ( ManchesterInterrupts::available ())
Serial.print ((char) ManchesterInterrupts::read ());
} // end of loop
In a similar way to the hardware serial, you can go about your business in loop() and check if data is available, and then do something with it.
I think this is nice and simple. You can test by connecting pin D8 of the sending example on one Arduino to pin D2 on the other one for receiving.
You can even test on a single board:
#include <ManchesterSend.h>
#include <ManchesterInterrupts.h>
// digital pins
const byte RECEIVE_PIN = 2;
const byte SEND_PIN = 8;
void sendString (const char * s)
{
while (*s)
ManchesterSend::write (*s++);
}
void setup ()
{
ManchesterSend::begin (SEND_PIN);
// incoming on pin D2
ManchesterInterrupts::dataPin = RECEIVE_PIN;
// need a change interrupt to detect incoming data
attachInterrupt (0, ManchesterInterrupts::isr, CHANGE);
Serial.begin (115200);
Serial.println ();
// send out on pin 8
sendString ("hello, world\n");
} // end of setup
void loop ()
{
if ( ManchesterInterrupts::available ())
Serial.print ((char) ManchesterInterrupts::read ());
} // end of loop
Thanks to everyone who inspired me to attempt this, in particular carl47 who gave me the idea to read the Atmel application note (not an easy read) and nut out a way of doing it with interrupts.