|
Вычисления с помощью макросов, Проблема с выводом значения в реальном времени |
|
|
|
Mar 25 2008, 18:00
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Вывожу на ЖКИ 24-битное значение adc_value АЦП с периодом 1 сек. Это значение используется для вычисления дифференциального давления, которое вычисляется по формуле. Если попытаться выводить сразу в пересчитанное значение дифф. давления, то возникает проблема (виснет программа), хотя по идее макрос заменяется своим определением во время работы препроцессора, поэтому не вызывает затрат времени. И стек не должен потреблять на мой взгляд. Код #define Vref 5.0 #define GAIN 64.0 // Gain #define STEPS_B 8388608.0 // Full-Scale 2^(24-1) for bipolar operation #define SPAN 16.7 // Span (mV) of Pressure Sensors = 1 psi #define mm_Hg 51.714 // мм. рт. ст. (@ 0 гр. C)
#define Vin(adc_value) (((((adc_value)/STEPS_B) - 1.0)*Vref)/GAIN)
diffPressure = (Vin(adc_value)/SPAN)*mm_Hg; Почему так происходит? Как мне выводить значение давления в реальном времени? Это работает под управлением ОС (scmRTOS).
|
|
|
|
|
 |
Ответов
|
Mar 27 2008, 10:59
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
В общем, сделал так: Код #define Kp (Vref*mm_Hg)/(STEPS_B*GAIN*SPAN) А перед отображением значения давления на ЖКИ : Код diffPressure = ((double)adc_value-STEPS_B)*Kp; Увеличил стек для процесса measure , и все заработало  Цитата(Сергей Борщ @ Mar 27 2008, 14:28)  Поставив скобки вы ограничили поле деятельности оптимизатору. Поскольку вы делаете вычисления с плавающей точкой, то потери точности в этом выражении не ожидается и поэтому можно убрать лишние скобки, положившись на приоритет операций. Думаю, в этом случае оптимизатор сможет свести ваше выражение к y = kx+b. Вы имеете в виду вместо Код #define Vin(adc_value) ((((((double)adc_value)/STEPS_B) - 1.0f)*Vref)/GAIN) написать так? Код #define Vin(adc_value) (((double)(adc_value)/STEPS_B - 1.0f)*Vref/GAIN) Здесь аргумент заключен в скобки. Нужно ли здесь явное приведение к типу (double) , если при вызове макроса Vin параметр будет явно преобразован к (double)? .................... PS.Проблема была в большом количестве скобок и нехватки стека для процесса measure. Поэтому основные вычисления процессору пришлось выполнять в run time. Если убрать лишние скобки, то препроцессор преобразует вычисление к виду y=(x-a)/b, что собственно я и сделал только по-другому, определив Kp=1/b и во время вычисления diffPressure=(adc_value-a)*Kp. Теперь при вызове макроса Vin(adc_value)все работает  Спасибо, СергейБорщ и rezident. PS2. Для наглядности перевода значения АЦП в давление создал вложенный макрос: Код #define Vin(adc_value) (((adc_value)/STEPS_B - 1.)*Vref/GAIN)
#define SPAN 16.7 // Span (mV) of Pressure Sensors = 1 psi #define mm_Hg 51.714 // мм. рт. ст. (@ 0 гр. C) #define Kp mm_Hg/SPAN
#define PRESSURE(adc_value) (Vin(adc_value)*Kp) Проверил. Работает
|
|
|
|
|
Mar 27 2008, 14:18
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alux @ Mar 27 2008, 12:59)  Здесь аргумент заключен в скобки. Нужно ли здесь явное приведение к типу (double) , если при вызове макроса Vin параметр будет явно преобразован к (double)? Сушествуют правила неявного приведения типов. Если один из операндов имеет "более старший" тип, то второй преобразуется к этому типу. "Старшинство" выглядит примерно так: char->int->ling->long long->float->double. И параллельно беззнаковый->знаковый. Если STEPS_B у вас имеет тип с плавающей точкой, то adc_value будет приведено к такому же типу. Цитата(alux @ Mar 27 2008, 12:59)  (adc_value)/STEPS_B - 1. здесь можно было бы написать ((adc_value) - (uint32_t)STEPS_B)/STEPS_B - заменяете одно вычитание с плавающей точкой на вычитание с фиксированной => меньше кода, выше скорость.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 27 2008, 18:22
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(Сергей Борщ @ Mar 27 2008, 18:18)  здесь можно было бы написать ((adc_value) - (int32_t)STEPS_B)/STEPS_B - заменяете одно вычитание с плавающей точкой на вычитание с фиксированной => меньше кода, выше скорость. Не могу отказать себе в удовольствии подловить профессионала на такой элементарной ошибке. Так не будут отображаться отрицательные значения (если adc_value будет иметь тип unsigned long). По Правилам преобразования типов: "Если один из операндов имеет тип unsigned, то другой преобразуется к типу unsigned". Вы здесь ошиблись: Цитата(Сергей Борщ @ Mar 27 2008, 20:39)  А adc_value будет приведено из uint32_t к int32_t автоматически, по правилам приведения типов. adc_value также должен быть типа signed long  ................................... PS. Вконец запутался. Чтобы уменьшить количество скобок изменил Код #define Vin(adc_value) ((((adc_value)-(signed long)STEPS_B)/STEPS_B)*Vref/GAIN) на Код #define Vin(adc_value) (((adc_value)-(signed long)STEPS_B)*Vref/GAIN*STEPS_B) , что с арифметической точки зрения равнозначно, а на экран вместо цифр выводит ерунду (слеши, точки...). Почему?
|
|
|
|
|
Mar 27 2008, 20:43
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(alux @ Mar 27 2008, 20:22)  PS. Вконец запутался. Чтобы уменьшить количество скобок изменил Код #define Vin(adc_value) ((((adc_value)-(signed long)STEPS_B)/STEPS_B)*Vref/GAIN) на Код #define Vin(adc_value) (((adc_value)-(signed long)STEPS_B)*Vref/GAIN*STEPS_B) , что с арифметической точки зрения равнозначно Равнозначно будет Код #define Vin(adc_value) (((adc_value)-(signed long)STEPS_B)*Vref/GAIN/STEPS_B)
|
|
|
|
|
Mar 28 2008, 05:24
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(IgorKossak @ Mar 28 2008, 00:43)  Равнозначно будет Код #define Vin(adc_value) (((adc_value)-(signed long)STEPS_B)*Vref/GAIN/STEPS_B) Спасибо. Действительно, ведь операции выполняются слева направо. Теперь вывожу на ЖКИ непосредственно значение Vin. Только есть еще одна маленькая проблема. Максимальное значение положительного входного напряжения при GAIN=64 должно быть 0.078125V. А на самом деле на ЖКИ выводит 0.78125 V. Хотя в симуляторе подставлял значение 0xffffff при вызове Vin и получалось 7.8125 E-2. Почему на ЖКИ выводится на порядок больше, не пойму никак...  Ф-ции, обеспечивающие вывод на ЖКИ, я приводил в предыдущих постах. Это, должно быть, как-то связано с макросом Vin , потому что тестовый вывод значения АЦП в double типе выводит нормально (0xFFFFFF = 16777215.0). ....................................... PS. Похоже, снова "фокусы" со стеком. Попробовал полученное значение diffPressure после Vin() домножить на 10000 и вывести на экран с помощью itoa вместо ftoa. Вывело значение 781. Т.е. 781 / 10000 = 0.0781 V . Как и должно быть. Буду переписывать ф-цию ftoa.
|
|
|
|
Сообщений в этой теме
alux Вычисления с помощью макросов Mar 25 2008, 18:00 meister diffPressure = (Vin(0)/SPAN)*mm_Hg;
Тоже виснет? Mar 25 2008, 18:49 singlskv Цитата(alux @ Mar 25 2008, 21:00) Вывожу ... Mar 25 2008, 18:54 alux Цитата(singlskv @ Mar 25 2008, 22:54) ну ... Mar 25 2008, 19:10  singlskv Цитата(alux @ Mar 25 2008, 22:10) В форму... Mar 25 2008, 22:14   alux Цитата(singlskv @ Mar 26 2008, 02:14) А В... Mar 26 2008, 07:22  meister Цитата(alux @ Mar 25 2008, 22:10) Так не ... Mar 26 2008, 04:38 rezident alux, у вас оптимизация при компиляции используетс... Mar 25 2008, 22:39 tag Цитата(alux @ Mar 25 2008, 21:00) Вывожу ... Mar 26 2008, 08:46 alux Цитата(tag @ Mar 26 2008, 12:46) ...а вы ... Mar 26 2008, 09:20  tag Цитата(alux @ Mar 26 2008, 12:20) В симул... Mar 26 2008, 10:50   alux Цитата(tag @ Mar 26 2008, 14:50) ...а вси... Mar 26 2008, 13:28    tag Цитата(alux @ Mar 26 2008, 16:28) Из него... Mar 27 2008, 06:16     alux Цитата(tag @ Mar 27 2008, 10:16) Если adc... Mar 27 2008, 06:45      Сергей Борщ Цитата(alux @ Mar 27 2008, 08:45) Если пе... Mar 27 2008, 10:28       alux Цитата(Сергей Борщ @ Mar 27 2008, 13:28) ... Apr 8 2008, 10:42        Сергей Борщ Цитата(alux @ Apr 8 2008, 13:42) Здесь вы... Apr 8 2008, 15:15  alux Цитата(Сергей Борщ @ Mar 27 2008, 18:18) ... Mar 27 2008, 15:35   Сергей Борщ Цитата(alux @ Mar 27 2008, 17:35) И, соот... Mar 27 2008, 16:39 alux На этот раз стек здесь ни при чем. Проблема была в... Mar 29 2008, 19:45 alux И еще один маленький, но очень большой вопрос.
Как... Apr 9 2008, 08:18
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|