простые интересные РАДИОСХЕМЫ сделанные своими руками


» СХЕМЫ И СТАТЬИ

» Гость

Мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизируйтесь!





Отметить прочитанными   -   Поиск   -   Правила   -   Новые сообщения

  • Страница 6 из 7
  • «
  • 1
  • 2
  • 4
  • 5
  • 6
  • 7
  • »
Модератор форума: Sam  
Форум радиолюбителей » СХЕМЫ » АВТОМОБИЛИ » Блок адаптера для спидометра от абс (Адаптации сигнала с датчика абс для спидометра с датчика кпп)
Блок адаптера для спидометра от абс
Пн, 16.03.2020, 07:03 | Сообщение # 51        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
Цитата Tygra ()
Программный таймер это на основе циклов задержки ?

На основе аппаратного таймера.
Цитата Tygra ()
разница будет минимальной ибо период высчитан
да, основная задержка - вычисления нового периода, надо умножить и разделить, что недешево по времени.
Пн, 16.03.2020, 08:48 | Сообщение # 52        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
Начнём потихоньку...
Для начала объявим несколько констант и регистров.
Код

.equ    FREQCLK  = 9600000       ;Частота мк
.equ    CS0_VAL  = 64        ;прескалер Т0

.def    TKEY  = R23         ;Счётчик опроса кнопок

.def    Flags  = R22          ;Флаги
    .equ    F_KEY  = 0  ;Опросить кнопки
    .equ    F_PULL  = 1  ;Нажата кнопка
    .equ    F_NEW_TIME    = 2  ;Новый период
    
.def    SSREG  = R15  ;временная хранилка

.equ    TIME_UPDATE_KEY  = 20    ;время опроса кнопок, мс

Теперь определимся с таймером, настраиваем его на прерывание каждую миллисекунду, для более точной работы используем прерывание по совпадению регистра OCR0A или OCR0B. Чтобы не пересчитывать на калькуляторе, каждый раз при изменении частоты мк или прескалера таймера, заставим это делать компилятор
Код

.equ    OC0A_VALUE    = FREQCLK/1000/CS0_VAL-1   ;значение регистра сравнения Т0

По тем же причинам, дабы не лазить каждый раз в даташит, когда нам вдруг взбредет в голову изменить прескалер таймера, набросаем макрос установки прескалера
Код

.macro set_tim0_prescaler    ;Установить прескалер таймера 0
    .if @0==1
  ldi  R16, (0<<CS02)|(0<<CS01)|(1<<CS00)    ;прескалер 1
    .elif @0==8
  ldi  R16, (0<<CS02)|(1<<CS01)|(0<<CS00)    ;прескалер 8
    .elif @0==64
  ldi  R16, (0<<CS02)|(1<<CS01)|(1<<CS00)    ;прескалер 64
    .elif @0==256
  ldi  R16, (1<<CS02)|(0<<CS01)|(0<<CS00)    ;прескалер 256
    .elif @0==1024
  ldi  R16, (1<<CS02)|(0<<CS01)|(1<<CS00)    ;прескалер 1024
    .else
  .error "Timer prescaler specified incorrectly CS=1||8||64||256||1024"
    .endif
    out    TCCR0B, R16
.endm


И ещё один макрос, это инвертирование ноги порта
Код

.macro invert    ;инвертирует линию порта: invert PORTB, PB2
    push    R16
    push    R17
    in   R16, @0   ;считываем порт @0
    ldi  R17, (1<<@1)    ;маска для инвертирования (позиция с @1 будет проинвертирована)
    eor  R16, R17  ;инвертируем значение
    out  @0, R16   ;отдаем в порт инвертированное значение
    pop  R17
    pop  R16
.endm


Предварительно выделим память для переменных: входной период, выходной период и делитель
Код

.dseg

time_update_out:    .byte    2    ;период выходного импульса
time_update_in:  .byte    4    ;период входного импульса
divider:   .byte    2    ;делитель

Так, осталось настроить векторы прерываний и инициализация периферии.
Векторы прерываний
Код

.cseg
    .org   0      ;Инициализация программы (вектор сброса)
     rjmp  initial
    .org    ACIaddr   ;Компаратор
  rjmp    int_AC  ;Переходим на обработку
    .org    OC0Aaddr  ;Совпадение по таймеру 0 A
  rjmp    int_OC0A    ;Переходим на обработку


И инициализация периферии
Код

initial:

;инициализация таймера 0
ldi    R16, (1<<WGM01)   ;режим СТС
out    TCCR0A, R16    ;(сброс по совпадению)
set_tim0_prescaler    CS0_VAL ;установить прескалер
ldi    R16, OC0A_VALUE   ;
out    OCR0A, R16    ;
ldi    R16, (1<<   ;
out TIMSK0, 1<<OCIE0A
;инициализация компаратора (вход по AIN1, AIN0 посажен на внутреннюю опору)
ldi R16, (0<<ACD)|(1<<ACBG)|(0<<ACO)|(1<<ACIE)|(1<<ACIS1)|(0<<ACIS0)    ;внутренняя опора, вкл прерывание, по спаду
out ACSR, R16    ;
;инициализация порта B
ldi    R16, 1<<PB2  ;PB2 будет выходом, остальные входом
out    DDRB, R16  ;

sei  ;разрешить глобальные прерывания

Закончили с рутиной, теперь можно набросать обработчики прерываний...


Отредактировал nolpofaze - Вт, 17.03.2020, 13:58
Пн, 16.03.2020, 11:25 | Сообщение # 53        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
После инициализации периферии, создаем главный цикл (main), который будет обрабатывать флаги опроса кнопок и вычисления выходного периода.
Код

main:    ;главный цикл
    sbrc    Flags, F_KEY
  rcall    keyboard
    sbrc    Flags, F_NEW_TIME
  rcall    calc_new_time
rjmp main


Для себя пометим, что две регистровые пары Y и Z будут использоваться как таймеры, Y для определения периода входного сигнала (Y будет работать как кольцевой 16-битный счетчик), Z для формирования выходного сигнала (Z в данном случае - регистр сравнения, считает с декрементом от значения периода выходного сигнала до 0, в 0 инвертирует линию порта и обновляет свое значение). R23 объявленный ранее как TKEY - для проставления флага опроса кнопок.
Код

int_OC0A:    ;обработка прерывания по совпадению таймера 0
    in  SSREG, SREG    ;ныкаем флаги состояния мк
int_OC0A_in:    ;счётчик таймера 1, инкремент по кольцу
    adiw    YL, 1
int_OC0A_out:    ;счетчик таймера 2, считает с декрементом, в 0 обновляется из регистров сравнения
    sbiw    ZL, 1
    brne    int_OC0A_key
  ;Инвертируем вывод
  invert PORTB, PB2
  ;обновляем период
  lds  ZL, time_update_out
  lds  ZH, time_update_out+1
int_OC0A_key:    ;счётчик опроса кнопок
    dec  TKEY
    brne    int_OC0A_end
  sbr  Flags, F_KEY   ;ставим флаг опросить клаву
  ldi  TKEY, TIME_UPDATE_KEY    ;обновляем счётчик
int_OC0A_end:
    out  SREG, SSREG    ;извлекаем заныканные флаги мк
    reti

16 бит счётчики периода входного и выходного сигнала вместят по 65 535 мс периода; время опроса кнопок можно регулировать константой TIME_UPDATE_KEY.

В прерывании компаратора определяем период входного сигнала. Вычитаем из текущего значения предыдущее и пишем в память, всё просто
Код

int_AC:  ;обработка прерывания компаратора
    in  SSREG, SREG    ;ныкаем флаги состояния мк
    lds  R18, time_update_in+2    ;считали предыдущее значение
    lds  R19, time_update_in+3    ;таймера в R18, R19
    sts  time_update_in+2, YL    ;и записали на его место новое
    sts  time_update_in+3, YH    ;значение таймера
    movw    R20, YL
    sub  R20, R18     ;нашли период
    sbc  R21, R19     ;
    sts  time_update_in, R20  ;записали его
    sts  time_update_in+1, R21    ;в память

    sbr  Flags, 1<<F_NEW_TIME    ;поставили флаг "новый период готов"
int_AC_end:
    out  SREG, SSREG    ;извлекаем заныканные флаги мк
    reti


Добавляем заглушки на пп опроса кнопок и расчета период выходного сигнала и можно пробовать собрать hex.
Код

keyboard: ;опрос кнопок
    cbr  Flags, 1<<F_KEY

keyboard_end:
    ret

calc_new_time:  ;вычисление периода

calc_new_time_end:
    cbr  Flags, 1<<F_NEW_TIME
    ret

Вышло что-то около 15% из 1 кБ доступного. Места вполне достаточно для всяких вычислений и обработок кнопок.
Всё в куче прикреплено во вложении. Осталось самое сложное, как посчитать делитель/множитель.

Добавлено (16.03.2020, 11:34)
---------------------------------------------
Ещё забыл один важный момент, после initial: надо инициализировать стек, и не мешало бы очистить память от мусора
Код

;инициализация стека
.ifdef SPL
    ldi R16,Low(RAMEND)
    out SPL,R16
    .ifdef SPH
  ldi R16,High(RAMEND)
  out SPH,R16
    .endif
.else
    ldi R16,RAMEND
    out SP,R16
.endif
;Очистка памяти
    ldi ZL,Low(SRAM_START)
    ldi ZH,High(SRAM_START)
    clr R16
flush:
    st Z+,R16
    cpi ZH,High(RAMEND+1)
    brne flush
    cpi ZL,Low(RAMEND+1)
    brne flush
    clr ZL
    clr ZH


Отредактировал nolpofaze - Пн, 16.03.2020, 14:47
Пн, 16.03.2020, 15:34 | Сообщение # 54        
msmmmm
аватар
  Постов: 1134  Offline Друзья 
Цитата nolpofaze ()
надо умножить и разделить
Зачем? Просто умножить на коэффициент.
Цитата nolpofaze ()
надо инициализировать стек
Оно-то и не навредит, но тинька сама по сбросу инициализирует стек.
Пн, 16.03.2020, 16:02 | Сообщение # 55        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
Цитата msmmmm ()
Оно-то и не навредит, но тинька сама по сбросу инициализирует стек.
- далеко не всегда инициализирует и уж точно не навредит smile
Цитата msmmmm ()
Зачем? Просто умножить на коэффициент.
- это уже я сказать не могу, циферий нету конкректных, может только умножить, но пока для получения кэффициента 1:1 надо делить на 2.
Да, еще есть ограничение у этих таймеров, максимальная выходная частота, при настройке таймера 0 на 1 мс, будет 500Гц, причем чем ближе мы будем пододвигаться к границе, тем больше будет погрешность как при измерении периода, так и при формировании сигнала. Как вариант уменьшить частоту прерываний таймера 0 (например 100мкс или 10мкс) и увеличить разрядность счетчиков периода до 24 бит.

Добавлено (16.03.2020, 17:00)
---------------------------------------------
msmmmm, нет, всё таки надо умножить и разделить, у нас же только целые числа, к примеру, получили период 900мс, а нам надо 6000мс т.е. в 6,667 раз меньше частота, умножаем 900 на 6667, делим на 2000 = 3000 мс (для формирования сигнала нужен полупериод). Или только умножить на 6 или на 7 и сдвиг вправо, но с потерей точности, это если разговор идет о увеличении периода (или уменьшения частоты). А если надо крутить коэффициент в другую сторону, уменьшать период? Из 900 получить 60мс: 900*67/2000=30мс.

Пн, 16.03.2020, 18:35 | Сообщение # 56        
msmmmm
аватар
  Постов: 1134  Offline Друзья 
Я так понимаю, что нужно сделать делитель или умножитель периода на фиксированный коэффициент? С максимальной скоростью вычислений и без претензий к точности?
Для этого вычислять лучше в попугаях:
получили 900 мкс, должно быть 6000мкс.
6000/900=6,66667
Если нужна точность чуть больше процента, умножаем 6,66667*256=1706,667
Округляем, =1707. Это и будет коэффициент.
В тиньке 1707*900=1536300 и отбрасываем младший байт (/256), получаем 6 001, чего для данного применения вполне достаточно.
проверим на 100мкс: 100*6,66667=666,667 (это должно получиться)
1707*100/256=666 (это после вычислений)
/256 - не выполняется, просто не учитывается младший байт результата.
Вычисление в обратную сторону ничем не отличаются.
Если точности все же недостаточно, умножаем и делим не на 256, а на 512, 1024 и т.д, и в тиньке не только отбрасываем байт, но и сдвигаем результат вправо (/2) нужное количество раз. Но это, как мне кажется, лишнее.
Пн, 16.03.2020, 18:58 | Сообщение # 57        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
msmmmm, а если коэффициент не фиксированный? По замыслу он должен изменяться кнопками, для более точной подстройки делителя/умножителя.

Добавлено (16.03.2020, 19:22)
---------------------------------------------
Хотя да, пойдёт, какая нам по сути разница, на 1000 или на 1024, или на 256 делитель делать. Осталось определиться с частотой прерывания... Это уже нужна инфа от ТС smile

Пн, 16.03.2020, 20:16 | Сообщение # 58        
Tygra
аватар
  Постов: 2803  Offline Друзья 
Надо "переварить" , днем был занят, приборка на дастере у отца погасла в ноль , весь день провозился, вроде запустил, но потестить еще не успел , щас разгребу и буду изучать что тут )

Коэффициент задается один раз на старте программы . нет смысла его по ходу корректировать , один раз из памяти загрузили и все .
Пн, 16.03.2020, 20:44 | Сообщение # 59        
nolpofaze
аватар
  Постов: 679  Offline Друзья 
Цитата Tygra ()
старте программы . нет смысла его по ходу корректировать

Не совсем согласен. Хранить можно в eeprom, и действительно грузить при старте, а как его определять с помощью кнопок? Так понимаю должно быть что то вроде калибровки, садим калибровщика с навигатором, даём ему кнопки и он, жмякая на кнопки, добивается показаний спидометра, таких же как и на навигаторе. Ну а сохранять можно, скажем через 5 секунд как отпустили кнопки...
Пн, 16.03.2020, 21:35 | Сообщение # 60        
vrytsev
аватар
  Постов: 561  Offline Друзья 
Цитата nolpofaze ()
садим калибровщика с навигатором

Может проще вывесить колеса. А если проверить частоты на показаниях спидометра какой частоте соответствует 10 км/ч ~~ 200 км/ч. Я к тому если подать 200 Гц то будет ли на спидометре 200 км/ч, или 10 Гц то 10 км/ч. Или я чего-то не понял.
Форум радиолюбителей » СХЕМЫ » АВТОМОБИЛИ » Блок адаптера для спидометра от абс (Адаптации сигнала с датчика абс для спидометра с датчика кпп)
  • Страница 6 из 7
  • «
  • 1
  • 2
  • 4
  • 5
  • 6
  • 7
  • »
Поиск:

Кто есть кто на форуме радиолюбителей: Администратор Модераторы Друзья Проверенные Новички
Группа вконтакте Канал ютуб Группа в фэйсбук © 2010-2021 "Радиосхемы" Все права защищены Почта Моб.версия