Подскажите алгоритм уменьшения времени расчёта радиации

Сейчас считаю так, модуль ESP8266:

struct DATA {
  uint32_t DOSE_CBM20[34];
  volatile uint8_t SECONDS = 0;
  uint64_t SUMM = 0;
  uint32_t RESULT = 0;
};

DATA DATA;

IRAM_ATTR void timerISR() 
{
  ++DATA.SECONDS;
  if (DATA.SECONDS >= 33)
    DATA.SECONDS = 0;
  DATA.DOSE_CBM20[DATA.SECONDS] = 0;
  timer0_write(ESP.getCycleCount() + 80000000L);                        //Тактовая частота 80MHz, получаем секунду
}

IRAM_ATTR void SBM20() 
{
  ++DATA.DOSE_CBM20[DATA.SECONDS];
}

void setup() {
  noInterrupts();
  
  timer0_isr_init(); 
  timer0_attachInterrupt(timerISR);                                 //настраиваем прерывание (привязка к функции)
  timer0_write(ESP.getCycleCount() + 80000000L);                    //Тактовая частота 80MHz, получаем секунду
  
  attachInterrupt(14, SBM20, FALLING);

  interrupts();
  Serial.begin(115200);
}


void loop() {
  DATA.SUMM = 0;
      
  for (uint32_t DOSE_CBM20 : DATA.DOSE_CBM20)
    DATA.SUMM = DATA.SUMM + DOSE_CBM20;

  
  Serial.println(DATA.SUMM);
}

Время расчёта 34 секунды, для расчёта фона отличный результат, данные со счётчика соответствуют данным других дозиметров.

Но стоит приблизить прибор к источнику, так он ещё 34 секунды показывает завышенные показания, пока круг не обнулиться, уважаемые форумчане, подскажите каким алгоритмом показания с дозиметра можно сделать более актуальными, куда копать?

(сообщение удалено автором)

К сожалению, не понял точный смысл этих строк, но догадываюсь))

 for (uint32_t DOSE_CBM20 : DATA.DOSE_CBM20)
    DATA.SUMM = DATA.SUMM + DOSE_CBM20;

И если

Надо делать “скользящий” массив - при поступлении нового значения - отбрасывать первое, сдвигать массив на одну позицию , и на свободное место вписывать новое значение. Т.е. , нужно получать актуальный массив данных и
делать расчёт каждую секунду.
Возможно, будет достаточно, из общей суммы вычесть старое значение(заранее сохранив его в памяти), и, добавить новое
см. “алгоритм скользящего окна”

1 лайк

Вы бы поаккуратнее с использованием volatile для членов классов. Не то, чтобы этого делать нельзя, можно, конечно, но надо чётко понимать, что делаешь. Боюсь, в Вашем случае этого нет.

Вообще-то вместо этого принято использовать кольцевой буфер - чтобы не гонять данные постоянно туда-сюда.

МелкоМягкий, Вы бы написали подробно, что считаете и как считаете, тогда можно было бы подумать, как это сделать оптимальнее. А когда приведен готовый код - он какой есть, такой есть, и количество вариантов оптимизации резко уменьшается (притом, уменьшается как раз за счет самых эффективных).

Вот лично мне непонятно, как вообще можно считать радиацию, если у Вас нигде не фигурирует период полураспада. А вот прерывания к расчету радиации ну никак не могут иметь отношения, поэтому, зачем Вы привели их, совершенно непонятно.
У меня складывается впечатление, что текст вопроса вообще не имеет никакого отношения к тому, что Вам на самом деле нужно.

1 лайк

вапще лехко. Но к теме вопроса, да, это отношение не имеет.

А, ну да, как в анекдоте:
В. Ваши сильные стороны?
О. Я умею быстро считать.
В. Сколько будет 8765 умножить на 4321?
О. 123456.
В. Но это неверно.
О. Зато быстро.

Почему именно столько? А не, например, 1 секунда, для усреднения разбитая на 10 интервалов по 100 мСек ?

хм… туплю, наверное… почему при ПРИБЛИЖЕНИИ к источнику показания должны снижаться?

Вообще-то когда исправный ручной дозиметр за секунды меняет показания, о скорости алгоритма можно уже не беспокоиться…

Безопасные дозы радиации улавливаемые классическими датчиками должны детектироваться именно в режиме статического накопления неподвижным прибором. В случае скользящего окна вы конечно же увидите тенденцию, но точный замер будет гарантировано после заполнения всего окна.

Если следовать выдержке:

ESP8266 : следует использовать volatileдля глобальных переменных, которые изменяются в рамках процедуры обработки прерываний (ISR) и считываются основным циклом программы, и наоборот. Это предотвращает необходимость компилятора делать предположения о значении переменной и гарантирует, что при каждом обращении к переменной из памяти считывается её самое актуальное значение.

Получается, это как раз тот момент, для чего он нужен, но в чём может быть проблема, пожалуйста расскажите?

Извините не правильно выразился, когда приближаю дозиметр к источнику показания растут, но если удаляю, показания начинают падать не сразу, а через 34 секунды, пока не пройдёт полный круг.

Что-то вроде этого?

uint32_t WINDOW(uint32_t *nums, uint8_t k) {
 
  uint32_t sum = 0;
  for (uint8_t i = 0; i < k; i++) {                                      
    sum += nums[i];
  }

  uint32_t res = sum; 
  uint8_t count = sizeof(nums) / sizeof(uint32_t);
  for (uint8_t i = k; i < count; i++) {                                
    sum += nums[i] - nums[i - k]; 
    res = max(res, sum);
  }

  return res / k;
}

Но при каких условиях его начинать сужать?

С форумов подцепил информацию, что сумма срабатываний счётчика за 34 секунды равна дозе мкР/ч.

++DATA.SECONDS;
  if (DATA.SECONDS >= 33)
    DATA.SECONDS = 0;
  DATA.DOSE_CBM20[DATA.SECONDS] = 0;

Так я же его вроде и реализовал, считаем до 33 элемента включительно, затем возвращаемся к нулевому значению и так по кругу, или Вы о другом?

Извините за первое сообщение написал его сумбурно, попытаюсь объяснить идею подробно:

1. На форумах я нашёл информацию, что сумма срабатываний счётчика СБМ-20 за последние 34 секунды равна дозе мкР/ч, что похоже соответствует правде, так как эти показания сходятся с показаниями двух дозиметров, которые у меня имеются.

2. Алгоритм счёта такой:

2.1 Программа считает количество срабатываний счётчика СБМ-20 в течении одной секунды и суммирует их, записывая полученное значение в ячейку массива.

2.2 Затем когда секунда проходит, срабатывает прерывание и мы переходим к следующей ячейке и снова в неё записываем сумму срабатывания счётчика.

2.3 Когда мы подходим к 35 элементу массива, то возвращаемся к нулевому, что бы зациклить расчёт по кругу (получается идём с 0 до 33, затем снова возвращаемся к 0 и т.д.).

2.4 В цикле loop считаем сумму значений всего массива.

Если такой алгоритм подходит для счёта фона радиации, то не подходит для поиска источника радиации, потому что стоит нам поднести источник радиации к счётчику, как его значения резко растут, но стоит источник тут же отдалить от счётчика, завышенный фон продолжит держаться, пока не пройдёт 34 секунды (полный круг) и значения массива не начнут обнуляться.

Поэтому уважаемые форумчане, подскажите порядок действий расчётов при кратковременном поднесении источника радиации к счётчику?