ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

О программировании Arduino, использование библиотек, примеры и общие вопросы программирования.
Ответить
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение Berk »

https://youtu.be/vcou4tGG4dE

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

/**
ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ

После загрузки скетча рекомендуется сбросить питание с модуля.
*/

#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 100
#define MY_LED 27
#define MY_BUTTON_ADC_PIN 1 // номер пина АЦП смотреть в MyBoardNRF5.cpp
#include <MySensors.h>
bool detection;

void preHwInit() {
pinMode(MY_LED, OUTPUT);  
}

void before()
{
NRF_POWER->DCDCEN = 1; // закоментировать если E73
NRF_UART0->ENABLE = 0;  
}

void setup() {
  analogReference(AR_DEFAULT);
  lpComp();
  led(2,1);
  detection = false;
  wait(5000);
}

void loop() {
  sleep(10000);
  if (detection) {
    s_lpComp();
    led(10,3);
    detection=false;
    NRF_LPCOMP->EVENTS_UP=0;
    r_lpComp();
  } else {
    led(1,1);
  }
}


void led(uint8_t flash, uint8_t iteration) {
  for (int x = 0; x < iteration; x++) {
    for (int i=0; i < flash; i++) {
      digitalWrite(MY_LED, HIGH);
      wait(30);
      digitalWrite(MY_LED, LOW);
      wait(70);
    }    
      wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL=MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT=1; // детектирование EVENTS_UP.
  NRF_LPCOMP->INTENSET=B0100; // активация прерывания для EVENTS_UP
  NRF_LPCOMP->ENABLE=1;
  NRF_LPCOMP->TASKS_START=1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR=B0100; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET=B0100;
}

#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
        event = 0;                                                                   \
        (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif

//В одну строку..
extern "C" { void LPCOMP_IRQHandler(void) {detection=true; NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_UP); NRF_LPCOMP->EVENTS_UP=0; MY_HW_RTC->CC[0]=(MY_HW_RTC->COUNTER+2);}}
Последний раз редактировалось Berk 07 июл 2019, 19:21, всего редактировалось 1 раз.
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение Berk »

Проверочная "шляпа" для nrf51822 - Тест прерываний на любом пине gpio, тест прерывания через LPCOMP (AIN2-AIN7)

Видосик - https://youtu.be/EQ-yw1gGC0A

Тестовая прожка

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

#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 9
#define MY_LED 22
#define MY_BUTTON_ADC_PIN 7 // номер пина АЦП смотреть в MyBoardNRF5.cpp
#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN - 1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################


#include <MySensors.h>
int8_t  detection;

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before()
{
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_DEFAULT);
  lpComp();  // if y use lpcomp interrupt
  led(2, 1);
  detection = 0;
  wait(3000);
}

void loop() {


/*
  detection = sleep(digitalPinToInterrupt(MY_BUTTON_PIN), FALLING, 3600000, false);
  if (detection == MY_BUTTON_PIN) {
    led(10, 3);
  }
  if (detection == -1) {
    led(1, 1);
  }
*/


  sleep(3600000);
  if (detection == 1) {
    s_lpComp();
    led(10, 3);
    detection = 0;
    NRF_LPCOMP->EVENTS_DOWN = 0;
    r_lpComp();
  } else {
    led(1, 1);
  }

  
}


void led(uint8_t flash, uint8_t iteration) {
  for (int x = 0; x < iteration; x++) {
    for (int i = 0; i < flash; i++) {
      digitalWrite(MY_LED, HIGH);
      wait(30);
      digitalWrite(MY_LED, LOW);
      wait(70);
    }
    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 2; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B0010; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B0010; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B0010; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B0010;
}

#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif

extern "C" {
  void LPCOMP_IRQHandler(void) {
    detection = 1;
    NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_DOWN);
    NRF_LPCOMP->EVENTS_DOWN = 0;
    MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);
  }
}
pasha413
Сообщения: 20
Зарегистрирован: 29 ноя 2019, 16:52

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение pasha413 »

Здравствуйте. как код работает. но как добавить сюда проверку напряжения батареи, когда добавляю, код перестает работать...
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение Berk »

pasha413 писал(а): 29 ноя 2019, 16:55 Здравствуйте. как код работает. но как добавить сюда проверку напряжения батареи, когда добавляю, код перестает работать...
Приветствую, а как вы меряете?(код) Питание с батарейки напрямую?
pasha413
Сообщения: 20
Зарегистрирован: 29 ноя 2019, 16:52

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение pasha413 »

Вот в сетапе отправляю напряжение батареи. но вот как проснуться и отправить напряжение батареи (допустим, каждые сутки) так и не понял, не нашел решения.

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
#define MY_PARENT_NODE_ID 0

#define MY_LED 0
#define MY_KEY 4
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 6 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long timer = 30;

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");  
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
//  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  send(msgVolt.set(((float)hwCPUVoltage()/1000),2)); //отправляю напряжение батареи
  lpComp();  // if y use lpcomp interrupt
  led(4, 1);
  detection = 0;
  wait(1000);
}

void loop() {
  sleep(2147483647);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("true!"));
      led(2, 1);   
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("false!"));
      led(1, 1);   
      wait(100);
    }
//    led(3, 3);   
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
//    led(1, 1);
  }
}

void led(uint8_t flash, uint8_t iteration) {
//    for (int x = 0; x < iteration; x++) {  //повтор
    for (int i = 0; i < flash; i++) {
      digitalWrite(MY_LED, HIGH);
      wait(20);
      digitalWrite(MY_LED, LOW);
      wait(20);
//    }
//    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" { void LPCOMP_IRQHandler(void) {detection = 1;NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS); NRF_LPCOMP->EVENTS_CROSS = 0; MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);}}
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение Berk »

pasha413 писал(а): 02 дек 2019, 11:31 Вот в сетапе отправляю напряжение батареи. но вот как проснуться и отправить напряжение батареи (допустим, каждые сутки) так и не понял, не нашел решения.

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
#define MY_PARENT_NODE_ID 0

#define MY_LED 0
#define MY_KEY 4
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 6 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long timer = 30;

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");  
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
//  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  send(msgVolt.set(((float)hwCPUVoltage()/1000),2)); //отправляю напряжение батареи
  lpComp();  // if y use lpcomp interrupt
  led(4, 1);
  detection = 0;
  wait(1000);
}

void loop() {
  sleep(2147483647);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("true!"));
      led(2, 1);   
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("false!"));
      led(1, 1);   
      wait(100);
    }
//    led(3, 3);   
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
//    led(1, 1);
  }
}

void led(uint8_t flash, uint8_t iteration) {
//    for (int x = 0; x < iteration; x++) {  //повтор
    for (int i = 0; i < flash; i++) {
      digitalWrite(MY_LED, HIGH);
      wait(20);
      digitalWrite(MY_LED, LOW);
      wait(20);
//    }
//    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" { void LPCOMP_IRQHandler(void) {detection = 1;NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS); NRF_LPCOMP->EVENTS_CROSS = 0; MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);}}


Например так:

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
#define MY_PARENT_NODE_ID 0

#define MY_LED 0
#define MY_KEY 4
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 6 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long timer = 30;
unsigned long sleep_batt = 14400000; // 4 часа

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
  //  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  send(msgVolt.set(((float)hwCPUVoltage() / 1000), 2)); //отправляю напряжение батареи
  lpComp();  // if y use lpcomp interrupt
  led(4, 1);
  detection = 0;
  wait(1000);
}

void loop() {
  sleep(sleep_batt);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("true!"));
      led(2, 1);
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("false!"));
      led(1, 1);
      wait(100);
    }
    //    led(3, 3);
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
    send(msgVolt.set(((float)hwCPUVoltage() / 1000), 2)); //отправляю напряжение батареи
  }
}

void led(uint8_t flash, uint8_t iteration) {
  //    for (int x = 0; x < iteration; x++) {  //повтор
  for (int i = 0; i < flash; i++) {
    digitalWrite(MY_LED, HIGH);
    wait(20);
    digitalWrite(MY_LED, LOW);
    wait(20);
    //    }
    //    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" {
  void LPCOMP_IRQHandler(void) {
    detection = 1;
    NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS);
    NRF_LPCOMP->EVENTS_CROSS = 0;
    MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);
  }
}

Это очень примитивно правда, тк не учитывает прерывание, тоесть после сработки прерывания сон будет снова установлен на 4 часа после которого будет отправка батарейки. По другому естественно тоже можно, я уже выкладывал, гляньте например в последней фиговине - https://mysku.ru/blog/diy/77226.html

там правда много букв, ...смотрите как работает вот эта часть:
12212.png
12212.png (66.17 КБ) 14784 просмотра
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение Berk »

pasha413 писал(а): 04 дек 2019, 13:47 благодарю) буду разбираться
Если неполучится, напиши, я в свою очередь попозжее постораюсь накидать простой пример только по этой части. Н смысл там такой, перед уходом в сон запоминаем миллис, если прерывание, то чекаем опять миллис, выститываем сколько длился сон до прерывания, потом вычитываем это время из времени сна и усыпляем устройство уже на оставшееся время.
pasha413
Сообщения: 20
Зарегистрирован: 29 ноя 2019, 16:52

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение pasha413 »

Berk писал(а): 04 дек 2019, 13:51
pasha413 писал(а): 04 дек 2019, 13:47 благодарю) буду разбираться
Если неполучится, напиши, я в свою очередь попозжее постораюсь накидать простой пример только по этой части. Н смысл там такой, перед уходом в сон запоминаем миллис, если прерывание, то чекаем опять миллис, выститываем сколько длился сон до прерывания, потом вычитываем это время из времени сна и усыпляем устройство уже на оставшееся время.
да, я так и представлял себе, а вот как реализовать, буду пробовать в выходные.
реализация для датчика двери на зимнее время (да и не только), просто по истечении 2х суток без данных от датчика он отваливается...
pasha413
Сообщения: 20
Зарегистрирован: 29 ноя 2019, 16:52

Re: ТЕСТОВЫЙ СКЕТЧ КОНТРОЛЯ ПОНИЖЕННОГО ЭНЕРГОПОТРЕБЛЕНИЯ В РЕЖИМЕ СНА С ПРЕРЫВАНИЯМИ ДЛЯ nRF5

Сообщение pasha413 »

Berk писал(а): 04 дек 2019, 13:06
pasha413 писал(а): 02 дек 2019, 11:31 Вот в сетапе отправляю напряжение батареи. но вот как проснуться и отправить напряжение батареи (допустим, каждые сутки) так и не понял, не нашел решения.

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
#define MY_PARENT_NODE_ID 0

#define MY_LED 0
#define MY_KEY 4
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 6 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long timer = 30;

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");  
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
//  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  send(msgVolt.set(((float)hwCPUVoltage()/1000),2)); //отправляю напряжение батареи
  lpComp();  // if y use lpcomp interrupt
  led(4, 1);
  detection = 0;
  wait(1000);
}

void loop() {
  sleep(2147483647);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("true!"));
      led(2, 1);   
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("false!"));
      led(1, 1);   
      wait(100);
    }
//    led(3, 3);   
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
//    led(1, 1);
  }
}

void led(uint8_t flash, uint8_t iteration) {
//    for (int x = 0; x < iteration; x++) {  //повтор
    for (int i = 0; i < flash; i++) {
      digitalWrite(MY_LED, HIGH);
      wait(20);
      digitalWrite(MY_LED, LOW);
      wait(20);
//    }
//    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" { void LPCOMP_IRQHandler(void) {detection = 1;NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS); NRF_LPCOMP->EVENTS_CROSS = 0; MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);}}


Например так:

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
#define MY_PARENT_NODE_ID 0

#define MY_LED 0
#define MY_KEY 4
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 6 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long timer = 30;
unsigned long sleep_batt = 14400000; // 4 часа

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
  //  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  send(msgVolt.set(((float)hwCPUVoltage() / 1000), 2)); //отправляю напряжение батареи
  lpComp();  // if y use lpcomp interrupt
  led(4, 1);
  detection = 0;
  wait(1000);
}

void loop() {
  sleep(sleep_batt);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("true!"));
      led(2, 1);
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("false!"));
      led(1, 1);
      wait(100);
    }
    //    led(3, 3);
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
    send(msgVolt.set(((float)hwCPUVoltage() / 1000), 2)); //отправляю напряжение батареи
  }
}

void led(uint8_t flash, uint8_t iteration) {
  //    for (int x = 0; x < iteration; x++) {  //повтор
  for (int i = 0; i < flash; i++) {
    digitalWrite(MY_LED, HIGH);
    wait(20);
    digitalWrite(MY_LED, LOW);
    wait(20);
    //    }
    //    wait(500);
  }
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" {
  void LPCOMP_IRQHandler(void) {
    detection = 1;
    NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS);
    NRF_LPCOMP->EVENTS_CROSS = 0;
    MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);
  }
}

Это очень примитивно правда, тк не учитывает прерывание, тоесть после сработки прерывания сон будет снова установлен на 4 часа после которого будет отправка батарейки. По другому естественно тоже можно, я уже выкладывал, гляньте например в последней фиговине - https://mysku.ru/blog/diy/77226.html

там правда много букв, ...смотрите как работает вот эта часть:
12212.png
попробовал по вашему примеру, но после отправки батареи перестает работать датчик двери:

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

//nrf51822
//6.2mkA
//16mA
#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 6
#define MY_DISABLED_SERIAL
//#define MY_PARENT_NODE_ID 0
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED

#define MY_LED 0
#define MY_KEY 9
//#define MY_BUTTON_ADC_PIN X // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN (MY_BUTTON_ADC_PIN X-1)  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)
#define MY_BUTTON_ADC_PIN 2 // номер пина АЦП смотреть в MyBoardNRF5.cpp
//#define MY_BUTTON_PIN 5  //this is the same pin number MY_BUTTON_ADC_PIN, see the pins table above (only nrf51, I think so)

//############## NRF51 ################
// X-1  -  X
//p0.01 - AIN2
//p0.02 - AIN3
//p0.03 - AIN4
//p0.04 - AIN5
//p0.05 - AIN6
//p0.06 - AIN7
//############## NRF51 ################

#include <MySensors.h>
#define CHILD_ID_Door 24                      // Id сенсоры ноды (0-254)
#define CHILD_ID_VOLT 100

uint16_t currentBatteryPercent;
uint16_t lastBatteryPercent = 1000;
uint16_t battery_vcc_min = 2400;
uint16_t battery_vcc_max = 3000;
uint16_t batteryVoltage;
uint16_t battery_alert_level = 25;

MyMessage msgDoor(CHILD_ID_Door, V_TEXT);
MyMessage msgVolt(CHILD_ID_VOLT, V_VOLTAGE);

int8_t  detection;
unsigned long sleep_batt = 30000; // 4 часа

void presentation() {
  sendSketchInfo("DoorSensor", "1.0");
  present(CHILD_ID_Door, S_DOOR, "Door Status");
//  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");
}

void preHwInit() {
  pinMode(MY_LED, OUTPUT);
  //  pinMode(MY_BUTTON_PIN, INPUT_PULLUP);
  pinMode(MY_KEY, INPUT_PULLUP);
  digitalWrite(MY_LED, LOW);
}

void before() {
  NRF_POWER->DCDCEN = 1; // закоментировать если E73
  NRF_UART0->ENABLE = 0;
}

void setup() {
  analogReference(AR_VBG);
  sendBatteryStatus();
  lpComp();  // if y use lpcomp interrupt
//  led(4, 1);
  detection = 0;
//  wait(100);
}

void loop() {
  sleep(sleep_batt);
  if (detection == 1) {
    s_lpComp();
    if (digitalRead(MY_KEY) == 1) {
      send(msgDoor.setDestination(0).set("1"));
//      led(2, 1);
      wait(100);
    }
    if (digitalRead(MY_KEY) == 0) {
      send(msgDoor.setDestination(0).set("0"));
//      led(1, 1);
      wait(100);
    }
    //    led(3, 3);
    detection = 0;
    NRF_LPCOMP->EVENTS_CROSS = 0;
    r_lpComp();
  } else {
    sendBatteryStatus();
  }
}

/*void led(uint8_t flash, uint8_t iteration) {
  //    for (int x = 0; x < iteration; x++) {  //повтор
  for (int i = 0; i < flash; i++) {
    digitalWrite(MY_LED, HIGH);
    wait(20);
    digitalWrite(MY_LED, LOW);
    wait(20);
    //    }
    //    wait(500);
  }
}*/

void sendBatteryStatus() {
  wait(20);
  batteryVoltage = hwCPUVoltage();
  wait(2);
  if (batteryVoltage > battery_vcc_max) {
    currentBatteryPercent = 100;
  } else if (batteryVoltage < battery_vcc_min) {
    currentBatteryPercent = 0;
  } else {
    currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min);
  }
  sendBatteryLevel(currentBatteryPercent, 1);
  wait(50);
  send(msgVolt.set(batteryVoltage), 1);
  wait(50);
}

void lpComp() {
  NRF_LPCOMP->PSEL = MY_BUTTON_ADC_PIN;
  NRF_LPCOMP->ANADETECT = 0; // детектирование EVENTS_DOWN.
  //ANADETECT=0; // детектирование EVENTS_CROSS.
  //ANADETECT=1; // детектирование EVENTS_UP.
  //ANADETECT=2; // детектирование EVENTS_DOWN.
  NRF_LPCOMP->INTENSET = B1000; // активация прерывания для EVENTS_DOWN
  //B1000; // прерываниt для EVENTS_CROSS
  //B0100; // прерываниt для EVENTS_UP
  //B1000; // прерываниt для EVENTS_DOWN
  NRF_LPCOMP->ENABLE = 1;
  NRF_LPCOMP->TASKS_START = 1;
  NVIC_SetPriority(LPCOMP_IRQn, 15);
  NVIC_ClearPendingIRQ(LPCOMP_IRQn);
  NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
  if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
    NRF_LPCOMP->INTENCLR = B1000; //деактивация прерывания для LPCOMP
  }
}

void r_lpComp() {
  NRF_LPCOMP->INTENSET = B1000;
}
#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)                                                 \
  event = 0;                                                                   \
  (void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif
//В одну строку..
extern "C" { void LPCOMP_IRQHandler(void) {
    detection = 1;
    NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_CROSS);
    NRF_LPCOMP->EVENTS_CROSS = 0;
    MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);
  }
}
Ответить