Node goes offline sporadically

63 views
Skip to first unread message

Alvaro Lobato

unread,
Dec 7, 2017, 5:22:27 PM12/7/17
to souliss
Hello again,


I have a network with about 11 nodes the last one I added is a Mega with 8 simple lights and a dimmable light. Also the input comes from a RS485 interface to an optoisolated input device which has 16 inputs. The problem I see with this node is that when I try to change something from the Android application, many times it goes to Synch and then offline for 2 to 8 seconds. I've added debug logs and there is no pause in the processing, the node seems to be working fine during that offline time.
Also, I don't know if related or not, when I try to change the dimm level of the dimmer light it will go to SYNC and the value of the dimmer will go back to the original value, I can't change the dimmer value at all. While doing it the offline problem usually happens too.

The whole read from RS485 inputs takes around 10 to 20 ms so I don't think this could be related.

This is the code I have, any help would be greatly appreciated.
Thanks in advance.

#include <SoulissFramework.h>
/**************************************************************************
  ARDUINO MEGA
  Dynamic Addressing
  RS485 Input
***************************************************************************/
// Let the IDE point to the Souliss framework
#include "SoulissFramework.h"
//Debug
#define SERIALPORT_INSKETCH
#define LOG          Serial
//#define SOULISS_DEBUG_INSKETCH
//#define SOULISS_DEBUG 0
//#define VNET_DEBUG_INSKETCH
//#define VNET_DEBUG  1
//#define MaCaco_DEBUG_INSKETCH
//#define MaCaco_DEBUG 1


#include <bconf/StandardArduino.h>          // Use a standard Arduino
#include "conf/ethW5100.h"                  // Ethernet through Wiznet W5100

#include "conf/DynamicAddressing.h"                             // Use dynamic address

//Not a bridge
//#include "conf/SuperNode.h"                                     // The main node is the SuperNode


// Include framework code and libraries
#include <SPI.h>
#include <EEPROM.h>

/*** All configuration includes should be above this line ***/
#include "Souliss.h"
#include "util_local.h"
#include "util.h"

// This is the memory slot used for the execution of the logic
#define TEMPERATURE_SLOT        0  //Temperature uses 2 slots
#define LIGHT1                  2
#define LIGHT2                  3
#define LIGHT3                  4
#define LIGHT4                  5
#define LIGHT5                  6
#define LIGHT6                  7
#define LIGHT7                  8
#define LIGHT8                  9

#define DIMMER1_CONTROL         10
#define DIMMER1_INTENSITY       11
                 

// Pinouts
#define RELAY1                  A0
#define RELAY2                  A1
#define RELAY3                  A2
#define RELAY4                  A3

#define RELAY5                  A4
#define RELAY6                  A5
#define RELAY7                  A6
#define RELAY8                  A7

#define DIMMER1_PIN              9

#define TEMP_1WIRE              13

#define RS485_DE               A9
#define RS485_RE_NEG           A8
#define RS485_SERIAL           Serial1
#define RS485_BAUD             9600



//Temperature
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire(TEMP_1WIRE); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
boolean hasSensor;

//RS485 ModBus
#include <ModbusMaster.h>
ModbusMaster node;
U8 RS485InPinStatus[16];

void setup() {
  SetLED();
  serialInit();
  display_srcfile_details(PSTR(__FILE__));
  
  Serial.println("Iniciando...");
  Serial.print("Init Souliss...");
  Initialize();
  Serial.println("OK");

  // Set the status LED and let it blink for a couple of seconds
  TurnOnLED();
  
  // Set the inputs
  Serial.print("Init I/O...");
  
  initLowOnRealy(RELAY1);
  initLowOnRealy(RELAY2);
  initLowOnRealy(RELAY3);
  initLowOnRealy(RELAY4);
  initLowOnRealy(RELAY5);
  initLowOnRealy(RELAY6);
  initLowOnRealy(RELAY7);
  initLowOnRealy(RELAY8);
  
  pinMode(DIMMER1_PIN, OUTPUT); 
  Serial.println("OK");

  // Define Simple Light logics for the relays
  Serial.print("Set up lights...");
  Set_SimpleLight(LIGHT1);
  Set_SimpleLight(LIGHT2);
  Set_SimpleLight(LIGHT3);
  Set_SimpleLight(LIGHT4);
  Set_SimpleLight(LIGHT5);
  Set_SimpleLight(LIGHT6);
  Set_SimpleLight(LIGHT7);
  Set_SimpleLight(LIGHT8);
  Set_DimmableLight(DIMMER1_CONTROL); 
  Serial.println("OK");

  // Setup the network configuration dynamic from gateway
  Serial.print("Init dynamic addressing...");
  SetDynamicAddressing();
  Serial.println("OK");

  Serial.print("GetAddress...");
  GetAddress_Timeout(120000);
  Serial.println("OK");
  logAddresses();


  Serial.print("Init temperature...");
  // IC Default 9 bit. If you have troubles consider upping it 12. Ups the delay giving the IC more time to process the temperature measurement
  Set_Temperature(TEMPERATURE_SLOT);   // Start up the library
  sensors.begin();
  sensors.requestTemperatures();
  Serial.println("OK");
  Serial.print("Sensor count:");
  Serial.println(sensors.getDeviceCount());
  hasSensor = sensors.getDeviceCount() > 0;


  RS485Init();
  Serial.println("Initialization finished");
}

unsigned long start=0;

void loop(){
  // Here we start to play
  EXECUTEFAST() {
    UPDATEFAST();

    FAST_50ms() {   // We process the logic and relevant input and output every 50 milliseconds
      //Read from RS485 input box
      uint8_t result;
      
      // Read 16 registers starting at 0)
      result = node.readDiscreteInputs(0, 16);
      if (result == node.ku8MBSuccess) {
        uint16_t response=node.getResponseBuffer(0);
          //for (j=0;j<16;j++){
          for (short j=0;j<8;j++){
            RS485ProcessInput(j, response & (1<<j), Souliss_T1n_ToggleCmd, LIGHT1+j);
          }
          //8
          //RS485ProcessInput(7, response & (1<<7), Souliss_T1n_ToggleCmd, DIMMER1_CONTROL);
      }

      // Execute the logic for Relays
      Logic_SimpleLight(LIGHT1);
      Logic_SimpleLight(LIGHT2);
      Logic_SimpleLight(LIGHT3);
      Logic_SimpleLight(LIGHT4);
      Logic_SimpleLight(LIGHT5);
      Logic_SimpleLight(LIGHT6);
      Logic_SimpleLight(LIGHT7);
      Logic_SimpleLight(LIGHT8);
     
      // Drive the Relays - These are inverted low is on
      LowDigOut(RELAY1, Souliss_T1n_Coil, LIGHT1);
      LowDigOut(RELAY2, Souliss_T1n_Coil, LIGHT2);
      LowDigOut(RELAY3, Souliss_T1n_Coil, LIGHT3);
      LowDigOut(RELAY4, Souliss_T1n_Coil, LIGHT4);
      LowDigOut(RELAY5, Souliss_T1n_Coil, LIGHT5);
      LowDigOut(RELAY6, Souliss_T1n_Coil, LIGHT6);
      LowDigOut(RELAY7, Souliss_T1n_Coil, LIGHT7);
      LowDigOut(RELAY8, Souliss_T1n_Coil, LIGHT8);


      // Execute the logic that handle dimmable
      Logic_DimmableLight(DIMMER1_CONTROL);
      //Send the dimmable ouput
      analogWrite(DIMMER1_PIN, mOutput(DIMMER1_INTENSITY));
      }
    
    // Here we process all communication with other nodes
    FAST_PeerComms();
  }
  
  EXECUTESLOW() {  
    UPDATESLOW();
    SLOW_10s() { 
      // Process the timer every 10 seconds
      Timer_SimpleLight(LIGHT1);
      Timer_SimpleLight(LIGHT2);
      Timer_SimpleLight(LIGHT3);
      Timer_SimpleLight(LIGHT4);
      Timer_SimpleLight(LIGHT5);
      Timer_SimpleLight(LIGHT6);
      Timer_SimpleLight(LIGHT7);
      Timer_SimpleLight(LIGHT8);
      
      // The timer handle timed-on states
      Timer_DimmableLight(DIMMER1_CONTROL);

      if (hasSensor) {
        float temperature;
        sensors.requestTemperatures();             // Request temperatures
        temperature = sensors.getTempCByIndex(0);     // Read value and convert it to "simple-precision" or "double-precision"
        Souliss_ImportAnalog(memory_map, TEMPERATURE_SLOT, &temperature);
        Logic_Temperature(TEMPERATURE_SLOT);
      }

      // Once the join has been completed, turn the LED solid on
      if (!JoinInProgress()) {
        TurnOnLED();
      }
    }

    // Here we periodically check for a gateway to join
    SLOW_PeerJoin();
    SLOW_15m () {
      if (JoinInProgress()) {
        Serial.print("GetAddress...");
        GetAddress_Timeout(3000);
        Serial.println("OK");
        logAddresses();
      }
    }
  }
}

/*
 * Sets the relay pin as output for a low enabled relay. It will make sure it defaults to HIGH
 */
void initLowOnRealy(U8 pin){
  digitalWrite(pin,HIGH); // Low enabled realy, avoid it relay to start connected
  pinMode(pin, OUTPUT);
}
/*
 * Initializes the RS485 communication with the external device and the variables to process the read
 */
void RS485Init() {
  Serial.print("Init RS485 input...");
  pinMode(RS485_RE_NEG, OUTPUT);
  pinMode(RS485_DE, OUTPUT);
  RS485ReceiveMode();
  RS485_SERIAL.begin(RS485_BAUD);
  // Modbus slave ID 1
  node.begin(1, RS485_SERIAL);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(RS485SendMode);
  node.postTransmission(RS485ReceiveMode);

  for(U8 i=0; i<16; i++){
    RS485InPinStatus[i]  = PINRESET;
  }
  
  Serial.println("OK");
}

/*
 * Read the input from the external RS485 device and writes to the memory map
 */
inline U8 RS485ProcessInput(U8 pin, U8 pin_value, U8 value, U8 slot) {
  if (pin_value) {
    if (RS485InPinStatus[pin] == PINRESET) {
      RS485InPinStatus[pin] = PINSET;
      memory_map[MaCaco_IN_s + slot] = value;
      return value;
    }
  } else {
    RS485InPinStatus[pin] = PINRESET;
  }
  return MaCaco_NODATACHANGED;
}


void RS485SendMode() {
  digitalWrite(RS485_RE_NEG, 1);
  digitalWrite(RS485_DE, 1);
}

void RS485ReceiveMode() {
  digitalWrite(RS485_RE_NEG, 0);
  digitalWrite(RS485_DE, 0);
}


Di Maio, Dario

unread,
Dec 8, 2017, 8:07:11 AM12/8/17
to sou...@googlegroups.com

When SoulissApp send a command, it goes in Synch waiting for a state change. Likely your node is not notifying a state change properly.

As first try, scroll down in SoulissApp inside the node and see if the status goes from synch to online properly.

Dario.

--
You received this message because you are subscribed to the Google Groups "souliss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to souliss+unsubscribe@googlegroups.com.
To post to this group, send email to sou...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/souliss/a57f6ef4-82e2-4139-8825-1f94211ce843%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alvaro Lobato

unread,
Dec 10, 2017, 5:25:48 AM12/10/17
to souliss
Hello,

I've done some tests and it seems to work fine scrolling down from the node page. The offline seems randomly happen after an operation when it syncs, ie: turning on a light or changing the dinner value.

It happens more often (almost all the times) when changing the dinner value, and it would return back to the original value.

If it happens turning on a light it won't display the on state of the light although it has correctly been turned on.

What can I do to find the issue?

Thanks

Di Maio, Dario

unread,
Dec 10, 2017, 5:55:04 AM12/10/17
to sou...@googlegroups.com
Your sketch looks fine, but your 50ms FAST is too large. It does Modbus processing and multiple lights, then the node shall also process the Souliss communication.
You should consider that having a 20-30ms action (Modbus as you reported) into a 50ms phase will completely broke the timing of the node, you should process that action periodically at no less than 10 times the require time to execute. So no less than 300ms, but 500ms will be fine enough if you haven't the fastest finger of the west :)

Then your sketch shall be broken in several SHIFT pieces. SHIFT_50ms(n) where n is a number, gives execution at 50ms but you can build several shift using different n values. So split your FAST in 3 to 5 SHIFTs.
Out of dimmer, I cannot see the reason to have that many lights at 50ms, you should anyhow lower the frequency.

Let me know,
Dario.

Alvaro Lobato

unread,
Dec 10, 2017, 6:18:29 PM12/10/17
to souliss
Thanks for the valuable tips, I'll work in that direction.
Reply all
Reply to author
Forward
0 new messages