├── PJON_ASK.cpp ├── PJON_ASK.h ├── README.md ├── examples ├── BlinkTest │ ├── Receiver │ │ └── Receiver.ino │ └── Transmitter │ │ └── Transmitter.ino ├── NetworkAnalysis │ ├── Receiver │ │ └── Receiver.ino │ └── Transmitter │ │ └── Transmitter.ino ├── SendArbitraryValues │ ├── Receiver │ │ └── Receiver.ino │ └── Transmitter │ │ └── Transmitter.ino └── SpeedTest │ ├── Receiver │ └── Receiver.ino │ └── Transmitter │ └── Transmitter.ino ├── includes └── digitalWriteFast.h ├── keywords.txt └── library.properties /PJON_ASK.cpp: -------------------------------------------------------------------------------- 1 | 2 | /*-O//\ __ __ 3 | |-gfo\ |__| | | | |\ | 4 | |!y°o:\ | __| |__| | \| v1.0 5 | |y"s§+`\ Giovanni Blu Mitolo 2012 - 2015 6 | /so+:-..`\ gioscarab@gmail.com 7 | |+/:ngr-*.`\ 8 | |5/:%&-a3f.:;\ PJON_ASK is a device communications bus system wireless implementation 9 | \+//u/+g%{osv,,\ that connects up to 255 arduino boards up to 256B/s in multi-master configuration. 10 | \=+&/osw+olds.\\ Contains acknowledge, collision detection, CRC all done with micros() 11 | \:/+-.-°-:+oss\ and delayMicroseconds(), with no use of interrupts or timers. 12 | | | \oy\\ Cheap 433Mhz TX/RX kit suggested as wirelles communication medium. 13 | > < 14 | _____-| |-________________________________________________________________________ 15 | | BIT_WIDTH 350 | BIT_SPACER 750 | | 16 | |----------------------------------------------------------------------------------| 17 | |Transfer speed: 256 B/s | Absolute bandwidth: 256 B/s | 18 | |Baud rate: 2564 baud | Data throughput: 212 B/s | 19 | |__________________________________________________________________________________| 20 | 21 | Copyright (c) 2012-2015, Giovanni Blu Mitolo All rights reserved. 22 | 23 | Redistribution and use in source and binary forms, with or without 24 | modification, are permitted provided that the following conditions are met: 25 | - Redistributions of source code must retain the above copyright 26 | notice, this list of conditions and the following disclaimer. 27 | 28 | - Redistributions in binary form must reproduce the above copyright 29 | notice, this list of conditions and the following disclaimer in the 30 | documentation and/or other materials provided with the distribution. 31 | 32 | - All advertising materials mentioning features or use of this software 33 | must display the following acknowledgement: 34 | This product includes PJON_ASK software developed by Giovanni Blu Mitolo. 35 | 36 | - Neither the name of PJON, PJON_ASK nor the 37 | names of its contributors may be used to endorse or promote products 38 | derived from this software without specific prior written permission. 39 | 40 | This software is provided by the copyright holders and contributors"as is" 41 | and any express or implied warranties, including, but not limited to, the 42 | implied warranties of merchantability and fitness for a particular purpose 43 | are disclaimed. In no event shall the copyright holder or contributors be 44 | liable for any direct, indirect, incidental, special, exemplary, or consequential 45 | damages (including, but not limited to, procurement of substitute goods or services; 46 | loss of use, data, or profits; or business interruption) however caused and on any 47 | theory of liability, whether in contract, strict liability, or tort (including 48 | negligence or otherwise) arising in any way out of the use of this software, even if 49 | advised of the possibility of such damage. */ 50 | 51 | #include "PJON_ASK.h" 52 | 53 | /* Initiate PJON passing pin number: 54 | Device's id has to be set through set_id() 55 | before transmitting on the PJON network. */ 56 | 57 | PJON_ASK::PJON_ASK(uint8_t input_pin, uint8_t output_pin) { 58 | this->initialize(input_pin, output_pin); 59 | } 60 | 61 | 62 | /* Initiate PJON passing pin number and the device's id: */ 63 | 64 | PJON_ASK::PJON_ASK(uint8_t input_pin, uint8_t output_pin, uint8_t device_id) { 65 | _device_id = device_id; 66 | this->initialize(input_pin, output_pin); 67 | } 68 | 69 | 70 | /* Initialization tasks: */ 71 | 72 | void PJON_ASK::initialize(uint8_t input_pin, uint8_t output_pin) { 73 | _input_pin = input_pin; 74 | _output_pin = output_pin; 75 | 76 | if(input_pin == NOT_USED || output_pin == NOT_USED) 77 | _simplex = true; 78 | 79 | this->set_error(dummy_error_handler); 80 | this->set_receiver(dummy_receiver_handler); 81 | 82 | for(int i = 0; i < MAX_PACKETS; i++) { 83 | packets[i].state = NULL; 84 | packets[i].timing = 0; 85 | packets[i].attempts = 0; 86 | } 87 | } 88 | 89 | 90 | /* Set the device id, passing a single byte (watch out to id collision) */ 91 | 92 | void PJON_ASK::set_id(uint8_t device_id) { 93 | _device_id = device_id; 94 | } 95 | 96 | 97 | /* Pass as a parameter a void function you previously defined in your code. 98 | This will be called when a correct message will be received. 99 | Inside there you can code how to react when data is received. 100 | 101 | void receiver_function(uint8_t length, uint8_t *payload) { 102 | Serial.print(sender_id); 103 | Serial.print(" "); 104 | 105 | for(int i = 0; i < length; i++) 106 | Serial.print((char)payload[i]); 107 | 108 | Serial.print(" "); 109 | Serial.println(length); 110 | }; 111 | 112 | network.set_receiver(receiver_function); */ 113 | 114 | void PJON_ASK::set_receiver(receiver r) { 115 | _receiver = r; 116 | } 117 | 118 | 119 | /* Pass as a parameter a static void function you previously defined in your code. 120 | This will be called when an error in communication occurs 121 | 122 | static void error_handler(uint8_t code, uint8_t data) { 123 | Serial.print(code); 124 | Serial.print(" "); 125 | Serial.println(data); 126 | }; 127 | 128 | network.set_error(error_handler); */ 129 | 130 | void PJON_ASK::set_error(error e) { 131 | _error = e; 132 | } 133 | 134 | 135 | /* Check if the channel if free for transmission: 136 | If an entire byte received contains no 1s it means 137 | that there is no active transmission */ 138 | 139 | boolean PJON_ASK::can_start() { 140 | pinModeFast(_input_pin, INPUT); 141 | this->send_bit(0, 2); 142 | if(!this->read_byte()) 143 | return true; 144 | 145 | return false; 146 | } 147 | 148 | 149 | /* Send a bit to the pin 150 | digitalWriteFast is used instead of standard digitalWrite 151 | function to optimize transmission time */ 152 | 153 | void PJON_ASK::send_bit(uint8_t VALUE, int duration) { 154 | digitalWriteFast(_output_pin, VALUE); 155 | delayMicroseconds(duration); 156 | } 157 | 158 | 159 | /* Every byte is prepended with 2 synchronization padding bits. The first 160 | is a longer than standard logic 1 followed by a standard logic 0. 161 | __________ ___________________________ 162 | | SyncPad | Byte | 163 | |______ |___ ___ _____ | 164 | | | | | | | | | | | 165 | | | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | 166 | |_|____|___|___|_____|___|___|_____|___| 167 | | 168 | ACCEPTANCE 169 | 170 | The reception tecnique is based on finding a logic 1 as long as the 171 | first padding bit within a certain threshold, synchronizing to its 172 | falling edge and checking if it is followed by a logic 0. If this 173 | pattern is recognised, reception starts, if not, interference, 174 | synchronization loss or simply absence of communication is 175 | detected at byte level. */ 176 | 177 | void PJON_ASK::send_byte(uint8_t b) { 178 | digitalWriteFast(_output_pin, HIGH); 179 | delayMicroseconds(BIT_SPACER); 180 | digitalWriteFast(_output_pin, LOW); 181 | delayMicroseconds(BIT_WIDTH); 182 | 183 | for(uint8_t mask = 0x01; mask; mask <<= 1) { 184 | digitalWriteFast(_output_pin, b & mask); 185 | delayMicroseconds(BIT_WIDTH); 186 | } 187 | } 188 | 189 | 190 | /* An Example of how the string "@" is formatted and sent: 191 | 192 | ID 12 LENGTH 4 CONTENT 64 CRC 130 193 | ________________ ________________ ________________ __________________ 194 | |Sync | Byte |Sync | Byte |Sync | Byte |Sync | Byte | 195 | |___ | __ |___ | _ |___ | _ |___ | _ _ | 196 | | | | | | | | | | | | | | | | | | | | | | | | 197 | | 1 |0|0000|11|00| 1 |0|00000|1|00| 1 |0|0|1|000000| 1 |0|0|1|0000|1|0| 198 | |___|_|____|__|__|___|_|_____|_|__|___|_|_|_|______|___|_|_|_|____|_|_| 199 | 200 | A standard packet transmission is a bidirectional communication between 201 | two devices that can be divided in 3 different phases: 202 | 203 | Channel analysis Transmission Response 204 | _____ _____________________________ _____ 205 | | C-A | | ID | LENGTH | CONTENT | CRC | | ACK | 206 | <--|-----|---------|----|--------|---------|-----|--> <----|-----| 207 | | 0 | | 12 | 4 | 64 | 130 | | 6 | 208 | |_____| |____|________|_________|_____| |_____| */ 209 | 210 | int PJON_ASK::send_string(uint8_t ID, char *string, uint8_t length) { 211 | if (!*string) return FAIL; 212 | 213 | if(!_simplex) 214 | if(!this->can_start()) return BUSY; 215 | 216 | uint8_t CRC = 0; 217 | pinModeFast(_output_pin, OUTPUT); 218 | 219 | this->send_byte(ID); 220 | CRC ^= ID; 221 | this->send_byte(length + 3); 222 | CRC ^= length + 3; 223 | 224 | for(uint8_t i = 0; i < length; i++) { 225 | this->send_byte(string[i]); 226 | CRC ^= string[i]; 227 | } 228 | 229 | this->send_byte(CRC); 230 | digitalWriteFast(_output_pin, LOW); 231 | 232 | if(ID == BROADCAST || _simplex) return ACK; 233 | 234 | unsigned long time = micros(); 235 | int response = FAIL; 236 | 237 | /* Receive byte for an initial BIT_SPACER bit + standard bit total duration. 238 | (freak condition used to avoid micros() overflow bug) */ 239 | while(response == FAIL && !(micros() - time >= BIT_SPACER + BIT_WIDTH)) 240 | response = this->receive_byte(); 241 | 242 | if (response == ACK || response == NAK) return response; 243 | 244 | return FAIL; 245 | }; 246 | 247 | 248 | /* Insert a packet in the send list: 249 | The added packet will be sent in the next update() call. 250 | Using the timing parameter you can set the delay between every 251 | transmission cyclically sending the packet (use remove() function stop it) 252 | 253 | int hi = network.send(99, "HI!", 3, 1000000); // Send hi every second 254 | _________________________________________________________________________ 255 | | | | | | | | | 256 | | device_id | length | content | state | attempts | timing | registration | 257 | |___________|________|_________|_______|__________|________|______________| */ 258 | 259 | int PJON_ASK::send(uint8_t ID, char *packet, uint8_t length, unsigned long timing) { 260 | if(length >= PACKET_MAX_LENGTH) { 261 | this->_error(CONTENT_TOO_LONG, length); 262 | return FAIL; 263 | } 264 | 265 | char *str = (char *) malloc(length); 266 | 267 | if(str == NULL) { 268 | this->_error(MEMORY_FULL, FAIL); 269 | return FAIL; 270 | } 271 | 272 | memcpy(str, packet, length); 273 | 274 | for(uint8_t i = 0; i < MAX_PACKETS; i++) 275 | if(packets[i].state == NULL) { 276 | packets[i].content = str; 277 | packets[i].device_id = ID; 278 | packets[i].length = length; 279 | packets[i].state = TO_BE_SENT; 280 | if(timing > 0) { 281 | packets[i].registration = micros(); 282 | packets[i].timing = timing; 283 | } 284 | return i; 285 | } 286 | 287 | this->_error(PACKETS_BUFFER_FULL, MAX_PACKETS); 288 | return FAIL; 289 | } 290 | 291 | 292 | /* Update the state of the send list and so 293 | check if there are packets to send or erase 294 | the correctly delivered */ 295 | 296 | void PJON_ASK::update() { 297 | for(uint8_t i = 0; i < MAX_PACKETS; i++) { 298 | if(packets[i].state != NULL) 299 | if(micros() - packets[i].registration > packets[i].timing + pow(packets[i].attempts, 2)) 300 | packets[i].state = send_string(packets[i].device_id, packets[i].content, packets[i].length); 301 | 302 | if(packets[i].state == ACK) { 303 | if(!packets[i].timing) 304 | this->remove(i); 305 | else { 306 | packets[i].attempts = 0; 307 | packets[i].registration = micros(); 308 | packets[i].state = TO_BE_SENT; 309 | } 310 | } 311 | if(packets[i].state == FAIL) { 312 | packets[i].attempts++; 313 | 314 | if(packets[i].attempts > MAX_ATTEMPTS) { 315 | this->_error(CONNECTION_LOST, packets[i].device_id); 316 | if(!packets[i].timing) 317 | this->remove(i); 318 | else { 319 | packets[i].attempts = 0; 320 | packets[i].registration = micros(); 321 | packets[i].state = TO_BE_SENT; 322 | } 323 | } 324 | } 325 | } 326 | } 327 | 328 | 329 | /* Remove a packet from the send list: */ 330 | 331 | void PJON_ASK::remove(int id) { 332 | free(packets[id].content); 333 | packets[id].attempts = 0; 334 | packets[id].device_id = NULL; 335 | packets[id].length = NULL; 336 | packets[id].state = NULL; 337 | packets[id].registration = NULL; 338 | } 339 | 340 | /* Check if a byte is coming from the pin: 341 | This function is looking for padding bits before a byte. 342 | If value is 1 for more than ACCEPTANCE and after 343 | that comes a 0 probably a byte is coming: 344 | ________ 345 | | Init | 346 | |--------| 347 | |_____ | 348 | | | | | 349 | |1 | |0 | 350 | |__|__|__| 351 | | 352 | ACCEPTANCE */ 353 | 354 | int PJON_ASK::receive_byte() { 355 | float value = 0.5; 356 | unsigned long time = micros(); 357 | 358 | /* Update pin value until the pin stops to be HIGH or passed more time than 359 | BIT_SPACER duration (freak condition used to avoid micros() overflow bug) */ 360 | while(!(micros() - time > BIT_SPACER) && digitalReadFast(_input_pin)) 361 | value = (value * 0.999) + (digitalReadFast(_input_pin) * 0.001); 362 | 363 | /* Save how much time passed */ 364 | time = micros(); 365 | 366 | /* If pin value is in average more than 0.5, is a 1, and if is more than 367 | ACCEPTANCE (a minimum HIGH duration) and what is coming after is a LOW bit 368 | probably a byte is coming so try to receive it. */ 369 | if(value > 0.5) { 370 | value = 0.5; 371 | 372 | /* (freak condition used to avoid micros() overflow bug) */ 373 | while(!(micros() - time > BIT_WIDTH)) 374 | value = (value * 0.999) + (digitalReadFast(_input_pin) * 0.001); 375 | 376 | if(value < 0.5) return this->read_byte(); 377 | } 378 | return FAIL; 379 | } 380 | 381 | 382 | /* Read a byte from the pin */ 383 | 384 | uint8_t PJON_ASK::read_byte() { 385 | uint8_t byte_value = B00000000; 386 | 387 | for(uint8_t i = 0; i < 8; i++) { 388 | unsigned long time = micros(); 389 | float value = 0.5; 390 | /* (freak condition used to avoid micros() overflow bug) */ 391 | while(!(micros() - time > BIT_WIDTH)) 392 | value = ((value * 0.999) + (digitalReadFast(_input_pin) * 0.001)); 393 | 394 | byte_value += (value > 0.5) << i; 395 | } 396 | return byte_value; 397 | } 398 | 399 | 400 | /* Try to receive a string from the pin: */ 401 | 402 | int PJON_ASK::receive() { 403 | int state; 404 | int package_length = PACKET_MAX_LENGTH; 405 | uint8_t CRC = 0; 406 | 407 | for (uint8_t i = 0; i < package_length; i++) { 408 | data[i] = state = this->receive_byte(); 409 | 410 | if (state == FAIL) return FAIL; 411 | 412 | if(i == 0 && data[i] != _device_id && data[i] != BROADCAST) 413 | return BUSY; 414 | 415 | if(i == 1) 416 | if(data[i] > 3 && data[i] < PACKET_MAX_LENGTH) 417 | package_length = data[i]; 418 | else return FAIL; 419 | 420 | CRC ^= data[i]; 421 | } 422 | 423 | if (!CRC) { 424 | if(data[0] != BROADCAST && !_simplex) { 425 | pinModeFast(_output_pin, OUTPUT); 426 | this->send_byte(ACK); 427 | digitalWriteFast(_input_pin, LOW); 428 | } 429 | this->_receiver(data[1] - 3, data + 2); 430 | return ACK; 431 | } else { 432 | if(data[0] != BROADCAST && !_simplex) { 433 | pinModeFast(_output_pin, OUTPUT); 434 | this->send_byte(NAK); 435 | digitalWriteFast(_input_pin, LOW); 436 | } 437 | return NAK; 438 | } 439 | } 440 | 441 | 442 | /* Try to receive a string from the pin repeatedly: */ 443 | 444 | int PJON_ASK::receive(unsigned long duration) { 445 | int response; 446 | long time = micros(); 447 | /* (freak condition used to avoid micros() overflow bug) */ 448 | while(!(micros() - time >= duration)) { 449 | response = this->receive(); 450 | if(response == ACK) 451 | return ACK; 452 | } 453 | return response; 454 | } 455 | -------------------------------------------------------------------------------- /PJON_ASK.h: -------------------------------------------------------------------------------- 1 | 2 | /*-O//\ __ __ 3 | |-gfo\ |__| | | | |\ | 4 | |!y°o:\ | __| |__| | \| v1.0 5 | |y"s§+`\ Giovanni Blu Mitolo 2012 - 2015 6 | /so+:-..`\ gioscarab@gmail.com 7 | |+/:ngr-*.`\ 8 | |5/:%&-a3f.:;\ PJON_ASK is a device communications bus system that connects up to 255 9 | \+//u/+g%{osv,,\ arduino boards over one wire up to 5.29kB/s data communication speed. 10 | \=+&/osw+olds.\\ Contains acknowledge, collision detection, CRC and encpryption all done 11 | \:/+-.-°-:+oss\ with micros() and delayMicroseconds(), with no use of interrupts or timers. 12 | | | \oy\\ Pull down resistor on the bus is generally used to reduce interference. 13 | > < 14 | _____-| |-________________________________________________________________________ 15 | | BIT_WIDTH 512 | BIT_SPACER 328 | | 16 | |----------------------------------------------------------------------------------| 17 | |Transfer speed: 202 B/s | Absolute bandwidth: 202 B/s | 18 | |Baud rate: 1620 baud | Data throughput: 150 B/s | 19 | |__________________________________________________________________________________| 20 | 21 | 22 | Copyright (c) 2012-2015, Giovanni Blu Mitolo All rights reserved. 23 | 24 | Redistribution and use in source and binary forms, with or without 25 | modification, are permitted provided that the following conditions are met: 26 | - Redistributions of source code must retain the above copyright 27 | notice, this list of conditions and the following disclaimer. 28 | 29 | - Redistributions in binary form must reproduce the above copyright 30 | notice, this list of conditions and the following disclaimer in the 31 | documentation and/or other materials provided with the distribution. 32 | 33 | - All advertising materials mentioning features or use of this software 34 | must display the following acknowledgement: 35 | This product includes PJON_ASK software developed by Giovanni Blu Mitolo. 36 | 37 | - Neither the name of PJON, PJON_ASK nor the 38 | names of its contributors may be used to endorse or promote products 39 | derived from this software without specific prior written permission. 40 | 41 | This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, 42 | but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event 43 | shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential 44 | damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business 45 | interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence 46 | or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. */ 47 | 48 | #ifndef PJON_ASK_h 49 | #define PJON_ASK_h 50 | 51 | #include "includes/digitalWriteFast.h" 52 | #include "Arduino.h" 53 | 54 | /* The following constants setup is quite conservative and determined only 55 | with a huge amount of time and blind testing (without oscilloscope) 56 | tweaking values and analysing results. Theese can be changed to obtain 57 | faster speed. Probably you need experience, time and an oscilloscope. */ 58 | 59 | #define BIT_WIDTH 512 60 | #define BIT_SPACER 328 61 | #endif 62 | 63 | #define ACK 6 64 | #define NAK 21 65 | #define FAIL 0x100 66 | #define BUSY 666 67 | #define BROADCAST 124 68 | #define TO_BE_SENT 74 69 | 70 | #define NOT_USED 9999 71 | 72 | // Errors 73 | #define CONNECTION_LOST 101 74 | #define PACKETS_BUFFER_FULL 102 75 | #define MEMORY_FULL 103 76 | #define CONTENT_TOO_LONG 104 77 | 78 | // Maximum sending attempts before throwing CONNECTON_LOST error 79 | #define MAX_ATTEMPTS 250 80 | 81 | // Packets buffer length, if full PACKET_BUFFER_FULL error is thrown 82 | #define MAX_PACKETS 10 83 | 84 | // Max packet length, higher if necessary (affects memory) 85 | #define PACKET_MAX_LENGTH 50 86 | 87 | struct packet { 88 | uint8_t attempts; 89 | uint8_t device_id; 90 | char *content; 91 | uint8_t length; 92 | unsigned long registration; 93 | int state; 94 | unsigned long timing; 95 | }; 96 | 97 | typedef void (* receiver)(uint8_t length, uint8_t *payload); 98 | typedef void (* error)(uint8_t code, uint8_t data); 99 | 100 | static void dummy_error_handler(uint8_t code, uint8_t data) {}; 101 | static void dummy_receiver_handler(uint8_t length, uint8_t *payload) {}; 102 | 103 | class PJON_ASK { 104 | 105 | public: 106 | PJON_ASK(uint8_t input_pin, uint8_t output_pin, uint8_t device_id); 107 | PJON_ASK(uint8_t input_pin, uint8_t output_pin); 108 | 109 | void initialize(uint8_t input_pin, uint8_t output_pin); 110 | 111 | void set_id(uint8_t id); 112 | void set_receiver(receiver r); 113 | void set_error(error e); 114 | 115 | int receive_byte(); 116 | int receive(); 117 | int receive(unsigned long duration); 118 | 119 | void send_bit(uint8_t VALUE, int duration); 120 | void send_byte(uint8_t b); 121 | int send_string(uint8_t ID, char *string, uint8_t length); 122 | int send(uint8_t ID, char *packet, uint8_t length, unsigned long timing = 0); 123 | 124 | void update(); 125 | void remove(int id); 126 | 127 | uint8_t read_byte(); 128 | boolean can_start(); 129 | 130 | uint8_t data[PACKET_MAX_LENGTH]; 131 | packet packets[MAX_PACKETS]; 132 | 133 | private: 134 | uint8_t _device_id; 135 | int _input_pin; 136 | int _output_pin; 137 | boolean _simplex; 138 | receiver _receiver; 139 | error _error; 140 | }; 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![PJON_ASK](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) 2 | ## PJON_ASK v1.0 stable 3 | ##### Warning: Obsolete codebase, PJON_ASK has been integrated in the PJON repository, see [OverSampling](https://github.com/gioblu/PJON/wiki/OverSampling) 4 | 5 | PJON_ASK was an early implementation of the [PJON Standard](https://github.com/gioblu/PJON/wiki), designed to be compatible with noisy and unreliable media like cheap 315/433Mhz ASK/FSK/OOK radio transceivers. 6 | 7 | #### What is PJON? 8 | [PJON](https://github.com/gioblu/PJON) (Padded Jittering Operative Network) is an Arduino compatible, multi-master, multi-media communications bus system. It proposes a Standard and it is designed as a framework for digital communication. It is a valid alternative to i2c, 1-Wire, Serial and other Arduino compatible protocols. If you are interested to know more about the PJON Standard, visit the [Wiki](https://github.com/gioblu/PJON/wiki). If you need help see the [documentation](https://github.com/gioblu/PJON/wiki/Documentation) or if something is not working visit the [Troubleshooting page](https://github.com/gioblu/PJON/wiki/Troubleshooting). If you own a Saleae Logic Analyzer see [saleae-pjon-protocol-analyzer](https://github.com/aperepel/saleae-pjon-protocol-analyzer) crafted by Andrew Grande. 9 | 10 | [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Donate](http://img.shields.io/paypal/donate.png?color=blue)](https://www.paypal.me/PJON) 11 | 12 | #### Features 13 | - Device id implementation to enable univocal communication up to 254 devices 14 | - Bus id implementation to optionally enable shared medium communication 15 | - Multi media compatibility (wires up to 50m, radio up to 5km) 16 | - Physical layer abstraction 17 | - 2 pin compatibility to enable twisted pair / radio modules 18 | - Optional auto-addressing with id collision avoidance (experimental) 19 | - CRC8 table-less cyclic redundancy check implementation 20 | - Acknowledgement of correct packet sending 21 | - Collision avoidance to enable multi-master capability 22 | - Broadcast functionality to contact all connected devices 23 | - Packet manager to track and retransmit a failed packet sending in background 24 | - Error handling 25 | 26 | #### Compatibility 27 | - ATmega88/168/328 16Mhz (Diecimila, Duemilanove, Uno, Nano, Mini, Lillypad) 28 | - ATmega2560 16Mhz (Arduino Mega) 29 | - ATmega16u4/32u4 16Mhz (Arduino Leonardo) 30 | - ATtiny45/85 8Mhz, see https://github.com/gioblu/PJON/wiki/ATtiny-interfacing 31 | - SAMD (Arduino Zero) 32 | - ESP8266 v.1-7 80Mhz "AI-THINKER AT" firmware, see https://github.com/esp8266/Arduino 33 | - ESP8266 NodeMCU v0.9-1.0 80Mhz, see https://github.com/esp8266/Arduino 34 | - MK20DX256 96Mhz (Teensy 3.1) 35 | 36 | #### License 37 | 38 | ```cpp 39 | /* Copyright 2012-2016 Giovanni Blu Mitolo 40 | 41 | Licensed under the Apache License, Version 2.0 (the "License"); 42 | you may not use this file except in compliance with the License. 43 | You may obtain a copy of the License at 44 | 45 | http://www.apache.org/licenses/LICENSE-2.0 46 | 47 | Unless required by applicable law or agreed to in writing, software 48 | distributed under the License is distributed on an "AS IS" BASIS, 49 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 50 | See the License for the specific language governing permissions and 51 | limitations under the License. */ 52 | ``` 53 | -------------------------------------------------------------------------------- /examples/BlinkTest/Receiver/Receiver.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 44); 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | network.set_receiver(receiver_function); 9 | pinMode(13, OUTPUT); 10 | digitalWrite(13, LOW); 11 | }; 12 | 13 | static void receiver_function(uint8_t length, uint8_t *payload) { 14 | if(payload[0] == 'B') { 15 | Serial.println("BLINK"); 16 | digitalWrite(13, HIGH); 17 | delay(30); 18 | digitalWrite(13, LOW); 19 | } 20 | } 21 | 22 | void loop() { 23 | network.receive(1000); 24 | }; 25 | -------------------------------------------------------------------------------- /examples/BlinkTest/Transmitter/Transmitter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 45); 5 | 6 | void setup() { 7 | // Send B to device 44 every second 8 | network.send(44, "B", 1, 1000000); 9 | } 10 | 11 | void loop() { 12 | network.update(); 13 | }; -------------------------------------------------------------------------------- /examples/NetworkAnalysis/Receiver/Receiver.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 44); 5 | 6 | void setup() { 7 | Serial.begin(115200); 8 | }; 9 | 10 | void loop() { 11 | 12 | /* 13 | receive() function without parameter 14 | should not be used because is a low level 15 | function and is not aware of packets. Here is 16 | is used only to detect the maximum bandwidth. 17 | */ 18 | 19 | network.receive(); 20 | }; -------------------------------------------------------------------------------- /examples/NetworkAnalysis/Transmitter/Transmitter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float test; 4 | float mistakes; 5 | int busy; 6 | int fail; 7 | 8 | // network(Arduino pin used, selected device id) 9 | PJON_ASK network(11, 12, 45); 10 | 11 | int packet; 12 | char content[] = "01234567890123456789"; 13 | 14 | void setup() { 15 | Serial.begin(115200); 16 | 17 | Serial.println("PJON_ASK - Network analysis"); 18 | Serial.println("Starting a 10 seconds communication test.."); 19 | Serial.println(); 20 | } 21 | 22 | void loop() { 23 | long time = millis(); 24 | while(millis() - time < 10000) { 25 | 26 | /* 27 | Here send_string low level function is used to 28 | be able to catch every single sending result. 29 | */ 30 | 31 | int response = network.send_string(44, content, 20); 32 | if(response == ACK) 33 | test++; 34 | if(response == NAK) 35 | mistakes++; 36 | if(response == BUSY) 37 | busy++; 38 | if(response == FAIL) 39 | fail++; 40 | delayMicroseconds(14); 41 | } 42 | 43 | Serial.print("Absolute com speed: "); 44 | Serial.print( (test * 24 ) / 10 ); 45 | Serial.println("B/s"); 46 | Serial.print("Practical bandwidth: "); 47 | Serial.print( (test * 20 ) / 10 ); 48 | Serial.println("B/s"); 49 | Serial.print("Packets sent: "); 50 | Serial.println(test); 51 | Serial.print("Mistakes (error found with CRC) "); 52 | Serial.println(mistakes); 53 | Serial.print("Fail (no answer from receiver) "); 54 | Serial.println(fail); 55 | Serial.print("Busy (Channel is busy or affected by interference) "); 56 | Serial.println(busy); 57 | Serial.print("Accuracy: "); 58 | Serial.print(100 - (100 / (test / mistakes))); 59 | Serial.println(" %"); 60 | Serial.println(" --------------------- "); 61 | 62 | test = 0; 63 | mistakes = 0; 64 | busy = 0; 65 | fail = 0; 66 | }; -------------------------------------------------------------------------------- /examples/SendArbitraryValues/Receiver/Receiver.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 44); 5 | 6 | void setup() { 7 | Serial.begin(115200); 8 | network.set_receiver(receiver_function); 9 | }; 10 | 11 | static void receiver_function(uint8_t length, uint8_t *payload) { 12 | if((char)payload[0] == 'T') { 13 | Serial.print("Temperature received: "); 14 | Serial.print(payload[1] << 8 | payload[2] & 0xFF); 15 | // Get back the original integer from the 2 separate bytes 16 | } 17 | Serial.println(); 18 | } 19 | 20 | void loop() { 21 | network.receive(1000); 22 | }; 23 | -------------------------------------------------------------------------------- /examples/SendArbitraryValues/Transmitter/Transmitter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 45); 5 | 6 | void setup() { 7 | Serial.begin(115200); 8 | network.set_error(error_handler); 9 | } 10 | 11 | static void error_handler(uint8_t code, uint8_t data) { 12 | if(code == CONNECTION_LOST) { 13 | Serial.print("Connection lost with device id "); 14 | Serial.println(data); 15 | } 16 | } 17 | 18 | 19 | unsigned long time = millis(); 20 | 21 | void loop() { 22 | 23 | if(millis() - time > 1000) { 24 | time = millis(); 25 | int temperature = analogRead(A0); 26 | 27 | //Send a "T", break the int in two bytes 28 | char content[3] = {'T', temperature >> 8, temperature & 0xFF}; 29 | 30 | network.send(44, content, 3); 31 | } 32 | 33 | network.update(); 34 | }; -------------------------------------------------------------------------------- /examples/SpeedTest/Receiver/Receiver.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float test; 4 | float mistakes; 5 | 6 | // network(Arduino pin used, selected device id) 7 | PJON_ASK network(11, 12, 44); 8 | 9 | void setup() { 10 | Serial.begin(115200); 11 | network.set_receiver(receiver_function); 12 | }; 13 | 14 | static void receiver_function(uint8_t length, uint8_t *payload) { 15 | // Primitive connection quality graph 16 | Serial.print("-"); 17 | } 18 | 19 | void loop() { 20 | long time = millis(); 21 | int response = 0; 22 | while(millis() - time < 1000) { 23 | response = network.receive(1000); 24 | if(response == ACK) 25 | test++; 26 | if(response == NAK) 27 | mistakes++; 28 | } 29 | 30 | Serial.println(); 31 | Serial.print("Absolute com speed: "); 32 | Serial.print(test * 13); 33 | Serial.print(" B/s |Practical bandwidth: "); 34 | Serial.print(test * 10); 35 | Serial.print(" B/s |Packets sent: "); 36 | Serial.print(test); 37 | Serial.print(" |Mistakes "); 38 | Serial.print(mistakes); 39 | Serial.print(" |Accuracy: "); 40 | Serial.print(100 - (100 / (test / mistakes))); 41 | Serial.print(" %"); 42 | Serial.println(); 43 | 44 | if(mistakes > test / 4 || test == 0) { 45 | Serial.println("Check wiring!"); 46 | Serial.println("1) Check wiring connections of both modules."); 47 | Serial.println("2) Transmitter voltage source has to be regulated."); 48 | } 49 | 50 | test = 0; 51 | mistakes = 0; 52 | }; -------------------------------------------------------------------------------- /examples/SpeedTest/Transmitter/Transmitter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // network(Arduino pin used, selected device id) 4 | PJON_ASK network(11, 12, 45); 5 | 6 | int packet; 7 | char content[] = "0123456789"; 8 | 9 | void setup() { 10 | Serial.begin(115200); 11 | packet = network.send(44, content, 10); 12 | network.set_error(error_handler); 13 | } 14 | 15 | static void error_handler(uint8_t code, uint8_t data) { 16 | if(code == CONNECTION_LOST) { 17 | Serial.print("Connection lost with device id "); 18 | Serial.println(data); 19 | } 20 | } 21 | 22 | void loop() { 23 | if(!network.packets[packet].state) 24 | packet = network.send(44, content, 10); 25 | 26 | network.update(); 27 | }; -------------------------------------------------------------------------------- /includes/digitalWriteFast.h: -------------------------------------------------------------------------------- 1 | 2 | /* Updated version of digitalWriteFast library with ATmega 1280/2560 and ATtiny25/45/85 support 3 | Copyright (c) 2012-2015, Giovanni Blu Mitolo All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | - All advertising materials mentioning features or use of this software 16 | must display the following acknowledgement: 17 | "This product includes digitalWriteFast software developed by Giovanni Blu Mitolo." 18 | 19 | - Neither the name of PJON, PJON_ASK, digitalWriteFast nor the 20 | names of its contributors may be used to endorse or promote products 21 | derived from this software without specific prior written permission. 22 | 23 | This software is provided by the copyright holders and contributors"as is" 24 | and any express or implied warranties, including, but not limited to, the 25 | implied warranties of merchantability and fitness for a particular purpose 26 | are disclaimed. In no event shall the copyright holder or contributors be 27 | liable for any direct, indirect, incidental, special, exemplary, or consequential 28 | damages (including, but not limited to, procurement of substitute goods or services; 29 | loss of use, data, or profits; or business interruption) however caused and on any 30 | theory of liability, whether in contract, strict liability, or tort (including 31 | negligence or otherwise) arising in any way out of the use of this software, even if 32 | advised of the possibility of such damage. */ 33 | 34 | #if defined(ARDUINO) && (ARDUINO >= 100) 35 | #include "Arduino.h" 36 | #else 37 | #include "WProgram.h" 38 | #include 39 | #endif 40 | 41 | #define BIT_READ(value, bit) (((value) >> (bit)) & 0x01) 42 | #define BIT_SET(value, bit) ((value) |= (1UL << (bit))) 43 | #define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit))) 44 | #define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit)) 45 | 46 | #if !defined(digitalPinToPortReg) 47 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 48 | // Arduino Mega Pins 49 | #define digitalPinToPortReg(P) \ 50 | (((P) >= 22 && (P) <= 29) ? &PORTA : \ 51 | ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \ 52 | (((P) >= 30 && (P) <= 37) ? &PORTC : \ 53 | ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \ 54 | ((((P) >= 0 && (P) <= 3) || (P) == 5) ? &PORTE : \ 55 | (((P) >= 54 && (P) <= 61) ? &PORTF : \ 56 | ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \ 57 | ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \ 58 | (((P) == 14 || (P) == 15) ? &PORTJ : \ 59 | (((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL)))))))))) 60 | 61 | #define digitalPinToDDRReg(P) \ 62 | (((P) >= 22 && (P) <= 29) ? &DDRA : \ 63 | ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \ 64 | (((P) >= 30 && (P) <= 37) ? &DDRC : \ 65 | ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \ 66 | ((((P) >= 0 && (P) <= 3) || (P) == 5) ? &DDRE : \ 67 | (((P) >= 54 && (P) <= 61) ? &DDRF : \ 68 | ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \ 69 | ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \ 70 | (((P) == 14 || (P) == 15) ? &DDRJ : \ 71 | (((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL)))))))))) 72 | 73 | #define digitalPinToPINReg(P) \ 74 | (((P) >= 22 && (P) <= 29) ? &PINA : \ 75 | ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \ 76 | (((P) >= 30 && (P) <= 37) ? &PINC : \ 77 | ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \ 78 | ((((P) >= 0 && (P) <= 3) || (P) == 5) ? &PINE : \ 79 | (((P) >= 54 && (P) <= 61) ? &PINF : \ 80 | ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \ 81 | ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \ 82 | (((P) == 14 || (P) == 15) ? &PINJ : \ 83 | (((P) >= 62 && (P) <= 69) ? &PINK : &PINL)))))))))) 84 | 85 | #define __digitalPinToBit(P) \ 86 | (((P) >= 7 && (P) <= 9) ? (P) - 3 : \ 87 | (((P) >= 10 && (P) <= 13) ? (P) - 6 : \ 88 | (((P) >= 22 && (P) <= 29) ? (P) - 22 : \ 89 | (((P) >= 30 && (P) <= 37) ? 37 - (P) : \ 90 | (((P) >= 39 && (P) <= 41) ? 41 - (P) : \ 91 | (((P) >= 42 && (P) <= 49) ? 49 - (P) : \ 92 | (((P) >= 50 && (P) <= 53) ? 53 - (P) : \ 93 | (((P) >= 54 && (P) <= 61) ? (P) - 54 : \ 94 | (((P) >= 62 && (P) <= 69) ? (P) - 62 : \ 95 | (((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \ 96 | (((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \ 97 | (((P) == 19) ? 2 : \ 98 | (((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \ 99 | (((P) == 2) ? 4 : \ 100 | (((P) == 3 || (P) == 4) ? 5 : 7))))))))))))))) 101 | 102 | // 15 PWM 103 | #define __digitalPinToTimer(P) \ 104 | (((P) == 13 || (P) == 4) ? &TCCR0A : \ 105 | (((P) == 11 || (P) == 12) ? &TCCR1A : \ 106 | (((P) == 10 || (P) == 9) ? &TCCR2A : \ 107 | (((P) == 5 || (P) == 2 || (P) == 3) ? &TCCR3A : \ 108 | (((P) == 6 || (P) == 7 || (P) == 8) ? &TCCR4A : \ 109 | (((P) == 46 || (P) == 45 || (P) == 44) ? &TCCR5A : 0)))))) 110 | 111 | #define __digitalPinToTimerBit(P) \ 112 | (((P) == 13) ? COM0A1 : (((P) == 4) ? COM0B1 : \ 113 | (((P) == 11) ? COM1A1 : (((P) == 12) ? COM1B1 : \ 114 | (((P) == 10) ? COM2A1 : (((P) == 9) ? COM2B1 : \ 115 | (((P) == 5) ? COM3A1 : (((P) == 2) ? COM3B1 : (((P) == 3) ? COM3C1 : \ 116 | (((P) == 6) ? COM4A1 : (((P) == 7) ? COM4B1 : (((P) == 8) ? COM4C1 : \ 117 | (((P) == 46) ? COM5A1 : (((P) == 45) ? COM5B1 : COM5C1)))))))))))))) 118 | 119 | #else 120 | 121 | #if defined(__AVR_ATmega8__) // PWM ATmega 8 122 | #define __digitalPinToTimer(P) \ 123 | (((P) == 9 || (P) == 10) ? &TCCR1A : (((P) == 11) ? &TCCR2 : 0)) 124 | #define __digitalPinToTimerBit(P) \ 125 | (((P) == 9) ? COM1A1 : (((P) == 10) ? COM1B1 : COM21)) 126 | #endif 127 | 128 | #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) 129 | #define digitalPinToPortReg(P) \ 130 | (((P) >= 0 && (P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC)) 131 | 132 | #define digitalPinToDDRReg(P) \ 133 | (((P) >= 0 && (P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC)) 134 | 135 | #define digitalPinToPINReg(P) \ 136 | (((P) >= 0 && (P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC)) 137 | 138 | #define __digitalPinToBit(P) \ 139 | (((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14)) 140 | 141 | // 6 PWM 142 | #define __digitalPinToTimer(P) \ 143 | (((P) == 6 || (P) == 5) ? &TCCR0A : \ 144 | (((P) == 9 || (P) == 10) ? &TCCR1A : \ 145 | (((P) == 11 || (P) == 3) ? &TCCR2A : 0))) 146 | 147 | #define __digitalPinToTimerBit(P) \ 148 | (((P) == 6) ? COM0A1 : (((P) == 5) ? COM0B1 : \ 149 | (((P) == 9) ? COM1A1 : (((P) == 10) ? COM1B1 : \ 150 | (((P) == 11) ? COM2A1 : COM2B1))))) 151 | #endif 152 | 153 | #if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) 154 | #define digitalPinToPortReg(P) \ 155 | &PORTB 156 | 157 | #define digitalPinToDDRReg(P) \ 158 | &DDRB 159 | 160 | #define digitalPinToPINReg(P) \ 161 | &PINB 162 | 163 | #define __digitalPinToBit(P) \ 164 | P - 6 165 | #endif 166 | 167 | #endif 168 | #endif 169 | 170 | 171 | #define __atomicWrite__(A,P,V) \ 172 | if ( (int)(A) < 0x40) { bitWrite(*(A), __digitalPinToBit(P), (V) );} \ 173 | else { \ 174 | uint8_t register saveSreg = SREG; \ 175 | cli(); \ 176 | bitWrite(*(A), __digitalPinToBit(P), (V) ); \ 177 | SREG=saveSreg; \ 178 | } 179 | 180 | #ifndef digitalWriteFast 181 | #define digitalWriteFast(P, V) \ 182 | do { \ 183 | if (__builtin_constant_p(P) && __builtin_constant_p(V)) __atomicWrite__((uint8_t*) digitalPinToPortReg(P),P,V) \ 184 | else digitalWrite((P), (V)); \ 185 | } while (0) 186 | #endif //#ifndef digitalWriteFast2 187 | 188 | #if !defined(pinModeFast) 189 | #define pinModeFast(P, V) \ 190 | do { if (__builtin_constant_p(P) && __builtin_constant_p(V)) __atomicWrite__((uint8_t*) digitalPinToDDRReg(P),P,V) \ 191 | else pinMode((P), (V)); \ 192 | } while (0) 193 | #endif 194 | 195 | #ifndef noAnalogWrite 196 | #define noAnalogWrite(P) \ 197 | do { if (__builtin_constant_p(P) ) __atomicWrite((uint8_t*) __digitalPinToTimer(P),P,0) \ 198 | else turnOffPWM((P)); \ 199 | } while (0) 200 | #endif 201 | 202 | #ifndef digitalReadFast 203 | #define digitalReadFast(P) ( (int) _digitalReadFast_((P)) ) 204 | #define _digitalReadFast_(P ) \ 205 | (__builtin_constant_p(P) ) ? ( \ 206 | ( BIT_READ(*digitalPinToPINReg(P), __digitalPinToBit(P))) ) : \ 207 | digitalRead((P)) 208 | #endif 209 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PJON 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PJON KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | update KEYWORD2 16 | send KEYWORD2 17 | remove KEYWORD2 18 | send_bit KEYWORD2 19 | send_byte KEYWORD2 20 | send_string KEYWORD2 21 | syncronization_bit KEYWORD2 22 | read_byte KEYWORD2 23 | can_start KEYWORD2 24 | receive_byte KEYWORD2 25 | receive KEYWORD2 26 | 27 | ####################################### 28 | # Instances (KEYWORD2) 29 | ####################################### 30 | 31 | 32 | ####################################### 33 | # Constants (LITERAL1) 34 | ####################################### 35 | 36 | ACK LITERAL1 37 | NAK LITERAL1 38 | FAIL LITERAL1 39 | BUSY LITERAL1 40 | BROADCAST LITERAL1 41 | TO_BE_SENT LITERAL1 42 | CMD LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=PJON_ASK 2 | version=1.0 3 | author=Giovanni Blu Mitolo 4 | maintainer=Giovanni Blu Mitolo 5 | sentence=PJON_ASK is a PJON communication bus system implementation over cheap ASK 433Mhz radio transceivers 6 | paragraph=Provides radio data communication with acknowledge, collision detection, CRC and encpryption all done with micros() and delayMicroseconds(), without using interrupt or timers. 7 | category=Communication 8 | url=https://github.com/gioblu/PJON_ASK 9 | architectures=avr 10 | --------------------------------------------------------------------------------