LC-1F vs MTX-L PLUS - секреты скорости. Часть 2. продолжение

Проблематика измерения R nernst...

После того как были изменены калибровки и была добавлена фильтрация к измерениям R nernst и Rpump - лямбды стали калиброваться более менее одинаково и всегда с одним и тем же результатом но все же с сильно разными температурами работы на выходе от сенсора к сенсору и от типа сенсора к типу сенсора и от платы к плате. Поэтому настала очередь разобраться с с магией и сделать ее лучше.

Почти эквивалентная (упрощенная) схема нашей магии выглядит примерно как то вот так:

Результаты цепочки расчетов симуляции измерения R Nernst по приведенной выше модели в excel:

Однако в этом расчете все же есть недостатки - он использует "идеальные ОУ", а было бы интересно учесть некоторые эффекты возникающие в реальных ОУ, которые в теории может учитывать современная, более скажем так приближенная к реальности, симуляция. Кроме того я не люблю аналоговую схемотехнику, и могу банально где то ошибаться и не замечать этого. Поэтому было решено накидать не только модель идеального измерения (в excel) но и эквивалентную схему измерения для возможности расчета решения в симуляторе - в качестве которого использовался бесплатный LTspice от Linerar Technology.

Источник PA2 - меандр 0-5в 3.4кГц.

Для симулятора соответственно: Rin(internal) = ( V(adc3)phase+  - V(adc3)phase- ) * 1024 / 5 * 8 / 7

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

1) Все прерывания на все время измерения запрещать.

2) Мультиплексор канала АЦП подключать к каналу измерения еще до момента подачи импульса нагрузки ячейки Нернста, для более точной балансировки выхода ОУ и входа АЦП микропроцессора и нивелирования возможного ранее накопленного значения в емкости входа АЦП микропроцессора.

3) По тактам строго была просчитана задержка момента семплирования с учетом тактовой частоты АЦП (125кгц) и времени семплирования (1.5 такта частоты АЦП). Выбраны новые коэффициенты задержек.

 После этих доработок выбросы Rnernst в минус полностью прекратились. Но все же в разных платах c прошивкой LC-1F калибровка давала разные результаты по Rnernst и главное - разную среднюю мощность нагревателя (этот параметр вычисляется в логах "Матрицы" с LC-1F).а значит по факту и разные температуры керамики. Т.е. какие то элементы схем (возможно конденсатор C1 или неточность всех резисторов) все же вносят достаточно большую погрешность в измерения, поэтому в итоге решено было вынести Target Rnernst на панель "Setup" комплекса "Матрица", чтоб была возможность оперативно задать любое желаемое  значение и таким образом любую желаемую температуру сенсора.. 

Если же проанализировать различные прошивки LC1-LC2-MTXL - то можно увидеть как в них тоже постоянно менялось калибровочное значение R nernst. Т.е. разработчики толком сами еще не определились, что там у них как должно работать (на самом деле - нет, причина их замен совсем в другом, но об этом будет ниже).... 

Подключаем LSU ADV к LC-1F

Если у вас есть LSU ADV и LSU 4.9 то можно сделать многое, например можно соединить их друг с другом вот в такого "котопса":

Кстати если котопса закрутить в выхлоп до катализатора и после - там будут происходить сложные электрохимические процессы, как нагреется... Но это не так интересно, гораздо более интереснее подключить LSU ADV к LC-1F и научить ее с ней работать.

В LSU ADV Bosch не очень то много поменял. Для начала отказались от калибровочного резистора и проводов теперь всего 5. Калибровка от этого скорее всего никуда не делась, и теперь  обеспечивается исключительно 2й лямбдой установленной за катализатором (системы управления и  раньше так делали, чтоб компенсировать сдвиг характеристики при старении - но сейчас это стало основным способом калибровки!) таким образом LSU ADV не может быть установлена в автомобиль где нет 2-го сенсора, и в случае использования LSU ADV ни второй сенсор ни катализатор ни в коем случае нельзя удалять! Нам же от этого не жарко не холодно - поскольку в LC-1F лямбда калибруется на свободном воздухе и калибровочный резистор у нее никакого значения не имеет. В LSU ADV так же изменилось сопротивление нагревателя.  Таким образом изменились калибровочные точки, для отражения % прогрева зонда и момент вступления в действие измерителя Rnernst  тоже измерены. Изменилась константа максимального эффективного напряжения на нагревателе - теперь она 12в вместо прежних 13в. LC-1F стала поддерживать ее только недавно но уже опционально для LSU ADV пришлось поправить... R nernst рекомендуемый вроде как остался старым (300) но те лямбды что у меня то ли уже мертвенькие,  то ли опять же проблематика измерений.. На 300 они даже и не думают работать, работают только с Rnernst <200.

Однако не все так гладко - по даташиту на LSU ADV предельно допустимый ток Ipump=4mА. Нам приходится использовать ток 6.22мА - так как это самый маленький из доступных к выбору токов Ipump. Технически если ячейка насоса не будет деградировать и выходить из строя - можно остановится на этом варианте. Если будет - заменить один из резисторов убрав поддержку NTK зонда. Но в общем и целом - все хорошо. Есть поддержка еще одного достаточно современного типа ШДК. 

Оправданна ли методика калибровки нагревателя в MTX-L PLUS?

Собственно в предыдущей статье был описан быстрый метод калибровки, основанный на фильтрации отношения Rnernst/Rpump на значительном интервале при значительных (+-40) отклонениях Rnernst от целевого значения. После того как удалось в LC-1F стабилизировать схему измерений для конкретного сенсора LSU ADV получены опытные результаты измерений пары из Rnernst  и соответствующего ему Rpump - причем ошибка для каждого из параметров находится не более, чем в пределах 2 дискрет измерений. Результаты проанализированы в Scidavis:

Погоду сильно портят крайние значения - поскольку они находятся уже на пределе устойчивости работы нагревателя или наличия цикла. Если их убрать то SciDAvis выдает такую формулу :

Линейная регрессия приближение по набору данных: Table1_2, используя функцию: A*x+B От значения по x = 80 до значения по x = 180 B (y-intercept) = 40,0952380952381 +/- 0,554306986991563 A (slope) = 0,642857142857143 +/- 0,00412393049421161 Chi^2/doF = 0,119047619047619 R^2 = 0,999835418038183 

Кстати 1/0,642857142857143=1,555555555555555555555 

Действительно существует сильная линейная связь но кроме множителя есть еще и смещение - т.е. методика используемая в MTXL PLUS может быть использована, но при более строгом соответствии Rnernst целевому (отклонение не более +-5 дискрет). Хотя над этим надо будет еще поработать. Возможно нет смысла измерения R nernst. Ведь если окажется что A и B - фундаментальные константы, для каждого типа сенсоров (или вообще для всех сенсоров), то целевое Rpump в регуляторе может быть получено в 2 действия из целевого R nernst и весь его неустойчивый матан с дифцепями и конденсаторами окажется попросту лишним... Пока же понятно, что как минимум для этого конкретного датчика  R pump= R nernst /1,5555555555 + 40

Сводная таблица попытки калибровки конкретного датчика LSU ADV с разными целевыми R nernst :

R nernst target R pump % мощности нагрева Период цикла на свободном воздухе. мс.
220 - - Error 8 sensor timing
200 170 56-58 14.6-15
180 156 58.1 14.7-16.316
160 143 60.7 17.6
140 130 63.2 19.361
120 117 68.3 20.796
100 104 73.9 22.801
80 92 83.6 24.891
60 83 95.8 26.493
50 - > 100%  прогрев и калибровка невозможны

Минимально возможное достижимое R nernst для LSU ADV при 100% подводимой мощности нагревателя и эффективном напряжении на нагревателе = 12в - 55 единиц. R nernst середины рабочего диапазона = 130.

Сводная таблица калибровки LSU 4.2 которую обычная LC1 считает мертвой (error 08 sensor timing):

Rnernst target R pump % мощности нагрева Примечание
100 -   не калибруется
80 -   не калибруется
70 241   нет цикла
65 238   нет цикла
60 227   нет цикла
50 197   раскачка - измерения не стабильны Error 8 sensor timing
40 164 50 8.4-5.6 нормальная работа.
35 144 51.6 20
30 129 56.7 30 
25 112 61 15-40 нестабильно.
20 96 68.5 20-45 нестабильно.

Сводная таблица калибровки новой оригинальной новой LSU 4.2 0 258 007 361 

Rnernst target R pump % мощности нагрева Период измерения на свободном воздухе (в стехиометрии). мс. Примечание
120 432 17-40 - Error 08 цикл не стабилен, затруднения при калибровке
100 360 23-27 4,3-5,9 (1,722) цикл не стабилен
80 284 23-36 8,046 (2,77)  
70 238-239 30-32 10,2 (4,13)
65 228 33 10,8 (4,2)  
60 217 33,5 12,2  
50 183 35-37 15  
40 154 39 20 (8)  
30 129 44.5 24,6  
20 107 50.7 33,8

 

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

В первых версиях ПО LC1F, чтоб не загружать контроллер всякой ерундой, вычисления lambda вообще не производились. Исходные данные времен передавались в ПК, и уже там производились вычисления (по алгоритму, аналогичному тому, что был в старой LC1). В последующих было решено вернуть вычисления (для реализации некоторых идей, результат измерения все же был нужен внутри), но при этом полностью избавится  от формата с плавающей точкой! Дело в том, что у формата с плавающей точкой слишком много проблем. Возможно непредсказуемое поведение библиотеки, глюки, потеря точности, ну и конечно проблемы низкой производительности подобных вычислений, а производительность всегда нужна - поскольку контроллер, кроме прочего, рассчитывает данные для цилиндровой селекции и PID регулятор у него несколько усложнен. Кроме того - формат с плавающей точкой вообще не нужен, поскольку это искусственно созданная, т.е. не наблюдаемая в реальной природе абстракция. В реальной системе управления примером которой является данный измеритель мы всегда имеем дело исключительно с натуральными значениями у любой операций ввода-вывода, то есть "полтора бита с АЦП" - такая же ересь как "полтора землекопа" ("Страна невыученных уроков")..

Давайте вспомним, что и как у нас вычислялось (это было описано во второй части статей про innovate):

DC=(T1-T2)/(T1+T2)

Для положительных значений DCexhaust:   lambda=DCair/(DCair-DCexhaust)

Для отрицательных значений DCexhaust:    lambda=(DCair/(DCair-DCexhaust))*0,71428+(1-0,71428)

Формула для вычисления % кислорода:    %O2=(DCexhaust/DCair)*20,9+0,08

Стоит заметить, что лямбда само собой не передается по каналу в виде float результата этих вычислений, и поэтому в конце нужно еще будет сделать преобразование в представление для протокола LC1 по формуле: lambda_int=lambda*1000-500 а %O2_int=%O2*10 cоответсвенно.

Казалось бы действий не так много - но нет! Сложение и вычитание времен идет в int формате, соответственно у вычитания может быть знак, сложение же по определению не имеет знака, поскольку все входные данные - натуральные. Дальше оба результата конвертируются sint2float и производится уже float деление для вычисления DC. Остальные вычисления чистые float в конце производится преобразование обратно в int.

Переведем все это в целочисленную форму. Для начала, что такое "положительные значения DC"? очевидно это когда T1>T2. Т.е. нам надо вычесть из T1 T2 и запомнить знак этой операции, чтоб потом сменить коэффициенты в алгоритме в процессе вычисления. На самом деле сменить надо даже не коэффициенты - а всю ветку программы. Поскольку требования к производительности алгоритма у нас высокие, а к расходованию байтов в памяти программ низкие (П.О. написано на ассемблере и места там навалом) - выгоднее использовать 2 почти идентичные ветки, в конце второй при этом будет сложение.

Примем за T(n)_FA значение T(n) на свободном воздухе полученное при калибровке и запишем нашу формулу для положительных значений DC следующим образом:

lambda_int = ((T1_FA-T2_FA)/(T1_FA+T2_FA))/ ((T1_FA-T2_FA)/(T1_FA+T2_FA)-(T1-T2)/(T1+T2))*1000-500 

а для отрицательных соответственно:

lambda_int = (((T1_FA-T2_FA)/(T1_FA+T2_FA))/ ((T1_FA-T2_FA)/(T1_FA+T2_FA)-(T1-T2)/(T1+T2))*0,71428+(1-0,71428))*1000-500

Для простоты записи упрощений в дальнейшем примем за: a = T1_FA, b = T2_FA, c=T1, d=T2

выражение: ((T1_FA-T2_FA)/(T1_FA+T2_FA))/ ((T1_FA-T2_FA)/(T1_FA+T2_FA)-(T1-T2)/(T1+T2)) можно заменить на: (T1_FA*T1-T2_FA*T2)/(T1_FA*T2-T2_FA*T1)*0,5+0,5

Для расчета % O2 соответственно так же можно заменить соотношение DC на конструкцию вида:

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

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

2) Все умножения в правой части не имеют знака (в отличие от всех делений знаковых чисел в левой части). От знака в правой части вообще легко избавится - хотя учитывая библиотечную реализацию деления signed int (другого напомню - нет) в данном конкретном случае смысла это в общем то не имеет.

3) Деление на 2 может быть заменено сдвигом вправо на 1 бит (если потребуется), умножение на 2 сдвигом влево соответственно. Однако в реальности это так же не нужно, поскольку у нас есть еще участки цифр в формулах (*1000-500) таким образом, наличие каких либо констант в правой части, для быстродействия вычислений значения не имеет, мало того часть констант в результате преобразований вырождаются.

Итого, формула вычислений лямбды для положительных значений будет иметь вид:

lambda_int = 500*(T1_FA*T1-T2_FA*T2)/(T1_FA*T2-T2_FA*T1)

а для отрицательных соответственно:

lambda_int = 357,14*(T1_FA*T1-T2_FA*T2)/(T1_FA*T2-T2_FA*T1)+142,86

для  %O2_int = 209.8-418*(ad-bc)/((ac-bd)+(ad-bc))

В результате, у нас на все про все, для вычисления лямбды будет производится четыре целочисленные умножения 16x16 и одно 32x32, значение 357,14 округляется до 357, а так же 2 вычитания, причем знаки их результатов должны совпасть, иначе результат всей операции будет отрицательным - а это не допустимо. На самом деле, это возможно лишь в случае, если измеренное DC превышает калибровочное DC - т.е. при ошибке калибровки.. Так же у нас есть одно деление - единственная серьезно затратная операция, но она тоже целочисленная. Точность вычислений при таком методе для положительных значений - абсолютна (это исходит из свойств натуральных чисел). Для отрицательных увы в пределах младшего значащего бита результата, поскольку мы вводим в формулу сторонние округленные константы.

Алгоритм вычисления следующий:

1) Предварительно вычисляем 2 выражения (ad-bc) и  (ac-bd) их результаты мы будем использовать по разному в зависимости от веток вычисления лямбды или %O2 но они нам нужны в любом случае.

2) Вычитаем из T1 T2 и запоминаем знак результата (сам результат не нужен).

3) Для лямбды: Умножаем верхнее выражение на константу зависящую от результата вычитания T1-T2 рассчитанного в предыдущем пункте (500 или 357) и делим на нижнее. Прибавляем 143 если нужно.

4) Если результат не превышает AFR=99.00 (99.00*1000/14.7-500) - лямбда вычислена! Иначе вычисляем %O2. 

6) Для %O2: Умножаем верхнее выражение на 418 делим на нижнее, результат умножения вычитаем из 210.

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

Почему на самом деле MTXL+ (а вместе с ней и LC2 и обычная MTXL) нормально не работают...

Часто можно услышать жалобы на LC2 - типа купил новую лямбду, проработала пару дней и сдохла. Некоторые замечают, что в показаниях что то не то и прогрев идет как то не нормально. И тому есть причина - управление нагревателем в этих приборах неработоспособно! Это очень сложно понять даже при многократных тестах - связано это с тем что цикл может быть устойчивым в очень  широком температурном диапазоне керамики сенсора.

Ошибки в ПО которые привели к этой ситуации возникли там не единовременно, но момент когда эти ошибки превратились в проблему возник, когда решили, отказаться от алгоритма однократной калибровки нагревателя при смене зонда и перейти к калибровке нагревателя при каждом включении прибора. Т.е. довольно давно. Фактически все, что выпущено после LC1 так или иначе содержит этот серьезный баг.

Как я уже писал в прошлой части суть управления нагревателем можно разделить на 2 части - управление с прямой связью (по модели объекта) и управление с обратной связью (ПИД регулирование). У нас не особо много априорных знаний об объекте, поэтому модель объекта в нашем случае представлена всего лишь одной этой цифрой:

 

Грубо говоря, если мы подаем на нагреватель номинальное напряжение - то сенсор находящийся в стандартных условиях атмосферы достигает номинальной температуры.. Это позволяет нам управлять нагревателем, даже в условиях когда не доступна, или не достоверна информация о реальной температуре сенсора. Так же мы можем ограничить действие интегратора в алгоритме, так как в условиях стационарности по температуре целевое напряжение в общем случае не будет сильно отклонятся от номинального напряжения. И это действие действительно ограниченно в режиме когда лямбда прогрета до рабочей температуры и есть цикл значением ошибки интегратора +-1000, что при применяемом значении интегрального коэффициента дает диапазон интегратора +-4.88v 

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

Процесс прогрева и калибровки нагревателя в этих приборах реализован в виде конечного автомата упрощенный граф состояний которого представлен ниже:

Инициализация номинального напряжения нагревателя происходит в состоянии 4. В это состояние можно попасть из состояний 5 8 и 10. Однако в состояние 5 можно попасть только из 4 и 10. В состояние 8 из 5, а в состояние 10 вообще нет входа. Таким образом алгоритм никогда не окажется ни в одном из этих состояний! Переменная среднего эффективного напряжения нагревателя останется не проинициализированной. При первоначальном анализе кода я даже не поверил, что подобная ошибка возможна и несколько раз проверил граф переходов из одного состояния в другое, но ошибка  не исчезала, и в конце концов понял, что необходимо проверить ее наличие с 100%й гарантией, поэтому  дописал в код MTXL+ процедуру снятия дампа ОЗУ при нормальной работе, которая ранее так же была дописана в LC1. Кусок дампа выглядит так:

В принципе достигнутое значение R pump=124 находится в пределе рабочих температур, однако при включении и калибровке с целевым R nernst=65 сенсор на короткое время может принимать значительную температуру (>1000градусов), поскольку значение интегратора ограниченно лишь при нормальной работе, при калибровке же это ограничение не действует... 

Можно проследить историю возникновения проблем управления нагревателем по прошивкам различных приборов. Фактически лишена проблем только прошивка LC1 - 1.10 для LSU4.2. Однако эта прошивка была склонна к срыву управления и сваливанию в ошибку 8 (как мы теперь уже знаем - из за ошибки в входных данных регулятора) . В 1.20 появилось ограничение значения в интеграторе, в результате чего, выбросы ошибок измерения не могли оказывать на регулятор значительного влияния. Сама идея этого ограничения  в принципе верна, но значение ограничителя было выбрано очень маленькое 0.366v, и таким образом если коэффициенты ПИД выбраны неверно (а это по сути так) - интегратор не позволял достичь целевого значения R pump, 1.21 была идентична 1.20 Алгоритм изменения калибровки нагревателя (калибровка при включении) появился в LC2 v1.00, так же несколько изменились коэффициенты ПИД.  

.. продолжение следует..

(c) Maxi(РПД) 2017-2018 Копирование материалов ресурса без разрешения автора запрещено.