All code in this post copyleft 2008, please reproduce & reuse, and give credit where due.
Example transmit code:
int ledPin = 13; // LED connected to digital pin 13
int inputpin = 0;
int val = 0; // variable to store the read value
int sw[8]; // switches / their values
int xmitpin = 8;
unsigned int curInt;
int dlyms = 208;
void xmitByte(byte vData) {
byte bitv = 128;
for (int bitc = 0; bitc < 8; bitc++) {
if (vData & bitv) {
digitalWrite(xmitpin, HIGH);
delayMicroseconds(dlyms*2);
digitalWrite(xmitpin, LOW);
delayMicroseconds(dlyms);
}
else {
digitalWrite(xmitpin, HIGH);
delayMicroseconds(dlyms);
digitalWrite(xmitpin, LOW);
delayMicroseconds(dlyms);
}
bitv = bitv >> 1;
}
}
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
digitalWrite(ledPin, HIGH);
int cnt = 2; // counter
while (cnt <= 7) {
sw[cnt] = 1;
pinMode(cnt, INPUT); // set to input
digitalWrite(cnt, HIGH); // enable pull-up
cnt++;
}
pinMode(xmitpin, OUTPUT);
}
void loop()
{
int cnt = 2;
int vin = 0;
cnt = 2;
while (cnt <= 7) { // poll pins 2 through 7
vin = digitalRead(cnt); // poll the pin.
if (vin != sw[cnt]) { // has its state changed?
sw[cnt] = vin; // store the new state
curInt = 0x4000 + (8 * vin) + cnt; // set number to transmit to reflect this
}
cnt++;
}
for (int xbr = 0; xbr < 3; xbr++) xmitByte(0);
xmitByte(150); // preamble
xmitByte(curInt >> 8); // data
xmitByte(curInt & 0xFF);
xmitByte(~curInt >> 8); // to error check
xmitByte(~curInt & 0xFF);
xmitByte(0); // padding
digitalWrite(xmitpin, HIGH);
curInt++;
}
This code turns on pins 2 through 7 internal pull-up resistor, and polls them for changes. It also continuously transmits data on pin 8, the data being an unsigned int stored in curInt. Shorting a pin (2 through 7) to ground causes this number to change, and it also changes when the pin is disconnected or its level goes high.
The data sent to indicate a switch event will always have bit 0x4000 set, and the bit with mask 0x8 indicates high or low. Bits with mask 0x7 (the three LSBits in curInt) indicates which pin the event occurred on. The number 2 in the loops above can be changed to 0 to accommodate two more pins, if one is not also using the serial port.
Receiving end:
int ledPin = 13; // LED connected to digital pin 13
byte amlvl = 15;
unsigned int lastint;
int waitOnlvl(byte vLvl) {
byte wlvl = digitalRead(12);
byte wlvl2 = wlvl;
int lvlcnt;
while (wlvl2 != vLvl) {
lvlcnt = 0;
while (wlvl2 == wlvl) {
wlvl2 = digitalRead(12);
lvlcnt++;
}
wlvl = wlvl2;
delayMicroseconds(40);
}
return(lvlcnt);
}
unsigned int recvInt(void) {
// check for level change
unsigned long starttime = millis();
int tmocyc = 0;
byte reftm = amlvl + 40;
byte reftm2 = reftm + (reftm / 2);
//read potential bits
unsigned long curdata = 0;
unsigned int preamble = 0;
byte lvlq = 0;
byte cbit = 0;
waitOnlvl(0);
waitOnlvl(1);
while ((preamble != 150) && (tmocyc < 5000)) {
preamble = (preamble << 1) + (curdata >> 31);
curdata = curdata << 1;
cbit = waitOnlvl(0);
if ((cbit < reftm) && (cbit > amlvl)) {
reftm = cbit;
reftm2 = reftm + (reftm / 2);
}
if (cbit > reftm2) curdata++;
waitOnlvl(1);
tmocyc++;
if ((tmocyc % 128) == 127) {
if (millis() - starttime > 1000) tmocyc = 5000;
}
}
if (tmocyc == 5000) {
return(0);
}
else {
if ((preamble == 150) && ((curdata >> 16) == (~curdata & 0xFFFF))) {
return(curdata >> 16);
}
}
}
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
pinMode(12, INPUT);
digitalWrite(12, LOW);
Serial.begin(115200); // open serial
}
void loop()
{
unsigned int newInt;
newInt = recvInt();
if ((newInt != lastint) && (newInt != 0) && (newInt != 65535)) {
Serial.print(newInt >> 8, BYTE);
Serial.print(newInt & 0xFF, BYTE);
lastint = newInt;
}
}
The receive code simply looks for legible data coming in on pin 12, and when it sees good data and the number is different than the last one received, it prints it to the serial port. This is since, the transmitter will be continuously transmitting a number in curInt, which only changes with the line levels of pins 2-7 on the transmitting MCU.
Hopefully that works this time. I had a lot of extra function in my code that I snipped out for the purposes of this example, and I couldn't test it. But it did work before snipping out the unrelated code.
To have the loop print the received number in decimal, change the two Serial.print lines above to, Serial.println(newInt, DEC);
Please post here if you're getting results! I'll check back from time to time, and hopefully soon I'll have motivation enough to rewrite this code to use this 8b/10b encoding, and perhaps turn it all into a library.
Dustin, we must be using different modules. Mine are likely cheaper in price & quality. They certainly do not work as you described - changing the tx on one to high or low does not cause the receivers rx to do the same, unless the line level in changing rapidly. This was my whole reason for trying to implement manchester-ish encoding.
(arrgh 5500 char post limit)