Вопрос по системам счисления или сага о пропавшей "0b"

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

Привет всем! Курил даташит RTC DS3231 на предмет вывода из нее температуры, вывел, но получил какие-то хреновые значения. Разобрался, что микросхема по запросу выдает на шину I2C два байтика, в одном лежит целая часть числа, а во втором - дробная его часть. То есть, если у нас в комнате 25.25 градусов, то на шину свалится "00011001" и следующим  упадет огрызок дробной части в виде "01". О как, обрадовался я, значит, думаю, переведу это дело в DEC и будет мне щастье. Ага, щас. Лезет что попало. Тогда я создал фиктивную переменную со значением из даташита, 25 градусов, но что бы я ни делал, в монитор падает строго единичка. Только лишь если я отправляю не "00011001", а "0b00011001", в мониторе порта оказывается заветная "25". Вот код, кто захочет повторить.

#define button 13 //будет кнопка на пине 13, шобы светик загорался на всякий
void setup()
{
  pinMode(button, INPUT); //подтягиваем резистором
  digitalWrite(button, HIGH); //устанавливаем состояние
  Serial.begin(9600); //тут и сериал подтянулся
}

void loop()
{
  if (digitalRead(button) == LOW) //если кнопка нажата то
  {
    delay(500); //ждем 100мс
    byte byte1 = 0;
    byte byte2 = 0;//создаем парочку локальных переменных 
    byte1 = 00011001; //и суем в них вот эти значения (ЭТО 25 в DEC!)
    //А далее пытаемся вывести в монитор порта разные варианты представления этой переменной

    Serial.println(byte1); //для начала просто грубо суем ее в порт. Получаем единицу. WTF?
    Serial.println(byte1, DEC); //ладно, пробуем принудительно вывести ее в десятичной системе
                             //но хер там плавал. Снова получаем единицу.
    Serial.println(byte1, HEX); //Может тогда в шестнадцатеричной?.. Кол!
    Serial.println(byte1, BIN); //и повторим результат выводом тем же бинарным кодом
    //везде единички
    Serial.println(" "); //пробел для наглядности
    //зато как только я написал вот в таком формате, сразу же все получилось
    //и заветное "25" вылетело на монитор
    byte2 = 0b00011001;
    Serial.println(byte2);
    Serial.println(" "); //пробел для наглядности, если захочется еще раз
    //нажать кнопочку
  }
}

В связи со всем вышеописанным, у меня вопрос, наверняка не зря мне дуина кол ставит, очевидно я не знаю каких-то великих тайн ардуиностроения, прошу направить меня на путь истинный, или же предложить, как переделать получаемое с датчика значение в виде "00011001" в вот такое вот удобное для понимания контроллера: "0b00011001". Да и вообще, с чего это дуинка бинарный код во что-то свое собственное переделывает?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Усаживайтесь поудобнее и берите попкорн - Вы тут надолго ))))

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

Звучит многообещающе:D

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

А где тут работа с ds3231? Что б считать температуру, программы то на 6 строчек..

Wire.beginTransmission(0x68);
Wire.write(0x11);
Wire.endTransmission();
Wire.requestFrom(0x68, 2);
int temp= Wire.read()<<2 | Wire.read()>>6;
Serial.print((float)temp*0.25);

 

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

И правда, ваш скетч работает:о А не могли бы вы объяснить, зачем смещать на два, потом второй полученный байт на шесть, а затем умножать на 0.25 полученное значение temp?

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

ellfmd пишет:
Тогда я создал фиктивную переменную со значением из даташита, 25 градусов, но что бы я ни делал, в монитор падает строго единичка. Только лишь если я отправляю не "00011001", а "0b00011001", в мониторе порта оказывается заветная "25".

ellfmd, в 16 строке ты присваиваешь байтовой переменной 11 тыщ один, компилятор честно 11 тыщ откидывает, а единичку помещает в переменную byte1.

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

Andy, а если я указываю, что это 11001 в BIN, то почему ничего не меняется?

byte1 = 00011001, BIN;

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ellfmd, вы недокурили даташит:) Там же всё есть, даже с картинками. На два бита влево -что б зарезервировать  в результатирующей переменной в качестве младших бит два бита из второго байта. А на 6 вправо -потому, что два бита во втором байте лежат на месте старших бит. 0.25 -это разрешение. Каждый "попугай" получившегося значения после всех передвижек -это 0,25 градуса. С умножением число становится в привычном счислении.

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

dimax пишет:

ellfmd, вы недокурили даташит:) 

Или перекурили чего-то ещё.

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

Не понял, в чём фишка.

Запись 0b00011001 означает число 25, а запись 00011001 - число 4609. При преобразовании в байт 4609 даёт 1 - именно её Вы и наблюдали.

В чём непонятка то?

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

dimax, ааа, всё сразу стало ясно! Спасибо большое))

Хотя я и правда не видел, чтобы там было написано про сдвиг в какую-либо сторону...  А вот еще такой вопрос, написав

 Wire.write(0x11);

я делаю запрос на получение оттуда байта. А ведь есть еще регистр 0x12, который, получается, не используется? Но ведь он является "LSB of Temp", как указано в адресной карте. Или запросом двух байт сразу из регистра 0х11 сразу запрашивается и 0х12?

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

ЕвгенийП, да понял уж... Все это дело изучаю не так давно, поэтому смею встречать лицом грабли, в виде таких очевидностей:)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ellfmd, это особенность библиотеки wire, достаточно указать адрес, с которого начинать чтение, и можно читать последовательно нужное кол-во байт.

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

ellfmd пишет:

ЕвгенийП, да понял уж... Все это дело изучаю не так давно, поэтому смею встречать лицом грабли, в виде таких очевидностей:)

Уверен. что понял? И понимаешь почему "00011001 - число 4609"? Точно? Т.е. ты понимаешь почему вот такой код:

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

void setup() {
	Serial.begin(115200);
	int n0 = 00011001;
	int n1 = 11001;
	Serial << "n0=" << n0 << "\n";
	Serial << "n1=" << n1 << "\n";
}

void loop() {}

Выдаст вот такие значения:

n0=4609
n1=11001

Тебя здесь ничего не смущает и всё понятно?

Если нет, то лучше уж разберись, потому что завтра опять на эти же грабли наступишь.

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

Можно, кстати, нескромный вопрос? А на кой хрен Вам сдалась температура поверхности кристалла RTC?

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

ЕвгенийП пишет:

n0=4609
n1=11001

Тебя здесь ничего не смущает и всё понятно?

Полагаю, что n1=11001 он распознал, как число в десятичной системе, да так его и сунул в порт.

А n0, так как увидел, что она начинается с нулей, то подумал:"Ага! Это, 100% BIN".

А вот дальше что он стал делать, я честно не понимаю:с Ведь в двоичной это 25... Или я путаю толстое с мягким?

Не, ну а чо бы не использовать внутренний термометр кристалла, чтобы измерить температуру окружающей среды)

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

ЕвгенийП пишет:

 00011001 - число 4609. 

Я не понял ... Почему? 11001, это одиннадцать тысяч один.

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

brokly пишет:

Я не понял ... Почему? 11001, это одиннадцать тысяч один.

Совершенно верно.

А вот 011001 - это 4609

Запустите мой скетч и убедитесь сами.

См. мой следующий пост.

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

ellfmd пишет:

А n0, так как увидел, что она начинается с нулей, то подумал:"Ага! Это, 100% BIN".

А вот дальше что он стал делать, я честно не понимаю:с Ведь в двоичной это 25... Или я путаю толстое с мягким?

Ну, вот, а говорил, что разобрался :)

Если числовая константа начинается с лидируещего нуля, то в С (как и в С++) это восьмиричная константа. Стало понятнее?

ellfmd пишет:

Не, ну а чо бы не использовать внутренний термометр кристалла, чтобы измерить температуру окружающей среды)

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

 

 

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

Так вот оно чо! В голове всё сразу прояснилось)
Да вряд ли она сильно нагреется... но она достаточно точно определяет температуру приложенного к ней пальца. Кстати, а реально ли получить минусовое значение температуры на экране, если оно действительно опустилось ниже нуля?

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

ellfmd пишет:
Кстати, а реально ли получить минусовое значение температуры на экране, если оно действительно опустилось ниже нуля?
Не знаю. С микросхемой я работал (с прерываниями, с генератором 32кГц сигнала и т.п.), но вот температуру у неё ни разу не спрашивал и не особо с нею разбирался ввиду ненадобности.

Последнее, что я с этой микросхемой делал - "сгибридил" её с ESP8266 и полуил устройство, которое само устанавливается на точное время (через NTP получает), а заодно скачивает с gismeteo прогноз погоды :)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ellfmd, можно пользоваться встроенным термометром, и хоть на первой странице даташита заявлена точность +/- 3 °С считаю, что они  этой цифрой  сильно перестраховались. Фактическая точность не многим хуже популярного ds18b20, приклеить к чипу небольшой радиатор, что-б тот выходил  за пределы корпуса изделия, и хорошо измеряет. С отрицательной тем-рой нет проблем, только в примере из #3 я знак затёр, нужно переделать вот так:

int temp= (Wire.read()<<8 | Wire.read() )>>6;

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

ЕвгенийП пишет:

brokly пишет:

Я не понял ... Почему? 11001, это одиннадцать тысяч один.

Совершенно верно.

А вот 011001 - это 4609

Запустите мой скетч и убедитесь сами.

См. мой следующий пост.

А какое этому объяснение ? Где здравый смысл зарыт !?

Sindbad
Offline
Зарегистрирован: 08.12.2015

brokly пишет:
А какое этому объяснение ? Где здравый смысл зарыт !?

,

ЕвгенийП пишет:
Если числовая константа начинается с лидируещего нуля, то в С (как и в С++) это восьмиричная константа. Стало понятнее?

 

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

brokly пишет:

А какое этому объяснение ? Где здравый смысл зарыт !?

Ну, я же сказал смотреть следующий пост. Там ясно написано, что если есть лидирующий ноль, то константа - восьмиричное число. Переведите 011001 из восьмиричной системы в десятичную и получите 4609.

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

ЕвгенийП пишет:

Не знаю. С микросхемой я работал (с прерываниями, с генератором 32кГц сигнала и т.п.), но вот температуру у неё ни разу не спрашивал и не особо с нею разбирался ввиду ненадобности.

Последнее, что я с этой микросхемой делал - "сгибридил" её с ESP8266 и полуил устройство, которое само устанавливается на точное время (через NTP получает), а заодно скачивает с gismeteo прогноз погоды :)

Прикольно, я хочу заказать с али ESP8266, думаю, стоит того))

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

dimax, а знак как тут должен появиться? Сейчас довольно тепло, проверить не получается:D

Вроде одинаковое значение получается при обоих операциях... Как отсюда минус извлечь?

int temp= Wire.read()<<2 | Wire.read()>>6;
int temp= (Wire.read()<<8 | Wire.read() )>>6;

 

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

ellfmd пишет:

Прикольно, я хочу заказать с али ESP8266, думаю, стоит того))

  1. управление у неё через UART - будьте готовы
  2. скорость UART - как повезёт, подбирать будете. У меня оказалась зашита 115200 и SoftwareSerial не хватало - лезла грязь. C HardwareSerial всё нормально
  3. будьте готовы дать ей нормальное питание 3,3В не от Ардуины – она жрёт до 200мА (а когда нихрена не делает, так до 70), а 3,3В от Ардуины вроде не более 50. Так что кормить её надо от чего-то другого.
  4. аккуратнее с преобразованием уровней - она сильно не любит 5В. Провод от неё к АТМеге можно не преобразовывать (атмега понимает 3,3), а вот от атмеги к ней - обязательно, 5V её убьёт. Преобразовать можно по разному, если нужно могу отличную статью про это дать
  5. кстати об её прожорливости, мне она постоянно не нужна (спросила время и прогноз, и отдыхай), так я её питание завёл через полевой транзистор, и включаю его только когда она мне нужна, а когда не нужна – обесточиваю
  6. в принципе она сама по себе достаточно мощный контроллер и можно запрограммировать её, чтобы она делала всё сама, а ардуинке выдавала только готовые результаты, но я с этим не баловался и пользовал её обычными AT-командами.
ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

ЕвгенийП пишет:

  1. управление у неё через UART - будьте готовы
  2. скорость UART - как повезёт, подбирать будете. У меня оказалась зашита 115200 и SoftwareSerial не хватало - лезла грязь. C HardwareSerial всё нормально
  3. будьте готовы дать ей нормальное питание 3,3В не от Ардуины – она жрёт до 200мА (а когда нихрена не делает, так до 70), а 3,3В от Ардуины вроде не более 50. Так что кормить её надо от чего-то другого.
  4. аккуратнее с преобразованием уровней - она сильно не любит 5В. Провод от неё к АТМеге можно не преобразовывать (атмега понимает 3,3), а вот от атмеги к ней - обязательно, 5V её убьёт. Преобразовать можно по разному, если нужно могу отличную статью про это дать
  5. кстати об её прожорливости, мне она постоянно не нужна (спросила время и прогноз, и отдыхай), так я её питание завёл через полевой транзистор, и включаю его только когда она мне нужна, а когда не нужна – обесточиваю
  6. в принципе она сама по себе достаточно мощный контроллер и можно запрограммировать её, чтобы она делала всё сама, а ардуинке выдавала только готовые результаты, но я с этим не баловался и пользовал её обычными AT-командами.

Питать-то я ее буду от внешнего аккумулятора, а вообще, хотелось бы запрограммировать, чтобы она делала всё сама, раз уж такая возможность у нее имеется. Киньте статью по преобразованию 3.3-5В?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ellfmd, знак появиться когда результат выводится. Не переживайте, будет минус. Можно модуль в морозильник на 5 мин положить, потом быстро подключить  :)

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

ellfmd пишет:

Киньте статью по преобразованию 3.3-5В?

http://we.easyelectronics.ru/Shematech/soglasovanie-logicheskih-urovney-...

Правда, сам я делал через  ж  ... в смысле. через Альпы - поставил туда операционный усилитель. Вернее 2 - первый по инвертирующей схеме понижал, а второй "взад" инвертировал. Они как раз оба в одной миксросхеме живут.

ellfmd пишет:

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

Имеется специальный сайт/форум фанатов этой микросхемы - там много чего и о её программировании трётся. Сходите. полюбопытствуйте.

 

 

ellfmd
ellfmd аватар
Offline
Зарегистрирован: 27.03.2016

dimax пишет:

ellfmd, знак появиться когда результат выводится. Не переживайте, будет минус. Можно модуль в морозильник на 5 мин положить, потом быстро подключить  :)

Есть минус, всего три минуты в морозилке) 

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

vk007
Offline
Зарегистрирован: 16.06.2015

ellfmd пишет:

минус как-то тоже определять (определять, что он наступил и ставить соответствующую черточку)

Я наверное чего-то не понимаю, но неужели не поможет сравнение числа на "меньше нуля"? Ну а вообще-то минус хранится в самом старшем бите числа. Чтобы много не расписывать - вот.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ellfmd, Минус лежит в старшем бите  if (temp&1<<15)  значит минусовая. Но можно и по-простому  if (temp<0)