Перевод битов в десятичное число

Lion777
Offline
Зарегистрирован: 20.05.2016

 Решил разобратся как работают датчики и начал писать функцию для разбора данных с датчика DHT11, прилетает мне в ответе 40 бит, как мне их разобрать для вывода в десятичном виде ? Видел с побитовыми операторами, но чет не понял что и как...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Бит - число двоичное. Только так их и можно выводить.

Это - если отдельные биты.

Но чаще биты фигурируют как часть некоторого многобитного объекта. В этом случае нужно выводить не биты, а нечто, что характеризует сам объект (а не отдельные его биты). Но для этого надо знать, что за объект перед нами.

Lion777
Offline
Зарегистрирован: 20.05.2016

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andriano пишет:

В этом случае нужно выводить не биты, а нечто, что характеризует сам объект (а не отдельные его биты). Но для этого надо знать, что за объект перед нами.

Боюсь, что ТС

Lion777 пишет:

чет не понял что и как...

:((((((((((

sadman41
Offline
Зарегистрирован: 19.10.2016

Lion777 пишет:

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

Берите исходный код для любой библиотеки DHT, найдите там что-то типа:

      crc = bits[0] + bits[2];
      humidity    = bits[0] * 10;  // bits[1] == 0;
      temperature = bits[2] * 10;  // bits[3] == 0;

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

Lion777
Offline
Зарегистрирован: 20.05.2016

Готовое решение есть, я не могу там понять как выводятся данные с этих битов

у меня в массив byte data[40] , согласно даташиту, записанны биты, тип 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0

 

вот как их преобразовать в десятичные числа, я бы, например, разделил их по 8 бит, побайтно и перевел с двоичной в десятичную,

блин стыдно )), но немогу понять, как по простому все это сделать, раньше никогда не работал с этим

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Не стремитесь к преждевременной оптимизации. Сделайте, как понимаете: разбейте на 5 фрагментов по 8 ячеек. Два цикла, один вложен в другой. Во внешнем перебираете "байты", во внутреннем "биты". Перед началом вложенного цикла инициализируйте временную переменную (обнуляйте) размером в байт. Во вложенном цикле выставляйте ей биты. Если не знаете, как делать это битовыми операциями, начните с https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitset/ . По завершении вложенного цикла у вас есть сформированный во временной переменной байт. Пишите ее в массив "байты". По завершению внешнего цикла у вас есть заполненный массив "байты". 

Сделаете, результат осмыслите и можете переходить к оптимизациям - битовые операции, все действия в одном цикле, прямая модификация элементов массивов "байты" без временных переменных.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Lion777 пишет:

у меня в массив byte data[40] , 

Жесть - читать с DHT 40 бит в массив из 40 байт - такого оверхеда давненько не видел :)

Lion777
Offline
Зарегистрирован: 20.05.2016

ну так подскажите как правильно сделать? А то оверхед...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Lion777 пишет:

ну так подскажите как правильно сделать? А то оверхед...

Ну вы же как-то читаете с линии, правда? Вот и пакуйте прочитанное значение в байты. 40 бит - это 5 байт, прочитать можно так (ПСЕВДОКОД! это значит, что он для демонстрации алгоритма, а не для чтения с DHT):

byte bytes[5] = {0};
int currentByteNum = 0;
byte bitmask = 0x80; // старший бит байта установлен в единичку, его будем двигать вниз

for(int i=0;i<40;i++) // читаем 40 бит
{
  byte bitValue = readOneBitFromLine(); // читаем бит (1 или 0) с линии
  
  if(bitValue) // единичка
  {
	  bytes[currentByteNum] |= bitmask; // выставляем её в байте
  }
	// сдвигаем маску вправо
	bitmask >>= 1;
	
  if(!bitmask) // дошли до конца байта
  {
	bitmask = 0x80;
	currentByteNum++; // читаем в следующий байт
  }	
 
}

Что именно непонятно? Сами битовые операции? 

Lion777
Offline
Зарегистрирован: 20.05.2016

Да, я пока не понимаю толком как их использовать, до вашего сообщения сидел и думал, похожее прилетело в голову, что-бы небыло 40 байт

застопорился как дозаписывать байт с каждой новой итерацией, тип 8 итерацей - создали байт

вот мой набросок

////// Начинаем принимать данные 40 бит
  ///
  byte data[5]       = { 0 };     // массив для данных 5 байт
  unsigned char indxData = 0;     // индекс для перехода к записи следующего байта
  unsigned char cntBit   = 0;     // счетчик бит по 8 для создания байта данных
  
  for (int i = 0; i < 40; i++) {
    // 0 - 50мкс
    timeOut = 0;
    while (digitalRead(pinDht) == LOW) {
      if (timeOut++ > 100) {
        return 3;
      }
      delayMicroseconds(4);
    }

    // сам прием, если длительность импульса 1-цы больше 40мкс, то пишем как 1, иначе 0
    // 0 - 28мкс, 1 - 70мкс

    // засекаем время удержания 1
    unsigned long int timeHoldHigh = micros();
    timeOut = 0;
    while (digitalRead(pinDht) == HIGH) {
      if (timeOut++ > 100) {
        return 4;
      }
      delayMicroseconds(4);
    }
//// тут думаю ))
    if ((micros() - timeHoldHigh) > 32) {
      data[indxData] = 1 <<;
    }
    else {
      data[indxData] = 0;
    }
    // считаем количество бит, если больше 8 - обнуляем счетчик и записываем новый байт
    if(cntBit++ > 7) {
      cntBit = 0;
      indxData++;
    }
  }

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Lion777 пишет:

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

Вам не нужно переводить двоичную систему в десятичную, за Вас это потом сделает процедура print(), Вам нужно упаковать биты в байты по 8 штук в каждом. Прочитали очередной бит - записали его в младший (или старший - смотрите по дэйташиту) бит байта. Посмотрели, не готов ли целый байт (8 битов). Если готов - выдали наружу, если нет - сдвинули результат на 1 для приема следующего бита.

А вот когда байт готов целиком - посылаете его процедурой print() на экран и она сама представит его в десятичном виде.

Lion777
Offline
Зарегистрирован: 20.05.2016

Да я понял уже, раньше с таким не работал, да и почти 2 года ниче не кодил и тяжело врубится было, с этой штукой реально целый день ушел, тестировать в ардуино тяжело, на VS поигрался, дошло

// ConsoleApplication1.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
	unsigned char data[16] = { 0,1,1,0, 1,0,1,1, 0,1,1,0, 1,1,1,0 };
	               // 0 0 0 0 0 0 0 0  0 0 0 0 0 0 0 0
	// 107 110
	unsigned int dataByte[2] = { 0 };

	////// Начинаем принимать данные 40 бит
	///
	
	unsigned char indxData = 0;     // индекс для перехода к записи следующего байта
	unsigned char cntBit = 7;     // счетчик бит по 8 для создания байта данных, начало со старшего бита

	for (int i = 0; i < 16; i++) {
		

		  //0 1 1 0 1 1 1 0
//0 0 0 0 0 0 0 0
		//dataByte[indxData] << 1;
		if(data[i] == 1)
		dataByte[indxData] |= (1 << cntBit);
		//cout << indxData << " " << cntBit << endl;
		
		if (cntBit-- == 0) {
			cntBit = 7;
			indxData++;

		}


	}
		cout << dataByte[0] << endl;
		cout << dataByte[1] << endl;
	
	system("pause");

	return 0;
}