Беда с зависанием простой ноды на NRF5

О программировании Arduino, использование библиотек, примеры и общие вопросы программирования.
Ответить
SrFatCat
Сообщения: 2
Зарегистрирован: 04 дек 2019, 18:05

Беда с зависанием простой ноды на NRF5

Сообщение SrFatCat »

Итак, есть совсем простенькая нода на NRF52832 (Е73 от EBYTE), по команде с контроллера тыкает домофон (параллельно кнопке выхода) через оптрон. Питается от домофона же через DC DC (нормальный народный 5-24 в 3.3 от не самого дохлого бренда WAVGAT)
Снимок.JPG
Снимок.JPG (125.5 КБ) 5045 просмотров
Скетч скопипазжен со стандартного с незначительными изменениями:
Spoiler
Show

Код: Выделить всё


 // Enable debug prints to serial monitor
//#define MY_DEBUG

//#define RF24_CHANNEL	   76             //RF channel for the sensor net, 0-127
//#define RF24_DATARATE 	   RF24_250KBPS   //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
//#define RF24_PA_LEVEL 	   RF24_PA_LOW    //Sensor PA Level == RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBM, and RF24_PA_MAX=0dBm
//#define RF24_PA_LEVEL_GW   RF24_PA_LOW  //Gateway PA Level, defaults to Sensor net PA Level.  Tune here if using an amplified nRF2401+ in your gateway.
//#define BASE_RADIO_ID 	   ((uint64_t)0xA8A8E1FC00LL) // This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network.

#define MY_NODE_ID 10

// Enable and select radio type attached
//#define MY_RADIO_RF24
#define MY_RADIO_NRF5_ESB
//#define MY_RADIO_RFM69
//#define MY_RADIO_RFM95

//#define MY_RF24_CE_PIN 10
//#define MY_RF24_CS_PIN 9

// Enable repeater functionality for this node
#define MY_REPEATER_FEATURE

//#define MY_WITH_LEDS_BLINKING_INVERSE

// Set blinking period
//#define MY_DEFAULT_LED_BLINK_PERIOD 300

// Flash leds on rx/tx/err
// Uncomment to override default HW configurations
#define MY_DEFAULT_ERR_LED_PIN 8 // Error led pin
#define MY_DEFAULT_RX_LED_PIN  5// Receive led pin
#define MY_DEFAULT_TX_LED_PIN  11// Transmit led pin

#include <MySensors.h>

#define RELAY_PIN 25  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define RELAY_ON LOW  // GPIO value to write to turn on attached relay
#define RELAY_OFF HIGH // GPIO value to write to turn off attached relay
#define CLICK_LONG 300 //ms
#define RELAY_AS_CHILD_SENSOR_ID 1

void setup()
{
	pinMode(RELAY_PIN, OUTPUT);
	digitalWrite(RELAY_PIN, RELAY_OFF);
}

void presentation()
{
	sendSketchInfo("ClickRelayNRF5", "1.0");
	present(RELAY_AS_CHILD_SENSOR_ID, S_BINARY, "Intercom relay");
	wdt_enable(WDTO_4S);
}


void loop(){
	wait(10000);
	if (!sendHeartbeat(true)) {
		digitalWrite(MY_DEFAULT_ERR_LED_PIN, LOW);
		wait(1000);
		digitalWrite(MY_DEFAULT_ERR_LED_PIN, HIGH);
	}
}

void receive(const MyMessage& message)
{
	// We only expect one type of message from controller. But we better check anyway.
	if (message.type == V_STATUS && message.getBool()) {
		// Change relay state
		digitalWrite(RELAY_PIN, RELAY_ON);
		CORE_DEBUG("Incoming change for sensor: %i\n", message.getBool());
		wait(CLICK_LONG);
		digitalWrite(RELAY_PIN, RELAY_OFF);
	}
}
Работала без нареканий около 2х недель. Перестала подавать признаки жизни. Светодиоды не мигали, в контроллере "Offline". Передернул питание. Отработала еще 4 дня и опять. Думал попала влага или еще чего.... Снял, все проверил 10 раз , воткнул в скетч сторожевой таймер. Отработала еще 2 дня и повисла. Собака не спасла. Переткнул питание еще и снова 2 дня и зависон.
Куда рыть?

На всякий случай:
Фото готового устройства
Show
g1.jpg
g1.jpg (629.51 КБ) 5044 просмотра
g2.jpg
g2.jpg (441.73 КБ) 5044 просмотра
Корпус: распредкоробка 43х43 из Леруа
Компилировал и заливал в Visual Code for Visual Studio, через J-Link
Опции здесь:
Show
Безымянный.jpg
Безымянный.jpg (339.48 КБ) 5031 просмотр
SrFatCat
Сообщения: 2
Зарегистрирован: 04 дек 2019, 18:05

Re: Беда с зависанием простой ноды на NRF5

Сообщение SrFatCat »

Поскольку случай самопроизвольного отвисания через 12 часов был - продолжаю бороться программными методами.
Добавил отправку причины перезагрузки и добавил софтовую перезагрузку при 20 неудачных попытках подряд отправить хеарбит (типа страховка от зависания радио).
Скетч обрел такой вид
Show

Код: Выделить всё


#define PROJECT "MyS Clicker"
#define VERSION "1.1"
//#define MY_DEBUG

#define MY_NODE_ID 10
#ifndef MY_DEBUG
#define MY_PARENT_NODE_ID 0
#else
#define MY_PARENT_NODE_ID 50
#endif
#define MY_PARENT_NODE_IS_STATIC
// Enable and select radio type attached
#define MY_RADIO_NRF5_ESB
// Enable repeater functionality for this node
#define MY_REPEATER_FEATURE
#define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 0
//#define MY_WITH_LEDS_BLINKING_INVERSE
// Flash leds on rx/tx/err
#define MY_DEFAULT_ERR_LED_PIN 8 // Error led pin
#define MY_DEFAULT_RX_LED_PIN  5// Receive led pin
#define MY_DEFAULT_TX_LED_PIN  11// Transmit led pin
#include <MySensors.h>
#define RELAY_PIN 25  //  Digital I/O pin number for relay 
#define RELAY_ON LOW  // GPIO value to write to turn on attached relay
#define RELAY_OFF HIGH // GPIO value to write to turn off attached relay
#define CLICK_LONG 300 //ms
#define RELAY_ID 1
#define RESETREAS_ID 2
MyMessage myResetReason(RESETREAS_ID, V_VAR1);
void setup()
{
    wdt_enable(WDTO_4S);
    pinMode(RELAY_PIN, OUTPUT);
    digitalWrite(RELAY_PIN, RELAY_OFF);
    
    uint16_t n_try = 0;
    bool isSend = false;
    while (!isSend && n_try++ < 10) {
        isSend = send(myResetReason.set(NRF_POWER->RESETREAS), true);
    }
    if (isSend) NRF_POWER->RESETREAS = (0xFFFFFFFF);
    
}
void presentation()
{
    sendSketchInfo(PROJECT, VERSION);
    present(RELAY_ID, S_BINARY, "Intercom relay");
    present(RESETREAS_ID, S_CUSTOM, "Debug info");
    
}

void loop(){
    static uint8_t hbErrNum = 0;
    wait(10000);
    if (!sendHeartbeat(true)) {
        _transportSM.failedUplinkTransmissions = 0;
        hbErrNum++;
        digitalWrite(MY_DEFAULT_ERR_LED_PIN, LOW);
        wait(1000);
        digitalWrite(MY_DEFAULT_ERR_LED_PIN, HIGH);
        if (hbErrNum == 20) hwReboot();
    }
    else hbErrNum = 0;
}
void receive(const MyMessage& message)
{
    // We only expect one type of message from controller. But we better check anyway.
    if (message.type == V_STATUS && message.getBool()) {
        // Change relay state
        digitalWrite(RELAY_PIN, RELAY_ON);
        CORE_DEBUG("Incoming change for sensor: %i\n", message.getBool());
        wait(CLICK_LONG);
        digitalWrite(RELAY_PIN, RELAY_OFF);
    }
}
Причина перезагрузки передается контроллеру на Мажордомо. Там расшифровывается так:
Текст скрипта исполняемого при получении нового кода причины перезагрузки
Show

Код: Выделить всё

$resetReasons = Array();
$oneReason = Array('Str' => 'from wake-up from OFF mode detected by entering into debug interface mode', 
                  'Msk' =>  (1 << 18));
define(POWER_RESETREAS_DIF_Str, 'from wake-up from OFF mode detected by entering into debug interface mode');
define(POWER_RESETREAS_DIF_Pos, 18); /*!< Position of DIF field. */
define(POWER_RESETREAS_DIF_Msk, (1 << POWER_RESETREAS_DIF_Pos)); /*!< Bit mask of DIF field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from wake-up from OFF mode detected by the use of ANADETECT signal from LPCOMP', 
                  'Msk' =>  (1 << 17));
define(POWER_RESETREAS_LPCOMP_Str, 'from wake-up from OFF mode detected by the use of ANADETECT signal from LPCOMP');
define(POWER_RESETREAS_LPCOMP_Pos, 17); /*!< Position of LPCOMP field. */
define(POWER_RESETREAS_LPCOMP_Msk, (1 << POWER_RESETREAS_LPCOMP_Pos)); /*!< Bit mask of LPCOMP field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from wake-up from OFF mode detected by the use of DETECT signal from GPIO', 
                  'Msk' =>  (1 << 16));
define(POWER_RESETREAS_OFF_Str, 'from wake-up from OFF mode detected by the use of DETECT signal from GPIO');
define(POWER_RESETREAS_OFF_Pos, 16); /*!< Position of OFF field. */
define(POWER_RESETREAS_OFF_Msk, (1 << POWER_RESETREAS_OFF_Pos)); /*!< Bit mask of OFF field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from CPU lock-up detected', 
                  'Msk' =>  (1 << 3));
define(POWER_RESETREAS_LOCKUP_Str, 'from CPU lock-up detected');
define(POWER_RESETREAS_LOCKUP_Pos, 3); /*!< Position of LOCKUP field. */
define(POWER_RESETREAS_LOCKUP_Msk, (1 << POWER_RESETREAS_LOCKUP_Pos)); /*!< Bit mask of LOCKUP field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from AIRCR.SYSRESETREQ detected', 
                  'Msk' =>  (1 << 2));
define(POWER_RESETREAS_SREQ_Str, 'from AIRCR.SYSRESETREQ detected');
define(POWER_RESETREAS_SREQ_Pos, 2); /*!< Position of SREQ field. */
define(POWER_RESETREAS_SREQ_Msk, (1 << POWER_RESETREAS_SREQ_Pos)); /*!< Bit mask of SREQ field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from watchdog detected', 
                  'Msk' =>  (1 << 1));
define(POWER_RESETREAS_DOG_Str, 'from watchdog detected');
define(POWER_RESETREAS_DOG_Pos, 1); /*!< Position of DOG field. */
define(POWER_RESETREAS_DOG_Msk, (1 << POWER_RESETREAS_DOG_Pos)); /*!< Bit mask of DOG field. */
$resetReasons[] = $oneReason;
$oneReason = Array('Str' => 'from pin-reset detected', 
                  'Msk' =>  1);
define(POWER_RESETREAS_RESETPIN_Str, 'from pin-reset detected');
define(POWER_RESETREAS_RESETPIN_Pos, 0); /*!< Position of RESETPIN field. */
define(POWER_RESETREAS_RESETPIN_Msk, (1 << POWER_RESETREAS_RESETPIN_Pos)); /*!< Bit mask of RESETPIN field. */
$resetReasons[] = $oneReason;
$s = "";
foreach($resetReasons as $reason){
    if (($this->getProperty('debugVar') & $reason['Msk']) > 0) {
     $s.=((strlen($s) > 0? ", " : "").$reason['Str']); 
    }
}
if (strlen($s) == 0) $s = "power failed.";
say('Перегрузился кликер: '.$s);
Ответить