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

Стало хуже. В прошлые разы не только с порядком проблема, там средний байт слева 255, а справа 254 был

Спойлер

15 255 2 7 127 0

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

зато стало понятно в чем трабла

#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() {

  uint32_t ms = micros();

  if (ind == -1) {
    ind = 0;
    microsArr[ind] = ms;
  } else if (ms - microsArr[ind] > silence) {
    ind = 0;
    microsArr[ind] = ms;
  } else {
    ind++;
    microsArr[ind] = ms;
  }
  
}

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        - 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;

      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; // позиция бита в числе

            //      0 1      8 9     16 17     25
            // res1 1 11111111 11111111 111111111
            //     26 27    33 34    41 42     50
            // res2 1 11111111 11111111 111111111

            if (pos == 26) bit = true; // если первая часть пакета закончилась - сброс на стартовое

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


          }

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

        }

      }

      // вычленяем результаты
      uint8_t A =  (uint32_t)res1 >> 1 ;
      uint8_t B =  (uint32_t)res1 >> 9 ;
      uint8_t C =  (uint32_t)res1 >> 17;
      uint8_t A2 = (uint32_t)res2 >> 1 ;
      uint8_t B2 = (uint32_t)res2 >> 9 ;
      uint8_t C2 = (uint32_t)res2 >> 17;
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим

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

ну-ка

как то так

Спойлер

15 255 3 131 255 0

15 255 0 131 63 0

15 255 1 131 127 0

15 255 2 131 63 0

15 255 3 131 255 0

15 255 0 131 63 0

15 255 1 131 127 0

15 255 1 131 127 0

15 255 3 131 255 0

15 255 0 131 63 0

15 255 1 131 127 0

15 255 2 131 63 0

15 255 3 131 255 0

15 255 0 131 63 0

15 255 1 131 127 0

15 255 2 131 63 0

15 255 3 131 255 0

15 255 0 131 63 0

15 255 1 131 127 0

15 255 2 131 63 0

15 255 3 131 255 0

немного спутался уже, просьба еще раз:

#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() {

  uint32_t ms = micros();

  if (ind == -1) {
    ind = 0;
    microsArr[ind] = ms;
  } else if (ms - microsArr[ind] > silence) {
    ind = 0;
    microsArr[ind] = ms;
  } else {
    ind++;
    microsArr[ind] = ms;
  }
  
}

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        - 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;

      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) {

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

            //      24    17 16     9 8      1 0
            // res1 11111111 11111111 11111111 1

            //      49    42 41    34 33    26 25 - должно начинаться снова с нуля
            // res2 11111111 11111111 11111111 1

            if (pos == 25) bit = true; // если первая часть пакета закончилась - сброс на стартовое

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


          }

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

        }

      }

      // вычленяем результаты
      uint8_t A =  (uint32_t)res1 >> 1 ;
      uint8_t B =  (uint32_t)res1 >> 9 ;
      uint8_t C =  (uint32_t)res1 >> 17;
      uint8_t A2 = (uint32_t)res2 >> 1 ;
      uint8_t B2 = (uint32_t)res2 >> 9 ;
      uint8_t C2 = (uint32_t)res2 >> 17;
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}
Спойлер

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 3 7 255 1

15 255 1 7 255 0

15 255 1 7 255 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 2 7 127 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

15 255 1 7 255 0

15 255 3 7 255 1

15 255 0 7 127 0

15 255 1 7 255 0

вот ощущение что они все деленные на 2 (нацело), я хз почему

#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() {

  uint32_t ms = micros();

  if (ind == -1) {
    ind = 0;
    microsArr[ind] = ms;
  } else if (ms - microsArr[ind] > silence) {
    ind = 0;
    microsArr[ind] = ms;
  } else {
    ind++;
    microsArr[ind] = ms;
  }
  
}

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        - 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;

      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) {

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

            //      24    17 16     9 8      1 0
            // res1 11111111 11111111 11111111 1

            //      49    42 41    34 33    26 25 - должно начинаться снова с нуля
            // res2 11111111 11111111 11111111 1

            if (pos == 25) bit = true; // если первая часть пакета закончилась - сброс на стартовое

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


          }

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

        }

      }

      // вычленяем результаты
      uint8_t A =  (uint32_t)res1 >> 1 ;
      uint8_t B =  (uint32_t)res1 >> 9 ;
      uint8_t C =  (uint32_t)res1 >> 17;
      uint8_t A2 = (uint32_t)res2 >> 1 ;
      uint8_t B2 = (uint32_t)res2 >> 9 ;
      uint8_t C2 = (uint32_t)res2 >> 17;
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим

      ind = -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() {

  uint32_t ms = micros();

  if (ind == -1) {
    ind = 0;
    microsArr[ind] = ms;
  } else if (ms - microsArr[ind] > silence) {
    ind = 0;
    microsArr[ind] = ms;
  } else {
    ind++;
    microsArr[ind] = ms;
  }
  
}

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        - 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;

      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) {

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

            //      24    17 16     9 8      1 0
            // res1 11111111 11111111 11111111 1

            //      49    42 41    34 33    26 25 - должно начинаться снова с нуля
            // res2 11111111 11111111 11111111 1

            if (pos == 25) bit = true; // если первая часть пакета закончилась - сброс на стартовое

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


          }

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

        }

      }

      // вычленяем результаты
      uint8_t A =  (uint32_t)res1 >> 1 ;
      uint8_t B =  (uint32_t)res1 >> 9 ;
      uint8_t C =  (uint32_t)res1 >> 17;
      uint8_t A2 = (uint32_t)res2 >> 1 ;
      uint8_t B2 = (uint32_t)res2 >> 9 ;
      uint8_t C2 = (uint32_t)res2 >> 17;

      Serial.print(res1, BIN);
      Serial.print(' ');
      Serial.println(res2, BIN);
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим

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

я пока ухожу, не раньше чем через час посмотрю результат

У нас же до перевода в числа, вроде обе части одинаковые были ?

Спойлер

15 255 0 15 254 0

15 255 0 15 254 0

15 255 2 15 254 0

15 255 3 15 254 3

15 255 0 15 254 0

15 255 1 15 254 1

15 255 2 15 254 0

15 255 3 15 254 3

15 255 0 15 254 0

15 255 1 15 254 1

15 255 2 15 254 0

15 255 3 15 254 3

15 255 0 15 254 0

15 255 0 15 254 0

15 255 2 15 254 0

15 255 3 15 254 3

15 255 0 15 254 0

15 255 1 15 254 1

15 255 2 15 254 0

15 255 3 15 254 3

15 255 0 15 254 0

15 255 0 15 254 0

15 255 2 15 254 0

15 255 3 15 254 3

OK

Спойлер

15 255 2 7 127 0

1011111111000011111 1111111000001111

15 255 2 7 127 0

11111111000011111 1111111000001111

15 255 0 7 127 0

111111111000011111 11111111000001111

15 255 1 7 255 0

1011111111000011111 1111111000001111

15 255 2 7 127 0

1111111111000011111 111111111000001111

15 255 3 7 255 1

11111111000011111 1111111000001111

15 255 0 7 127 0

111111111000011111 11111111000001111

15 255 1 7 255 0

1011111111000011111 1111111000001111

15 255 2 7 127 0

1111111111000011111 111111111000001111

15 255 3 7 255 1

11111111000011111 1111111000001111

15 255 0 7 127 0

111111111000011111 11111111000001111

15 255 1 7 255 0

Мужики, а вы не можете всё это обсуждение перенести в личку? 100 постов переписываетесь вдвоём. Похоже только вам это интересно.

Я не знал, что это кому-то мешает.

Заниматься реинженерингом на публичных форумах это мовитон. К тому же если это было бы интересно хотя бы половине здесь живущим, то куда не шло, но ваша хотелка даже в первом посте не рассказано какова конечная цель, и что она будет делать, когда этот протокол всё же будет расколот. Помню был на форуме человек занимался расколом протокола автосигналки, так там понятно было зачем. А у вас ДЛЯ ЧЕГО все эти мытарства? Уважение должно быть к участникам форума IМНО.

Как раз таки рассказана конечная цель. именно в первом посте. Замена штатного дисплея на свой, соответствующий новым задачам устройства.

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

Читайте внимательно правила форума. Это клуб по интересам. Вы же заметили, что интереса к теме нет у 99 процентов участников. Ни одной темы за всё время не ставил в игнор.

Вы то внимательно читали первый пост мой? Напрашивается аналогия про соломинку и бревно.

Я понял.
Третий раз попробую спросить, МЕШАЕТ ЧЕМ?

не совсем так. Мы либо 1 либо 2 обрабатывали. Я нашел косяк. При переходе на 2 часть нарушается четность n изза чего весь пакет идет со смещением.

Вероятнее всего это решение:

#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() {

  uint32_t ms = micros();

  if (ind == -1) {
    ind = 0;
    microsArr[ind] = ms;
  } else if (ms - microsArr[ind] > silence) {
    ind = 0;
    microsArr[ind] = ms;
  } else {
    ind++;
    microsArr[ind] = ms;
  }
  
}

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

  attachInterrupt(0, chng, CHANGE);  
}


/* 0   2   4   6   8   10  12  14  16  18  20  22  24  26  28  30  32  34  36  38  40  42  44  46  48
 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)
// 49 (нарушена четность!!!)
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        - 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" то нужно ПОСЛЕ заполнения текущего бита поменять значение заполняемых бит на противоположное

     24    17 16     9 8      1 0
res1 11111111 11111111 11111111 1

     49    42 41    34 33    26 25 - должно начинаться снова с нуля
res2 11111111 11111111 11111111 1

*/


void loop() {

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

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

      // тут будем хранить вытащенные из очереди биты
      uint32_t res1 = 0, res2 = 0;

      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) {

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

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

          }

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

        }

      }

      // вычленяем результаты
      uint8_t A =  (uint32_t)res1 >> 1 ;
      uint8_t B =  (uint32_t)res1 >> 9 ;
      uint8_t C =  (uint32_t)res1 >> 17;
      uint8_t A2 = (uint32_t)res2 >> 1 ;
      uint8_t B2 = (uint32_t)res2 >> 9 ;
      uint8_t C2 = (uint32_t)res2 >> 17;

      Serial.print(res1, BIN);
      Serial.print(' ');
      Serial.println(res2, BIN);
      
      Serial.println(String(A) + " " + String(B) + " " + String(C) + " " + String(A2) + " " + String(B2) + " " + String(C2)); // выводим

      ind = -1; // сбрасываем индекс
      
    }
    
   // 
    
}
1 лайк
Спойлер

15 255 3 15 255 3

111111111000011111 111111111000011111

15 255 1 15 255 1

1011111111000011111 1011111111000011111

15 255 2 15 255 2

1111111111000011111 1111111111000011111

15 255 3 15 255 3

11111111000011111 11111111000011111

15 255 0 15 255 0

111111111000011111 111111111000011111

15 255 1 15 255 1

1011111111000011111 1011111111000011111

15 255 2 15 255 2

1111111111000011111 1111111111000011111

15 255 3 15 255 3

1111111111000011111 1111111111000011111

15 255 3 15 255 3

111111111000011111 111111111000011111

15 255 1 15 255 1

1011111111000011111 1011111111000011111

15 255 2 15 255 2

1111111111000011111 1111111111000011111

15 255 3 15 255 3

11111111000011111 11111111000011111

1 лайк

ну вот… если будут вопросы, как оно работает - спрашивайте. Есть нюанс что если нагрузить цикл, то обработчик в loop() может начать “не всегда” успевать забирать данные до их сброса прерыванием. А если это “не всегда” будет близко к периоду передачи пакетов, то могут появиться довольно длительные периоды “оффлайна” датчика и/или искажения показаний. Как вариант в таком случае обработку тоже перевести в прерывание. Но суть главное мы поняли как в принципе этот датчик читать.

P.s. корректность получения проще всего проверить на равенство res1 == res2

Александр спасибо огромное. Есть пара вопросов, но действительно хочется задать их в личке. Как это тут можно сделать, я не найду.