CodeWire, a range optimized version of VirtualWire

Hi there,

i got some of these 433Mhz RF-transmitters and recievers and planed to use them in a home automation project. Some arduinos should exchange data wirelessly.
But after some testing i noticed the very low signal range of these devices using the VirtualWire-library. VirtualWire isn't using any forward-error-correction (FEC). It can only verificate if the message is received properly or not by checking the CRC-checksum. So i decided to write an enhanced version of the library including some error-correction-algorithm in cost of data throughput.

My CodeWire-library is based on VirtualWire and uses a barker-code sequence to improve the signal to noise ratio and the manchaster-code to remove dc-components from the signal. It is even possible to determine the signal-strength of received messages. Using the CodeWire-library is fairly easy, because the commands of both libraries a nearly the same. Look at CodeWire.h for additional information.

Example:

Server Code:

#include <CodeWire.h>
uint8_t buf[16];
uint8_t i = 0;
uint8_t len = 16;
unsigned long timer = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(6, OUTPUT);
  pinMode(13, OUTPUT);
  //startup CodeWire-library
  cw_setup(1000); //define transmission speed
  cw_rx_start(); //enable receiver-module
  timer = millis()-1000;
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly: 
  //wait for incoming messages and reply them after a short break
  if (cw_have_message() == true){
    len = 16;
    cw_get_message(buf, &len);
    delay(1000); //important: wait until the superregenation-receiver of the server recalibrated the input level! Otherwise long ranged transmissions are not possible!
    cw_send(buf, len);
    timer = millis();
  }
  if (millis()-timer < 50){
    digitalWrite(6, true);
  }else{
    digitalWrite(6, false);
  }
}

Client Code:

#include <CodeWire.h>
uint8_t sen_buf[16];
uint8_t rec_buf[16];
uint8_t i = 0;
uint8_t len = 16;
unsigned long timer = 0;
uint8_t ok = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(6, OUTPUT);
  pinMode(13, OUTPUT);
  //startup CodeWire-library
  cw_setup(1000); //define transmission speed
  cw_rx_start(); //enable receiver-module
  
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  // send out ping-singnal every 10 seconds.
  if (millis()-timer > 10000){
    timer = millis();
    for(i=0;i<16;i++){
      sen_buf[i] = random(256); //randomize message
    }
    cw_send(sen_buf, 16); //send 16 byte of message data
    Serial.print("sent message:");
    for(i=0;i<16;i++){
      Serial.print(" ");
      Serial.print(sen_buf[i], HEX);
    }
    Serial.println("");
    
  }
  if (cw_have_message() == true){
    ok = true;
    len = 16;
    cw_get_message(rec_buf, &len); //receive message
    Serial.print("got message:");
    for(i=0;i<16;i++){
      Serial.print(" ");
      Serial.print(sen_buf[i], HEX);
      if (sen_buf[i] != rec_buf[i]){ //compare it with original message
        ok = false;
      }
    }
    Serial.println("");
    if (ok = true){
      Serial.println("message ok");
    }else{
      Serial.println("message fail");
    }
    Serial.println(cw_rx_signal_strength()); //print signal strength of last received message
    Serial.println("");
  }
}

Modules i used:
transmitter-module: XD-FST
receiver-module: XD-RF-5V
Link VirtualWire-library: VirtualWire: VirtualWire library for Arduino and other boards

CodeWire.zip (10.7 KB)

Thank you for sharing this upgrade. Do you have any test data on the improvements gained, especially at the edge of range? How far are you able to space these now inside your home?

Geoff

I use virtualwire of two years ago and with 12 volt units I transmit and receive from a water tank in direct line of sight 500 meters away without error. I'd like to know what distances you are getting too?