Обсуждаем контроллеры компании Atmel.
Ответить

помогите обуздать датчик AHT20

Пн июн 13, 2022 22:44:14

Привет мужики! Делаю гляделку в застеклёный зимний сад OLED 128*64 и Attiny85, показания температуры/влажность.
Нарыл в интернете библиотеку, подключил, вроде бы как все заработало, по лог.анализатору вижу адекватную работу с датчиком, данные считываются и меняются если дыхнуть. Тож самое показывает если на ардуине собрать и посмотреть лог.анализатором. Но вывод на экранчик одно и тоже число -50 и 0 влажность, не соответствующее достоверности. Библиотеку приложил, основной код в main.cpp вот выложил.
Код:
#include "main.h"
#include "millis_micros.cpp"
#include "USI_TWI_Master.cpp"
#include "TinyWireM.cpp"
#include "SPARKFUN_AHT20.cpp"
#include "TinyOzOLED.cpp"

#define AHT20_VCC  PB4

float t_f,h_f;

AHT20 AHT;

int main(void)
{   
   PORTB|=(1<<AHT20_VCC);
   AHT.begin();
   OzOled.init();  //инициализация дисплей
   OzOled.setNormalDisplay();      //нормальный режим
   OzOled.setPageMode();           //адресация страничная
   OzOled.sendCommand(0xA1);       //выбор ориентации сверху - вниз
   OzOled.sendCommand(0xC8);       //слева - направо
   
    while (1)
    {      
      t_f = AHT.getTemperature();   // Читаем новые значения температуры 
       h_f = AHT.getHumidity();           // и влажности

      
      OzOled.clearDisplay();
      OzOled.printNumber(t_f,1, 0, 0);
      _delay_ms(1000);
      OzOled.clearDisplay();
      OzOled.printNumber(h_f,2, 0, 10);
      _delay_ms(1000);
    }
}


Добавлено after 1 hour 27 minutes 36 seconds:
Код:
float AHT20::getTemperature()
{
    if (sensorQueried.temperature == true)
    {
        //We've got old data so trigger new measurement
        triggerMeasurement();

        delay(75); //Wait for measurement to complete
       
        uint8_t counter = 0;
        while (isBusy())
        {
            delay(1);
            if (counter++ > 100)
                return (false); //Give up after 100ms
        }

        readData();
    }

    //From datasheet pg 8
    float tempCelsius = ((float)sensorData.temperature / 1048576) * 200 - 50;

    //Mark data as old
    sensorQueried.temperature = true;

    return tempCelsius;
}

Вот к примеру функция из библиотеки возвращает значение температуры, всё обшарил ума не приложу что тут может не работать!
Вложения
SPARFUN_AHT20.zip
(2.88 KiB) Скачиваний: 77

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 09:23:15

Мужики ни у кого мыслей нет, почему функция не возвращает результат?

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 09:56:19

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

Добавлено after 3 minutes 37 seconds:
Попробуйте 1048576 указать как float.

Добавлено after 1 minute 39 seconds:
Пользуйтесь отладкой, можно же все пошагово просмотреть, увидеть где какие данные есть. Заодно и писать красиво научитесь.

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 10:24:04

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

Добавлено after 3 minutes 37 seconds:
Попробуйте 1048576 указать как float.

Добавлено after 1 minute 39 seconds:
Пользуйтесь отладкой, можно же все пошагово просмотреть, увидеть где какие данные есть. Заодно и писать красиво научитесь.

Методом проб и ошибок было выявлено что вот эта функция считывае 6 последовательных байтов, что я вижу в лог.анализаторе, но потом их не правильно видимо приводит. Хотя в ардуино работает без нареканий.
Код:
void AHT20::readData()
{
    //Clear previous data
    sensorData.temperature = 0;
    sensorData.humidity = 0;

    if (_i2cPort->requestFrom(_deviceAddress, (uint8_t)6) > 0)
    {
        uint8_t state = _i2cPort->read();

        uint32_t incoming = 0;
        incoming |= (uint32_t)_i2cPort->read() << (8 * 2);
        incoming |= (uint32_t)_i2cPort->read() << (8 * 1);
        uint8_t midByte = _i2cPort->read();

        incoming |= midByte;
        sensorData.humidity = incoming >> 4;

        sensorData.temperature = (uint32_t)midByte << (8 * 2);
        sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 1);
        sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 0);

        //Необходимо избавиться от данных в битах> 20
        sensorData.temperature = sensorData.temperature & ~(0xFFF00000);

        //Пометить данные как свежие
        sensorQueried.temperature = false;
        sensorQueried.humidity = false;
    }
}

из аналогичной библиотеки делает так:
Код:
bool ATH20::getSensor(float *h, float *t)
{
    startSensor();
    Wire.requestFrom(0x38, 6);


    unsigned char str[6];
    int index = 0;
    while (Wire.available())
    {
        str[index++] = Wire.read(); // receive a byte as character
    }

    if(str[0] & 0x80)return 0;

    unsigned long __humi = 0;
    unsigned long __temp = 0;

    __humi = str[1];
    __humi <<= 8;
    __humi += str[2];
    __humi <<= 4;
    __humi += str[3] >> 4;

    *h = (float)__humi/1048576.0;

    __temp = str[3]&0x0f;
    __temp <<=8;
    __temp += str[4];
    __temp <<=8;
    __temp += str[5];

    *t = (float)__temp/1048576.0*200.0-50.0;

    return 1;

}

буду разбираться в битовыми операциями, что то пошло не так :kill: моя писанина пока так на коленке, потом приведу в божеский вид.

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 11:01:13

В последней функции явно указан float.

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 11:10:53

В последней функции явно указан float.


но и там тоже приведение типов есть - функции float AHT20::getHumidity(); и float AHT20::getTemperature(); используют void AHT20::readData()
и в них указано приведение типа float:
Код:
  .........     
     readData();
    } 
    //From datasheet pg 8
    float tempCelsius = ((float)sensorData.temperature / 1048576.0) * 200.0 - 50.0;

и
Код:
  .........     
     readData();
    }
    //From datasheet pg 8
    float relHumidity = ((float)sensorData.humidity / 1048576.0) * 100.0;

вы имели ввиду это 1048576 перевести в 1048576.0

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 11:21:55

Ну конечно, не зря же там .0

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 13:29:34

Уф... все поперло, переделал функцию readData(); заработало :beer: Один вопрос остался, в коде написал что делает эта строка
Код:
if(str[0] & 0x80)return 0;
я так и не понял, предположу если условие равно 1 выкинет нам ноль, а зачем нам 0 мы его ни где не ждем. Поэтому убрал return 0; т.к. не компилировалось на скорую руку.
Код:
void AHT20::readData()
{
    //Очистить предыдущие данные
    sensorData.temperature = 0;
    sensorData.humidity = 0;

    _i2cPort->requestFrom(_deviceAddress, 6); //считали шесть байт
   
      unsigned char str[6];
      int ind = 0;
      while (_i2cPort->available())
      {
         str[ind++] = _i2cPort->read(); //получаем байт
      }
      
      if(str[0] & 0x80); //НЕ ЗНАЮ ЗАЧЕМ, КТО ПОМОЖЕТ ОБЪЯСНИТЬ ЧТО ТУТ ДЕЛАЕМ?

      unsigned long __humi = 0;
      unsigned long __temp = 0;

      __humi = str[1];
      __humi <<= 8;
      __humi += str[2];
      __humi <<= 4;
      __humi += str[3] >> 4;
      
     sensorData.humidity = __humi; //передаем значение чтоб далее работало без переделок в других функциях

      __temp = str[3]&0x0f;
      __temp <<=8;
      __temp += str[4];
      __temp <<=8;
      __temp += str[5];
      
      sensorData.temperature = __temp; //передаем значение чтоб далее работало без переделок в других функциях
      
        //Пометить данные как свежие
        sensorQueried.temperature = false;
        sensorQueried.humidity = false;
   
}

Re: помогите обуздать датчик AHT20

Вт июн 14, 2022 14:35:13

Ну так void и не должен ничего возвращать.

Добавлено after 3 minutes 18 seconds:
А там идёт проверка первого принятого байта и если он равен 0x80 возвращается 0.

Re: помогите обуздать датчик AHT20

Вт июн 21, 2022 13:09:50

korsaj писал(а):А там идёт проверка первого принятого байта и если он равен 0x80 возвращается 0.

Если он равен или больше 0х80
Код:
(str[0] & 0x80)
вернет 0, если в str[0] старший бит нулевой, т.е. значение 0x00..0x7F и вернет 0х80, если старший бит единичка - значение str[0] в диапазоне 0x80-0xFF

v---- 0x80
1 0 0 0  0 0 0 0

Re: помогите обуздать датчик AHT20

Вт июн 21, 2022 16:02:49

Правильно сказать - если 7 бит равен 1.

Re: помогите обуздать датчик AHT20

Вт июн 21, 2022 16:49:32

korsaj, можно и так. Подробно разжевал больше для kote52

Re: помогите обуздать датчик AHT20

Ср июн 22, 2022 15:17:58

korsaj, можно и так. Подробно разжевал больше для kote52

Спасибо! :beer:
Ответить