Прошу помощи в декодирование протокола

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200;              // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t cycle_half = 40000 / 2;  // половина цикла (периода) отправки пакетов

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 0) if (micros() - microsArr[ind] > cycle_half) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (cnt == 2) val = !val;

          if (n % 2 == 0) res += val ? "1" : "0";

          if (n == 24) res += " - ";
          
          n += cnt;

        }

      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

По поводу мусора, может точное указание 200мкс влияет?
Там же плавает оно ± 20 может учитывать погрешность это надо? Или не в этом дело?

Последний вывод

1111000011111 - 1110100000000000111000000011111

1111000011111 - 111110000000000011100000000011111

1111000011111 - 111110000000000011100000000011111111011110000000001000011000001111101111111

1111000011111 - 111100000000000011100000000111111

1111000011111 - 1110100000000000111000000011111

1111000011111 - 111110000000000011100000000011111

1111000011111 - 111000000000000011100000001111111

1111000011111 - 111100000000000011100000000111111

1111000011111 - 1110100000000000111000000011111

1111000011111 - 11101000000000001110000000111111111001111100000100000000001000011111111111111111111111111111111111111111111111111111111111111111111111111111111111

1111000011111 - 111000000000000011100000001111111

1111000011111 - 111100000000000011100000000111111

1111000011111 - 1110100000000000111000000011111

1111000011111 - 111110000000000011100000000011111

1111000011111 - 111110000000000011100000000011111111011110000000001000011000001111101111111

1111000011111 - 111000000000000011100000001111111111011110000000001000011000001111101111111

1111000011111 - 1110100000000000111000000011111

1111000011111 - 111110000000000011100000000011111

1111000011111 - 111000000000000011100000001111111

1111000011111 - 111100000000000011100000000111111

1111000011111 - 111100000000000011100000000111111111011110000000001000011000001111101111111

1111000011111 - 111110000000000011100000000011111

вообще я учел в строке 40, после деления идет в скобках

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200;              // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t cycle_half = 40000 / 2;  // половина цикла (периода) отправки пакетов

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 0) if (micros() - microsArr[ind] > cycle_half) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (n % 2 == 0) res += val ? "1" : "0";

          if (cnt == 2) val = !val;

          if (n % 2 == 24) {
            res += " - ";
            val = true;
          }
          
          n += cnt;

        }

      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

Значит не зря они две одинаковых части сделали ))

11111000011111111010000000000111000000011111

1111100001111111111000000000011100000000011111

1111100001111111100000000000011100000001111111

1111100001111111110000000000011100000000111111

11111000011111111010000000000111000000011111

1111100001111111111000000000011100000000011111

1111100001111111100000000000011100000001111111

1111100001111111100000000000011100000001111111111011110000000000100001100000111110111111

11111000011111111010000000000111000000011111

1111100001111111111000000000011100000000011111

1111100001111111100000000000011100000001111111

1111100001111111110000000000011100000000111111

11111000011111111010000000000111000000011111

1111100001111111111000000000011100000000011111

1111100001111111111000000000011100000000011111111011110000000000100001100000111110111111

1111100001111111110000000000011100000000111111

1111100001111111110000000000011100000000111111111011110000000000100001100000111110111111

111110000111111110100000000001110000000111111111100111110000010000000001000011111111111111111111111111111111111111111111111111111111111111111111111111111111111

1111100001111111100000000000011100000001111111

1111100001111111100000000000011100000001111111111011110000000000100001100000111110111111

11111000011111111010000000000111000000011111

1111100001111111111000000000011100000000011111

1111100001111111100000000000011100000001111111

1111100001111111110000000000011100000000111111

скорее дублирование для проверки я думаю. Блин нащупал же почти, близко где-то))

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200;              // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t cycle_half = 40000 / 2;  // половина цикла (периода) отправки пакетов

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 0) if (micros() - microsArr[ind] > cycle_half) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (n % 2 == 0) res += val ? "1" : "0";

          if (cnt == 2) val = !val;
          
          n += cnt;

        }

      } else {
        val = true;
        res += " ";
      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

вообще я знаю откуда мусор, мы его попячим скоро

Я вот сейчас смотрю, полный пакет не всегда 20мс, иногда 22.
От количества широких импульсов зависит наверное.
Вот там где первый рабочий байт 0, общая длинна 22

последний код мне кажется должен дать результат…

Не компилится, где-то скобка лишняя чтоли… Ищу

вот

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200; // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t silence = 200 * 10; // если за это время не будет изменений - пакет получен, начинаем обработку

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 0) if (micros() - microsArr[ind] > silence) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (n % 2 == 0) res += val ? "1" : "0";

          if (cnt == 2) val = !val;
          
          n += cnt;

        } else {

          val = true;
          res += " ";

        }

      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

там не то что скобка а блок else не туда воткнул…

1111100001111111101000000 1111000111111100000
1111100001111111111000000 111100011111111100000
1111100001111111100000000 111100011111110000000
1111100001111111110000000 111100011111111000000
1111100001111111101000000 1111000111111100000

1111100001111111111000000 111100011111111100000
1111100001111111100000000 111100011111110000000
1111100001111111110000000 111100011111111000000
1111100001111111101000000 1111000111111100000
1111100001111111111000000 111100011111111100000
1111100001111111100000000 111100011111110000000

1111100001111111110000000 111100011111111000000

1111100001111111101000000 1111000111111100000
1111100001111111111000000 111100011111111100000

1111100001111111100000000 111100011111110000000

прям близко-близко))

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200; // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t silence = 200 * 10; // если за это время не будет изменений - пакет получен, начинаем обработку

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 0) if (micros() - microsArr[ind] > silence) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (n % 2 == 0) res += val ? "1" : "0";

          if (cnt == 2) val = !val;
          
          n += cnt;

        } else {

          n = 0;
          val = true;
          res += " ";

        }

      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

)))

1111100001111111111000000 1111100001111111111000000
1111100001111111100000000 1111100001111111100000000
1111100001111111110000000 1111100001111111110000000
1111100001111111101000000 1111100001111111101000000
1111100001111111111000000 1111100001111111111000000
1111100001111111100000000 1111100001111111100000000

1111100001111111110000000 1111100001111111110000000
1111100001111111101000000 1111100001111111101000000
1111100001111111111000000 1111100001111111111000000
1111100001111111100000000 1111100001111111100000000

1111100001111111110000000 1111100001111111110000000

переносы это же пустые строчки образовались, да?

#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200; // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t silence = 200 * 10; // если за это время не будет изменений - пакет получен, начинаем обработку

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


void loop() {

  if (ind > 3) if (micros() - microsArr[ind] > silence) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      String res = "";

      bool val = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        uint32_t dt = microsArr[i + 1] - microsArr[i];  // сколько времени между соседними сменами состояний
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0); // кол-во "тиков" (с учетом погрешности)

        if (cnt < 3) {

          if (n % 2 == 0) res += val ? "1" : "0";

          if (cnt == 2) val = !val;
          
          n += cnt;

        } else {

          n = 0;
          val = true;
          res += " ";

        }

      }

      Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

Да, там вот так всё!

но в целом оно даже работает… осталось побороть скорость вычислений и преобразовать в числа. 10 минут))

Надо наверное и две половинки сравнить и если одинаковые, то одну перевести в числа, если разные, пойти дальше. Да?

не, мы же строки сейчас попячим, т.к. это очень медленные операции. Нам нада сначала вычленить числа, потом их сравнивать и делать выводы

1 лайк
#define BTNPIN 2

// максимально возможное кол-во смен состояния входа за прием одного пакета (включая следом идущую копию)
const uint16_t maxc = 255;  // представить себе, что там будет 1010101010101010101010... короче количество бит + 1
int16_t ind = -1;
uint32_t microsArr[maxc];
const uint32_t tickwidth = 200; // количество микросекунд, соотв. длительности импульса одного бита в пакете
const uint32_t silence = 200 * 10; // если за это время не будет изменений - пакет получен, начинаем обработку

//void ISR (void* para) { // повесить на GPIO_INTR_ANYEDGE
void chng() {

  ind++;
  if (ind == maxc) ind = 0;
  microsArr[ind] = micros();
}

void setup() {
  pinMode(BTNPIN, INPUT_PULLUP);
  Serial.begin(115200);

  attachInterrupt(0, chng, CHANGE);  
}


/*
 4 1 1 1 1 1 1 1 1 2   1 1 1 1 1 1 2   1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2   1 1 1 1 1 1 1 1 1 1 1 1 1        - 1я часть, паузы между изменениями состояния (кратно tickwidth)
54 1 1 1 1 1 1 1 1 2   1 1 1 1 1 1 2   1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2   1 1 1 1 1 1 1 1 1 1 1 1 1 195    - 2я часть, паузы между изменениями состояния (кратно tickwidth)
   1   1   1   1   1   0   0   0   0   1   1   1   1   1   1   1   1   1   0   0   0   0   0   0   0        - биты данных

получается, если пауза > 2 то она для нас не несет битов, но свидетельствует о сбросе последовательности
информацию несет каждый четный элемент очереди (0, 2, 4, ...)
причем если этот элемент равен "2" то нужно поменять значение заполняемых бит на противоположное

*/


void loop() {

  
  if (ind > 3) if (micros() - microsArr[ind] > silence) {

      // в массиве шото есть, и последнее шото добавилось достаточно давно

      // тут будем хранить вытащенные из очереди биты
      uint32_t res1 = 0, res2 = 0;
      // какой из res1 res2 заполнять
      bool first = false;
      //String res = "";

      bool bit = true;
      uint16_t n = 0;

      for (uint16_t i = 0; i < ind; i++) {

        // сколько времени между соседними сменами состояний
        uint32_t dt = microsArr[i + 1] - microsArr[i];
        // кол-во "тиков/импульсов" (с учетом погрешности)
        uint16_t cnt = dt / tickwidth + (((dt % tickwidth) > (tickwidth / 2)) ? 1 : 0);

        if (cnt < 3) {

          // если cnt == 1 или 2 - тут идут данные

          if (n % 2 == 0) {

            uint8_t pos = n / 2; // позиция бита в числе

            // сдвигаем бит на позицию, побитово складываем с заполняемым сейчас результатом
            if (first) res1 |= (uint32_t)bit << pos;
            else       res2 |= (uint32_t)bit << pos;

          }
          //if (n % 2 == 0) res += bit ? "1" : "0";

          // если это сдвоенный импульс, то следующие биты будут инвертированы
          if (cnt == 2) bit = !bit;
          
          // увеличиваем счетчик
          n += cnt;

        } else {

          // если cnt оказалось больше 2, то это в лучшем случае начало второй части "посылки"

          n = 0; // сбрасываем счетчик
          bit = true; // сбрасываем бит
          first = !first; // переключаемся между res1 и res2
          //res += " ";

        }

      }

      // вычленяем результаты
      uint8_t A =   (uint32_t)res1 & 0xff;
      uint8_t B =  ((uint32_t)res1 & 0xff00) >> 8;
      uint8_t C =  ((uint32_t)res1 & 0xff0000) >> 16;
      uint8_t A2 =  (uint32_t)res2 & 0xff;
      uint8_t B2 = ((uint32_t)res2 & 0xff00) >> 8;
      uint8_t C2 = ((uint32_t)res2 & 0xff0000) >> 16;
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим
      
      //Serial.println(res);

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}

рискнем психикой… )