Перейти к содержанию

Sheleh

Members
  • Постов

    27
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Sheleh

  1. @22580 , у меня CA18 тоже изначально был карбюраторный и зажигание с центробежным регулятором и вакуумным корректором, в общем классическая схема. Потом я заметил что на тоетах, точнее именно на 3S-FE до 94 кажись года стоял впрыск с точно таким же простым датчиком, всего 4 импульса на 2 оборота коленвала. Так я прикрутил на ниссан комп от тоеты, вместе с тоетовским дадом, датчиками температуры, клапаном ХХ и ДПДЗ. Да, и из трамблера выкинул механические регуляторы. Родные форсунки от 3S не подошли, заливало конкретно. Подобрал другие форсы, меньшей производительностью (от эскудика), и видимо неплохо угадал. Так уже больше года ездил вынашивая план по созданию своего ЭБУ, потому-что настройки не идеальные, а тоетовский во-первых не настроишь, все зашито намертво в ПЗУ процессора. Там стоит расширенный аналог мотороловского 6801. Их чипуют - переводят в режим работы с внешней памятью, а занятые ноги как то эмулируют, и все это при помощи FPGA. Вариант интересный, но секретный и узконаправленный. Во-вторых из одновременного впрыска таким образом фазированный не получить. А фазированный гораздо лучше для газа, из-за того что впрыски длиннее.

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

    Примерный план такой:

    1. Подать на INT0 сигнал с выхода на инжекторы со своего ЭБУ. Подключить форсунки раздельно уже к своей плате. Запустить без пересчета - пришло прерывание - открыл/закрыл форсунки.

    2. Запустить простую математику. Импульсы с ЭБУ измерять и пересчитывать в фазированные. Нужен ДФ.

    3. Если все хорошо. То ввести объемную коррекцию. Отладить ее он-лайн редактирование.

    4. Проделать тоже самое с зажиганием.

    5. Реализовать ХХ и прочие управления.

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

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

    @DJ_DыM , прошивка своя, в разработке. Пока работает в протеусе. Умеет выдавать фазированные впрыск и зажигание по сигналу 4-1. Значение длительности впрыска и УОЗ берет из таблиц 16х16. Других коррекций пока нет, как и связи с ПК.

    Скрытый текст

    '$Regfile = "m16def.dat"
    $Regfile = "m8535.dat"
    $Crystal=16000000
    $hwstack=40
    $swstack = 16
    $framesize = 32

    '----------------------------------------------------------------------------------------------
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0
    Config Lcdmode = Port
    Cls
    Cursor Off
    '----------------------------------------------------------------------------------------------


    '----------------------------------------------------------------------------------------------
    Config Timer0 = Timer , Prescale = 8                        'таймер для PWM HOLD форсунок
    On Timer0 OnTimer0:
    Enable Timer0

    Config Timer1 = Timer , Prescale = 256 , Clear Timer = 0    'основной таймер
    Enable Timer1
    Compare1a = 100                                             'конфигурируем по сравнению
    On Compare1A OnTimer1
    Enable Compare1a


    'Config Timer2 = Timer , Prescale = 8
    'On Timer2 OnTimer2:
    'Enable Timer2
    '----------------------------------------------------------------------------------------------

    Enable Interrupts                                           'конфигурируем прерывание с ДПКВ
    Config Pind.2 = Input
    On Int0 Onint0
    Config Int0 = Rising
    Enable Int0

    '------------------конфигурация АЦП-------------------------
    Config Adc = Single , Prescaler = 128 , Reference = Aref
    Config Pina.5 = Input
    Config Pina.0 = Input
    Start Adc
    '----------------------------------------------------------------------------------------------

    '------------------конфигурация USART-----------------------
    $baud = 57600
    Config Pind.1 = Output
    Config Pind.0 = Input
    Echo Off
    '-----------------------------------------------------------

    Config Pind.7 = Output                                      'форсунки
    Config Pind.6 = Output
    Config Pind.5 = Output
    Config Pind.4 = Output


    Config PIND.0 = Output

    Declare Sub SetPortState(byval F As Byte , byval S As Byte)

    Const CylindersCount = 4                                    'количество цилиндров в данной конфигурации

    Dim Rx As String * 100

    Dim H As Bit , Pulseflag As Bit

    Dim N As Byte , J As Byte , I As Byte , Cycle As Byte , Port As Byte , EventEnable(5) As Byte
    Dim X1 As Byte , X2 As Byte , X3 As Byte , X4 As Byte , EventShift(5) As Byte , PortState(5) As Byte
    Dim TimeIgtCharge As Byte , InjLagTime As Byte


    Dim D As Integer , X As Integer , Y As Integer , EventTime(5) As Integer , AFS As Integer

    Dim Interspace As Word , PhaseInjShift As Word
    Dim Kx As Word , Ky As Word , C as Word , G As Word , RPM As Word
    Dim IgtAngle As Word , InjTime As Word


    'Dim HN(260) As Byte

    Cycle = 1                                                   'счетчик наступления рабочтей точки МВТ
    PhaseInjShift = 10                                          'за какое количество тиков таймера до ВМТ дожна зыкрыться форсунка
    TimeIgtCharge = 255                                         'время включения катушки перед моментом зажигания
    InjLagTime = 62

    Do
       If Pulseflag = 1 Then                                     'если сработало предывание от ДПКВ
          Pulseflag = 0
          PortB.0 = 0
          C = TIMER1


          AFS = GetADC(0) - 254                                   '259                                   'обрезаем все что ниже нижней работчей границы ДАД

          if AFS < 1 then AFS = 1                                 'Убираем отрицательные значения
          AFS = AFS * 10                                          'Масштабируем в Byte
          AFS = AFS / 32

          RPM = 37600 / Interspace                                'Масштабируем обороты. при частоте 16МГц значению 255 будет соответствовать 10000об/мин
          X = RPM / 16                                          'Вычисляем положение в таблице
          Y = AFS / 16
          I = Y * 16 : I = I + X                                'Вычисляем N соответсвубщего значения в массиве
          h = 0
          Kx = X * 16                                             'находим коэффициент для интерполяции по оборотам
          Kx = RPM - Kx
          Kx = Kx * 10                                          'Для того что бы не работать с дробными числами
          Kx = Kx / 16                                            '
          Ky = Y * 16                                           'находим коэффициент для интерполяции по давлению
          Ky = AFS - Ky
          Ky = Ky * 10                                          'Для того что бы не работать с дробными числами
          Ky = Ky / 16                                          '
          X1 = Lookup(I , Saturation)                           'Заносим в X1
          incr I                                                'Следующий
          X2 = Lookup(I , Saturation)
          I = I + 16                                            'переходим на следующую строку
          X4 = Lookup(I , Saturation)
          decr I
          X3 = Lookup(I , Saturation)                           'И так у нас есть 4 искомых значения для того что бы из них интерполировать искомое
          goto L3
          L2:
          H = 1
          I = I - 16
          X1 = Lookup(I , AngleTable)                           'Заносим в X1
          incr I                                                'Следующий
          X2 = Lookup(I , AngleTable)
          I = I + 16                                            'переходим на следующую строку
          X4 = Lookup(I , AngleTable)
          decr I
          X3 = Lookup(I , AngleTable)                           'И так у нас есть 4 искомых значения для того что бы из них интерполировать искомое

          L3:
          X = X2 - X1
          X = X * 10
          X = X * Kx
          X = X / 100                                           'Что бы не работать с дробью, ранее мы умножали на 100 и на 10. Настала пора делить обатно
          X = X + X1
          Y = X4 - X3
          Y = Y * 10
          Y = Y * Kx
          Y = Y / 100                                           'Что бы не работать с дробью, ранее мы умножали на 100 и на 10. Настала пора делить обатно
          Y = Y + X3
          X = Y - X
          X = X * Ky
          X = X / 100                           'искомое интерполированное значение
                                                 
          if h = 0 then
            InjTime = X1 + X         'для времени впрыска         
            goto L2
          End If

          IgtAngle = X1 + X         'для угла

          InjTime = InjTime * 5
          InjTime = InjTime + InjLagTime

          Disable Compare1a                                     'Отключем "ядро", для исключения совместных запросов в буферные переменные
          EventTime(2) = Interspace - PhaseInjShift             'Время закрытия форсунки
          EventTime(4) = Interspace - IgtAngle                  'Момент зажигания
          EventTime(1) = EventTime(2) - InjTime                 'Время открытия форсунки
          EventTime(3) = EventTime(1) + InjLagTime              'время включения PWM
          EventTime(5) = EventTime(4) - TimeIgtCharge           'Заряд катушки зажигания
          for i = 1 to 5 : EventShift(i) = 0 : next             'сбросим сдвиги
          for i = 1 to CylindersCount -1
             for j = 1 to 5
                if EventTime(j) < 0 then                        'расчитаем сдвиги событий. Например, если форсунка должна закрыться в текущем
                   EventTime(j) = EventTime(j) + Interspace     'такте, но время ее открытия не "влезает" в текущий такт, т.е. идет перкрытие
                   incr EventShift(j)                           'Т.е. если время открытого состояния форсунки больше времени между соседними
                end if                                          'работчими МВТ, то вычисляем сдвиг, на какую фазу придется данное событие
             next
          next
          if EventTime(1) < 0 then EventTime(1) = 1
          if EventTime(3) < 0 then EventTime(3) = 1
          D = Compare1a - TIMER1                                'перед запуском прерванного ядра проверяем
          if D < 2 then Compare1a = TIMER1 + 2                  'не пропустили ли мы какое-нибудь событие
          Enable Compare1a                                      'запускаем ядро

          C = TIMER1 - C
          PortB.0 = 1
          C = 50 * RPM

          if C > 0 then
             Locate 1 , 1
             lcd "         "
             locate 1 , 1
             Lcd C
             Locate 2 , 1
             lcd "         "
             locate 2 , 1
             Lcd IgtAngle                                       '
          end if


        'Print Hex(interspace)

          If Ischarwaiting() = 1 Then                             'проверка наличия команды в буфере UART
             Input "" , Rx
             If Len(rx) = 5 Then                                   '
            'S=mid(Rx,1,2)
            'T=HEXVAL(S)
            'S=mid(Rx,3,2)
            'dd=HEXVAL(S)
                Print Hex(interspace)
                Rx = ""
             End If
          End If


       End If
    Loop

    Sub SetPortState(byval F As Byte , byval S As Byte)
       if S < 4 then
          if S = 3 then S = 1
          if S = 2 then S = 0
          if F = 1 then Portd.7 = S                               '1. форсунки в порядке их работы
          if F = 2 then Portd.6 = S                               '2.
          if F = 3 then Portd.5 = S                               '3.
          if F = 4 then Portd.4 = S                               '4.
        'if F = 5 then PortB.7 = S
        'if F = 6 then PortB.6 = S
        'if F = 7 then PortB.5 = S
        'if F = 8 then PortB.4 = S
          else
          S = S - 4
          if F = 1 or F = 3 then PortB.7 = S                      '1-3 зажигание DIS-2
          if F = 2 or F = 4 then PortB.6 = S                      '2-4
    '    if F = 3 then PortB.5 = S
    '    if F = 4 then PortB.4 = S
       end if
    End Sub


    OnTimer0:
       if PortState(1) = 3 then Toggle Portd.7                   'тут по таймеру происходит непрерывная инверсия
       if PortState(2) = 3 then Toggle Portd.6                   'выходов форсунок, находящихся в режиме PWM HOLD
       if PortState(3) = 3 then Toggle Portd.5                   '
       if PortState(4) = 3 then Toggle Portd.4                   '
      'if PortState(5) = 3 then Toggle PortB.7
      'if PortState(6) = 3 then Toggle PortB.6
      'if PortState(7) = 3 then Toggle PortB.5
      'if PortState(8) = 3 then Toggle PortB.4
    Return

    OnTimer1:                                                   'таймер с самозагузкой. Выполняет очередь событий
    L:
       Port = EventShift(n) + Cycle : if Port > CylindersCount then Port = Port - CylindersCount       'вычисляе порт, на котором должно произойти событие
       Call SetPortState(Port , n)                              'выполняем событие
       if n < 4 then PortState(Port) = n                        'если событие не связано с зажиганием, изменяем статус порта форсунки(если n=3 то HOLD PWM)
       EventEnable(n) = 0                                       'помечаем событие, как исполненное

       n = 0
       D = interspace                                           'ищем следующие событие.
       for j = 1 to 5
          if EventEnable(j) = 1 and EventTime(j) < D then          'выбираем ближайшее по времени событие. Они не отсортированы
             D = EventTime(j)
             n = j                                                  'запоминаем его номер
          end if
       next

       if n <> 0 then                                           'если события не закончились
          D = EventTime(n) - TIMER1                             'записываем разницу между текущим временем таймера и планируемым
          if D < 5 then goto L                                     'если осталось мало времени до его исполнения,
          Compare1a = EventTime(n)                                 'или вообще мы его успели просахатить, то отправляемся на его немедленное исполнение
       end if                                                    'если время еще есть, грузим планируемое премя следующего события в регистр сравнения.
    Return                                                      'как только подойдет время таймера все повторится


    Onint0:                                                     'обработчик прерывания датчика в трамблере
       Interspace = Timer1                                      'запомнили сколько тиков натикало с момента предыдущего прерывания. Почти RPM
       Timer1 = 0                                               'обнуляем счетчик
       Pulseflag = 1
       Compare1a = Interspace                                   'загружаем в регистр сравнения максимальное время периода RPM
       for j = 1 to 5                                           'прогоним очереь сообщений на предмет неисполненых. Такое возможно, если обороты увеличились
          if EventEnable(j) = 1 then
             Port = EventShift(j) + Cycle : if Port > CylindersCount then Port = Port - CylindersCount
             Call SetPortState(Port , j)                          'выполняем немедлянно все неисполненные.
             if j < 4 then PortState(Port) = j
          end if

          if EventTime(j) < Compare1a then                       'перебираем очередь сообщений
             Compare1a = EventTime(j)                             'загружаем ближайщее событие
             n = j
          end if
          EventEnable(j) = 1                                     'настал новые период, помечаем все сообщения как неисполненные
       next

       Incr Cycle : If Cycle > CylindersCount Then Cycle = 1    'увеличиваем счетчик периода
       if Compare1a < 4 then Compare1a = 4                      'если событие дишит в затылок. Отодвинем его чуть-чуть. В начале цикла это не зажигание. Значит не страшно

       'Start Timer1
    Return

    End


    Saturation: 
       Data 26 , 27 , 28 , 28 , 28 , 28 , 29 , 30 , 31 , 32 , 33 , 33 , 32 , 32 , 31 , 30
       Data 30 , 31 , 32 , 32 , 32 , 32 , 34 , 35 , 36 , 37 , 38 , 38 , 37 , 37 , 36 , 35
       Data 35 , 36 , 37 , 37 , 37 , 37 , 39 , 41 , 42 , 43 , 44 , 44 , 43 , 43 , 42 , 41
       Data 41 , 42 , 43 , 43 , 43 , 43 , 45 , 48 , 49 , 50 , 51 , 51 , 50 , 50 , 49 , 48
       Data 48 , 49 , 50 , 50 , 50 , 50 , 52 , 56 , 57 , 58 , 59 , 59 , 58 , 58 , 57 , 56
       Data 56 , 57 , 58 , 58 , 58 , 58 , 60 , 65 , 66 , 67 , 68 , 68 , 67 , 67 , 66 , 65
       Data 65 , 66 , 67 , 67 , 67 , 67 , 70 , 75 , 77 , 78 , 79 , 79 , 78 , 78 , 77 , 75
       Data 75 , 77 , 78 , 78 , 78 , 78 , 81 , 87 , 89 , 90 , 92 , 92 , 90 , 90 , 89 , 87
       Data 87 , 89 , 90 , 90 , 90 , 90 , 94 , 101 , 103 , 104 , 107 , 107 , 104 , 104 , 103 , 101
       Data 101 , 103 , 104 , 104 , 104 , 104 , 109 , 117 , 119 , 121 , 124 , 124 , 121 , 121 , 119 , 117
       Data 117 , 119 , 121 , 121 , 121 , 121 , 126 , 136 , 138 , 140 , 144 , 144 , 140 , 140 , 138 , 136
       Data 136 , 138 , 140 , 140 , 140 , 140 , 146 , 158 , 160 , 162 , 167 , 167 , 162 , 162 , 160 , 158
       Data 158 , 160 , 162 , 162 , 162 , 162 , 169 , 183 , 186 , 188 , 194 , 194 , 188 , 188 , 186 , 183
       Data 183 , 186 , 188 , 188 , 188 , 188 , 196 , 212 , 216 , 218 , 225 , 225 , 218 , 218 , 216 , 212
       Data 212 , 216 , 218 , 218 , 218 , 218 , 227 , 246 , 251 , 253 , 255 , 255 , 253 , 253 , 251 , 246
       Data 246 , 251 , 253 , 253 , 253 , 253 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255

    AngleTable:
       Data 184 , 188 , 192 , 197 , 201 , 205 , 210 , 214 , 219 , 224 , 229 , 234 , 239 , 244 , 250 , 255
       Data 130 , 133 , 136 , 139 , 142 , 145 , 148 , 151 , 155 , 158 , 162 , 165 , 169 , 172 , 176 , 180
       Data 92 , 94 , 96 , 98 , 100 , 102 , 105 , 107 , 109 , 112 , 114 , 117 , 119 , 122 , 125 , 127
       Data 65 , 66 , 68 , 69 , 71 , 72 , 74 , 76 , 77 , 79 , 81 , 82 , 84 , 86 , 88 , 90
       Data 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 55 , 56 , 57 , 58 , 59 , 61 , 62 , 63
       Data 32 , 33 , 34 , 35 , 35 , 36 , 37 , 38 , 39 , 39 , 40 , 41 , 42 , 43 , 44 , 45
       Data 23 , 23 , 24 , 24 , 25 , 25 , 26 , 27 , 27 , 28 , 28 , 29 , 30 , 30 , 31 , 32
       Data 16 , 16 , 17 , 17 , 18 , 18 , 18 , 19 , 19 , 20 , 20 , 21 , 21 , 21 , 22 , 22
       Data 11 , 12 , 12 , 12 , 12 , 13 , 13 , 13 , 14 , 14 , 14 , 14 , 15 , 15 , 15 , 16
       Data 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 , 10 , 10 , 10 , 10 , 10 , 11 , 11 , 11
       Data 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 , 8 , 8 , 8
       Data 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 6
       Data 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4
       Data 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3
       Data 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
       Data 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1

    Софт так же еще в стадии наработок.

     

     

     

  2. @22580 , немного изменил плату(injectorMega16.lay6). А то была уж очень размашистой. Плюс сделал ее таким образом, что бы можно было по максимуму задействовать ноги контроллера.

    NewLay.thumb.PNG.cfa771684f5a40dc5c2dffd392e6f41f.PNG

    Планы по функциональности расширились. Данный девайс можно будет использовать как:

    1. Субкомпьютер или функциональный расширитель имеющейся ЭСУД. Например, если уже стоит старый с одновременным или попарным впрыском, то можно будет его преобразовать в фазированный, выкинуть трамблер поставив катушки. Ну и с он-лайн настройкой карт. Только в этом режиме в картах будут хранится не абсолютные значения, а относительные. Может даже получится (если это кому-нибудь будет нужно) реализовать функционал для перевод атмосферы на турбо.

    2. Контроллер ГБО.

    3. Самостоятельная ЭСУД.

    Завтра буду травить, собирать, и начинать испытания на реальном авто. Хотя нет. Сначала на столе с осциллографом, а уже потом на авто.

  3. @22580

    28 минут назад, 22580 сказал:

    Изучил вопрос по ГБО, как я понял из КоАП, ГБО конкретно не выделяется. И является "неисправностью" авто

    Вы оказывается многое пропустили. Наверстывайте!

     

    Скрытый текст

     

    А то, что у ГИБДДшников нет доверенностей, сами ГИБДД ликвидированы. Закон "О Полиции" Медведев не подписал. Не уже ли еще кто-то этого не знает? Да не имеют права они вас нагибать, это противозаконно с их стороны. Есть еще куча ЗАКОННЫХ оснований посылать данных товарищей в пешее эротическое путешествие.

    Давайте так. Законодательство у нас запретительное. Т.е. все, что не запрещено, то можно. А теперь назовите закон, запрещающий мне ездить на газе? Прямо об этом ничего не сказано. Значит притянуто за уши, и толкуется как им вздумается. А кодексы всякие, ПДД - законами не являются. Написано, что он принят государственной думой в 2001году. Ок. Тогда где этот основной документ, который дума приняла. Кто из лиц, имеющих соответственные полномочия, подписал? Где копия с подписью? Мне вот щас на вскидку даже не удается найти номер постановления, этой госдумы, не говоря уже об скане этого документа. И вот такие вопросы надо уметь задавать этим полицейским. Если они ссылаются на какой то документ, будьте добры, предоставьте заверенную копию. Гражданин по закону имеет право требовать любые документы, непосредственно затрагивающие его права.

    Вот, наверстывайте, пока есть шанс. Скоро все очень сильно изменится.

    https://www.youtube.com/results?search_query=в+россии+нет+подписанных+законов

    Далее https://www.youtube.com/results?search_query=гибдд+нет+доверенностей

    https://www.youtube.com/results?search_query=гибдд+частная+организация

     

     

  4. @22580 , да нету в газе ничего сложного. Любой может дома в гараже поставить. Либо готовый новый комплект, либо б/у, что обходится значительно дешевле. В своем блоке я планирую изначальную поддержку как бензина так и газа с мгновенным переходом между настройками. Т.е. уже отпадает потребность в одном из самых дорогих компонентов ГБО-контроллере. И собственно стоимость сводится практически к двум деталям - подходящий баллон и газовый редуктор, ну и форсунки. На жигули не более 100 баксов.

    Дела продвигаются. Но пока в симуляторе. Но думаю уже очень скоро таки система заведет свой первый ДВС.  https://www.drive2.ru/l/456991943071629809/

    Она уже сей час способна завести, но еще много чего не хватает, что бы полноценно ехать.

    По поводу помощи. Сможете плату собрать? Вот эту ver2.PNG

     

    injector8535.lay6

  5. @22580 , ну карб я бы в первую очередь убрал, что бы двигателю легче дышалось. А не проще найти инжекторный коллектор?

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

    Дождитесь мою игрушку. И зажигание и впрыск в одной консткрукции. Плюс еще и LPG! Проект открытый, детали копеешные.

    Бензин кстати удобнее делать ввиде моно-впрыска, ибо он нужен будет лишь для запуска и до АГЗС доехать, а вот газ очень легко ставить как распределенный. В таком случае вообще можно карб оставить, пущай бензин мешает, как умеет. Проще поставить газовый балон и редуктор, чем переделывать карбюраторную систему в инжекторную.

     

  6. @sr86 , да нашел. Благодарю за наводку. В этом проекте меня интересует только кан, точнее k-line. Подсмотрю реализацию.

    Посмотрел внимательнее. Сам проект какой то странный. Много кода при минимуме функций. Впрыск одновременный. Зажигания нет.

  7. @hc13nx2 , в общем почитал я за расширенный 51 по периферии проц января. Он так то нифигово там расширен. AVR нервно курит. А мои попытки перенести код на 8052 вероятно обречены на провал. Уж очень мало там RAM всего 256байт. Половина очень необходимых переменных уже не помещается. Здесь только на чистом ассемблере если писать, и по какой-то совсем упрощенной логике.

    А вот AVR 8535 наоборот радует. Тут 512байт ОЗУ, запас пока есть. Сам код программы подходит к 65% объема Flash. В оставшиеся 35 надо уместить управление ХХ и обмен данными с ПК, а вот коррекция по лямбде уже вероятно не поместится. Но тут можно взять Atmega16 с такой же архитектурой и распиновкой, и карты перенести в RAM( 1кб ). А значит можно реализовать автонастройку карт силами самого контроллера, как сделано у этого товарища - https://www.drive2.ru/users/avtoelektron/#blog

  8. @sr86, по компиляторам: ну возможно GCC не так уж и плох (всяко лучше arduino'вского), но тем нее мнее BASCOM совсем не хуже. Кстати, он изначально разрабатывался для архитектуры 8051. Как заявляют разработчики он процентов на 30-40 уступает чистому ассемблеру по размеру прошивки. На сколько я знаю, ситуациия с GCC ничем не лучше. Лишь у IAR значительно лучше.

    Подожди. Ты хочешь сказать, что Январь работает на 8051? Я живу в Бурятии, и тачки на январе для нас тут редкость. В основном одни жапанцЫ.  Поэтому не силен в архитектуре западных (по отношению к Сибири) ЭСУД.

    Так что "бесплатность" такого блока у нас отсутствует. Вообще январь днем с огнем не сыщешь. Зато какой нибудь тоетовский на разборе можно за рублей 500 взять, если не GTE конечно.

  9. Ура, получилось! В школе по математике я был далеко не отличником. Я даже среднеспециальное не закончил. Хотя мне говорили, хочешь быть программистом, дружи с матиматикой. Fuck U asshole!!!

    Даже не верится, что сам разобрался с интерполяцией. Не ну конечно, любой отличик бы наверное справился бы с этим за 15 мин... Хотя очень сомневаюсь, что современным отличникам это по зубам.

    при чем даже без использования чисел с плавающей запятой. (Если задействовать, хотя бы одну такую переменную, то код прошивки сразу вырастает процентов на 10. )

    Скрытый текст
    
        AFS = GetADC(0) - 259                                   'обрезаем все что ниже нижней работчей границы ДАД
        if AFS < 1 then AFS = 1                                 'Убираем отрицательные значения
        AFS = AFS * 10                                          'Масштабируем в Byte
        AFS = AFS / 32
        RPM = 37600 / Interspace                                'Масштабируем обороты. при частоте 16МГц значению 255 будет соответствовать 10000об/мин
        X = RPM / 16 : Y = AFS / 16                             'Вычисляем положение в таблице
        Kx = X * 16                                             'находим коэффициент для интерполяции по оборотам
        Kx = RPM - Kx
        Ky = Y * 16                                             'находим коэффициент для интерполяции по давлению
        Ky = AFS - Ky
        I = Y * 16 : I = I + X                                  'Вычисляем N соответсвубщего значения в массиве
        X1 = Lookup(I , Saturation)                             'Заносим в X1
        incr I                                                  'Следующий
        X2 = Lookup(I , Saturation)
        I = I + 16                                              'переходим на следующую строку
        X4 = Lookup(I , Saturation)
        decr I
        X3 = Lookup(I , Saturation)                              так у нас есть 4 искомых значения для того что бы из них интерполировать искомое
        Ky = Ky * 100                                           'Для того что бы не работать с дробными числами
        Ky = Ky / 16                                            '
        Kx = Kx * 100                                           'Для того что бы не работать с дробными числами
        Kx = Kx / 16                                            '
        X2 = X2 - X1                                            'Дальше уже сложо коменнтировать, ибо код родился
        X4 = X4 - X3                                            'каким то мгновенным озарением.
        X2 = X2 * 10
        X = X2 * Kx
        X = X / 1000                                            'Что бы не работать с дробью, ранее мы умножали на 100 и на 10. Настала пора делить обатно
        X = X + X1
        X4 = X4 * 10
        Y = X4 * Kx
        Y = Y / 1000                                            'Что бы не работать с дробью, ранее мы умножали на 100 и на 10. Настала пора делить обатно
        Y = Y + X3
        X = Y - X
        X = X * Ky
        X = X / 100
        InjTime = X1 + X                                        'искомое интерполированное значение
    -------------------------------
          
    Saturation:
    Data 26 , 27 , 28 , 28 , 28 , 28 , 29 , 30 , 31 , 32 , 33 , 33 , 32 , 32 , 31 , 30
    Data 30 , 31 , 32 , 32 , 32 , 32 , 34 , 35 , 36 , 37 , 38 , 38 , 37 , 37 , 36 , 35
    Data 35 , 36 , 37 , 37 , 37 , 37 , 39 , 41 , 42 , 43 , 44 , 44 , 43 , 43 , 42 , 41
    Data 41 , 42 , 43 , 43 , 43 , 43 , 45 , 48 , 49 , 50 , 51 , 51 , 50 , 50 , 49 , 48
    Data 48 , 49 , 50 , 50 , 50 , 50 , 52 , 56 , 57 , 58 , 59 , 59 , 58 , 58 , 57 , 56
    Data 56 , 57 , 58 , 58 , 58 , 58 , 60 , 65 , 66 , 67 , 68 , 68 , 67 , 67 , 66 , 65
    Data 65 , 66 , 67 , 67 , 67 , 67 , 70 , 75 , 77 , 78 , 79 , 79 , 78 , 78 , 77 , 75
    Data 75 , 77 , 78 , 78 , 78 , 78 , 81 , 87 , 89 , 90 , 92 , 92 , 90 , 90 , 89 , 87
    Data 87 , 89 , 90 , 90 , 90 , 90 , 94 , 101 , 103 , 104 , 107 , 107 , 104 , 104 , 103 , 101
    Data 101 , 103 , 104 , 104 , 104 , 104 , 109 , 117 , 119 , 121 , 124 , 124 , 121 , 121 , 119 , 117
    Data 117 , 119 , 121 , 121 , 121 , 121 , 126 , 136 , 138 , 140 , 144 , 144 , 140 , 140 , 138 , 136
    Data 136 , 138 , 140 , 140 , 140 , 140 , 146 , 158 , 160 , 162 , 167 , 167 , 162 , 162 , 160 , 158
    Data 158 , 160 , 162 , 162 , 162 , 162 , 169 , 183 , 186 , 188 , 194 , 194 , 188 , 188 , 186 , 183
    Data 183 , 186 , 188 , 188 , 188 , 188 , 196 , 212 , 216 , 218 , 225 , 225 , 218 , 218 , 216 , 212
    Data 212 , 216 , 218 , 218 , 218 , 218 , 227 , 246 , 251 , 253 , 255 , 255 , 253 , 253 , 251 , 246
    Data 246 , 251 , 253 , 253 , 253 , 253 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255

     

    Теперь коэффициент VE изменяется плавно от 1 до 255. С дискретностью 1. В ms это будет 0,08ms

    По поводу чтения из флеш. В BASCOM это производится коммандой Lookup. Она медленее обычного присваивания из переменной в RAM. Но медленее она всего лишь в 2,2 раза, что на самом деле тоже очень быстро.  И держать большие объемы данных в ОЗУ имеет смысл лишь для полноценно-онлайновной настройки. Но тогда нужны будут чипы большей размерности. Но моя цель была попытаться использовать самый дешевый из возможных. Я конечно еще много чего не реализовал, но хотя бы появилась уверенность, что полноценный код таки можно уместить в 8кб.

    Весь код интерполяции плюс расчет временных задержек выполняется за 0.4 ms. И это без использования ассемблера.

    Так же в процессе реализации я пришел к выводу, что BASCOM - это супер-компилятор, ни чем не уступающий аналогичным решениям на С. Конечно лучшим решением для ядра AVR считается IAR, так как они учавствовали в разработке архитектуры ядра. BASCOM на мой взгляд занимает твердое второе место. А вот GCC я бы поставил на 3-е, есть статья на хабре, где они сравниваются.

    Исходя из вышеописанного становится реалистичнее идея засунуть полноценный алгоритм ЭСУД в древнейший чип на архитектуре Intel 8051. Конечно сам 8051 обладает лишь 4кБ памяти, а вот 8052 с 8кБ уже вполне подходит под наши задачи. Просто у меня их огромная куча, да и стоимость их на али не больше 100р за шт. И это за полноценных 40 ног! Вы только представьте, по себестоимости ЭБУ менее 500р, где большую часть бюджета - это транзисторы.

  10. Для интерполяции необходимо запрашивать сразу 4 соседних значения из таблицы. Т.е. 4 для топлива, и 4 для угла. Остальные поправки (от температур) можно обновлять реже. Если таблицу оставляю во флеш-памяти, то как это отразится на скорости. Понятно, что запись в Флеш медленая по причине сложности алгоритма, но нигде не сказано про скорость чтения. Я не знаток в архитектуре микроконтроллеров, но что мне подсказывает, что это не должно быть так критично. Вот на PC код программы сначала грузится в оперативу, а на МК, я так понял исполняется прямо из флеш. Значит флешка то достаточно быстрая? Или я не прав, и применяются каки-нибудь хитрости, типа кэширования.

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

  11. @hc13nx2 , а как вы сделали сам расчет длительности впрыска? Я имею ввиду, допустим я делаю карту 16х16. Если просто брать значения из таблицы, то получается дикая дискретность. Надо же как то с определнной линейностью интерполировать между соседними значениями таблицы. Если просто брать значения из таблицы, то явно же будут подергивания при переходе между ячейками.

  12. что бы уложиться в 1 Byte

    RPM = 47685 / Interspace (константу делю на количество тиков между прерываниями с ДПКВ)

    Получается 10000об/мин = 255. Соответственно 1000=25, 500=12. Т.е. с дискретностью в ~ 40 оборотов.

     

     

  13. @hc13nx2 , да, я так и планировал. У меня для прошивки и для настроки один и тот же шнурок.

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

     Можно даже на ходу перепрошивать, если едешь накатом. Или вообще не использовать оперативу, хранить во флеш, а дистанционно переписывать только необходимую область. Только я не знаю, можно ли averdud'у задать конкретный диапазон программируемой памяти. Будет быстрее, чем переписывать память целиком, но проц всеравно будет сбрасываться. Неудобно конечно.

     

    32 минуты назад, hc13nx2 сказал:

    По напряжению обычно применяют одномерную таблицу, напряжение-время.

    Пардон. Думаю об одном, пишу другое. Я это и имел ввиду.

     

  14. Согласен учитывать напряжение надо. Тут наверное достаточно небольшого двухмерного массива.

    Трамблер индуктивный. Физически центробежный регулятор уоз выкинут. Заварен намертво. Так что физически ничего никуда не должно плавать. Если имеется ввиду инерционность индуктивных процессов, то я о таком не слышал.
    .Сам трамблер примерно выглядит так:

    Скрытый текст

    proveryaem-kommutator-samostoyatelno_7_1.jpg.3d6da56d9da4fc509f86654eb36b2817.jpg

    А в какой именно момент надо снимать показания ДАД?

    По поводу правки таблицы в EEPROM. Не знаю. На самом деле я лишь недавно начал программировать под контроллеры и с ЕЕПРОМом мне работать пока не приходилось.

    А скорость работы на чтение с ЕППРОМ такая же как и с SRAM? (Надо почитать)

  15. Пока вообще не вижу смысла в тарированности ДАД. Таблицу я уже слил. У меня она там не в кПа, а в вольтах. Зачем переводить туда-сюда? По крайней мере настроить можно и по напряжению, а если что, то я смогу тарировать с помощью подопытного ЭБУ от тоеты из видео. Он же сыпет текучку в которой четко показывает какое в данный момент давление. Например врубил ему 2 вольта, а он столько то кПа, врубил 2.1в, и он соответственно. Сиди только записывай.

    Ну я бы не сказал, что управление шаговиком проще, хотя... У меня например нужно будет составить таблицу - насколько процентов открывать ШИМ канал управления клапаном в зависимости от оборотов. Хотя все это не принципиально. Можно и  шаговиком управлять, просто жалко 4 пина.

    По ДПКВ. У меня трамблер по-другому устроен. Нет никаких шторок. Есть зубцы, пролетающие мимо катушки. Я уже думал, могу в принципе еще один зубец наростить рядом с одним из 4х имеющихся. Можно сваркой наварить, и болгаркой придать необходимую форму. Програмно такой лишний зубец очень легко отлавливается на основании того, что прерывание на нем произойдет значительно раньше, чем это бы соответствовало текущим оборотам. А дальше я думаю понятно.

    По поводу ШИМа. Просто отдельный таймер 8бит. Срабатывает каждые сколько то там наносек, и единственное, что он делает - инвертирует пины форсунок, но не всех, а только тех, что находятся в статусе PWM HOLD. Получается програмно-апаратный шим. Программно конечно жрет, но судя по всему очень мало. Чатоту и скважность можно будет настраивать. Чем выше частота, тем больше срабатываний, тем меньше процессорного времени остается для работы остольного алгоритма. Тут надо эксперементировать, подбирать минимально возможную частоту шим, что бы ее хватало держать форсунку в удерживающем состоянии. Если как сей час при минимальной нагрузке, т.е. максимальное время таймера, то получается 4кГц при частоте кварца в 16мГц. Хватит ли такой частоты, не знаю. Бензиновые форсунки у меня высокоомные, им ШИМ не нужен, а вот газовые 2 ома, тут без ШИМа никак.

    Тут еще такая ситуация. Если програмный шим будет существенно нагружать проц, съедая драгоценное время, то это будет наиболее критично только с определенных оборотов, надеюсь достаточно высоких. Так, что на крайний случай, думаю, что шим можно будет отключать кратковременно, но только при определенных условиях. К примеру, если допустим у нас есть подпрограмма, которая должна вычислить актуальные временные задержки для топлива и зажигания. То, можно зафиксировать, сколько тиков таймера у нее на это уходит. Соответственно можно абсолютно точно установить, на каких оборотах этого времени будет, что называется "впритык".

    Вообще что бы не было каких либо проблем, на фоне нехватки ресурсов, я реализую такую ахитектуру. Тот исходник, который я предоставил - это, можно сказать пока только драйвер железа. Т.е. вы в него просто загружаете информацию, что и когда должно произойти, а дальше он ее мусолит самостоятельно, без всякого вмешательства по кругу(как будто бы режим работы ДВС устоявшийся). Т.е. все это работает на прерываниях, типа в отдельном кольце. При чем кольце реального времени. Т.е. если мы не успели пересчитать для предстоящей полуфазы такие вещи, как время подачи импульса открытия/закрытия/вклPWM форсунки, а так же время вкл/выкл катушки(ек) зажигания, эти данные уже есть из предыдущей полуфазы, и фраза "неуспели посчитать", означает, что просто не успели обновить, и никаких сбоев и провалов не произойдет, потому что предыдущие данные за одну полуфазу не очень то и устареют.

    И поэтому актуальные задержки и длительности для алгоритма-драйвера пускай считаются непрерывно по кругу за пределами этих прерываний, т.е. в основном цикле программы. И эти расчеты можно вести в асинхронном от фаз режиме. Например данные об оборотах мы не можем обновлять чаще, чем происходят прерывания с ДПКВ. В моем случае на нем всего 4 зубца. А это всего лишь 2 зубца на один оборот КВ. Что достаточно мало по современным меркам, особенно для режимов, когда надо резко ускоряться. Но зависимость длительности впрыска от оборотов не столь существенна, по сравнению с параметром разряжения во впускном коллекторе. И на низких оборотах этот параметр можно проверять чаще, чем частота импульсов с ДПКВ. Соответственно и готовить актуальные данные для драйверной части чаще. Тут только другой вопрос. Праметры ДАД пульсируют. И пишут, что их лучше снимать только в определенный момент.

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

    И вообще у меня тут появляются новые грабли. Как сделать он-лайн правку 2х таблиц 16х16 если они просто не влазят в SRAM. Если делать без он-лайн редактирования, то таблицы можно было бы держать как константы, и оператива им не нужна. Т.е. для этого бы хватило 8кб чипа - Атмега8535(512байт RAM). А так придется ставить Мегу16 с1кб озу.

  16. @hc13nx2 , ну софт - это громко сказано. Так, набросок на делфи. Там самое интересное, это компонент, позволяющий в 3D отображать таблицы.

    Сам алгоритм очень прост. Непрерывно МК измеряет 3 характеристики - время впрыска, время периода между впрысками, по которому мы определяем обороты, ну и АЦП цепи ДАД с резистором, меняющим напряжение от 0 до 5в. Кстати, таким образом можно все это подключить к любой машине и на ходу захватывать данные и формировать таблицу. Подобным способом можно так же слить карту УОЗ. 

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

    Если охота пощупать: открываете в протеусе INJECTOR8535.DSN, в МК загружаете main.hex (это откомпилированный исходник, который я приводил выше), запускаете симуляцию. Откроется анализатор. В нем нажимаете "capture", смотрите, что получилось. Там есть переменный резистор, изменение его сопротивление меняет напряжение на АЦП контроллера, внутри которого меняется значение от 0 до 1024. Умножая его на 3 я использую это значение в качестве времени впрыска. Эти цифры не имеют никакого отношения к реальности и к каким либо абсолютным величинам. Это просто для отладки алгоритма. Т.е. посмотреть как справляется МК с короткими впрысками, и что происходит при увеличении этого времени, когда они начинают перекрывать друг друга.

    По модели впрыска. В качестве ДАД у меня уже стоит тоетовский. выдает напряжение от 1,5в до 5. В качестве ДПКВ обычный трамблер 4 импульса на 2 оборота коленвала. ДФ пока нет. Думаю, как вообще его не использовать. Т.е. хочу программно придумать, как то определять нужную фазу (говорят на свежих ТАЗах ДФ отсутствует, а тем не менее впрыск фазированный). Типа заводиться на одновременном впрыске. Потом переключаться на фазированный и следить за оборотами. Если падают, то не угадал с фазой. И далее по циклу, пока обороты не перестанут падать.

    Датчики температуры тоже тоетовские. Но все это более менее стандартно. В качестве стабилизатора ХХ тоже тоетовский клапан, управлямый ШИМом по двум каналам. ДПДЗ у меня сей час контактный. Буду ставить резистивный. Но это самый второстепенный датчик. Обогощение при тапке в пол можно реализовать и по ДАДу.

    CarLoggerClient.rar

    SDL.zip

  17. Вы прямо весь проект кучей. Кое как отыскал исходник. Еще и на асме.

    У меня поскромнее пока.

    Скрытый текст
    
    $regfile = "m8535.dat"
    $crystal = 16000000
    $hwstack = 40
    $swstack = 16
    $framesize = 32
    
    '----------------------------------------------------------------------------------------------
     'Config Lcd = 16 * 2"
      'Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0"
      'Config Lcdmode = Port"
      'Cls"
     'Cursor Off"
    '----------------------------------------------------------------------------------------------
    
    
    '----------------------------------------------------------------------------------------------
    Config Timer0 = Timer , Prescale = 8                        'таймер для PWM HOLD форсунок
    On Timer0 OnTimer0:
    Enable Timer0
    
    Config Timer1 = Timer , Prescale = 256 , Clear Timer = 0    'основной таймер
    Enable Timer1
    Compare1a = 100                                             'конфигурируем по сравнению
    On Compare1A OnTimer1
    Enable Compare1a
    
    
    'Config Timer2 = Timer , Prescale = 8
    'On Timer2 OnTimer2:
    'Enable Timer2
    '----------------------------------------------------------------------------------------------
    
    Enable Interrupts                                           'конфигурируем прерывание с ДПКВ
    Config Pind.2 = Input
    On Int0 Onint0
    Config Int0 = Rising
    Enable Int0
    
    '------------------конфигурация АЦП-------------------------
    Config Adc = Single , Prescaler = 128 , Reference = Aref
    Config Pina.5 = Input
    Config Pina.0 = Input
    Start Adc
    '----------------------------------------------------------------------------------------------
    
    '------------------конфигурация USART-----------------------
    'Open "comb.4:115200,8,n,1" For Output As #1
    'Open "comb.3:115200,8,n,1" For Input As #2
    $baud = 57600
    Config Pind.1 = Output
    Config Pind.0 = Input
    Echo Off
    '-----------------------------------------------------------
    
    Config Pind.7 = Output                                      'форсунки
    Config Pind.6 = Output
    Config Pind.5 = Output
    Config Pind.4 = Output
    
    Declare Sub SetPortState(byval F As Byte , byval S As Byte)
    
    Dim J As Byte
    Dim D As Integer
    Dim N As Byte
    Dim I As Byte
    Dim R As Byte
    Dim Q As Byte
    Dim Rx As String * 100
    Dim Interspace As Integer                                   'время в единицих TIMER1 между импульсами ДПКВ
    Dim Pulseflag As Bit
    Dim Cycle As Byte : Cycle = 1                               'счетчик наступления рабочтей точки МВТ
    Dim PortState(8) As Byte                                    'в этом массиве я храню текущее состояние форсунок. Только для работы PWM HOLD
    Dim Port As Byte
    Dim AFS As integer
    Dim EventTime(5) As Integer                                 'время наступления событий
    Dim EventShift(5) As Byte                                   'расчетный период, когда должно наступить событие
    Dim EventEnable(5) As Byte                                  'массив флагов исполненности событий
    
    Dim CylindersCount As Byte : CylindersCount = 4             'количество цилиндров в данной конфигурации
    Dim PhaseInjShift As Integer : PhaseInjShift = 10           'за какой количество тиков таймера до ВМТ дожна зыкрыться форсунка
    Dim TimeIgtCharge As Integer : TimeIgtCharge = 500          'время включения катушки перед моментом зажигания
    Dim IgtAngle As Integer                                     'УОЗ
    
    
    Do
      If Pulseflag = 1 Then                                     'если сработало предывание от ДПКВ
        Pulseflag = 0
    
        AFS = GetADC(0) * 3
    
        EventTime(2) = Interspace - PhaseInjShift               'Время закрытия форсунки
        EventTime(4) = Interspace - IgtAngle                    'Момент зажигания
        EventTime(1) = EventTime(2) - AFS                       'Время открытия форсунки
        EventTime(3) = EventTime(1) + 100                       'время включения PWM
        EventTime(5) = EventTime(4) - TimeIgtCharge             'Заряд катушки зажигания
        for i = 1 to 5 : EventShift(i) = 0 : next               'обозначим события как неисполненные
        for i = 1 to CylindersCount -1
          for j = 1 to 5                                        '
            if EventTime(j) < 0 then                            'расчитаем сдвиги событий. Например, если форсунка должна закрыться в текущем
              EventTime(j) = EventTime(j) + Interspace          'такте, но время ее открытия не "влезает" в текущий такт, т.е. идет перкрытие
              incr EventShift(j)                                'Т.е. если время открытого состояния форсунки больше времени между соседними
            end if                                              'работчими МВТ, то вычисляем сдвиг, на какую фазу придется данное событие
          next
        next
        if EventTime(1) < 0 then EventTime(1) = 1
        if EventTime(3) < 0 then EventTime(3) = 1
    
    
    
        'Enable Timer1
    
        'Locate 1 , 1
        'lcd "         "
        'locate 1 , 1
        'Lcd AFS
        '
        'Locate 2 , 1
        'lcd "         "
        'locate 2 , 1
        'Lcd Interspace
    
    
    
        'Print Hex(interspace)
    
        If Ischarwaiting() = 1 Then                             'проверка наличия команды в буфере UART
          Input "" , Rx
          If Len(rx) = 5 Then                                   '
            'S=mid(Rx,1,2)
            'T=HEXVAL(S)
            'S=mid(Rx,3,2)
            'dd=HEXVAL(S)
            Print Hex(interspace)
            Rx = ""
          End If
        End If
    
    
      End If
    Loop
    
    Sub SetPortState(byval F As Byte , byval S As Byte)
      if S < 4 then
        if S = 3 then S = 1
        if S = 2 then S = 0
        if F = 1 then Portd.7 = S                               '1. форсунки в порядке их работы
        if F = 2 then Portd.6 = S                               '2.
        if F = 3 then Portd.5 = S                               '3.
        if F = 4 then Portd.4 = S                               '4.
        'if F = 5 then PortB.7 = S
        'if F = 6 then PortB.6 = S
        'if F = 7 then PortB.5 = S
        'if F = 8 then PortB.4 = S
      else
        S = S - 4
        if F = 1 or F = 3 then PortB.7 = S                      '1-3 зажигание DIS-2
        if F = 2 or F = 4 then PortB.6 = S                      '2-4
    '    if F = 3 then PortB.5 = S
    '    if F = 4 then PortB.4 = S
      end if
    End Sub
    
    
    OnTimer0:
      if PortState(1) = 3 then Toggle Portd.7                   'тут по таймеру происходит непрерывная инверсия
      if PortState(2) = 3 then Toggle Portd.6                   'выходов форсунок, находящихся в режиме PWM HOLD
      if PortState(3) = 3 then Toggle Portd.5                   '
      if PortState(4) = 3 then Toggle Portd.4                   '
      'if PortState(5) = 3 then Toggle PortB.7
      'if PortState(6) = 3 then Toggle PortB.6
      'if PortState(7) = 3 then Toggle PortB.5
      'if PortState(8) = 3 then Toggle PortB.4
    Return
    
    OnTimer1:                                                   'таймер с самозагузкой. Выполняет очередь событий
      L:
      Port = EventShift(n) + Cycle : if Port > CylindersCount then Port = Port - CylindersCount       'вычисляе порт, на котором должно произойти событие
      Call SetPortState(Port , n)                               'выполняем событие
      if n < 4 then PortState(Port) = n                         'если событие не связано с зажиганием, изменяем статус порта форсунки(если n=3 то HOLD PWM)
      EventEnable(n) = 0                                        'помечаем событие, как исполненное
    
      n = 0
      D = interspace                                            'ищем следующие событие.
      for j = 1 to 5
       if EventEnable(j) = 1 and EventTime(j) < D then          'выбираем ближайшее по времени событие. Они не отсортированы
         D = EventTime(j)
         n = j                                                  'запоминаем его номер
       end if
      next
    
      if n > 0 then                                             'если события не закончились
       D = EventTime(n) - TIMER1                                'записываем разницу между текущим временем таймера и планируемым
       if D < 5 then goto L                                     'если осталось мало времени до его исполнения,
       Compare1a = EventTime(n)                                 'или вообще мы его успели просахатить, то отправляемся на его немедленное исполнение
      end if                                                    'если время еще есть, грузим планируемое премя следующего события в регистр сравнения.
    Return                                                      'как только подойдет время таймера все повторится
    
    
    Onint0:                                                     'обработчик прерывания датчика в трамблере
       Interspace = Timer1                                      'запомнили сколько тиков натикало с момента предыдущего прерывания. Почти RPM
       Timer1 = 0                                               'обнуляем счетчик
       Pulseflag = 1
       Compare1a = Interspace                                   'загружаем в регистр сравнения максимальное время периода PRM
       for j = 1 to 5                                           'прогоним очереь сообщений на предмет неисполненых. Такое возможно, если обороты увеличились
         if EventEnable(j) = 1 then
           Port = EventShift(j) + Cycle : if Port > CylindersCount then Port = Port - CylindersCount
           Call SetPortState(Port , j)                          'выполняем немедлянно все неисполненные.
           if j < 4 then PortState(Port) = j
         end if
    
         if EventTime(j) < Compare1a then                       'перебираем очередь сообщений
           Compare1a = EventTime(j)                             'загружаем ближайщее событие
           n = j
         end if
         EventEnable(j) = 1                                     'настал новые период, помечаем все сообщения как неисполненные
       next
    
       Incr Cycle : If Cycle > CylindersCount Then Cycle = 1    'увеличиваем счетчик периода
       if Compare1a < 4 then Compare1a = 4                      'если событие дишит в затылок. Отодвинем его чуть-чуть. В начале цикла это не зажигание. Значит не страшно
    
       'Start Timer1
    Return
    
    
    
    
    
    End

     

    Сама сложная часть написана. Много чего еще осталось. Дальше я прикручу таблицы VE и УОЗ. Потом алгоритм их OnLine изменения. Плюс корекции всякие. Ну и ХХ. Буду делать так, что бы расчетов в МК было по-минимуму. Желательно вообще избежать использование чисел с плавающей точкой. Т.е. таблицы уже будут с готовыми значениями, пригодными для их непосредственной загрузки в таймеры. Все переводы значений из абсолютных (кПа, углы, температуры) в непосредственные значения регистров МК буду производить на стороне ПК. Тоже есть заготовка на делфи.

    Вот тут на драйве начало моих экспериментов и занимательное видео. Как я изучал работу компа от 3S-FE.

    Скрытый текст

     

     

  18. 22580, в общем то получается.

    5b824c3e6fe75_.thumb.PNG.13e968fc8b96e6e41256c80a88d8a767.PNG

    Вот два лога. С небольшим по длительности впрыском, и длительный с наложением. Во втором варианте что то типа ШИМа по отдельному таймеру. Частота на картинке 2кГц. Максимально можно сделать 16 кГц. Все события: включение, выключение форсунок, переход в режим ШИМ-удержание происходят через прерывания таймера, т.е. максимально точно по времени. Реализовал буфер событий, который полостью обрабатывается на прерываниях. Что то типа очереди, когда один таймер выполняет событие, и загружает следующиее из этой очереди, и так по кругу. Этот буфер событий можно править из основного цикла программы в любой момент, не задумываясь, что и когда должно произойти по времени. Даже если в осномном цикле будет происходит какая то сложная работа, или обмен по USARTу, это никак не отражается на выходном графике. На данный момент алгоритм занимает 2,5кб. Тестовый проц 90AT8535 на 8мГц. Если 8кБ хватит для реализации всего задуманного, попробую ради праздного интереса запустить все это на процах 8051

  19. В 13.01.2016 в 09:05, aka kasyan сказал:

    soacera опоздал с ответом , но всего на год. :thank_you2: вообще асинхронники не желательно (а проще говоря нельзя) питать от аналогичных схем, ясно на выходе мод. синус . Встречал несколько вариаций , как ранее заметил иногда ставят на выходе LC фильтр, углы чуть косятся, но ясно, что до синуса далеко.

    В более нормальных схемах делают так

    DC-DC 12-380, затем впускают это на мост, а раскачку моста обеспечивает платочка EG8010 (формирователь синуса), импульсы с мк поступают сначала на драйвер затем на мост.

    На выходе опять стоит LC фильтр для получения идеальной синусоиды.

    p.s. мод синусом нельзя питать асинхронники - но если нужно и на короткое время , то вполне возможно.

    Aka, а что если НЧ трансформатор раскачать синусом, сгенерирванным ШИМом? Т.е. в течении периода плавно увеличивая/уменьшая широту импульса. Будут ли полевики работать в ключевом режиме, или не будут успевать должным образом открываться/закрываться? типа _____-____--__---_----_------_----_--__-____-_____  Не будут ли полевики грется как печки?

    Технически я бы попробывал например на Atmega управлять шим выходами (PWM) по закону синуса увеличивать/умешьшать процент заполнения PWM. Исследовал несколько ИБП, но там почему-то полевики просто управляются меандром с неизменной скважностью. Может есть какие то препятствия, не позволяющие проделать мною описаный финт?

  20. Нет. 4. Просто плату развел на максимальное использование ног. Вдруг кто-нибудь на крузака захочет ) Крайние можно смело обрезать, если 4 достаточно. (Бил Гей тссс же говорил, что 640кб будет всем достаточно) Сей час работаю над алгоритмом. Жопа конечно делать фазированный впрыск и фазированное зажигание на чипе, у которого всего один 16-ти битный счетчик. И если бы фазы впрыска никогда не перекрывались, то это возможно было бы не такой сложной задачей. Но они же могут накладываться друг на друга. И тут хбз, че можно придумать. Атмега для этих целей несколько ущербна. Но я пытаюсь....

×
×
  • Создать...