I’ve found this Arduino compatible implementation of PJON for 433Mhz radio modules, A  weeks ago, I knew right along this is a promising library. It’s made by Giovanni Blu Mitolo he did a hell of a job in making the library.

giphy

PJON (Padded Jittering Operative Network) is an opensource multi-master communication bus system standard. Its 433Mhz radio implementation, PJON_ASK, can be a valid alternative to VirtualWire / RadioHead library (generally used for data transmission with these modules and Arduino). With PJON_ASK you have a real wireless multimaster network with up to 255 devices with an unique ID in half-duplex or simplex mode with CRC error detection and correct reception acknowledge. If you are interested to know more about the PJON standard.

Basic concepts

– Every device has an unique 1 byte ID (0-255)
– Every device transmits and receives on the same common PJON network medium
– Every device has an equal right to transmit and receive on the common medium
– Every device can be connected to n PJON network media (with n dedicated pins)
– Transmission occurs only if the communication medium is not in use
– Synchronization occurs every byte
– Devices communicate through packets

Transmitter

#include <PJON_ASK.h>     // Transmitter board 
PJON_ASK network(11, 12, 45); // receiver to pin 11, transmitter to pin 12, device id 45

void setup() {
  network.send(44, "B", 1, 1000000);
  // Send to device 44, "B" content of 1 byte length every 1000000 microseconds (1 second)
}

void loop() {
  network.update();
}

Reciever

#include <PJON_ASK.h>     // Receiver board 
PJON_ASK network(11, 12, 44); // receiver to pin 11, transmitter to pin 12, device id 44

void setup() {
  network.set_receiver(receiver_function); // Set the function used to receive messages
};

static void receiver_function(uint8_t length, uint8_t *payload) {
  if(payload[0] == 'B') { // If the first letter of the received message is B
    digitalWrite(13, HIGH);
    delay(30);
    digitalWrite(13, LOW);
  }
}

void loop() {
  network.receive(1000);
}

Features

ASK 315/433Mhz cheap transceiver implementation (200m range in urban environment)
Works with both simplex and half duplex setup.
Device id implementation to enable univocal communication up to 254 devices.
Cyclic Redundancy Check (CRC).
Acknowledgement of correct packet sending.
Collision avoidance to enable multi-master capability.
Broadcast functionality to contact all connected devices.
Packet manager to track and retransmit failed packet sendings in background.
Error handling.

Performance

Transfer speed: 202 B/s or 1620 Baud
Data throughput: 150 B/s
Accuracy: 99.995%
Range: 200 meters in urban environment (still not tested with LOS in open air)

Compatibility

Arduino Diecimila / Duemilanove
Arduino Mini
Arduino Uno
Arduino Nano
Arduino Mega

This library is tested effectively with many versions of the ASK 433Mhz module present on ebay and various other webshops. This implementation works with a simple oversampling approach, for this reason works also on wires and other radio modules. If you need communication through wire check the PJON wire implementation here.
Why not VirtualWire / RadioHead?

I don’t think VirtualWire is clear, efficient and understandable enough to be the standard library for wireless radio communication available to the community, because of its implementation mess and complexity. Moreover VirtualWire doesn’t have the support for multiple devices in multimaster setup, CRC, acknowledge, collision avoidance and packet management. For this reason I wrote this implementation to provide the user with the PJON standard also on wireless. 🙂

How to start

The first step is the physical layer. The suggested antenna if you have space available is a 69cm dipole antenna for both transmitter and receiver module:

       345mm                    345mm                  345mm                    345mm
   -------------------|--------------------        -------------------|--------------------
                    __|__                                          ___|________
                   | tx  |                                        | rx         |
                   |_____|                                        |____________|

Lets start coding, instantiate the PJON_ASK object that in the example is called network. To initialize a network based on PJON_ASK you need only to define the reception and transmission pin (any free digital pin on your board) where ASK receiver and transmitter are connected and a unique ID (0 – 255):

PJON_ASK network(11, 12, 123);

If you have only the transmitter on a board and the receiver on anotherone, you transmit in simplex mode. You should pass NOT_USED instead of the receiver pin:

PJON_ASK network(NOT_USED, 12, 123);

On the other side if you have only the receiver module:

PJON_ASK network(12, NOT_USED, 123);

Take in consideration that in simplex mode is impossible to know if the receiver got the right message. This happens because you don’t have on the transmitter side a receiver module able to hear the ACK, for this reason if one of the pins are NOT_USED PJON_ASK runs in simplex mode not sending ACK and not checking if the channel is used.

Transmit data

Data transmission is handled by a packet manager, the update() function has to be called at least once per loop cycle. Consider that this is not an interrupt driven system, all the time dedicated to delays or executing other tasks is postponing the sending of all the packets are scheduled to be sent:

network.update();

To send a string to another device connected to the bus simply call send() function passing the ID you want to contact, the string you want to send and its length:

network.send(100, "Ciao, this is a test!", 21);

I know that the packet length is boring to fill but is there to prevent buffer overflow. If sending arbitrary values NULL terminator strategy based on strlen() is not safe to detect the end of a string.

To send a value repeatedly simply add as last parameter the interval in microseconds you want between every sending:

int one_second_delay_test = network.send(100, "Test sent every second!", 23, 1000000);

one_second_delay_test contains the id of the packet. If you want to remove this repeated task simply:

network.remove(one_second_delay_test);

To broadcast a message to all connected devices, use the BROADCAST constant as recipient ID.

int broadcastTest = network.send(BROADCAST, "Message for all connected devices.", 34);

Receive data

Now define a void function that will be called if a correct message is received. This function receives 2 parameters: the message length and its content.

void receiver_function(uint8_t length, uint8_t *payload) {
Serial.print("Message content: ");

for(int i = 0; i < length; i++)
Serial.print((char)payload[i]);

Serial.print(" | Message length: ");
Serial.println(length);
};

Inform the network to call receiver_function when a correct message is received:

network.set_receiver(receiver_function);

To correctly receive data call receive() function at least once per loop cycle passing as a parameter, the maximum reception time in microseconds:

int response = network.receive(1000);

Consider that this is not an interrupt driven system and so all the time passed in delay or executing something a certain amount of packets will be potentially lost unheard. Structure intelligently your loop cycle to avoid huge blind timeframes.

ezgif.com-gif-maker

Download all Files for this project on github

Do you have any questions? Leave a comment down below!

Pin on Pinterest0Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0Buffer this pageDigg thisEmail this to someoneFlattr the authorShare on Reddit0Share on StumbleUpon0Share on Tumblr0Share on VKShare on Yummly0
  • Gio Blu

    Hi there! How its going with PJON_ASK? Thank you for your publication.

  • Hey Gio, you’re welcome! But all credits goes to you, you did all the hard work 🙂
    But unfortunately I don’t get it to work yet, probably it will be my fault (noob).
    Here is what I’m trying to setup https://github.com/AchimPieters/PJON_ASK, I put it all in a Fritzing example including the code. But when I load the code to the Aquino’s nothing happens? do you have a idea?

  • Gio Blu

    Please describe me your hardware software setup. I will try to understand, what is .fzz?

  • Fritzing is an open-source hardware initiative that makes electronics accessible as a creative material for anyone.
    you can find more information here: http://fritzing.org/home/

    But here are the two setup’s as a made them:

    Transmitter:

    #include // Transmitter board

    PJON_ASK network(11, 12, 45); // receiver to pin 11, transmitter to pin 12, device id 45

    void setup() {

    // Send to device 44, “B” content of 1 byte length every 1000000 microseconds (1 second)

    network.send(44, “B”, 1, 1000000);

    }

    void loop() {

    network.update();

    }

    Receiver:

    #include // Receiver board

    PJON_ASK network(11, 12, 44); // receiver to pin 11, transmitter to pin 12, device id 44

    void setup() {

    Serial.begin(9600);

    network.set_receiver(receiver_function); // Set the function used to receive messages

    pinMode(13, OUTPUT);

    digitalWrite(13, LOW);

    };

    static void receiver_function(uint8_t length, uint8_t *payload) {

    if(payload[0] == ‘B’) { // If the first letter of the received message is B

    Serial.println(“BLINK”);

    digitalWrite(13, HIGH);

    delay(30);

    digitalWrite(13, LOW);

    }

    }

    void loop() {

    network.receive(1000);

    }

  • Gio Blu

    Ciao Achim. Watch out to the pin “CS” or channel select. Depending on the modules you have it should be grounded or connected to 5v to receive correctly.

  • Hey Gio, Thank you for your reply! But unfortunately these modules have no CS pin or cs setting. Here are the specs:

    Description:

    This is 433Mhz wireless RF transmitter and receiver kit for Arduino ARM MCU

    Application environment:

    Remote control switch, receiver module, motorcycles, automobile
    anti-theft products, home security products, electric doors, shutter
    doors, windows, remote control socket, remote control LED, remote audio
    remote control electric doors, garage door remote control, remote
    control retractable doors, remote volume gate, pan doors, remote control
    door opener, door closing device control system, remote control
    curtains, alarm host, alarm, remote control motorcycle remote control
    electric cars, remote control MP3.

    Specification:

    Receiver module:

    Product Model: XD-RF-5V

    Operating voltage: DC5V

    Quiescent Current: 4MA

    Receiving frequency: 433.92MHZ

    Receiver sensitivity: -105DB
    Pinout from left → right: (VCC; DATA; DATA; GND)

    RF Transmitter:

    Technical parameters of

    Product Model: XD-FST

    Launch distance :20-200 meters (different voltage, different results)

    Operating voltage :3.5-12V

    Operating mode: AM

    Transfer rate: 4KB / S

    Transmitting power: 10mW

    Transmitting frequency: 433M

    Pinout from left → right: (DATA; VCC; GND)

    I have used these modules with another arduino libary and they worked well. So I don’t get my head around it (yet) 😉

  • Gio Blu

    Seems a model I never tested. please if you can make a test in simplex mode, so one module per arduino, lets see.

  • Okay I’ll give it a try as soon as possible!

    Here is my setup as I’m going to test it.

    TRANSMITTER:

    [code]
    #include // Transmitter board

    PJON_ASK network(NOT_USED, 12, 45); // receiver to pin 11, transmitter to pin 12, device id 45

    void setup() {
    // Send to device 44, “B” content of 1 byte length every 1000000 microseconds (1 second)
    network.send(44, “B”, 1, 1000000);
    }

    void loop() {
    network.update();
    }
    [/code]

    RECIEVER:

    [code]
    #include // Receiver board

    PJON_ASK network(11, NOT_USED, 44); // receiver to pin 11, transmitter to pin 12, device id 44

    void setup() {
    Serial.begin(9600);
    network.set_receiver(receiver_function); // Set the function used to receive messages
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);
    };

    static void receiver_function(uint8_t length, uint8_t *payload) {
    if(payload[0] == ‘B’) { // If the first letter of the received message is B
    Serial.println(“BLINK”);
    digitalWrite(13, HIGH);
    delay(30);
    digitalWrite(13, LOW);
    }
    }

    void loop() {
    network.receive(1000);
    }
    [/code]

  • Hey Gio, Sorry that it took so long but I’ve test it, and….. it worked!
    So you can add these modules as well to your list.
    I’ll will write as soon as possible a new blog with all the steps regarding your PJON_ASK and the 433 MHZ modules.