добрый день всем.сразу говорю,возможно я выбрал не верный раздел,но не увидел раздела по кодингу. итак,задача: из игрового руля на 270 градусов сделать руль с возможностью изменения угла реализация я взял руль Thrustmaster Rallye GT Force Feedback Clutch,вынул из него потенциометр,поставил вместо него абсолютный энкодер BOURNS EAW0J-B24-AE0128L его показания получаю в atmega8,считаю количество пройденных пинов и умножаю их на множитель(про него дальше) для получения значения,которое устанавливаю в OCR1A про множитель для начала надо повторить базовую реализацию угла в 270 градусов.у энкодера позиции 0-127,т.е. 360 градусов равняется 128 пинам.простой математикой получаем что угол 270 градусов это 96 пинов.ещё раз считаем и получаем что 1 пин равняется 2.83 градуса.вот соответственно множитель и устанавливаем в 2.83 но практика показала что 2.83 это и близко не то значение.реально я сейчас подобрал что примерно 5.5 это близкое значение,но и то это ещё не оно.это проблема номер раз а проблема номер два это то что оно выходит на крайнее левое и крайнее правое значение при абсолютно разных значениях пройденных пинов.у руля есть штатная прога для калибровки,где наглядно можно наблюдать куда я его поворачиваю
я добавил кнопку програмной центровки руля,и пробовал центровать нормально,повёрнутым вправо,повёрнутым влево и повёрнутым на 180 градусов.вообще разное количество пинов от крайнего левого до крайнего правого положения.за середину при центровке всегда задаётся 48 пинов(якобы уже пройдено)-потому что 96\2:
Цитата:
крайнее левое: физический пин:114 пинов пройдено от 0:24 значение OCR1A:132 крайнее правое: физический пин:38 пинов пройдено от 0:76 значение OCR1A:418 крайнее левое: физический пин:11 пинов пройдено от 0:21 значение OCR1A:115 крайнее правое: физический пин:69 пинов пройдено от 0:79 значение OCR1A:434 крайнее левое: физический пин:121 пинов пройдено от 0:22 значение OCR1A:121 крайнее правое: физический пин:69 пинов пройдено от 0:98 значение OCR1A:539
разброс мягко говоря бредовый. я не могу понять чем это обусловлено.вполне допускаю что я что-то не правильно указал в настройках ШИМа,поэтому я уже замахался искать сам проблему,прошу помощи у более опытных людей.ниже код проги,в ней много отладочного кода,тот-же вывод показаний на трёхциферный семисегментный индикатор пришлось сделать,чтоб увидеть в железе как оно считает.HELP
//массив соответствия номера пина к его двоичному коду const uint8_t pos_table[128] PROGMEM = {127,63,62,58,56,184,152,24,8,72,73,77,79,15,47,175,191,159,31,29,28,92,76,12,4,36,164,166,167,135,151,215,223,207,143,142,14,46,38,6,2,18,82,83,211,195,203,235,239,231,199,71,7,23,19,3,1,9,41,169,233,225,229,245,247,243,227,163,131,139,137,129,128,132,148,212,244,240,242,250,251,249,241,209,193,197,196,192,64,66,74,106,122,120,121,125,253,252,248,232,224,226,98,96,32,33,37,53,61,60,188,190,254,126,124,116,112,113,49,48,16,144,146,154,158,30,94,95}; int A1,A2,A3;
//код для вывода данных на индикатор if (!bit_is_clear(PINB,3)) { if (can_toggle_angle==1) { angle_toggler_itter++; if (angle_toggler_itter>2) { angle_toggler_itter=0; }
can_toggle_angle=0; }
} if (angle_toggler_itter==0) { show_digit(enc_pos); } if (angle_toggler_itter==1) { show_digit(wheel_pos); } if (angle_toggler_itter==2) { show_digit(electricity_pos); } //конец вывода // OCR1A=electricity_pos;
} }
Добавлено after 14 minutes 4 seconds: да.совсем забыл,могу дать проект в протеусе.хотя не знаю нужен-ли,ведь по железу всё работает.
UPD2:а может и в железе.на ноге ШИМа ещё стоит ФНЧ такого типа,и только после этого идёт уже питание в управляющую схему руля
так он поделился... примером, как не надо программировать. и проектировать. Так перемешать энкодер и индикатор, и затем преодолевать трудности - это надо постараться. А ведь вся программа могла свестить к полсотни строчек...
если б вы внимательно читали-то увидели б что индикатор туда добавлен для отладки.в рабочем варианте он вообще там не нужен.
Цитата:
Ну вот - только заинтересовал - и сразу удалять. Поделился бы.
весь прикол оказался в том,что родная схема руля ждала от энкодера значения не от 0В(крайнее левое положение) до 4.9В(крайнее правое),а от 0.15В до 3.85В,соответственно преобразовывая значения в угол поворота руля. я подпаялся к потенциометру в педалях,и снимал с него показания вольтажа,нажимая педаль и глядя как руль крутится в программе тестирования.снял таблицу показаний при разных углах. возможна некоторая погрешность,но в целом видно более-менее линейное изменение уменьшения шага множителя по мере увеличения угла поворота.осталось обернуть это в формулу.
что-то не могу я подобрать параметры ШИМа.пробовал и только по длительности импульса подбирать шаг,и сразу по частоте ещё-не получается. не могу понять на что умножать количество пройденных пинов,для получения нужного тока. может у кого голова светлее моей,и накинет идею как это посчитать? я вывел усреднёно что 45 градусов это 0.96В,90 градусов это 1.85В,135 это 2.47В,180 это 2.99В,225 это 3.34В,270 это 3.85В для круглости цифр поставил ICR1 в 1000,набросал вот таблицу составил график разницы значений это ни на что не похоже адекватное. как?хелп.
Последний раз редактировалось sanitar_zaz Вт июн 18, 2024 00:17:47, всего редактировалось 1 раз.
//массив соответствия номера пина к его двоичному коду const uint8_t pos_table[128] PROGMEM = {127,63,62,58,56,184,152,24,8,72,73,77,79,15,47,175,191,159,31,29,28,92,76,12,4,36,164,166,167,135,151,215,223,207,143,142,14,46,38,6,2,18,82,83,211,195,203,235,239,231,199,71,7,23,19,3,1,9,41,169,233,225,229,245,247,243,227,163,131,139,137,129,128,132,148,212,244,240,242,250,251,249,241,209,193,197,196,192,64,66,74,106,122,120,121,125,253,252,248,232,224,226,98,96,32,33,37,53,61,60,188,190,254,126,124,116,112,113,49,48,16,144,146,154,158,30,94,95};
int main(void) { char initialisation,can_toggle_angle,angle_toggler_itter; int p[8],tmp,forwarded,enc_pos,last_enc_pos,wheel_pos,electricity_pos,wheel_center,max_perm_pins; float voltage_modifier;
я и через процентное соотношение пробовал вычислять.например: 4.95В это 100% 4.95/100=0.0495,следовательно 1% это 0.0495 3.85/0.0495=77.77(3.85В это 77.77% от полного напряжения) OCR1A 430 это 3.85В и это 96 пинов 96/77.77=1.23(столько пинов составляют 1%) теперь берём,к примеру,положение 32 пина 32/1.23=26.01% 540(ICR1)/26.01=20.76 т.е. получается что при OCR1A=21 у меня должно быть 1.85 вольта,в то время как оно такое при 205
//считывание позиции энкодера по 8 ногам if (!bit_is_clear(PINB,0)) { p[0]=1; } else { p[0]=0; } if (!bit_is_clear(PIND,7)) { p[1]=1; } else { p[1]=0; } if (!bit_is_clear(PIND,6)) { p[2]=1; } else { p[2]=0; } if (!bit_is_clear(PIND,5)) { p[3]=1; } else { p[3]=0; } if (!bit_is_clear(PINB,7)) { p[4]=1; } else { p[4]=0; } if (!bit_is_clear(PINB,6)) { p[5]=1; } else { p[5]=0; } if (!bit_is_clear(PIND,3)) { p[6]=1; } else { p[6]=0; } if (!bit_is_clear(PIND,4)) { p[7]=1; } else { p[7]=0; }}
Здесь вы как бы совсем не видите проблемы? Вроде как должно быть очевидно, что такое "чтение энкодера" работать правильно не может в принципе.
Уж не говоря о том, что автор похоже даже не знает что такое циклы....
очевидно?что ж,давайте обратимся к даташиту на энкодер:
каждый проход основного цикла программы опрашиваем 7 ног микрухи,чтоб знать низкое/высокое значение сейчас на каждом пине,собрать это значение в двоичный код и дальше по таблице получить позицию энкодера. нет,я не вижу проблем в том что я написал. если вы знаете как по-другому решить эту задачу-поделитесь пожалуйста,мне будет интересно(без сарказма) и если что-индикатор показал что код определения позиции энкодера работает верно.проблема дальше,с ШИМ.
это начальная инициализация значений элементов массива.оставлять переменные без начального значения,"на авось"-ещё больший быдлокодинг
Во-первых: Исходя из того как вы используете тот массив, его вполне можно сделать статическим. А статические переменные инициализуруются нулями сишным стартап-кодом. Достаточно объявить массив как: static int p[8] = {0}; всё. И кода никакого в main() не надо. А если нужна именно автоматическая переменная (на стеке), то для этого есть memset(...). Или, на худой конец - цикл. Ну и - использовать для хранения значений 0 и 1 переменные типа int на 8-битном контроллере!.... тут даже слов не находится Уж не говоря о том, что там и массив то никакой не нужен. А можно сразу прочитать все ноги.
1. Вы читаете не все пины энкодера одновременно, а отдельные пины в разное время. Что при вращении энкодера может давать "неожиданные" результаты. Тем более скорость прохода цикла main() у вас никак не фиксирована, а значит крутится он быстро, читая отдельные ноги в разное время. Какой смысл в таком? Почему не прочитать сразу все ноги одной-двумя операциями чтения порта? 2. Скорость прохода цикла тоже никак не фиксирована. И может болтаться в разные стороны. 3. (Самое главное) У вас энкодер - механический? Что такое дребезг контактов - знаете? В реальных механических энкодерах это серьёзная проблема. И если сначала (пока он новый и контакты не ушатанные) вы её можете не замечать (только редкие глюки), то потом дела ухудшатся.
Нормальная реализация чтения позиции энкодера (программная) - например: Периодическое прерывание (от таймера). В котором с фиксированной известной частотой читаются сигналы энкодера (все сразу). Делается их анализ (на корректность). Делается подавление дребезга. Делается анализ на корректность изменения состояний энкодера (при вращении в любую сторону есть определённый порядок смены состояний сигналов; ПО должно его контролировать; и при нарушении - сбрасывать алгоритм работы в исходное состояние).
а прочитать сразу ВЕСЬ порт и сразу получить двоичный код ума не хватает?
посмотрите внимательно,3 ноги на порту B,4 ноги на порту D
Цитата:
Ну и - использовать для хранения значений 0 и 1 переменные типа int на 8-битном контроллере
ну тут спорить не буду,мой проёбище.
Цитата:
1. Вы читаете не все пины энкодера одновременно, а отдельные пины в разное время. Что при вращении энкодера может давать "неожиданные" результаты. Тем более скорость прохода цикла main() у вас никак не фиксирована, а значит крутится он быстро, читая отдельные ноги в разное время. Какой смысл в таком? Почему не прочитать сразу все ноги одной-двумя операциями чтения порта?
хм,я не думал в такой плоскости.я как-то воспринимал что скорость одной итерации main на столько велика,что физически невозможно крутануть энкодер быстрее,чем он снимет показания со всех ног.
Цитата:
У вас энкодер - механический? Что такое дребезг контактов - знаете? В реальных механических энкодерах это серьёзная проблема. И если сначала (пока он новый и контакты не ушатанные) вы её можете не замечать (только редкие глюки), то потом дела ухудшатся.
знаю конечно.энкодер механический.со временем перейду на оптический.пока этот есть,и пока он новый-вопрос дребезга можем игнорировать.
Цитата:
Нормальная реализация чтения позиции энкодера (программная) - например: Периодическое прерывание (от таймера). В котором с фиксированной известной частотой читаются сигналы энкодера (все сразу). Делается их анализ (на корректность). Делается подавление дребезга. Делается анализ на корректность изменения состояний энкодера (при вращении в любую сторону есть определённый порядок смены состояний сигналов; ПО должно его контролировать; и при нарушении - сбрасывать алгоритм работы в исходное состояние).
спасибо,я подумаю над этим.
но давайте представим сферического коня в вакууме что позиции энкодера считает нормально.что дальше с ШИМом?почему при вроде линейности данных,которые отдаёт потенциометр(в 3-м сообщении описывал),значение длительности импульса для достижения нужного вольтажа такое разное,что не видно закономерности,на что умножить кол-во пройденных пинов?
Как вариант. ICR1=540 соответствует максимальному числу шагов энкодера OCR1A=K*N/256 или K=540*256/128=1080 середина N=64 OCR1A=1080*64/256=270 минимальное N=64-48 OCR1A=1080*16/256=67 максимальное N=64+48 OCR1A=1080*112/256=472
хм,я не думал в такой плоскости.я как-то воспринимал что скорость одной итерации main на столько велика,что физически невозможно крутануть энкодер быстрее,чем он снимет показания со всех ног.
Причём тут "снимет показания со всех ног"? Я говорил о том, что у вас отдельные сигналы общей параллельной шины снимаются в разное время. Без какого-то синхросигнала. При наличии даже минимального дребезга можете получать странные значения.
значение длительности импульса для достижения нужного вольтажа такое разное,что не видно закономерности,на что умножить кол-во пройденных пинов?
Сначала вам нужно привести код в порядок. Та куча, что у вас навалена - совершенно нечитаема. Сначала код нужно нормально оформить (со всем нужным форматированием; убиранием закомментированного мусора; убиранием портянок линейного код вместо циклов и т.д.). Тогда и может и проблема станет сразу видна. А в вашей куче почти ничего не видно.
Заголовок сообщения: Re: странное поведение ШИМ,возможно дело в коде
Добавлено: Чт июн 20, 2024 13:09:13
Вымогатель припоя
Карма: 1
Рейтинг сообщений: 129
Зарегистрирован: Вт мар 03, 2015 20:13:46 Сообщений: 617 Откуда: рядом с "не резиновой" живу в деревне
Рейтинг сообщения:0
jcxz писал(а):
Без какого-то синхросигнала. При наличии даже минимального дребезга можете получать странные значения.
Мой скромный опыт пробы пера с энкодером, говорит ровно тоже.. дребезг большущая проблема и если есть вариант сделать фильтрацию за пределами контролёра - это нужно сделать.
Как вариант. ICR1=540 соответствует максимальному числу шагов энкодера OCR1A=K*N/256 или K=540*256/128=1080 середина N=64 OCR1A=1080*64/256=270 минимальное N=64-48 OCR1A=1080*16/256=67 максимальное N=64+48 OCR1A=1080*112/256=472
спасибо,но не совсем.во-первых 256 это что? во-вторых если брать максимальное значение,то там 96 пинов,и OCR1A=1080*96/256=405,а в свою очередь OCR1A=405 даёт 3.64В,в то время как при 96 пинах должно быть 3.85В и про минимальное я тоже не понял,почему у нас минимальный угол поворота составляет 16 пинов?16 пинов это мы уже на 45 градусов повернули энкодер.
Цитата:
Сделать 2 чтения, кэп? а потом соединить данные. Нет, никак?
та "как",конечно,чего ж никак)) если успею-сегодня переделаю и выложу.
Типовой прием ухода от дробных значений. Вряд ли удобнее умножать 1080/256=4,21875. Как следует из картинки и текста программы берется кодировка без смещения, т.е. середина положения энкодера 64 шага, а не 48. Как вариант, сместить таблицу кодировки на 16 шагов. Мой опыт применения такого энкодера - резисторы уменьшить до 1к и опрос осуществлять импульсом |_| лапой, подключенной к (C)COM.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения