Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: сделать конвертацию бит с АЦП в температуру
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Метценгерштейн
немного торможу, как лучше?
т.е. получил с АЦП данные- 33.
я знаю, что по таблице это температура = 10.

как-то через ф-ю завернуть надо
Код
uint8_t convert_to_temp (uint8_t data)
{
    
}



если через дефайн, то

#define 33 10

Код
uint8_t convert_to_temp (uint8_t data)
{
    return 33;
}


надо как-то избавиться от цифр, а то не так поймут. Вот как?
Sergei_Ilchenko
Кто не так поймет?
Метценгерштейн
может где в коде еще цифры встретятся, он их возьмет и дефайнами заменит- не нравится так.
Как-то по-другому можно, уверен. Но не пойму как.
Sergei_Ilchenko
Через массив не экономично?
_pv
чтобы провести прямую надо, как известно, две точки, это в случае если зависимость кода от температуры линейная
что покажет АЦП при температуре например 20? 30?

#define, слава богу, менять одни цифры на другие не обучен. только буквы на цифры или буквы на буквы.
Sergei_Ilchenko
Зависимость линейная или нет?
Метценгерштейн
точно! про него-то и не подумал)

зависимость логарифмическая
ViKo
Код
uint8_t convert_to_temp (uint8_t x)
{
    return (a + x * (b + x * (c + x * d))); // a + bx + cxx + dxxx
}
CrimsonPig
Цитата(Метценгерштейн @ Feb 6 2015, 15:42) *
точно! про него-то и не подумал)

зависимость логарифмическая


Какова разрядность ацп-то ?
А то размер массива (lookup table) будет 2^(разрядность ацп). Для 16-битного ацп потребуется массив размером 65536 элементов.
Забивать в него значения ручками будете ? sm.gif

Кроме того, при неграмотном написании кода весь этот массив может копироваться из ROM в RAM при каждом входе в функцию перекодировки.
Кое-кто тут уже всласть побегал по этим граблям sm.gif

Может дешевле будет вычислять с помощью кусочно-линейной аппроксимации. На easyelectornics.ru DiHalt (а может кто-то еще) писал очень доступную статью по этому поводу.
Метценгерштейн
АЦП 10 бит всего-то.
написал так:
Код
uint16_t mass_convert[121]= {20,21,22,23,25,26,27,28,30,31,33,35,36,38,40,42,44,46,48,50,52,54,57,59,62,65,6
8,71,74,77,80,83,87,90,94,98,102,106,110,114,118,123,
128,132,137,142,148,153,159,164,170,176,182,188,195,201,208,215,222,229,237,244,
252,260,268,276,284,293,302,310,319,329,338,347,357,367,377,387,397,407,418,428,
439,450,461,472,483,494,506,517,529,540,553,564,576,588,600,612,625,637,649,661,
673,685,697,709,721,733,745,758,770,782,795,808,821,833,847,860,873,887,900, };
    

uint8_t convert_to_temp (uint16_t data) // return celsius
{
    for (uint8_t i =0; i < 121; i++) // data = 24
    {
        if (data == mass_convert [i])
        {
            return i;
        }
        else if (data < mass_convert [i])
        {
            return (i-1);
        }
    }
    return 0;
}

данные в экселе посчитал и скопировал туда. Их не много.
Такой код нормальный?
_Pasha
Цитата(ViKo @ Feb 6 2015, 20:14) *
Код
uint8_t convert_to_temp (uint8_t x)
{
    return (a + x * (b + x * (c + x * d))); // a + bx + cxx + dxxx
}

+ пицот! Его только в форме Горнера и вычислять. И только кубик.
Остальные уже не так томно, особенно когда юзать стандартные полиномы для термопар.
A. Fig Lee
Цитата(Метценгерштейн @ Feb 8 2015, 05:04) *
АЦП 10 бит всего-то.
написал так:
Код
uint16_t mass_convert[121]= {...};
    

uint8_t convert_to_temp (uint16_t data) // return celsius
{
    for (uint8_t i =0; i < 121; i++) // data = 24
    {
    ...
        }
    return 0;
}

данные в экселе посчитал и скопировал туда. Их не много.
Такой код нормальный?


Вместо "121" в loop, лучше всегда пользовать sizeof(mass_convert)
так более нормально.
Метценгерштейн
Цитата(A. Fig Lee @ Feb 8 2015, 16:29) *
Вместо "121" в loop, лучше всегда пользовать sizeof(mass_convert)
так более нормально.

а вот и нет, т.к. выведет общую сумму байт.
а у меня 2 байта на ячейку.

тогда лучше делать sizeof(mass_convert)/sizeof(uint16_t)
SM
А какой великий смысл в двух сравнениях? На == и на <? Когда для проверки интервала достаточно одно условие <=. Докучи, Ваш код вернет (uint8_t)(0-1), что равно 0xFF для кодов АЦП, меньших 20. Это раз. А два - я бы делал поиск методом половинного деления, чем перебирать все значения по очереди... Это же долго...
Метценгерштейн
Цитата(SM @ Feb 8 2015, 18:06) *
А какой великий смысл в двух сравнениях? На == и на <? Когда для проверки интервала достаточно одно условие <=. Докучи, Ваш код вернет (uint8_t)(0-1), что равно 0xFF для кодов АЦП, меньших 20. Это раз. А два - я бы делал поиск методом половинного деления, чем перебирать все значения по очереди... Это же долго...

возвращает он номер элемента массива, что равно температуре. Думаете, номер массива вылезет за 0xFF ? Нет, конечно.
SM
Цитата(Метценгерштейн @ Feb 9 2015, 11:44) *
Думаете, номер массива вылезет за 0xFF ? Нет, конечно.


Не думаю, а вижу по Вашему коду. Пусть data = 10, i=0. Нулевой элемент массива = 20. Первое условие 10==20 не выполняется. Второе условие 10<20 - выполняется. Возвращаем "i-1", что равно "0-1", что равно 0xFF.

Поэтому логично было бы иметь не два условия, а одно, if (data <= table[i]) return i;
Метценгерштейн
да, так
только если
data = 24;
при условии
Код
if (data <= table[i])

вернет 4
а нужно бы на градус меньше, т.е. 3
SM
Цитата(Метценгерштейн @ Feb 9 2015, 15:37) *
вернет 4
а нужно бы на градус меньше, т.е. 3

так поуменьшите все числа в таблице на 1. Короче, не алгоритм подпиливают под таблицу, а таблицу под алгоритм.
ViKo
А что же не сделать линейную интерполяцию между ячейками таблицы?
SM
Цитата(ViKo @ Feb 9 2015, 15:55) *
А что же не сделать линейную интерполяцию

Я, конечно, не автор, но, думаю, в задаче нет требования искать доли градуса. Поэтому достаточно найти, между какими значениями искомый целочисленный градус находится.
Метценгерштейн
в задаче температура нужна с точностью 5 градусов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.