Twórcy biblioteki PJON napisali:
Dzięki PJON® (Padded Jittering Operative Network) z dużą elastycznością i bez potrzeby korzystania z usług zewnętrznego dostawcy lub usługi w chmurze możesz bezpiecznie łączyć sprzęt i produkty elektroniki użytkowej. Dołącz do rewolucji.
Czy to naprawdę rewolucja w łączeniu czujników z platformami i platform między sobą w różny sposób? Zobaczymy.
Spis treści
- Wysyłka przez WiFi. Najprostsza konfiguracja.
- Strategia Medium Wire
- Łączenie ESP32 z ESP8266
- Voltage tester device, czyli PJON w praktyce
- Linki
<a href="#nazwa_etykiety">opis odsyłacza</a>
(...)
<a name="nazwa_etykiety">(opis etykiety)</a>
1. Wysyłka przez WiFi. Najprostsza konfiguracja
Transmitter_v2 ESP32 lub ESP8266
#include <PJON.h>
#include <credentials.h> // plik w którym przechowuję mój ssid oraz password
// <Strategy name> bus(selected device id)
PJON<DualUDP> bus(45);
//const char* ssid = "MyNetworkSSID";
//const char* password = "MyNetworkPassword";
uint8_t content[] = "01234567890123456789";
void setup() {
Serial.begin(115200);
Serial.println("Transmitter started.");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
bus.set_communication_mode(PJON_SIMPLEX);
bus.begin();
bus.send(44, content, 20);
}
void loop() {
if(!bus.update()) // If all packets are delivered, send another
bus.send(44, content, 20);
};
Receiver_v2 ESP32 lub ESP8266
#include <PJON.h>
#include <credentials.h>
// <Strategy name> bus(selected device id)
PJON<DualUDP> bus(44);
//const char* ssid = "MyNetworkSSID";
//const char* password = "MyNetworkPassword";
float test;
float mistakes;
int busy;
int fail;
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
// Do nothing to avoid affecting speed analysis
}
void setup() {
Serial.begin(115200);
Serial.println("Receiver started.");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.printf("Now listening at IP %s\n", WiFi.localIP().toString().c_str());
bus.set_receiver(receiver_function);
bus.set_communication_mode(PJON_SIMPLEX);
bus.begin();
};
void loop() {
Serial.println("Starting 1 second communication speed test...");
long time = millis();
unsigned int response = 0;
while(millis() - time < 1000) {
response = bus.receive();
if(response == PJON_ACK)
test++;
if(response == PJON_NAK)
mistakes++;
if(response == PJON_BUSY)
busy++;
if(response == PJON_FAIL)
fail++;
}
Serial.print("Bandwidth: ");
Serial.print(test * (20 + bus.packet_overhead(bus.data[1])));
Serial.println("B/s");
Serial.print("Data throughput: ");
Serial.print(test * 20);
Serial.println("B/s");
Serial.print("Packets sent: ");
Serial.println(test);
Serial.print("Mistakes (error found with CRC): ");
Serial.println(mistakes);
Serial.print("Fail (no data found): ");
Serial.println(fail);
Serial.print("Busy (Channel is busy or affected by interference): ");
Serial.println(busy);
Serial.print("Accuracy: ");
Serial.print(100 - (100 / (test / mistakes)));
Serial.println(" %");
Serial.println(" --------------------- ");
// Avoid Serial interference during test flushing
Serial.flush();
test = 0;
mistakes = 0;
busy = 0;
fail = 0;
};
2. Strategia Medium Wire
bus.strategy.set_pin(12);
strategia: SoftwareBitBang
1. Łączymy dwie płytki Arduino (u mnie UNO z Nano) przez pin 12
device1
//device1
#include <PJON.h>
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 2};
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 44); // 1 Strategia Medium Wire, piny w użyciu: 1 lub 2
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
/* Make use of the payload before sending something, the buffer where payload points to is
overwritten when a new message is dispatched */
if ((char)payload[0] == 'B') {
if (!bus.update()) // If all packets are delivered, send another
bus.reply("A", 1);
Serial.print("device1 - ");
Serial.println((char)(payload[0]));
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
//delay(2000);
}
};
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off
bus.strategy.set_pin(12);
bus.set_receiver(receiver_function);
bus.begin();
bus.send(45, "B", 1);
Serial.begin(115200);
};
void loop() {
bus.receive(5000);
bus.update();
};
device2
//device2
#include <PJON.h>
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 2};
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 45);
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
/* Make use of the payload before sending something, the buffer where payload points to is
overwritten when a new message is dispatched */
if ((char)payload[0] == 'A') {
if (!bus.update()) // If all packets are delivered, send another
bus.reply("B", 1);
Serial.print("device 2 - ");
Serial.println((char)(payload[0]));
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
};
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off
bus.strategy.set_pin(12);
bus.set_receiver(receiver_function);
bus.begin();
bus.send(44, "B", 1);
Serial.begin(115200);
};
void loop() {
bus.receive(5000);
bus.update();
};
2. Połączyłem też dwa ESP8266 NodeMCU zmieniając bus.strategy.set_pin(4);
(D2) – działa. Na D1 (GPIO5) też działa.
Uwaga! Po podłączeniu czasem nic się nie dzieje. Trzeba zresetować device2. Reset device1 nie pomaga.
3. Dwa ESP32 na pinach 17 działają. Gdy device2 zmieniłem bus.strategy.set_pin(18);
też było OK.
3. Łączenie ESP32 z ESP8266
device 1 ESP8266 PIN D1(GPIO 5) <-> device 2 ESP32 (D1 R32) PIN12
device 1 ESP8266 PIN D1(GPIO 5) <-> device 2 ESP32 (D1 MINI HW-665) PIN25, PIN12 (TDI), PIN04
Device1_ESP8266_mix
/*
* Device1_ESP8266_mix
* Komplementarny z Device2_ESP32_mix
*/
#include <PJON.h>
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 100); // 1 Strategia Medium Wire, piny w użyciu: 1 lub 2
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
/* Make use of the payload before sending something, the buffer where payload points to is
overwritten when a new message is dispatched */
if ((char)payload[0] == 'B') {
if (!bus.update()) // If all packets are delivered, send another
bus.reply("Aida", 4);
Serial.print("device1 - ");
Serial.println((char)(payload[0]));
digitalWrite(LED_BUILTIN, LOW);
delay(1200);
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
//delay(2000);
}
};
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); // Initialize LED 13 to be off
bus.strategy.set_pin(15); // ESP8266 pin D8
bus.set_receiver(receiver_function);
bus.begin();
bus.send(101, "Biba", 4);
Serial.begin(115200);
};
void loop() {
bus.receive(5000);
bus.update();
};
Device2_ESP32_mix
/*
* Device2_ESP32_mix
* Komplementarny z Device1_ESP8266_mix
*/
#include <PJON.h>
#define LED 2
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 101);
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
/* Make use of the payload before sending something, the buffer where payload points to is
overwritten when a new message is dispatched */
if ((char)payload[0] == 'A') {
if (!bus.update()) // If all packets are delivered, send another
bus.reply("Biba", 4);
Serial.print("device 2 - ");
for(int i=0; i<length; i++){
Serial.print((char)(payload[i]));}
Serial.println();
digitalWrite(LED, HIGH);
delay(1200);
digitalWrite(LED, LOW);
delay(200);
}
};
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW); // Initialize LED BUILT IN to be off
bus.strategy.set_pin(4); // ESP32 PIN IO4
bus.set_receiver(receiver_function);
bus.begin();
bus.send(100, "Biba", 4);
Serial.begin(115200);
};
void loop() {
bus.receive(5000);
bus.update();
};
DOKUMENTACJA
- https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive
- https://www.pjon.org/SoftwareBitBang.php
4. Voltage tester device, czyli PJON w praktyce
Świetny przykład wykorzystania PJON w praktyce. Dwa arduino, połączone kabelkiem pin-y 12. W pierwszym (u mnie Arduino UNO) sprawdzamy napięcie na A0, rozbijamy wartość int na dwa bajty:
uint8_t content[3] = {'V', (uint8_t)(voltage >> 8), (uint8_t)(voltage & 0xFF)};
i wysyłamy kabelkiem (pin 12) do drugiego arduino (u mnie Nano) jako trzyelementową tablicę uint8_t z pierwszym elementem typu char ‘V’.
Transmitter
#include <PJON.h>
/* VOLTAGE TESTER DEVICE
This is a basic example to show how PJON can be used practically.
Lets print in the Serial monitor the voltage detected by the analog
pin (max 5v) of another Arduino compatible device connected to the bus.
This sketch contains the transmitter side. In the Serial monitor
is printed transmitted data, exchange duration and transmission speed
for easy benchmarking and nominal functionality assessment. */
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
unsigned long time;
int packet;
int voltage;
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 45);
void setup() {
bus.strategy.set_pin(12);
bus.begin();
Serial.begin(115200);
time = millis();
Serial.print("PJON - Device id ");
Serial.print(bus.device_id());
Serial.println(" A0 pin voltage cyclical packet sending...");
}
void loop() {
if(millis() - time > 2500) {
time = millis();
voltage = (float)(5.0 / (1023.0 / analogRead(A0))) * 1000;
Serial.print("Voltage: ");
Serial.print(voltage, DEC);
Serial.print("mV ");
/* Avoid Serial and PJON concurrency */
Serial.flush();
/* Send a "V", break the int in two bytes */
uint8_t content[3] = {'V', (uint8_t)(voltage >> 8), (uint8_t)(voltage & 0xFF)};
unsigned long send_time = micros();
/* Use a blocking version of send. */
packet = bus.send_packet_blocking(44, bus_id, content, 3);
/* Determine communication result and duration */
send_time = micros() - send_time;
float duration = send_time / 1000.0;
Serial.print((packet == PJON_ACK) ? " Transmitted" : " Some error occurred");
Serial.print(" - Duration: ");
Serial.print(duration);
Serial.print(" milliseconds");
Serial.print(" - Communication speed: ");
// 1 second / (duration / (overhead + length + PJON_ACK))
Serial.print((int)(1000.0 / (duration / (bus.packet_overhead() + 3 + 1))));
Serial.println("B/s");
}
};
Receiver
#include <PJON.h>
/* VOLTAGE TESTER DEVICE
This is a basic example to show how PJON can be used practically.
Lets print in the Serial monitor the voltage detected by the analog
pin of another Arduino compatible device connected to the bus.
This sketch contains the receiver side. In the Serial monitor
is printed the voltage detected and transmitted by the other device. */
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
// PJON object
PJON<SoftwareBitBang> bus(bus_id, 44);
void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {
/* Make use of the payload before sending something, the buffer where payload points to is
overwritten when a new message is dispatched */
Serial.print("RX:");
Serial.print(" Bus id: ");
Serial.print(packet_info.receiver_bus_id[0]);
Serial.print(packet_info.receiver_bus_id[1]);
Serial.print(packet_info.receiver_bus_id[2]);
Serial.print(packet_info.receiver_bus_id[3]);
Serial.print(" Device id: ");
Serial.print(packet_info.receiver_id);
Serial.print(" | TX: ");
Serial.print("Bus id: ");
Serial.print(packet_info.sender_bus_id[0]);
Serial.print(packet_info.sender_bus_id[1]);
Serial.print(packet_info.sender_bus_id[2]);
Serial.print(packet_info.sender_bus_id[3]);
Serial.print(" Device id: ");
Serial.print(packet_info.sender_id);
if((char)payload[0] == 'V') {
Serial.print(" | Voltage: ");
Serial.print((uint16_t)(payload[1] << 8) | (uint16_t)(payload[2] & 0xFF));
Serial.print("mV");
// Get back the original integer from the 2 separate bytes
}
Serial.println();
};
void setup() {
bus.strategy.set_pin(12);
bus.begin();
bus.set_receiver(receiver_function);
Serial.begin(115200);
};
void loop() {
bus.receive(1000);
};