Сделайте функцию, чтобы прочитать температуру от DS18B20 и показать на ЖК-дисплее - PullRequest
0 голосов
/ 11 мая 2019

Я хочу создать новую функцию, которая будет возвращать мне фактическую температуру из DS18B20 в качестве переменной с плавающей запятой.Мне нужна переменная такого типа для размещения строки на ЖК-дисплее.

Я уже использую функцию для чтения температуры следующим образом:

int8_t readTemp(struct ds18b20 *d) {
struct ds18b20 *newTemp;
char tempAct[5];
while (d->next != NULL)
{
    d = d->next;
    int fd = open(d->devPath, O_RDONLY);

    if (fd == -1)
    {
        perror("Couldn't open the w1 device.");
        return 1;
    }
    char buf[256];
    ssize_t numRead;
    while ((numRead = read(fd, buf, 256)) > 0)
    {
        newTemp = malloc(sizeof(struct ds18b20));
        strncpy(newTemp->tempData, strstr(buf, "t=") + 2, 5);
        //float tempC = strtof(d->tempData, NULL);
        sprintf(tempAct, "%s C", newTemp->tempData);
        //printf("Device: %s  - ", d->devID);
        //printf("Temp: %.3f C  ", tempC / 1000);
        //printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
    }
    close(fd);
}
return 1;}

У меня проблема со sprintf из этой строки:

  sprintf(tempAct, "%s C", newTemp->tempData);

В основном коде:

int main(void) {
struct ds18b20 *rootNode;
struct ds18b20 *devNode;
struct ds18b20 *getTemp;
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
while (1) {
    rootNode = malloc(sizeof(struct ds18b20));
    devNode = rootNode;
    getTemp = rootNode;
    int8_t devCnt = findDevices(devNode);
    printf("\n Found %d devices\n\n", devCnt);
    int8_t tempAct = readTemp(getTemp);
    printf("\n Temp Act: %d \n\n", tempAct);
    //readTemp(rootNode);
    // Free linked list memory

    while (rootNode) {

        // Start with current value of root node
        devNode = rootNode;
        // Save address of next devNode to rootNode before deleting current devNode
        rootNode = devNode->next;
        // Free current devNode.
        free(devNode);
    }
    free(rootNode);
}
return 0;}

Я пытаюсь воссоздать функции из finddevices:

int8_t devCnt = findDevices(devNode);
    printf("\n Found %d devices\n\n", devCnt);
    int8_t tempAct = readTemp(getTemp);
    printf("\n Temp Act: %d \n\n", tempAct);

Но tempData * не импортируетсяот функции readTemp к основному коду.

1 Ответ

3 голосов
/ 11 мая 2019

Код полон проблем, которые явно не являются частью вашего вопроса. Просто некоторые:

  • readTemp() не возвращает температуру. Фактически, он возвращает 1, если это не удалось, и 1, если это успешно Вероятно, это ошибка.

  • readTemp() выглядит так: все доступные датчики температуры, переданные ему в виде связного списка struct ds18b20, а не только одного. Но на самом деле пропускает корневой узел и обращается ко второму и последующему без проверки его корректности. Если в корневом узле нет устройства (только указатель на первое устройство), вам нужно только передать его, передав вместо него rootNode->next.

  • Не ясно, почему он динамически распределяет новый struct ds18b20 или почему он не может впоследствии отменить выделение. Это серьезная утечка памяти.

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

int readTemp( struct ds18b20 *d,         // List of sensors
              float* temperatures,       // Pointer to array to receive temperatures
              int8_t max_temperatures )  // Max number of temperatures to receive
{
    struct ds18b20* sensor = d ;
    int count = 0 ;
    while( sensor != NULL && count < max_temperatures )
    {
        int fd = open( sensor->devPath, O_RDONLY ) ;
        if( fd >= 0 )
        {
            if( read( fd, buf, sizeof(buf) ) > 0 )
            {
                char buf[256];
                char* temp_str = strstr(buf, "t=") + 2 ;
                sscanf( temp_str, "%f", &temperatures[count] ) ;
                temperatures[count] /= 1000 ;
                count++ ;
            }
            close( fd ) ;

            sensor = sensor->next ;
        }
        else
        {
            perror("Couldn't open the w1 device.");
        }
    }

    return count ;
}

Тогда вы можете назвать это так:

int8_t devCount = findDevices( rootNode ) ;

float* temperatures = malloc( devCnt * sizeof(float) ) ;
int8_t tempCount = readTemp( rootNode->next, temperatures, devCount ) ;

for( int i = 0; i < tempCount; i++ )
{
    printf( "Temp Act: %f\n", temperatures[i] ) ;
}

free( temperatures ) ;

Если вы знаете, что есть только одно устройство или вам нужно только напечатать первое, это можно упростить:

int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0 )
{
    float temperature = 0f ;
    int8_t tempCount = readTemp( rootNode->next, temperature, 1 ) ;
    if( tempCount > 0 )
    {
        printf( "Temp Act: %f\n", temperature ) ;
    }
}

Проблемы в вашем main() также различны, в том числе:

  • Корневой узел распределяется без необходимости динамически
  • несколько псевдонимов корневого узла создаются без необходимости
  • Список устройств многократно пересчитывается, а список устройств выделяется и освобождается на каждой итерации бесконечного цикла. Предполагая, что количество датчиков не изменяется во время выполнения кода, это не нужно.
  • Цикл никогда не заканчивается - даже в случае ошибки.

Лучшая реализация может выглядеть примерно так:

int main(void) 
{
    // Load pin configuration. Ignore error if already loaded
    system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");

    struct ds18b20 rootNode = { 0 } ;
    int8_t devCount = findDevices( rootNode ) ;

    if( devCount > 0)
    {
        struct ds18b20* devlist = rootNode->next ;
        float* temperatures = malloc( devCount * sizeof(float) ) ;
        int8_t tempCount = 0 ;

        do
        {
            tempCount = readTemp( devList, temperatures, devCount ) ;

            for( int i = 0; i < tempCount; i++ )
            {
                printf( "Temp Act: %f\n", temperatures[i] ) ;
            }

        } while (tempCount > 0 ) ;

        // Free resources after a temperature read fails 
        free( temperatures ) ;

        // Free linked list memory
        while( devlist != NULL ) 
        {
            // Save address of next before deleting current
            struct ds18b20* next = devlist->next ;

            // Free current devNode.
            free( devlist ) ;

            // get next
            devlist = next ;
        }
    }

    return 0 ;
}
...