Вопрос по спидометру на 2410 с кпп от 3110
- Автор
- Сообщение
-
Не в сети
- Интересующийся
- Сообщения: 170
- Зарегистрирован: Вс сен 08, 2013 20:56 pm
- Автомобиль: ГАЗ-2410 1987 г.в.
- Откуда: Астрахань
- Благодарил (а): 5 раз
Вопрос по спидометру на 2410 с кпп от 3110
Здравствуйте.
С момента покупки в автомобиле ГАЗ-2410 стояла КПП от 3110.
Спидометр показывает скорость быстрее, чем есть на самом деле. Одометр так же врёт.
Вариант разбирать коробку и менять валы от 2410 - не подходит.
Какие ещё есть варианты?
Может просто перерисовать шкалу? Но тогда одометр продолжит врать, хотя по большому счёту это не беда, если других вариантов нет.
Подскажите, на сколько точно больше показывает спидометр? Дабы мне высчитать погрешность и составить новую шкалу.
С момента покупки в автомобиле ГАЗ-2410 стояла КПП от 3110.
Спидометр показывает скорость быстрее, чем есть на самом деле. Одометр так же врёт.
Вариант разбирать коробку и менять валы от 2410 - не подходит.
Какие ещё есть варианты?
Может просто перерисовать шкалу? Но тогда одометр продолжит врать, хотя по большому счёту это не беда, если других вариантов нет.
Подскажите, на сколько точно больше показывает спидометр? Дабы мне высчитать погрешность и составить новую шкалу.
_________________
Suum cuique (Латынь)
Suum cuique (Латынь)
-
Не в сети
- Интересующийся
- Сообщения: 139
- Зарегистрирован: Пт окт 07, 2011 15:38 pm
- Автомобиль: ГАЗ 3110,98г.
- Откуда: Видное
- Поблагодарили: 2 раза
- Контактная информация:
Re: Вопрос по спидометру на 2410 с кпп от 3110
окститесь, какие валы вы собрались там менять.
там надо всего то поменять шестерню спидометра на вторичном валу.
там надо всего то поменять шестерню спидометра на вторичном валу.
_________________
не дорогой и качественный ремонт машин.
разные доработки в автомобиле по пожеланию клиента.
не дорогой и качественный ремонт машин.
разные доработки в автомобиле по пожеланию клиента.
-
Не в сети
- Волговод со стажем
- Сообщения: 1001
- Зарегистрирован: Вт мар 29, 2011 12:41 pm
- Автомобиль: 2410'92 31105 Chrysler'06
- Откуда: Тобольск
- Благодарил (а): 2 раза
- Поблагодарили: 34 раза
Re: Вопрос по спидометру на 2410 с кпп от 3110
160 по спидометру это должно быть 100 по факту. Отсюда и пляши с разметкой.
-
Не в сети
- Заслуженный участник форума
- Сообщения: 3429
- Зарегистрирован: Ср апр 08, 2009 12:01 pm
- Автомобиль: ГАЗ-24 (с дополнениями)
- Откуда: Москва, Бутово
- Благодарил (а): 95 раз
- Поблагодарили: 198 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
В КПП 24 - 624 оборота тросика на 1 километр пробега (или 1000 оборотов на милю)
в КПП 3110 - 1000 оборотов тросика на 1 километр пробега.
Следовательно, завышает в 1,6 раза.
в КПП 3110 - 1000 оборотов тросика на 1 километр пробега.
Следовательно, завышает в 1,6 раза.
_________________
Aнкета моего Бизона
"без кувалды и зубила, ты не слесарь - а..."
Куплю зелёные велюровые сиденья образца 3102/2410
Aнкета моего Бизона
"без кувалды и зубила, ты не слесарь - а..."
Куплю зелёные велюровые сиденья образца 3102/2410
-
Не в сети
- Волговод
- Сообщения: 940
- Зарегистрирован: Вт фев 02, 2010 2:47 am
- Автомобиль: Газ 24 10
- Откуда: Липецк
- Благодарил (а): 17 раз
- Поблагодарили: 7 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Батенька, не партесь! Поменяйте шестерню в кпп. Ничего страшного там нет. А градуировать спидометр может и не выйти, есть предположение, что "врёт " он неравномерно. Экспериментальным способом было вымерено, что до 100км.ч у него расхождение с реальностью порядка 40км.ч, а когда стрелка заходит уже на 160 и далее, погрешность уже другая.
_________________
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
-
Не в сети
- Интересующийся
- Сообщения: 73
- Зарегистрирован: Ср янв 26, 2011 18:44 pm
- Автомобиль: ГАЗ-2403 1983 г. в.
- Откуда: г.Макеевка Россия
- Поблагодарили: 1 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Букварь почитайте. Поменять нужно не только съемную шестерню но, и ту что стоит на выходном валу. А это все равно разборка КПП, и неслабая. Проще и менее затратно вставить в приборку газ-24-10 спидометр с 3110. И тут на форуме, и на других Волгофорумах этот вопрос уже столько раз обсасывали что его уже можно бояном назвать. Это если Вам нужна аутентичная приборка, А если нет то вариантов решения этой проблемы миллион. От установки спидометра с ВАЗ-2106 до замены всей приборки на 31105-ю.
-
Не в сети
- Волговод
- Сообщения: 940
- Зарегистрирован: Вт фев 02, 2010 2:47 am
- Автомобиль: Газ 24 10
- Откуда: Липецк
- Благодарил (а): 17 раз
- Поблагодарили: 7 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
aleks0373 поменять ведущую шестерню под пиво вечером за милое дело) А дрочить тему перестановки "слагаемых" не имеет смысла.
_________________
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
-
Не в сети
- Заслуженный участник форума
- Сообщения: 3429
- Зарегистрирован: Ср апр 08, 2009 12:01 pm
- Автомобиль: ГАЗ-24 (с дополнениями)
- Откуда: Москва, Бутово
- Благодарил (а): 95 раз
- Поблагодарили: 198 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
IceWind, aleks0373, в обоих Ваших предложениях есть резон: и КПП под пивко за вечер разобрать можно, и в старый спидометр новые потроха вставить можно. И в новых потрохах есть несомненный плюс: суточный пробег будет не сверху, а снизу, т.е при движении с самыми ходовыми скоростями по трассе (80-120) он не будет загораживаться стрелкой спидометра, как на штатном. Помню, в дальних поездках реально раздражала необходимость заглядывать "за стрелку", когда, например, нужный поворот ищешь "через 3,5 км". Так что оба решения имеют право на жизнь.
_________________
Aнкета моего Бизона
"без кувалды и зубила, ты не слесарь - а..."
Куплю зелёные велюровые сиденья образца 3102/2410
Aнкета моего Бизона
"без кувалды и зубила, ты не слесарь - а..."
Куплю зелёные велюровые сиденья образца 3102/2410
-
Не в сети
- Волговод
- Сообщения: 650
- Зарегистрирован: Ср апр 08, 2009 7:25 am
- Автомобиль: '91 ГАЗ 2410 ЗМЗ511, '01 ГАЗ 3110 ЗМЗ406
- Откуда: Йошкар-Ола
- Поблагодарили: 31 раз
Вопрос по спидометру на 2410 с кпп от 3110
Векторный файл изображения шкалы спидометра со стилистикой и шрифтами ГАЗ 2410.
Отверстия под одометр суточного и общего пробега, здесь сопоставлены с механизмом спидометра 3110. Отверстия под индикацию включения указателей поворота, обогрева заднего стекла и включения габаритных огней/ближнего света, смещены ниже относительно оригинала для совмещения с механизмом от 3110. Файл CorelDraw 11:
https://yadi.sk/d/le-IdCZrfR6pE
Шрифт цифр на спидометре 2410 ГОСТ 2930-62:
https://disk.yandex.ru/i/TG8kiEB_xlk3dg
скорость - высота 8 мм;
одометр - высота 5 мм.
Начертание страница 6, пункт г.
размеры Таблица 1, страница 7.
Скругление выполнено согласно пункта 7, страница 2: Допускается скругление острых углов букв, цифр и знаков радиусом, равным половине толщины обводки, кроме знаков, имеющих острый угол , в которых радиус скругления должен быть не более 0,1 мм
На чистую 24:
http://volga-69-gaz.2x2forum.ru/t293-topic
Последний раз редактировалось Mizantrop Ср янв 04, 2023 23:00 pm, всего редактировалось 3 раза.
_________________
Я люблю людей. © Дельфин
Я люблю людей. © Дельфин
-
Не в сети
- Волговод
- Сообщения: 940
- Зарегистрирован: Вт фев 02, 2010 2:47 am
- Автомобиль: Газ 24 10
- Откуда: Липецк
- Благодарил (а): 17 раз
- Поблагодарили: 7 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Mizantrop ГОДНО!!!
_________________
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
-
Не в сети
- Освоившийся
- Сообщения: 578
- Зарегистрирован: Сб фев 26, 2011 21:25 pm
- Автомобиль: ГАЗ 3102 91г.в. ГАЗ 31029 97г.в.
- Откуда: Брянск
- Благодарил (а): 12 раз
- Поблагодарили: 24 раза
Re: Вопрос по спидометру на 2410 с кпп от 3110
как вариант, взять спидометр от поздней 31029, они рассчитаны на 5ст кпп и тросиковый привод. единственное, придется переделать подключение ламп под клеммы, но это проще чем кпп скидывать.
я у себя просто отогнул спираль, которой управляется стрелка спидометра, чуть назад. т.е. без движения показывает чуть меньше 0, но зато при движении не завышает
я у себя просто отогнул спираль, которой управляется стрелка спидометра, чуть назад. т.е. без движения показывает чуть меньше 0, но зато при движении не завышает
-
Не в сети
- Волговод
- Сообщения: 609
- Зарегистрирован: Вт апр 14, 2009 13:13 pm
- Автомобиль: ГАЗ 24-10, 310221
- Откуда: Москва
- Благодарил (а): 7 раз
- Поблагодарили: 34 раза
Re: Вопрос по спидометру на 2410 с кпп от 3110
У меня уже давно в старом корпусе потроха от спидометра 3110
На 31029 такой же спидометр, просто в КПП стоят шестерни от 4х ступки и все...
Ничего не выйдет!tag писал(а):как вариант, взять спидометр от поздней 31029, они рассчитаны на 5ст кпп и тросиковый привод. единственное, придется переделать подключение ламп под клеммы, но это проще чем кпп скидывать.
На 31029 такой же спидометр, просто в КПП стоят шестерни от 4х ступки и все...
_________________
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
-
Не в сети
- Волговод
- Сообщения: 650
- Зарегистрирован: Ср апр 08, 2009 7:25 am
- Автомобиль: '91 ГАЗ 2410 ЗМЗ511, '01 ГАЗ 3110 ЗМЗ406
- Откуда: Йошкар-Ола
- Поблагодарили: 31 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Как реализован механизм сброса суточного пробега?Catmaps писал(а):У меня уже давно в старом корпусе потроха от спидометра 3110
_________________
Я люблю людей. © Дельфин
Я люблю людей. © Дельфин
-
Не в сети
- Волговод со стажем
- Сообщения: 1553
- Зарегистрирован: Чт янв 19, 2012 22:29 pm
- Автомобиль: ГАЗ-2477, универсал, 1978, дизель, 5КПП.
- Откуда: Санкт-Петербург
- Благодарил (а): 33 раза
- Поблагодарили: 108 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Вот здесь viewtopic.php?f=26&t=87501 все подробно разжевано про шестерни вторичного вала.
Кратко - нет шестерней для 5-ступок и 4-ступок, для 31-х и 24-х. Есть всего-навсего ДВЕ шестерни, под старый и новый спидометр. Никаких прочих коррекций скорости/пробега на Волгах тоже нет.
Если есть желание перерисовать шкалу - самое оптимальное откалибровать спидометр, по GPS хотя бы.
Если совмещать капиталку КПП с заменой этой шестерни - вот тогда ничего страшного, а высыпать всё содержимое из коробки с целью поменять эту самую шестерню - оно того не стоит, поверьте.
Кратко - нет шестерней для 5-ступок и 4-ступок, для 31-х и 24-х. Есть всего-навсего ДВЕ шестерни, под старый и новый спидометр. Никаких прочих коррекций скорости/пробега на Волгах тоже нет.
Если есть желание перерисовать шкалу - самое оптимальное откалибровать спидометр, по GPS хотя бы.
Если кто не знает, еще раз сообщаем - эта шестерня является ПОСЛЕДНЕЙ деталью, вынимаемой из коробки при полной разборке и, соответственно - ПЕРВОЙ, с которой и начинается обратная сборка.IceWind писал(а):Батенька, не партесь! Поменяйте шестерню в кпп. Ничего страшного там нет.
Если совмещать капиталку КПП с заменой этой шестерни - вот тогда ничего страшного, а высыпать всё содержимое из коробки с целью поменять эту самую шестерню - оно того не стоит, поверьте.
-
Не в сети
- Интересующийся
- Сообщения: 135
- Зарегистрирован: Ср июн 11, 2014 16:30 pm
- Автомобиль: ГАЗ-2410 1989г.в.
- Откуда: Москва, ЗАО
- Благодарил (а): 8 раз
- Поблагодарили: 6 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
У 3110 спидометр уже не тросом приводится, насколько я понял, а по проводам?
_________________
Не ошибается тот, кто ничего не делает!
Моя анкета: viewtopic.php?t=86197
Ищу бежевые обшивки дверей 2410
и пластиковые накладки низа дверей
Куплю рулевой редуктор 2410
Не ошибается тот, кто ничего не делает!
Моя анкета: viewtopic.php?t=86197
Ищу бежевые обшивки дверей 2410
и пластиковые накладки низа дверей
Куплю рулевой редуктор 2410
-
Не в сети
- Волговод
- Сообщения: 609
- Зарегистрирован: Вт апр 14, 2009 13:13 pm
- Автомобиль: ГАЗ 24-10, 310221
- Откуда: Москва
- Благодарил (а): 7 раз
- Поблагодарили: 34 раза
Re: Вопрос по спидометру на 2410 с кпп от 3110
Не путайте людей!Halfaxel писал(а):Вот здесь viewtopic.php?f=26&t=87501 все подробно разжевано про шестерни вторичного вала.
Кратко - нет шестерней для 5-ступок и 4-ступок, для 31-х и 24-х. Есть всего-навсего ДВЕ шестерни, под старый и новый спидометр. Никаких прочих коррекций скорости/пробега на Волгах тоже нет.
Шестерней, отвечающих за спидометр не две а ЧЕТЫРЕ!!!
Для 24,24-10,3102,31029 с любыми КПП и механическим спидометром:
- ведущая шестерня 24-3803033 - 6 зубов;
- ведомая шестерня 24-3803034 - 19 зубов.
Номера КПП с такими шестернями:
- 24-1700010-01 - 4х ступка.
- 31029-1700010 - 5ти ступка.
Для 3110,31105 с любой КПП, электронным спидометром и ГП в мосту 3,9:
- ведущая шестерня 3110-3803033-01 - 10 зубов;
- ведомая шестерня 3110-3803034-01 - 20 зубов.
Номера КПП с такими шестернями:
- 3110-1700010, 31105-1700010-10, 31105-1700010-20, 31105-1700010-70 - все 5ти ступки;
- 3110-1700010-10 - 4х ступка.
Для 31105 с любой КПП, электронным спидометром и ГП в мосту 3,58:
- ведущая шестерня 3110-3803033-01 - 10 зубов;
- ведомая шестерня 3110-3803034-10 - 18 зубов.
Номера КПП с такими шестернями:
31104-17000010-01, 31105-1700010-80 - все 5ти ступки.
Имеются еще разные ведущие и ведомые шестерни от Газелей.
Опять НЕ Ваша правда, ведущая шестерня спидометра вынимается первой из шестерен, правда вначале нужно вынуть вторичный вал А ведомая с наружной стороны КПП одним болтиком держится.Halfaxel писал(а):Если кто не знает, еще раз сообщаем - эта шестерня является ПОСЛЕДНЕЙ деталью, вынимаемой из коробки при полной разборке и, соответственно - ПЕРВОЙ, с которой и начинается обратная сборка.
Электрическим методом, с обратной стороны был прикреплен актюатор центрального замка двери с какой то иномарки, не очень большой по габаритам. Потом я его снял для переделки, но забросил это. Сейчас в процессе реализации совсем другой спидометр в старом корпусе, доделаю покажу...Mizantrop писал(а):Как реализован механизм сброса суточного пробега?
_________________
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
-
Не в сети
- Волговод со стажем
- Сообщения: 1553
- Зарегистрирован: Чт янв 19, 2012 22:29 pm
- Автомобиль: ГАЗ-2477, универсал, 1978, дизель, 5КПП.
- Откуда: Санкт-Петербург
- Благодарил (а): 33 раза
- Поблагодарили: 108 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Спасибо за просвещение, то есть привода спидометра 31029 и 24 коробок полностью совпадают?Catmaps писал(а): Не путайте людей!
Шестерней, отвечающих за спидометр не две а ЧЕТЫРЕ!!!
Я про ведущие шестеренки, их две, 6 зубов и 10 зубов. Ведомую поменять недолго.
Ой, да ладно? Только что перебирал 31029 коробку. Ну и как это - "вынуть вторичный вал"? Без полной разборки?Catmaps писал(а): Опять НЕ Ваша правда, ведущая шестерня спидометра вынимается первой из шестерен, правда вначале нужно вынуть вторичный вал А ведомая с наружной стороны КПП одним болтиком держится.
Не тот случай - "подлез с краешку и поменял".
Ведомую - ясен пень, можно за минуту снять-поставить, с ней проблем нет.
-
Не в сети
- Волговод
- Сообщения: 609
- Зарегистрирован: Вт апр 14, 2009 13:13 pm
- Автомобиль: ГАЗ 24-10, 310221
- Откуда: Москва
- Благодарил (а): 7 раз
- Поблагодарили: 34 раза
Re: Вопрос по спидометру на 2410 с кпп от 3110
Всегда рад поделится тем, что знаюHalfaxel писал(а):Спасибо за просвещение, то есть привода спидометра 31029 и 24 коробок полностью совпадают?
Приводы спидометров 31029 и 24 одинаковые.
Ну располовинить пятиступку не сложно, надо просто знать как. По мне полная разборка - это когда всё что снимается снятоHalfaxel писал(а):Ну и как это - "вынуть вторичный вал"? Без полной разборки?
_________________
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
ГАЗ 24-10, 90 год, ЗМЗ 402. КПП, мосты, стабы 31105
ГАЗ 310221, 99 год, ЗМЗ 402
-
Не в сети
- Волговод
- Сообщения: 940
- Зарегистрирован: Вт фев 02, 2010 2:47 am
- Автомобиль: Газ 24 10
- Откуда: Липецк
- Благодарил (а): 17 раз
- Поблагодарили: 7 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Halfaxel поверьте стоит того. Я заколебался смотреть как у меня накручивается одометр и не правильно показывает скорость. Два вечера и проблема решена, а если сидеть лениться и ныть, то конечно проще перерисовать шкалы.
Да и не сложно это вовсе. Подшипник вторичного вала главное не деформировать с горяча, а за ним и шестерня. Конечно геморно, что весь в масле будешь пока блок шестерён запихивать, но перерисовка и подгонка шкал по мне куда тяжелее)
Да и не сложно это вовсе. Подшипник вторичного вала главное не деформировать с горяча, а за ним и шестерня. Конечно геморно, что весь в масле будешь пока блок шестерён запихивать, но перерисовка и подгонка шкал по мне куда тяжелее)
_________________
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
Автомобиль - не роскошь, роскошь - это Волга!
На ДРАЙВЕ- http://www.drive2.ru/cars/gaz/24/2410/maskot/
-
Не в сети
- Интересующийся
- Сообщения: 135
- Зарегистрирован: Ср июн 11, 2014 16:30 pm
- Автомобиль: ГАЗ-2410 1989г.в.
- Откуда: Москва, ЗАО
- Благодарил (а): 8 раз
- Поблагодарили: 6 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
А эти шестерни отдельно продаются?IceWind писал(а):Halfaxel поверьте стоит того. Я заколебался смотреть как у меня накручивается одометр и не правильно показывает скорость. Два вечера и проблема решена, а если сидеть лениться и ныть, то конечно проще перерисовать шкалы.
Да и не сложно это вовсе. Подшипник вторичного вала главное не деформировать с горяча, а за ним и шестерня. Конечно геморно, что весь в масле будешь пока блок шестерён запихивать, но перерисовка и подгонка шкал по мне куда тяжелее)
Чтоб не выковыривать ее из родной 4-ст коробки!
_________________
Не ошибается тот, кто ничего не делает!
Моя анкета: viewtopic.php?t=86197
Ищу бежевые обшивки дверей 2410
и пластиковые накладки низа дверей
Куплю рулевой редуктор 2410
Не ошибается тот, кто ничего не делает!
Моя анкета: viewtopic.php?t=86197
Ищу бежевые обшивки дверей 2410
и пластиковые накладки низа дверей
Куплю рулевой редуктор 2410
-
Не в сети
- Волговод со стажем
- Сообщения: 1553
- Зарегистрирован: Чт янв 19, 2012 22:29 pm
- Автомобиль: ГАЗ-2477, универсал, 1978, дизель, 5КПП.
- Откуда: Санкт-Петербург
- Благодарил (а): 33 раза
- Поблагодарили: 108 раз
Re: Вопрос по спидометру на 2410 с кпп от 3110
Конечно, продаются. 250 руб стоит. Я как раз и выяснял для себя, как они выглядят и чем отличаются, перед тем, как коробку перебирать.Vankel писал(а): А эти шестерни отдельно продаются?
Чтоб не выковыривать ее из родной 4-ст коробки!
http://forum.uazbuka.ru/showthread.php? ... ac&t=70017
Вот здесь, между прочим, человек смастерил электронный корректор числа импульсов. Схемка и описание прилагаются. Продает, можно готовую купить у него или самому спаять, схему он не засекретил (уважаю).
Правда, она предназначена для электронных спидометров, а не тросовых. Так что это платку придется не в проводку щитка внедрять, а непосредственно внутрь Волговского спидометра. Плавная регулировка делается переменным резистором как на плюс, так и на минус.
-
Не в сети
- Волговод
- Сообщения: 650
- Зарегистрирован: Ср апр 08, 2009 7:25 am
- Автомобиль: '91 ГАЗ 2410 ЗМЗ511, '01 ГАЗ 3110 ЗМЗ406
- Откуда: Йошкар-Ола
- Поблагодарили: 31 раз
Вопрос по спидометру на 2410 с кпп от 3110
Если я правильно понял, вы хотите этой схемой корректировать спидометр 24, 2410, 3102, 31029?Halfaxel писал(а): http://forum.uazbuka.ru/showthread.php? ... ac&t=70017
Вот здесь, между прочим, человек смастерил электронный корректор числа импульсов. Схемка и описание прилагаются. Продает, можно готовую купить у него или самому спаять, схему он не засекретил (уважаю).
Правда, она предназначена для электронных спидометров, а не тросовых. Так что это платку придется не в проводку щитка внедрять, а непосредственно внутрь Волговского спидометра. Плавная регулировка делается переменным резистором как на плюс, так и на минус.
http://схема-авто.рф/sxema-i-ustrojstvo-spidometra.htmlМеханический спидометр устроен просто: поверх магнитного диска 1, приводимого тросом, расположен с небольшим зазором вращающийся на оси алюминиевый колпак (картушка) 2 со стрелкой и возвратной пружиной 3 (см. рис.). Когда диск вращается, его магнитные силовые линии возбуждают в картушке токи, создающие свое магнитное поле. При взаимодействии двух полей картушка увлекается за диском, но пружина ограничивает ее поворот углом, зависящим от скорости вращения диска. Циферблат отградуирован в соответствии с тарировкой прибора, зависящей от жесткости возвратной пружины. Любое изменение ее жесткости недопустимо – показания спидометра окажутся искажены.
Импульсов там нет. Там магнитное поле, в связи с чем мне корректировка показалась проблематичной.
Схема идет для типа спидометров 56.3802:
т.е. для "обмана" микросхем КР1086ХА1 (http://gazclub.ru/faq/?mess_id=1374)По внешнему виду первые электронные спидометры трудно отличить от механических. Стрелка на своем месте, барабанчики с цифрами тоже. Но отныне стрелка – деталь электронного измерителя числа импульсов от датчика скорости. Угол ее поворота пропорционален числу импульсов в единицу времени – подробности технологии пересчета оставим специалистам. Одометр похож на механический, но «декады» подчиняются управляемому электроникой микроэлектродвигателю.
или УР1101ХП31 (http://chip.tomsk.ru/chip/ChipDoc.nsf/f ... enDocument).
С расчетом на импульсы (думал спидометр 2410 уже с импульсами ) была практически допилена своя прошивка корректора для Atmega 8535, но к сезону похоже не успею.
Почему, собственно, механизм 3110 и вставляется в корпус 2410 на фото выше.
http://vk.com/hrom12
Элитная лоботомия дорого и ооочень больно ооочень долго.
http://radiokot.ru/lab/hardwork/06/
Установка для экспонирования фоторезиста на базе разбитой лампы ДРЛ 400 Вт. ACHTUNG! жесткое УФ-излучение:
http://www.chipdip.ru/product/xpewht-l1-0000-009a8/
http://lib.chipdip.ru/303/DOC000303030.pdf
http://www.chipdip.ru/product/tina-xp-w-fa10838/
http://lib.chipdip.ru/304/DOC000304006.pdf
Лучше FA10644 Tina-XP-D (diffuser)
Светорассеивающий пластик :
Сигнальные лампы:
Старое решение с лампами в таком случае не влезает.
Если просто поставить диоды будет точка света за пиктограммой.
При такой комбинации получается ровная подсветка указателя поворотов, включения обогрева заднего стекла и габаритов.
Позже было найдено еще более компактное решение:
https://luminofor.ru/index.php?cat=901
электролюминесцентная панель или El Panel
Шкала производства k1taez:
Подсветка шкалы, зеленая светодиодная лента:
Новый корпус напечатанный на 3d принтере:
Осцилограмма с 6-импульсного датчика скорости:
"скорость" при этом ~80 км/ч.
Соотношение частоты импульсов с датчика скорости и показаний скорости на спидометре 3110/3302:
Приборная панель "рижская"
5 км/ч ~ 8 Гц.
"С места в карьер" нельзя давать свыше 200 Гц (120 км/ч) - стрелка не будет показывать скорость, будет крутится только одометр. Частоту наращивать плавно.
Реализация механизма сброса суточного пробега без торчащего штока:
Серво двигатель:
http://xq-power.com/XQ-S42/show_54.html
Крепеж серво:
https://aliexpress.ru/item/32327647523. ... 33edEx7cgX
Предназначен для соответствия «стандартным размерам» JR, Futaba, Hitec
Шарнирный наконечник:
https://technobearing.ru/eshop1/product/59787811
Модели различных конструкций использованных в изделии (Solidworks 2012):
https://yadi.sk/d/d1m9T6T_cFyIIA
Последний раз редактировалось Mizantrop Вс окт 18, 2020 14:47 pm, всего редактировалось 1 раз.
_________________
Я люблю людей. © Дельфин
Я люблю людей. © Дельфин
-
Не в сети
- Волговод со стажем
- Сообщения: 1553
- Зарегистрирован: Чт янв 19, 2012 22:29 pm
- Автомобиль: ГАЗ-2477, универсал, 1978, дизель, 5КПП.
- Откуда: Санкт-Петербург
- Благодарил (а): 33 раза
- Поблагодарили: 108 раз
Вопрос по спидометру на 2410 с кпп от 3110
У меня скорее спортивный интерес был - поддаётся ли 24-й спидометр хоть какой-нибудь коррекции. Видимо, никакой.
Он и так у меня нормально показывает, не буду ковырять.
-
Не в сети
- Волговод
- Сообщения: 650
- Зарегистрирован: Ср апр 08, 2009 7:25 am
- Автомобиль: '91 ГАЗ 2410 ЗМЗ511, '01 ГАЗ 3110 ЗМЗ406
- Откуда: Йошкар-Ола
- Поблагодарили: 31 раз
Вопрос по спидометру на 2410 с кпп от 3110
Продолжу пока, не забыл, вроде не оффтоп.
"Кинематика" механизма сброса суточного пробега спидометра 3110:
ход штока по прямой, на моем спидометре составляет 4 мм, плечо рычага - 19 мм. Угол на который необходимо поворачивать рычаг - 12,9 градусов.
Сброс без штока осуществляется серводвигателем:
(с описанием работы "серв" можно ознакомиться здесь: https://arduinomaster.ru/motor-dvigatel ... pravlenie/). Управление серводвигателем осуществляется с помощью широтно-импульсной модуляции ШИМ (бурж. PWM), необходимо подобрать длительность импульсов, чтобы двигатель поворачивал вал с качалкой примерно на 13 градусов, плюс особенность двигателя имеющегося в наличии состоит в том, что он не возвращает вал в исходное положение после снятия управляющего сигнала.
Из документации на двигатель Running degree 110°(when 900~2100 µ sec), на градус поворота вала приходится (2100 - 900)/110 = 10,9 мк с длительности импульса.
В крайние положения двигатель лучше не загонять, выставить вал в центр - 1500 мк с, и двигать относительно этого положения => дельта длительности управляющего сигнала будет составлять 10,9 х 12,9 ~ 130,8 мк с => для сброса пробега нужно повернуть вал на 12,9 градусов, для чего подать на двигатель сигнал с импульсом длительностью 1500 + 130,8 = 1630 мк с и затем для возврата вала в центральное положение, подать сигнал с длительностью импульса 1500 мк с.
Формирование ШИМ можно осуществлять различными способами, выбрано управление с помощью микроконтроллера ATTiny 2313 (datasheet: https://yadi.sk/i/IAuhmz1dvTsiUA) в корпусе PDIP/SOIC.
Цена на момент написания поста 112 рублей в местных радиодеталях: http://radioremont.com/product/attiny2313a_pu/
Питание для данной микросхемы 2,7 - 5,5 В раздел Features, Operating voltages даташита стр.1
В автомобиле бортовая сеть -12 В.
Преобразователь 12>5 В собран на типовой схеме интегрального стабилизатора напряжения 7805:
Общая схема дополняется двумя диодами 1N4007: VD1 - для защиты от "переполюсовки" и VD2 - для защиты микросхемы 7805, и на данном этапе имеет вид:
Далее, имеются рекомендации по типовому подключению микроконтроллеров:
http://easyelectronics.ru/podklyuchenie ... ikbez.html
Пока схема никакой функции не выполняет, микроконтроллер необходимо настроить.
На борту микроконтроллера имеется 16-ти разрядный счетчик (16 bit Timer/Counter1)стр. 82 datasheet.
Функция - "тикает", как часы, и при этом считает. Длительность по времени одного "тика" задается
кварцем и составляет 1/Q, например 1/3276800 = 3.052х10^-7 секунды.
Кварц подключается к микроконтроллеру согласно рекомендациям страница 23:
Длительность "тика" может задавться другими способами, в этом устройстве - не используются.
Для счетчика выделена специальная облать памяти - регистр TCNT1.
При каждом "тике" значение регистра TCNT1 увеличивается на единицу, от 0 до 65535
(2^16 = 65535, таймер/счетчик 16-ти разрядный), либо от нуля до произвольного значения из
диапазона 0-65535 (задается настройкой режима функционирования счетчика).
Соответственно, при кварце Q = 3276800 (3,2768 МГц), таймер дотикает до значения 65535 за время
3,052х10^-7 х 65535 = 0,02 с. Далее произойдет сброс значения данных в регистре
TCNT1 в 0, и таймер/счетчик продолжит считать от 0 до 65535. Таким образом имеется периодическое колебание
с периодом T = 3,052х10^-7 х 65535 = 0,02 с или с частотой f = 1/T = 1/0,02 = 50 Гц,
необходимой для сигнала управления серводвигателем.
Также во время счета имеется возможность менять состояние определенных выводов (ног)
микроконтроллера - задавать длительность импульса, т.е. иметь на выходе ШИМ, в ATiny есть
походящий режим работы
счетчика Fast PWM Mode стр. 96 datasheet.
Временная диаграмма:
Из описания и временной диаграммы сначала не совсем понятно (было не только мне https://www.cyberforum.ru/avr/thread2088328.html), но время
до которого "нога" OC1B (вывод МК №16) будет включена задается регистром OCR1B, а последнее значение до которого считает счетчик - задается регистром OCR1A.
дополненная илюстрация:
Счетчик начинает считать от 0, увеличивая значение TCNT1 на единицу, при этом на выходе OC1B держит логическую "1", когда TCNT1 становится равным OCR1B, счетчик устанавливает на выходе OC1B логический "0" идержит его до тех пор, пока значение в TCNT1 не будет равно OCR1A.
Расчет частоты ШИМ для этого режима осуществляется по формуле: f = fclk/(N(1+TOP) (стр. 97),
где fclk - частота кварца, N - величина предделителя частоты (в устройстве N =1), TOP = 65535 - значение до которого считает счетчик (регистр OCR1A).
Чтобы счетчик микроконтроллера заработал в выше рассмотренном режиме FastPWM, необходимо выставить определенные биты в специальных областях, согласно таблице:
стр 106.
Mode 15, Timer/Counter Mode of operation - FastPWM, биты WGM13=1, WGM12=1, WGM11=1, WGM10=1.
Специальные области являются регистрами управления счетчиком Timer/Counter1 Control Register A (сокращенно TCCR1A) стр.104 и Timer/Counter1 Control Register B (сокращенно TCCR1B) стр. 107.
Биты WGM10 и WGM11 находятся в регистре TCCR1A, биты WGM12 и WGM13 находятся в регистре TCCR1B.
Я для себя представляю это двумя виртуальными панелями тумблеров внутри микроконтроллера
Для включения этих "тумблеров", да и вообще, далее понадобится компилятор.
Я работал в IAR AVR (тут имеется описание преимуществ: https://chipenable.ru/index.php/item/2 и описание некоторых частей нужных для написания первой программы)
Здесь описано создание первого проекта в картинках: https://chipenable.ru/index.php/item/33 (https://yadi.sk/d/mDbVnow7ccdqmQ)
На пункте:
Проекту дается какое-нибудь осмысленное название, типа "mileage_reset".
В окне main.c на данном этапе имеется только такая запись:
int main()
{
return 0;
}
Перед первой строкой добавляется: #include <ioavr.h>
#include <ioavr.h>
int main()
{
return 0;
}
#include <ioavr.h>
int main(void)
{
return 0;
}
Далее указываются данные для регистров OCR1A и OCR1B (для примера - половина периода 65535/2 = 32767):
#include <ioavr.h>
int main(void)
{
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
return 0;
}
Далее в программе настраивается таймер, выше было, что Биты WGM10 и WGM11 находятся в регистре TCCR1A:
стр. 104
При инициализации, включении микроконтроллера TCCR1A=00000000 (initial values, восемь нулей), и для режима FastPWM необходимо "включить" биты WGM10 и WGM11 под номерами #0 и #1 соответственно, установив их в "1" => TCCR1A=00000011
стр. 104
3-я строка описывает этот необходимый режим: сброс в логический ноль ноги OC1B при совпадении (со значением регистра OCR1B) и установку в логическую единицу вывода OC1B при достижении счетчиком значения TOP (значение в регистре OCR1A). Необходимо "включить" бит COM1B1 под №5 (#5). TCCR1A уже имеет вид 00000011, при изменении бита #5: TCCR1A=00100011.
Запись вида TCCR1A=00100011 нельзя подсунуть в IAR AVR, но можно перевести с помощью стандартного калькулятора ОС Windows, режим "программист", число в шестнадцатиричную систему (HEX) и записать как TCCR1A = 0x23;
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
return 0;
}
Далее необходимо настроить регистр TCCR1B, выше упоминалось, что здесь находятся биты биты WGM12 и WGM13:
стр. 107
При инициализации, включении микроконтроллера TCCR1B=00000000 и для режима FastPWM необходимо "включить" биты WGM12 и WGM13 под номерами #3 и #4 соответственно => TCCR1B=00011000.
В регистре TCCR1B находится еще одна настройка, предделитель таймера. С помощью данного делителя можно в некоторых пределах изменять длительность "тика" таймера/счетчика:
При инициализации, таймер выключен - биты CS12, CS11 и CS10 равны 0, в схеме предделитель не используется fclk/1 бит CS10=1 =>
TCCR1B=00011001 или в hex TCCR1B=0x19.
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
TCCR1B=0x19;
return 0;
}
После данных настроек необходимо сконфигурировать порт, с которого будет получатся управляющий сигнал.
https://www.radiokot.ru/start/mcu_fpga/avr/06/
"B" указывается вместо "X" в записи DDRX, тк PB4 = > нужен бит #4 и DDRX = DDRB = 00010000 в hex DDRB=0x10
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
TCCR1B=0x19;
DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Сохранить и откомпилировать согласно https://chipenable.ru/index.php/item/2 в IAR AVR.
Где-то на этом этапе возникает желание посмотреть, чо получилось, и желательно без пайки.
Для этого можно воспользоваться программой Proteus 8, у меня Release 8.9 SP2 (Build 28501).
Расположить в проекте микроконтроллер ATTiny2313:
Остальную "обвязку", которая фигурировала выше на принципиальной схеме, подключать необязательно.
Далее двойным щелчком левой кнопки мыши вызвать меню, которое заполнить следующим образом:
Отключен встроенный делитель частоты, подключен внешний "кварц", частота кварца в симуляции установлена 3,2768 МГц
Если все делалось согласно статьи https://chipenable.ru/index.php/item/2, то где-то на компьютере должна быть папка с таким содержимым:
В папке "Debug", в подпапке "Exe":
будет находиться файл прошивки с расширением .hex:
В программе Proteus 8, в меню для компонента ATTiny2313 "Edit Component" в поле "Program file", путем нажатия на изображения папки, выбирается файл прошивки mileage_reset.hex:
Сигнал снимается с вывода ОС1B, на него для контроля вешается частотомер (раздел INSTRUMENTS > COUNTER TIMER):
настраивается по двойному клику левой кнопки мыши следующим образом, Operating mode > Frequency:
и осциллограф (раздел INSTRUMENTS > OSCILLOSCOPE):
Внизу запускается симуляция:
и результат работы программы:
Частота сигнала - 50 Гц, скважность - 2 (коэффициент заполнения 0,5) - как и было запланировано.
Файлы на данном этапе:
https://yadi.sk/d/aqviIdm5yQia7A схема в Proteus
https://yadi.sk/d/2eG10n3nsMYzpQ - прошивка
Далее, записи вида:
текст программы после приведения к "красивому" виду:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10)|(1<<COM1B1);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x23;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Чтобы компилятор принял такую запись и не выдал ошибку:
Далее, для аутентичности необходимо, чтобы сброс суточного пробега осуществлялся с помощью ручки сброса расположенной рядом с часами. В оригинале она с помощью троса крутит барабаны, в устройстве же с помощью данной ручки планируется "нажимать" на два микро переключателя (микрика) или кнопки, как реализовано на плате панели приборов ВАЗ 2110:
Нажатие кнопок должно приводить к подаче микроконтроллером импульсов управления серводвигателем.
Подключения кнопки к микроконтроллеру с подтянутой землей.
При таком подключении состояние линии порта ввода вывода будет:
— при отжатой кнопке равно лог.«0»;
— при нажатой кнопке равно лог.«1»;
Электрическая схема на данном этапе имеет вид:
В программе при первичной инициализации таймера отключается вывод OC1B, сразу при включении импульсы с него поступать не будут:
TCCR1A|=(1<<WGM11)|(1<<WGM10); //исключается |(1<<COM1B1)
//TCCR1A=0x03
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Далее необходимо опросить ногу к которой подключена кнопка, выполняется с помощью "if"
if (условие выполняется)
{
сделать что-то;
}
else
{
ничего не делать;
}
таким образом:
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
Опрос кнопки надо выполнять постоянно, для реализации желания водителя сбросить суточный пробег:
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
И общий текст программы:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
return 0;
}
Далее, для кнопок характерен дребезг контактов:
https://uscr.ru/drebezg-kontaktov-i-spo ... -drebezga/
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
чтобы компилятор правильно обработал строку "__delay_cycles(10000);" - необходимо добавить в начало программы "#include <intrinsics.h>"
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
Схема в эмуляторе Proteus, дополняется источником постоянного напряжения DC 12 В, стабилизатором 7805 на 5В, кнопкой SB1 и резистором R2 номиналом 10 кОм:
Схема: https://yadi.sk/d/aTLedMyq7FAxIw
Прошивка: https://yadi.sk/d/4hSMaZA8GAGRWw
Величина OCR1B равная 32767 была выбрана для примера, чтобы выставить вал двигателя в центральное положение, необходимо подать импульс длительностью 1500 мкс, 1 "тик" таймера 3,052х10^-7 с => число тиков для формирования данного импульса должно составлять: N=(1500x10^-6)/(3,052x10^-7)=4915.2, примерно 4915 "тиков".
OCR1B=4915;
После нажатия кнопки SB1, длительность импульса должна увеличиться до значения 1630 мкс, или до примерно 5341 "тиков" таймера, OCR1B=5341.
Возникает необходимость регистру OCR1B, по нажатию кнопки SB1, присваивать значение некоторой переменной, с осмысленным названием, например angle типа unsigned int и начальным значением 4915. Тип представляет положительное целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита), и из-за этого диапазон предельных значений может меняться: от 0 до 65535 (для 2 байт), либо от 0 до 4 294 967 295 (для 4 байт). Применение данного типа при введении в программу некоторой переменной гарантирует, что она никогда не станет отрицательной. Кроме того, если имеются только положительные числа, можно воспользоваться тем, что данные указанного типа могут принимать большие значения, чем данные эквивалентного типа со знаком. Обычно это применяется при адресации памяти и организации счетчиков.
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915;
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
OCR1B=angle;
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
Дальнейшие действия основаны на прерываниях.
https://chipenable.ru/index.php/item/5
Данное прерывание будет возникать каждый раз, когда содержимое регистра TCNT таймера/счетчика 1 будет совпадать со значением находящемся в регистре OCR1B.
Функция прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5)
{
TCCR1A|=(1<<COM1B1);
}
}
Здесь на каждом окончании положительного импульса будет происходить увеличение временных переменных n и tmp, также на окончании пятого импульса включение вывода ОС1В.
Если оставить включение как в предыдущей логике, то на реальной схеме произойдет подача первого импульса случайной длительности, что приведет к "рывку" серводвигателя и поломке механики спидометра.
Также необходимо разрешить прерывание по совпадению для Таймера/счетчика1:
//разрешить прерывания для Timer/Counter1
TIMSK|=(1<<OCIE1B); стр. 109
переменные n и tmp надо прописать особым образом, https://chipenable.ru/index.php/program ... ction.html:
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp:
__monitor unsigned int get_tmp(void)
{
return tmp;
}
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
while (1)
{
OCR1B=angle;
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
//TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
//Прерывания:
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5)
{
TCCR1A|=(1<<COM1B1);
}
}
Есть смысл не запускать процесс сброса - движения серводвигателя, если он уже запущен и двигатель куда-то двигается. Поэтому добавляется перменная reset, reset=1; когда двигатель уже в работе и reset=0; когда двигатель остановлен. Соответствующая проверка добавляется в прерывание по совпадению: if (tmp==5 && reset==0) и в обработку нажатия кнопки:
if (reset==0)
{
if ((PIND&(1<<PD1))!=0) .......
Далее в каждом прерывании по совпадению происходит увеличение временной переменной tmp, используя это увеличение можно плавно изменять угол поворота серводвигателя:
В бесконечном цикле сравнивается значение переменной из прерывания с временной переменной tmpold, если они не различаются, то никакого действия не происходит:
if (get_tmp()==tmpold)
{
//ничего не делать;
}
Если tmp не равно tmpold, то необходимо увеличить либо уменьшить значение угла поворота: angle=anle+(какое-то значение) или angle:=angle-(какое-то значение).
В качестве какого-то значения можно задать переменную, с осмыссленным названием delta_angle. Величина данной переменной будет также определять скорость поворота качалки серводвигателя.
Как обычно практика разошлась с теорией, и чтобы сбросить пробег в моем случае пришлось отклонять качалку на больший угол и подавать для крайнего правого положения импульс с длительностью отличной от 1630 мк с, 1967 мк с или в "тиках" таймера 6475.
Скорость поворота практически выбрана 30=delta_angle => 6475-4915 = 1560, и при скорости изменения 30 переменная angle достигнет нужных значений за 52 раза изменения переменной tmp (1560/30=52). Вывод OC1B, для минимизации переходных процессов, включается со значения переменной tmp=5, => 5+52=57 после данного значения переменной tmp необходимо разворачивать поворот двигателя в обратную сторону т.е. angle=angle-delta_angle. После значения tmp=109 (57+52) необходимо остановить двигатель TCCR1A&=(~(1<<COM1B1)); и присвоить переменной reset значение 0, а переменной tmpold присвоить значение tmp:
if (get_tmp()==tmpold)
{
//ничего не делать
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1)
{
TCCR1A|=(1<<COM1B1);
}
}
Файл для Proteus остается предыдущий,
прошивка на данном этапе: https://yadi.sk/d/UVsG4Iu0B-1E4Q
визуализация:
Далее, рекомендация из руководства по эксплуатации:
Чтобы исключить данную возможность, на схему через ключ на полевом транзисторе VT1 (https://yandex.ru/turbo/sdelaysam-svoim ... store.html), резисторы R3, R4 и фильтрующий конденсатор С8 берутся прямоугольные импульсы с сдатчика скорости.
В микроконтроллере настраивается внешнее прерывание на любое изменение уровня на выводе INT1 (по фронту и тылу импульса):
В данном прерывании переменной block присваивается значение 1:
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
чтобы данное прерывание заработало, необходимо дополнительно включить его в регистре General Interrupt Mask Register (GIMSK) стр. 59
GIMSK=(1<<INT1);
а также задать возникновение прерывания по фронту и спаду импульса в регистре MCU Control Register (MCUCR) стр. 59
MCUCR=(1<<ISC10);
в обработку нажатия кнопки и включения вывода OC1B добавляется проверка переменной block, если block=1 - автомобиль движется и включать сброс суточного пробега нельзя:
if (reset==0 && block==0)
{
//обработка нажатий кнопки "Reset":
if ((PIND&(1<<PD1))!=0) ....
и в прерывании по совпадению:
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
} ...
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
//настройка внешних прерываний
MCUCR=(1<<ISC10);
GIMSK=(1<<INT1);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0 && block==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
}
}
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
При такой логике сброс суточного пробега будет срабатывать только до первого импульса с датчика скорости, т.к. никогда до перезагрузки микроконтроллера не произойдет обнуление переменной block.
Необходимо организовать сброс переменной block.
На борту микроконтроллера ATTiny 2313 остается еще один 8-битный таймер/счетчик 0 (8-bit Timer/Counter0) стр. 62
Частоту сброса переменной на данном таймере в режиме Normal аналогично FastPWM можно рассчитать по формуле:
стр. 69
По наблюдениям спидометр адекватно работает до частоты поступающих импульсов 5 Гц, частота же счетчика 8-bit Timer/Counter0 в режиме Normal даже с самым большим предделителем N=1024 будет f= 3276800/(1024x256) = 12,5 Гц и сброс переменной будет происходить в течении еще не закончившегося импульса. Поэтому сброс нужно выполнить хотя бы на 4-е переполнение счетчика Timer/Counter0 и частота составит 12,5/4 примерно 3 Гц.
Добавляется еще одно прерывание, по переполнению Timer/Counter0
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
}
В нем будет считатся значение новой переменной n1, если n1=4 -наступило четвертое переполнение, частота 3 Гц, необходимо сбросить переменную block:
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
if (n1==4)
{
block=0;
n1=0;
}
}
и обновить переменную n1 для дальнейшего корректного счета.
Также необходимо включить и настроить счетчик Timer/Counter0 стр.73:
//инициализация таймера T0:
TCCR0B|=(1<<CS02)|(1<<CS00);
//режим Normal
//предделитель частоты 1024
и разрешить прерывание по переполнению для счетчика T0:
TIMSK|=(1<<TOIE0);
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,n1,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация таймера T0:
TCCR0B|=(1<<CS02)|(1<<CS00);
//режим Normal
//предделитель частоты 1024
//инициализация счетчика T1:
OCR1A=65535;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B)|(1<<TOIE0);
//настройка внешних прерываний
MCUCR=(1<<ISC10);
GIMSK=(1<<INT1);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0 && block==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
}
}
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
if (n1==4)
{
block=0;
n1=0;
}
}
Ситуация, когда идет сброс суточного пробега и началось движение, на Волге мне кажется маловероятной.
Схема для Proteus:
https://yadi.sk/d/Jk43DwXjCDECzA
Прошивка для микроконтроллера:
https://yadi.sk/d/hh3ZWk1DB_HJ5w
Окончательный вариант схемы электрической принципиальной:
С8 - фильтрующий конденсатор, VD3 - диод от "переполюсовки".
Печатная плата для данной реализации SprintLayout 6:
https://yadi.sk/d/WYboVBCen9YHzw
Вид со стороны дорожек.
Для минимизации размеров без части для внутрисхемного программирования (ISP).
В качестве платы можно использовать что-нибудь готовое, типа https://www.tindie.com/products/bugrovs ... ttiny2313/
Я изготовил свою:
В качестве программатора использовалось устройство от "Мастеркит" ВМ9010 (https://masterkit.ru/shop/1321257):
Запустить под Windows 7 мне его не удалось, но имеется ноутбук под Windows XP.
Схема корректора спидометра 3110 на микроконтроллере Atmega8535:
R12 - Входной сигнал от датчика на КПП;
Выход на спидометр - 18-ая нога микроконтроллера (PD4/OC1B);
Светодиод D8 - индикация режима настройки;
Светодиоды D1-D7 - индикация коэффициента/изменения коэффициента коррекции в режиме настройки.
Корректировка коэффициента проводится по какому-нибудь GPS/Глонас - навигатору.
Схема для Proteus8, прошивка контроллера, EEPROM и содержимое файла main.c:
https://disk.yandex.ru/d/7cQdWB5EXBrOLg
Разводка платы в корпус реле указателя поворотов 575.3777 12В для SprintLayout6:
https://disk.yandex.ru/d/vw-T2MB1vGnOQg
Выносной пульт с диодами VD1-8:
"Кинематика" механизма сброса суточного пробега спидометра 3110:
ход штока по прямой, на моем спидометре составляет 4 мм, плечо рычага - 19 мм. Угол на который необходимо поворачивать рычаг - 12,9 градусов.
Сброс без штока осуществляется серводвигателем:
(с описанием работы "серв" можно ознакомиться здесь: https://arduinomaster.ru/motor-dvigatel ... pravlenie/). Управление серводвигателем осуществляется с помощью широтно-импульсной модуляции ШИМ (бурж. PWM), необходимо подобрать длительность импульсов, чтобы двигатель поворачивал вал с качалкой примерно на 13 градусов, плюс особенность двигателя имеющегося в наличии состоит в том, что он не возвращает вал в исходное положение после снятия управляющего сигнала.
Из документации на двигатель Running degree 110°(when 900~2100 µ sec), на градус поворота вала приходится (2100 - 900)/110 = 10,9 мк с длительности импульса.
В крайние положения двигатель лучше не загонять, выставить вал в центр - 1500 мк с, и двигать относительно этого положения => дельта длительности управляющего сигнала будет составлять 10,9 х 12,9 ~ 130,8 мк с => для сброса пробега нужно повернуть вал на 12,9 градусов, для чего подать на двигатель сигнал с импульсом длительностью 1500 + 130,8 = 1630 мк с и затем для возврата вала в центральное положение, подать сигнал с длительностью импульса 1500 мк с.
Формирование ШИМ можно осуществлять различными способами, выбрано управление с помощью микроконтроллера ATTiny 2313 (datasheet: https://yadi.sk/i/IAuhmz1dvTsiUA) в корпусе PDIP/SOIC.
Цена на момент написания поста 112 рублей в местных радиодеталях: http://radioremont.com/product/attiny2313a_pu/
Питание для данной микросхемы 2,7 - 5,5 В раздел Features, Operating voltages даташита стр.1
В автомобиле бортовая сеть -12 В.
Преобразователь 12>5 В собран на типовой схеме интегрального стабилизатора напряжения 7805:
Общая схема дополняется двумя диодами 1N4007: VD1 - для защиты от "переполюсовки" и VD2 - для защиты микросхемы 7805, и на данном этапе имеет вид:
Далее, имеются рекомендации по типовому подключению микроконтроллеров:
http://easyelectronics.ru/podklyuchenie ... ikbez.html
схема дополняется резистором R1 и конденсатором C5:Схема сброса
Резистор на RESET. Вообще в AVR есть своя внутренняя схема сброса, а сигнал RESET изнутри уже подтянут резистором в 100кОм к Vcc. НО! Подтяжка это настолько дохлая, что микроконтроллер ловит сброс от каждого чиха. Например, от касания пальцем ножки RST, а то и просто от задевания пальцем за плату. Поэтому крайне рекомендуется RST подтянуть до питания резистором в 10к.
Пока схема никакой функции не выполняет, микроконтроллер необходимо настроить.
На борту микроконтроллера имеется 16-ти разрядный счетчик (16 bit Timer/Counter1)стр. 82 datasheet.
Функция - "тикает", как часы, и при этом считает. Длительность по времени одного "тика" задается
кварцем и составляет 1/Q, например 1/3276800 = 3.052х10^-7 секунды.
Кварц подключается к микроконтроллеру согласно рекомендациям страница 23:
Длительность "тика" может задавться другими способами, в этом устройстве - не используются.
Для счетчика выделена специальная облать памяти - регистр TCNT1.
При каждом "тике" значение регистра TCNT1 увеличивается на единицу, от 0 до 65535
(2^16 = 65535, таймер/счетчик 16-ти разрядный), либо от нуля до произвольного значения из
диапазона 0-65535 (задается настройкой режима функционирования счетчика).
Соответственно, при кварце Q = 3276800 (3,2768 МГц), таймер дотикает до значения 65535 за время
3,052х10^-7 х 65535 = 0,02 с. Далее произойдет сброс значения данных в регистре
TCNT1 в 0, и таймер/счетчик продолжит считать от 0 до 65535. Таким образом имеется периодическое колебание
с периодом T = 3,052х10^-7 х 65535 = 0,02 с или с частотой f = 1/T = 1/0,02 = 50 Гц,
необходимой для сигнала управления серводвигателем.
Также во время счета имеется возможность менять состояние определенных выводов (ног)
микроконтроллера - задавать длительность импульса, т.е. иметь на выходе ШИМ, в ATiny есть
походящий режим работы
счетчика Fast PWM Mode стр. 96 datasheet.
Временная диаграмма:
Из описания и временной диаграммы сначала не совсем понятно (было не только мне https://www.cyberforum.ru/avr/thread2088328.html), но время
до которого "нога" OC1B (вывод МК №16) будет включена задается регистром OCR1B, а последнее значение до которого считает счетчик - задается регистром OCR1A.
дополненная илюстрация:
Счетчик начинает считать от 0, увеличивая значение TCNT1 на единицу, при этом на выходе OC1B держит логическую "1", когда TCNT1 становится равным OCR1B, счетчик устанавливает на выходе OC1B логический "0" идержит его до тех пор, пока значение в TCNT1 не будет равно OCR1A.
Расчет частоты ШИМ для этого режима осуществляется по формуле: f = fclk/(N(1+TOP) (стр. 97),
где fclk - частота кварца, N - величина предделителя частоты (в устройстве N =1), TOP = 65535 - значение до которого считает счетчик (регистр OCR1A).
Чтобы счетчик микроконтроллера заработал в выше рассмотренном режиме FastPWM, необходимо выставить определенные биты в специальных областях, согласно таблице:
стр 106.
Mode 15, Timer/Counter Mode of operation - FastPWM, биты WGM13=1, WGM12=1, WGM11=1, WGM10=1.
Специальные области являются регистрами управления счетчиком Timer/Counter1 Control Register A (сокращенно TCCR1A) стр.104 и Timer/Counter1 Control Register B (сокращенно TCCR1B) стр. 107.
Биты WGM10 и WGM11 находятся в регистре TCCR1A, биты WGM12 и WGM13 находятся в регистре TCCR1B.
Я для себя представляю это двумя виртуальными панелями тумблеров внутри микроконтроллера
Для включения этих "тумблеров", да и вообще, далее понадобится компилятор.
Я работал в IAR AVR (тут имеется описание преимуществ: https://chipenable.ru/index.php/item/2 и описание некоторых частей нужных для написания первой программы)
Здесь описано создание первого проекта в картинках: https://chipenable.ru/index.php/item/33 (https://yadi.sk/d/mDbVnow7ccdqmQ)
На пункте:
Из списка выбирается ATTiny2313Выбираем тип микроконтроллера
General Options > Target > Processor configuration
У меня это ATmega8535.
Проекту дается какое-нибудь осмысленное название, типа "mileage_reset".
В окне main.c на данном этапе имеется только такая запись:
int main()
{
return 0;
}
Оригинал: https://chipenable.ru/index.php/item/2Для каждого типа микроконтроллера есть свой заголовочный файл. Для ATMega8535 этот файл называется iom8535.h, для ATMega16 – iom16.h. По идее мы должны в начале каждой программы подключать заголовочный файл того микроконтроллера, который мы используем. Умные люди немного облегчили нам жизнь и написали заголовочный файл ioavr.h. Препроцессор обрабатывает этот файл и в зависимости от настроек проекта включает в нашу программу нужный заголовочный файл.
Итак, следущая строчка программы
Перед первой строкой добавляется: #include <ioavr.h>
#include <ioavr.h>
int main()
{
return 0;
}
Оригинал: https://chipenable.ru/index.php/item/2Основу любой сишной программы составляют функции, и любая программа на Си имеет хотя бы одну функцию – main().Вообще-то на примере main() не хотелось бы объяснять синтаксис функций, потому что main() хоть и является функцией, но вызывается не как обычно, а автоматически. С этой функции микроконтроллер начинает выполнение написанной нами программы. Вызовы всех других функций, наших или библиотечных, должны быть записаны в коде. Как вызывается функция, мы увидим дальше.
У функции есть заголовок – int main(void) и тело – оно ограниченно фигурными скобками {}. В тело функции мы и будем добавлять наш код.
#include <ioavr.h>
int main(void)
{
return 0;
}
Далее указываются данные для регистров OCR1A и OCR1B (для примера - половина периода 65535/2 = 32767):
#include <ioavr.h>
int main(void)
{
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
return 0;
}
Далее в программе настраивается таймер, выше было, что Биты WGM10 и WGM11 находятся в регистре TCCR1A:
стр. 104
При инициализации, включении микроконтроллера TCCR1A=00000000 (initial values, восемь нулей), и для режима FastPWM необходимо "включить" биты WGM10 и WGM11 под номерами #0 и #1 соответственно, установив их в "1" => TCCR1A=00000011
Также во время счета имеется возможность менять состояние определенных выводов (ног)
стр. 104
3-я строка описывает этот необходимый режим: сброс в логический ноль ноги OC1B при совпадении (со значением регистра OCR1B) и установку в логическую единицу вывода OC1B при достижении счетчиком значения TOP (значение в регистре OCR1A). Необходимо "включить" бит COM1B1 под №5 (#5). TCCR1A уже имеет вид 00000011, при изменении бита #5: TCCR1A=00100011.
Запись вида TCCR1A=00100011 нельзя подсунуть в IAR AVR, но можно перевести с помощью стандартного калькулятора ОС Windows, режим "программист", число в шестнадцатиричную систему (HEX) и записать как TCCR1A = 0x23;
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
return 0;
}
Далее необходимо настроить регистр TCCR1B, выше упоминалось, что здесь находятся биты биты WGM12 и WGM13:
стр. 107
При инициализации, включении микроконтроллера TCCR1B=00000000 и для режима FastPWM необходимо "включить" биты WGM12 и WGM13 под номерами #3 и #4 соответственно => TCCR1B=00011000.
В регистре TCCR1B находится еще одна настройка, предделитель таймера. С помощью данного делителя можно в некоторых пределах изменять длительность "тика" таймера/счетчика:
При инициализации, таймер выключен - биты CS12, CS11 и CS10 равны 0, в схеме предделитель не используется fclk/1 бит CS10=1 =>
TCCR1B=00011001 или в hex TCCR1B=0x19.
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
TCCR1B=0x19;
return 0;
}
После данных настроек необходимо сконфигурировать порт, с которого будет получатся управляющий сигнал.
https://www.radiokot.ru/start/mcu_fpga/avr/06/
В устройстве - необходимо Выводить сигнал с OC1B, согласно программе выше, он же PB4 нога 16 микросхемы (стр. 2), т.е порт "B".PortX содержит информацию, предназначенную для вывода.
PinX содержит вводимую информацию
DDRX содержит информацию о том, какой канал настроен на ввод, какой - на вывод.
То есть, DDRX определяет, грубо говоря, какая ножка микросхемы будет подключена к PinX, какая - к PortX:
0 - ввод
1 - вывод
"B" указывается вместо "X" в записи DDRX, тк PB4 = > нужен бит #4 и DDRX = DDRB = 00010000 в hex DDRB=0x10
Код программы на данном этапе будет иметь вид:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A = 0x23;
TCCR1B=0x19;
DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Сохранить и откомпилировать согласно https://chipenable.ru/index.php/item/2 в IAR AVR.
Где-то на этом этапе возникает желание посмотреть, чо получилось, и желательно без пайки.
Для этого можно воспользоваться программой Proteus 8, у меня Release 8.9 SP2 (Build 28501).
Расположить в проекте микроконтроллер ATTiny2313:
Остальную "обвязку", которая фигурировала выше на принципиальной схеме, подключать необязательно.
Далее двойным щелчком левой кнопки мыши вызвать меню, которое заполнить следующим образом:
Отключен встроенный делитель частоты, подключен внешний "кварц", частота кварца в симуляции установлена 3,2768 МГц
Если все делалось согласно статьи https://chipenable.ru/index.php/item/2, то где-то на компьютере должна быть папка с таким содержимым:
В папке "Debug", в подпапке "Exe":
будет находиться файл прошивки с расширением .hex:
В программе Proteus 8, в меню для компонента ATTiny2313 "Edit Component" в поле "Program file", путем нажатия на изображения папки, выбирается файл прошивки mileage_reset.hex:
Сигнал снимается с вывода ОС1B, на него для контроля вешается частотомер (раздел INSTRUMENTS > COUNTER TIMER):
настраивается по двойному клику левой кнопки мыши следующим образом, Operating mode > Frequency:
и осциллограф (раздел INSTRUMENTS > OSCILLOSCOPE):
Внизу запускается симуляция:
и результат работы программы:
Частота сигнала - 50 Гц, скважность - 2 (коэффициент заполнения 0,5) - как и было запланировано.
Файлы на данном этапе:
https://yadi.sk/d/aqviIdm5yQia7A схема в Proteus
https://yadi.sk/d/2eG10n3nsMYzpQ - прошивка
Далее, записи вида:
являются рабочими, но не совсем корректными в тексте программы, поэтому: https://chipenable.ru/index.php/item/4TCCR1A = 0x23;
TCCR1B=0x19;
DDRB=0x10;
текст программы после приведения к "красивому" виду:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10)|(1<<COM1B1);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x23;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Чтобы компилятор принял такую запись и не выдал ошибку:
оригинал: https://chipenable.ru/index.php/item/33Разрешаем использование имен битов определенных в хедер файле
В General Options > System ставим галочку Enable bit definitions in I/O-Include files
Далее, для аутентичности необходимо, чтобы сброс суточного пробега осуществлялся с помощью ручки сброса расположенной рядом с часами. В оригинале она с помощью троса крутит барабаны, в устройстве же с помощью данной ручки планируется "нажимать" на два микро переключателя (микрика) или кнопки, как реализовано на плате панели приборов ВАЗ 2110:
Нажатие кнопок должно приводить к подаче микроконтроллером импульсов управления серводвигателем.
Подключения кнопки к микроконтроллеру с подтянутой землей.
При таком подключении состояние линии порта ввода вывода будет:
— при отжатой кнопке равно лог.«0»;
— при нажатой кнопке равно лог.«1»;
Оригинал: https://habr.com/ru/post/256269/?mobile=noЕсли подключить один из контактов кнопки, например, к общему проводу («земле»), а второй к выбранной линии порта ввода/вывода микроконтроллера, который переключен в режим «Вход», то выяснится, что такой метод не работает. При нажатии кнопки линия порта микроконтроллера соединяется с землей, и программа будет считывать лог.«0» с этой линии порта ввода/вывода, но при отпущенной кнопке вывод микроконтроллера не будет соединен ни с чем, что часто и называют «висит в воздухе». В таком случае программа будет считать с вывода и лог.«0» и лог.«1» случайным образом, так как на не к чему не присоединённую линию порта ввода/вывода будут наводится наводки.
Правильное подключение предполагает, что в разомкнутом состоянии вывод микроконтроллера должен быть соединен через резистор, например с шиной питания, а в замкнутом — с землей, либо наоборот. Сопротивление резистора не должно быть слишком маленьким, чтобы ток, текущий через него при замкнутых контактах кнопки не был слишком большим. Обычно используют значения порядка 10-100 кОм.
Электрическая схема на данном этапе имеет вид:
В программе при первичной инициализации таймера отключается вывод OC1B, сразу при включении импульсы с него поступать не будут:
TCCR1A|=(1<<WGM11)|(1<<WGM10); //исключается |(1<<COM1B1)
//TCCR1A=0x03
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
return 0;
}
Далее необходимо опросить ногу к которой подключена кнопка, выполняется с помощью "if"
if (условие выполняется)
{
сделать что-то;
}
else
{
ничего не делать;
}
таким образом:
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
Опрос кнопки надо выполнять постоянно, для реализации желания водителя сбросить суточный пробег:
Оригинал: https://chipenable.ru/index.php/item/2нужно повторить кусок программы, зациклить его. Для этих целей в Си существуют три типа циклов: for, while и do. Мы используем while.
while(condition){
statement1;
statement2;
statement3;
}
while – имеет условие выполнения (condition), оно записано в скобках () и тело цикла, оно заключено между фигурными скобками {}. В качестве условия цикла может выступать переменная, константа, выражение или функция, возвращающая значение. Перед каждым выполнением цикла происходит проверка условия, если условие истинно, цикл выполняется, если условие ложно, цикл не выполняется. Любое ненулевое значение в скобках оператор воспримет как истину, и цикл будет выполняться.
while(1){ //этот цикл будет выполняться бесконечно
statement1;
statement2;
statement3;
}
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
И общий текст программы:
#include <ioavr.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
return 0;
}
Далее, для кнопок характерен дребезг контактов:
https://uscr.ru/drebezg-kontaktov-i-spo ... -drebezga/
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")Программный способ избавления от дребезга
Суть программного способа в том, чтобы внутри программы отличить случайные срабатывания из-за дребезга от настоящего нажатия. Самый простой способ: добавить задержку сразу после первого срабатывания. Тогда при срабатывании кнопки мы останавливаем выполнение программы и дожидаемся, пока контакты кнопки перестанут дребезжать. Ложных срабатываний не будет.
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
чтобы компилятор правильно обработал строку "__delay_cycles(10000);" - необходимо добавить в начало программы "#include <intrinsics.h>"
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
Схема в эмуляторе Proteus, дополняется источником постоянного напряжения DC 12 В, стабилизатором 7805 на 5В, кнопкой SB1 и резистором R2 номиналом 10 кОм:
Схема: https://yadi.sk/d/aTLedMyq7FAxIw
Прошивка: https://yadi.sk/d/4hSMaZA8GAGRWw
Величина OCR1B равная 32767 была выбрана для примера, чтобы выставить вал двигателя в центральное положение, необходимо подать импульс длительностью 1500 мкс, 1 "тик" таймера 3,052х10^-7 с => число тиков для формирования данного импульса должно составлять: N=(1500x10^-6)/(3,052x10^-7)=4915.2, примерно 4915 "тиков".
OCR1B=4915;
После нажатия кнопки SB1, длительность импульса должна увеличиться до значения 1630 мкс, или до примерно 5341 "тиков" таймера, OCR1B=5341.
Возникает необходимость регистру OCR1B, по нажатию кнопки SB1, присваивать значение некоторой переменной, с осмысленным названием, например angle типа unsigned int и начальным значением 4915. Тип представляет положительное целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита), и из-за этого диапазон предельных значений может меняться: от 0 до 65535 (для 2 байт), либо от 0 до 4 294 967 295 (для 4 байт). Применение данного типа при введении в программу некоторой переменной гарантирует, что она никогда не станет отрицательной. Кроме того, если имеются только положительные числа, можно воспользоваться тем, что данные указанного типа могут принимать большие значения, чем данные эквивалентного типа со знаком. Обычно это применяется при адресации памяти и организации счетчиков.
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915;
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
while (1)
{
OCR1B=angle;
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
Дальнейшие действия основаны на прерываниях.
https://chipenable.ru/index.php/item/5
разрешается общее прерывание, используя встроенную функцию.
__enable_interrupt();
Будет использоваться прерывание по совпадению Таймера/счетчика 1:Функция прерывания
Это не совсем простая функция, поскольку ее вызывает микроконтроллер, и она имеет особенный синтаксис.
Cинтаксис функции прерывания:
Функция прерывания задается с помощью директивы #pragma vector= и служебного слова __interrupt. Функция должна иметь тип void и не должна принимать никаких параметров.
#pragma vector = Address
__interrupt void Name(void)
{
//здесь располагается наш код
}
Name – имя функции, выбираем на наше усмотрение
Address – адрес вектора прерывания, можно задавать числом, можно именами определенными в заголовочном файле микроконтроллера (iom8535.h – раздел Interrupt Vector Definitions)
Данное прерывание будет возникать каждый раз, когда содержимое регистра TCNT таймера/счетчика 1 будет совпадать со значением находящемся в регистре OCR1B.
Функция прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5)
{
TCCR1A|=(1<<COM1B1);
}
}
Здесь на каждом окончании положительного импульса будет происходить увеличение временных переменных n и tmp, также на окончании пятого импульса включение вывода ОС1В.
Если оставить включение как в предыдущей логике, то на реальной схеме произойдет подача первого импульса случайной длительности, что приведет к "рывку" серводвигателя и поломке механики спидометра.
Также необходимо разрешить прерывание по совпадению для Таймера/счетчика1:
//разрешить прерывания для Timer/Counter1
TIMSK|=(1<<OCIE1B); стр. 109
переменные n и tmp надо прописать особым образом, https://chipenable.ru/index.php/program ... ction.html:
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp:
__monitor unsigned int get_tmp(void)
{
return tmp;
}
общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
while (1)
{
OCR1B=angle;
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
//TCCR1A|=(1<<COM1B1); //Включается вывод OC1B
}
}
}
return 0;
}
//Прерывания:
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5)
{
TCCR1A|=(1<<COM1B1);
}
}
Есть смысл не запускать процесс сброса - движения серводвигателя, если он уже запущен и двигатель куда-то двигается. Поэтому добавляется перменная reset, reset=1; когда двигатель уже в работе и reset=0; когда двигатель остановлен. Соответствующая проверка добавляется в прерывание по совпадению: if (tmp==5 && reset==0) и в обработку нажатия кнопки:
if (reset==0)
{
if ((PIND&(1<<PD1))!=0) .......
Далее в каждом прерывании по совпадению происходит увеличение временной переменной tmp, используя это увеличение можно плавно изменять угол поворота серводвигателя:
В бесконечном цикле сравнивается значение переменной из прерывания с временной переменной tmpold, если они не различаются, то никакого действия не происходит:
if (get_tmp()==tmpold)
{
//ничего не делать;
}
Если tmp не равно tmpold, то необходимо увеличить либо уменьшить значение угла поворота: angle=anle+(какое-то значение) или angle:=angle-(какое-то значение).
В качестве какого-то значения можно задать переменную, с осмыссленным названием delta_angle. Величина данной переменной будет также определять скорость поворота качалки серводвигателя.
Как обычно практика разошлась с теорией, и чтобы сбросить пробег в моем случае пришлось отклонять качалку на больший угол и подавать для крайнего правого положения импульс с длительностью отличной от 1630 мк с, 1967 мк с или в "тиках" таймера 6475.
Скорость поворота практически выбрана 30=delta_angle => 6475-4915 = 1560, и при скорости изменения 30 переменная angle достигнет нужных значений за 52 раза изменения переменной tmp (1560/30=52). Вывод OC1B, для минимизации переходных процессов, включается со значения переменной tmp=5, => 5+52=57 после данного значения переменной tmp необходимо разворачивать поворот двигателя в обратную сторону т.е. angle=angle-delta_angle. После значения tmp=109 (57+52) необходимо остановить двигатель TCCR1A&=(~(1<<COM1B1)); и присвоить переменной reset значение 0, а переменной tmpold присвоить значение tmp:
if (get_tmp()==tmpold)
{
//ничего не делать
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1)
{
TCCR1A|=(1<<COM1B1);
}
}
Файл для Proteus остается предыдущий,
прошивка на данном этапе: https://yadi.sk/d/UVsG4Iu0B-1E4Q
визуализация:
Далее, рекомендация из руководства по эксплуатации:
Чтобы исключить данную возможность, на схему через ключ на полевом транзисторе VT1 (https://yandex.ru/turbo/sdelaysam-svoim ... store.html), резисторы R3, R4 и фильтрующий конденсатор С8 берутся прямоугольные импульсы с сдатчика скорости.
В микроконтроллере настраивается внешнее прерывание на любое изменение уровня на выводе INT1 (по фронту и тылу импульса):
В данном прерывании переменной block присваивается значение 1:
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
чтобы данное прерывание заработало, необходимо дополнительно включить его в регистре General Interrupt Mask Register (GIMSK) стр. 59
GIMSK=(1<<INT1);
а также задать возникновение прерывания по фронту и спаду импульса в регистре MCU Control Register (MCUCR) стр. 59
MCUCR=(1<<ISC10);
в обработку нажатия кнопки и включения вывода OC1B добавляется проверка переменной block, если block=1 - автомобиль движется и включать сброс суточного пробега нельзя:
if (reset==0 && block==0)
{
//обработка нажатий кнопки "Reset":
if ((PIND&(1<<PD1))!=0) ....
и в прерывании по совпадению:
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
} ...
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация счетчика:
OCR1A=65535;
//OCR1B=32767;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B);
//настройка внешних прерываний
MCUCR=(1<<ISC10);
GIMSK=(1<<INT1);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0 && block==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
}
}
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
При такой логике сброс суточного пробега будет срабатывать только до первого импульса с датчика скорости, т.к. никогда до перезагрузки микроконтроллера не произойдет обнуление переменной block.
Необходимо организовать сброс переменной block.
На борту микроконтроллера ATTiny 2313 остается еще один 8-битный таймер/счетчик 0 (8-bit Timer/Counter0) стр. 62
Частоту сброса переменной на данном таймере в режиме Normal аналогично FastPWM можно рассчитать по формуле:
стр. 69
По наблюдениям спидометр адекватно работает до частоты поступающих импульсов 5 Гц, частота же счетчика 8-bit Timer/Counter0 в режиме Normal даже с самым большим предделителем N=1024 будет f= 3276800/(1024x256) = 12,5 Гц и сброс переменной будет происходить в течении еще не закончившегося импульса. Поэтому сброс нужно выполнить хотя бы на 4-е переполнение счетчика Timer/Counter0 и частота составит 12,5/4 примерно 3 Гц.
Добавляется еще одно прерывание, по переполнению Timer/Counter0
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
}
В нем будет считатся значение новой переменной n1, если n1=4 -наступило четвертое переполнение, частота 3 Гц, необходимо сбросить переменную block:
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
if (n1==4)
{
block=0;
n1=0;
}
}
и обновить переменную n1 для дальнейшего корректного счета.
Также необходимо включить и настроить счетчик Timer/Counter0 стр.73:
//инициализация таймера T0:
TCCR0B|=(1<<CS02)|(1<<CS00);
//режим Normal
//предделитель частоты 1024
и разрешить прерывание по переполнению для счетчика T0:
TIMSK|=(1<<TOIE0);
Общий текст программы:
#include <ioavr.h>
#include <intrinsics.h>
//объявление переменных:
unsigned int angle=4915,
reset=0,
right_angle=6475,
left_angle=4915,
tmpold=0,
delta_angle=30,
oldState;
volatile unsigned int //Атомарные переменные
//используются в прерываниях,
//частично не оптимизируются компилятором:
n=0,n1,tmp=0;
//функция получения переменной tmp
__monitor unsigned int get_tmp(void)
{
return tmp;
}
int main(void)
{
//инициализация таймера T0:
TCCR0B|=(1<<CS02)|(1<<CS00);
//режим Normal
//предделитель частоты 1024
//инициализация счетчика T1:
OCR1A=65535;
//OCR1A - значение до которого считает счетчик, определяющее частоту ШИМ
//OCR1B - значение до которого считает счетчик, определяющее длительность импульса
TCCR1A|=(1<<WGM11)|(1<<WGM10);
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
//TCCR1A = 0x03;
//TCCR1B=0x19;
DDRB|=(1<<DDB4);
//DDRB=0x10;
//Конфигурирование порта B, OC1B на выход
//Разрешение общего прерывания
__enable_interrupt();
//Разрешение прерывания по совпадению Таймера/счетчика 1 TCNT=OCR1B
TIMSK|=(1<<OCIE1B)|(1<<TOIE0);
//настройка внешних прерываний
MCUCR=(1<<ISC10);
GIMSK=(1<<INT1);
while (1)
{
if (get_tmp()==tmpold)
{
//do nothing
}
else
{
if (reset==1)
{
if (tmp>5 && tmp<57)
{
angle=angle+delta_angle;
}
if (angle>right_angle)
{
angle=right_angle;
}
if (tmp>57)
{
angle=angle-delta_angle;
}
if (angle<left_angle)
{
angle=left_angle;
}
if (tmp>109)
{
TCCR1A&=(~(1<<COM1B1));
reset=0;
}
}
tmpold=tmp;
}
OCR1B=angle;
/* обработка нажатия кнопки*/
if (reset==0 && block==0)
{
if ((PIND&(1<<PD1))!=0) //Если кнопка "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
{
__delay_cycles(10000); // Задержка
if ((PIND&(1<<PD1))!=0) //Если кнопка все еще "Сброс пробега SB1" нажата (на входе PD1/TXD/(Pin3) лог. "1")
//то выполняется действие:
{
reset=1; //работа двигателя, процесс сброса "reset"
oldState = __save_interrupt(); //сохраняется регистр SREG
__disable_interrupt(); //запрещаются прерывания
n=0; //обнуляется значение n-используемой в прерывании
__restore_interrupt(oldState); //восстанавливается SREG
tmp=0;
tmpold=0;
}
}
}
}
return 0;
}
//Прерывания:
//прерывание по совпадению TCNT=OCR1B
#pragma vector=0x18
__interrupt void Timer1_Compare_Match_B (void)
{
n=n+1;
tmp=n;
if (tmp==5 && reset==1 && block==0)
{
TCCR1A|=(1<<COM1B1);
}
}
//внешнее прерывание на любое изменение лог. уровня на выводе INT1
#pragma vector=0x04
__interrupt void External_Interrupt_Request_1 (void)
{
block=1;
}
//прерывание по переполнению счетчика Timer/Counter0
#pragma vector=0x0C
__interrupt void TIMER0_OVF0 (void)
{
n1=n1+1;
if (n1==4)
{
block=0;
n1=0;
}
}
Ситуация, когда идет сброс суточного пробега и началось движение, на Волге мне кажется маловероятной.
Схема для Proteus:
https://yadi.sk/d/Jk43DwXjCDECzA
Прошивка для микроконтроллера:
https://yadi.sk/d/hh3ZWk1DB_HJ5w
Окончательный вариант схемы электрической принципиальной:
С8 - фильтрующий конденсатор, VD3 - диод от "переполюсовки".
Печатная плата для данной реализации SprintLayout 6:
https://yadi.sk/d/WYboVBCen9YHzw
Вид со стороны дорожек.
Для минимизации размеров без части для внутрисхемного программирования (ISP).
https://el-shema.ru/publ/kontroller/pro ... /9-1-0-336Для переноса написанной нами программы на компьютере, в память микроконтроллера, после компиляции, необходим программатор. Другими словами, именно с помощью программатора, мы и прошиваем микроконтроллер. В интернете есть множество схем программаторов, начинающим могу порекомендовать для сборки программатор Громова, схема очень простая, в крайнем случае, программатор можно приобрести готовый, например, на Али экспресс. Для того чтобы прошить микроконтроллер, необходимо соединить шесть его выводов — ножек, с одноименными пинами, в колодке программатора:
В качестве платы можно использовать что-нибудь готовое, типа https://www.tindie.com/products/bugrovs ... ttiny2313/
Я изготовил свою:
В качестве программатора использовалось устройство от "Мастеркит" ВМ9010 (https://masterkit.ru/shop/1321257):
Запустить под Windows 7 мне его не удалось, но имеется ноутбук под Windows XP.
Схема корректора спидометра 3110 на микроконтроллере Atmega8535:
R12 - Входной сигнал от датчика на КПП;
Выход на спидометр - 18-ая нога микроконтроллера (PD4/OC1B);
Светодиод D8 - индикация режима настройки;
Светодиоды D1-D7 - индикация коэффициента/изменения коэффициента коррекции в режиме настройки.
Корректировка коэффициента проводится по какому-нибудь GPS/Глонас - навигатору.
Схема для Proteus8, прошивка контроллера, EEPROM и содержимое файла main.c:
https://disk.yandex.ru/d/7cQdWB5EXBrOLg
Разводка платы в корпус реле указателя поворотов 575.3777 12В для SprintLayout6:
https://disk.yandex.ru/d/vw-T2MB1vGnOQg
Выносной пульт с диодами VD1-8:
_________________
Я люблю людей. © Дельфин
Я люблю людей. © Дельфин