gioblu / PJON

PJON (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol.
Other
2.72k stars 240 forks source link

Slave on ATTiny84 won't work #304

Open jeffaries opened 5 years ago

jeffaries commented 5 years ago

Hi, I continue my investigations with PJON... after ESP8266 and ESP8285 only tests, I have started tests with an ESP8266 as Master and an ATTiny84 as Slave (I have just received these low-cost microcontrollers and my experience with these is not as extensive as with the ESPxxxx) Note: my tests of communication peer to peer were working (sending a message from ESP8266 to ATTiny with known device_id)

Here is my latest version on the ATTiny84:

#define PJON_INCLUDE_SWBB true
#define SWBB_RESPONSE_TIMEOUT 5000
#define SWBB_MODE   1
// Avoid using packet buffer
#define PJON_MAX_PACKETS        0
#include <PJONSlave.h>

/* Bus id - Initially set as localhost to demonstrate the ability of slaves to
   find a master thanks to its advertisement no matter which bus id is used */
uint8_t bus_id[] = {0, 0, 0, 0};
// Device address (unique address of a physical device)
uint8_t device_address[] = {1, 2, 3, 4, 50};

// PJON object
PJONSlave<SoftwareBitBang> bus(device_address);

void receiver_handler(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) {

};

void error_handler(uint8_t code, uint8_t data, void *custom_pointer) {
  // Standard PJON error
  if(code == PJON_CONNECTION_LOST) {
    Serial.print("Connection lost with device ");
    Serial.println((uint8_t)bus.packets[data].content[0], DEC);
  }
  // PJONSlave related errors
  if(code == PJON_ID_ACQUISITION_FAIL) {
    if(data == PJON_ID_CONFIRM)
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);
    if(data == PJON_ID_NEGATE)
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);

    if(data == PJON_ID_REQUEST)
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);
        digitalWrite(5, HIGH); 
        delay(100);
        digitalWrite(5, LOW); 
        delay(100);

  }
};

void setup() {
  bus.set_error(error_handler);
  bus.set_receiver(receiver_handler);
  bus.strategy.set_pin(2);
  bus.begin();
  pinMode(5, OUTPUT); 
  digitalWrite(5, HIGH); 
  delay(1000);
  digitalWrite(5, LOW); 
}

void loop() {
  if(bus.connected) {
    digitalWrite(5, HIGH); 
  }
  else
  {
    digitalWrite(5, LOW); 
  }
  bus.update();
  bus.receive(1000);
};

And on the ESP8266:

#define PJON_INCLUDE_SWBB true
#define SWBB_MODE   1
// Avoid using packet buffer
#define PJON_MAX_PACKETS        0
#define PJON_MAX_DEVICES        200
#include <PJONMaster.h>
// <Strategy name> bus(selected device id)
uint8_t bus_id[] = {0, 0, 1, 105};
PJONMaster<SoftwareBitBang> bus(bus_id); 

int c_time;

void error_handler(uint8_t code, uint16_t data, void *custom_pointer) {
  if(code == PJON_CONNECTION_LOST) {
    Serial.print("PJON error: connection lost with device id ");
    Serial.println((uint8_t)bus.packets[data].content[0], DEC);
  }
  if(code == PJON_DEVICES_BUFFER_FULL) {
    Serial.print("PJONMaster error: master devices' buffer is full with a length of ");
    Serial.println(data);
  }
};

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 debug is active prints addressing packet infromation
  if(packet_info.port == PJON_DYNAMIC_ADDRESSING_PORT) {
    Serial.print("Addressing request: ");
    Serial.print(payload[0]);
    Serial.print(" Device address: ");
    Serial.print(payload[1]);
    Serial.print(".");
    Serial.print(payload[2]);
    Serial.print(".");
    Serial.print(payload[3]);
    Serial.print(".");
    Serial.print(payload[4]);
    Serial.print(".");
    Serial.print(payload[5]);
  }

  // General packet data
  Serial.print(" Header: ");
  Serial.print(packet_info.header, BIN);
  Serial.print(" Length: ");
  Serial.print(length);
  Serial.print(" Sender id: ");
  Serial.print(packet_info.sender_id);

  // Packet content
  Serial.print(" Packet: ");
  for(uint8_t i = 0; i < length; i++) {
    Serial.print(payload[i]);
    Serial.print(" ");
  }
  Serial.print("Packets in buffer: ");
  Serial.println(bus.update());
};

void setup() {
  Serial.begin(115200);
  /* Let addressing procedure packets to be received by the receiver function
     to ease debugging or analysis */
  bus.debug = true;

  bus.strategy.set_pin(5);
  bus.set_receiver(receiver_function);
  bus.set_error(error_handler);
  bus.begin();
  c_time = millis();
};

void loop() {
  if(millis() - c_time > 5000) {
    Serial.println("List of slaves known by master: ");
    for(uint8_t i = 0; i < PJON_MAX_DEVICES; i++) {
      if(bus.ids[i].state) {
        Serial.print(" - Device id: ");
        Serial.print(i + 1); // Shifted by one to avoid PJON_BROADCAST
        Serial.print(" Device address: ");
        Serial.print(bus.ids[i].device_address[0]);
        Serial.print(".");
        Serial.print(bus.ids[i].device_address[1]);
        Serial.print(".");
        Serial.print(bus.ids[i].device_address[2]);
        Serial.print(".");
        Serial.print(bus.ids[i].device_address[3]);
        Serial.print(".");
        Serial.print(bus.ids[i].device_address[4]);
        Serial.println();
      }
    }
    Serial.println();
    Serial.flush();
    c_time = millis();
  }
  bus.receive(5000);
  bus.update();
};

The led connected to the pin 5 should at least blink to notify errors... but nothing is blinking (except during the initial test in Setup())

in the serial console, I have not more than

23:42:18.622 -> List of slaves known by master: 
23:42:18.622 -> 
23:42:23.616 -> List of slaves known by master: 
23:42:23.616 -> 
23:42:28.643 -> List of slaves known by master: 
23:42:28.643 -> 
23:42:33.636 -> List of slaves known by master: 
23:42:33.636 -> 
23:42:38.627 -> List of slaves known by master: 
23:42:38.627 -> 
23:42:43.646 -> List of slaves known by master: 
23:42:43.646 -> 
23:42:48.651 -> List of slaves known by master: 
23:42:48.651 -> 

Where am I wrong?

Thank you very much for your help

gioblu commented 5 years ago

Ciao @jeffaries try adding the missing braces in the error_handler of the first sketch you have pasted! Although I suspect memory issues may arise in ATtiny84 using PJONSlave, why dont you use the bare PJON class? Do you effectively need dynamic addressing in place? Consider if you could get away with static addressing because that would leave more space for the application.

jeffaries commented 5 years ago

Ciao @gioblu , First, thank you for your super fast answer... and if I took so much to also answer, it is because I wanted to test several things prior to revert to you.

In my project, I have a master that is sending simple commands to several devices (up to 200) via SBB. However, at installation time, the master doesn't know the list of devices. It is similar to an smarthouse where you would buy a central controller and spare smart lights. I wanted to rely on the Physical ID that you have introduced in the v3 (https://github.com/gioblu/PJON/blob/master/specification/PJON-dynamic-addressing-specification-v3.0.md) since it would have been a decent solution to "register" the devices (ATTiny84) on the Master (ESP8285) through a web interface.

If it was possible to use the 5 bytes physical id with bare library, I could probably live with it ;)

gioblu commented 5 years ago

@jeffaries thank you for your answer, what is the result of the networkAnalysis (having ATtiny on receiver side) example? Does that work? And the SpeeTest example (having the ATtiny on the transmitter side)? Those results would help to exclude an issue on a lower level.

If the results are fine the problem may be in the PJONMaster or PJONSlave procedure, although I suspect the issue is the available ram.