Делитель/умножитель ШИМ
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
Если выложите исходник, посмотрю что можно улучшить. Только уже наверное не раньше вторника.
- Реклама
[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3802697#p3802697"]... Может и исходник выложу. Там всего 500 байт кода. )
атмегу8 поменяю на тини2313 или13.
Никаких резисторов с АЦП не буду делать для онлайн руления коэффициентом. Тупо дип-переключатели. Выставил, нажал сброс, мк при инициализации перечитал значение и все...[/uquote]Было бы неплохо. А то, чувствую, продавцы за выходные совсем достанут.
атмегу8 поменяю на тини2313 или13.
Никаких резисторов с АЦП не буду делать для онлайн руления коэффициентом. Тупо дип-переключатели. Выставил, нажал сброс, мк при инициализации перечитал значение и все...[/uquote]Было бы неплохо. А то, чувствую, продавцы за выходные совсем достанут.
я свою идею тоже могу выложить в виде кода, но, к сожалению не ранее среды - четверга...
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Короче, все довольно просто.
Т0 настроен на прерывания по переполнению каждые 16 мкс. В котором он делает инкремент переменной счетчика. Также по флагу обновляет две переменных "Импульс" и "Пауза" из которых составляется новый период. Производит над ними вычисления простые (деление или умножение) и потом выводит в порт тупо дрыгая ногами, пока в переменных что-то есть.
Т1 настроен на захват (в начале думал им и измерять все, но не дошло до меня, как это потом использовать). В прерывании по нему он меняет фронт захвата, выставляет флаг, что импульс уже заполнен и пора переходить к паузе. Сохраняет две переменные из которых потом формируется новый импульс.
Все.
Далее надо сделать просто преключатель, который будет указывать делить или умножать и выбирать коэффициент. Потом кнопкой резет перезагружаем и в инициализации он будет этот коэффициент закидывать в переменную, которую дальше и использовать. Вот такой тупой интерфейс для пользователя. Зато надежный. Переменный резистор со временем может и сгнить и будет шуметь. А тут можно будет тупо запаять перемычки после настройки и все.
Конечно, эта часть кода не дописана еще, т.к. не до нее было, да она и простая.
Выкладываю все как есть. Быдлокод не оптимален и кривой не пинайте, на Си пишу первый раз с 2010 года. Много закомментированных строчек. Это просто был эксперимент. Чтобы заработало. В желе не пробовал еще. Но есть модель в протеусе. Тоже скидываю.
Не такой уж и коммерческий проект это. Одно устройство от ДМ-Гаджет у меня валяется, с которого я хотел сдернуть прошивку и тупо повторить. Но не поддалось.
И у меня до сих порт эту приблуду не забрали, значит не сильно нужна, а значит хрен продашь. )))) Хотелось бы конечно, на чем-нибудь заработать, т.к. с недавнего времени сижу без работы теперь...
Добавлено after 3 minutes 38 seconds:
Да. И плата под устройство со всеми формирователями четкого импульса, с выходным транзистором, со стабилизатором и защитами отправляется полностью на ваше усмотрение. ))) Автомобиль довольно жесткая среда для эксплуатации электроники. Тут надо от правильной разводки до элементарной базы подходить серьезнее.
Добавлено after 22 minutes 55 seconds:
Не дописал. Тестил только в Протеусе. А там не знаю как сделать не меандр.... (
Добавлено after 18 minutes 27 seconds:
В Тини13 нету таймера с захватом, как я понимаю, но есть вход для внешнего прерывания. А он, если мне память не изменяет, тоже может передний и задний фронт отслеживать, чего будет вполне достаточно.
Добавлено after 8 minutes 10 seconds:
И надо сделать, чтобы дробные корректно мог. А у меня все переменные целые... Тоже пока не соображаю как их в действительные, а потом как это выводить?. )
Т0 настроен на прерывания по переполнению каждые 16 мкс. В котором он делает инкремент переменной счетчика. Также по флагу обновляет две переменных "Импульс" и "Пауза" из которых составляется новый период. Производит над ними вычисления простые (деление или умножение) и потом выводит в порт тупо дрыгая ногами, пока в переменных что-то есть.
Т1 настроен на захват (в начале думал им и измерять все, но не дошло до меня, как это потом использовать). В прерывании по нему он меняет фронт захвата, выставляет флаг, что импульс уже заполнен и пора переходить к паузе. Сохраняет две переменные из которых потом формируется новый импульс.
Все.
Далее надо сделать просто преключатель, который будет указывать делить или умножать и выбирать коэффициент. Потом кнопкой резет перезагружаем и в инициализации он будет этот коэффициент закидывать в переменную, которую дальше и использовать. Вот такой тупой интерфейс для пользователя. Зато надежный. Переменный резистор со временем может и сгнить и будет шуметь. А тут можно будет тупо запаять перемычки после настройки и все.
Конечно, эта часть кода не дописана еще, т.к. не до нее было, да она и простая.
Выкладываю все как есть. Быдлокод не оптимален и кривой не пинайте, на Си пишу первый раз с 2010 года. Много закомментированных строчек. Это просто был эксперимент. Чтобы заработало. В желе не пробовал еще. Но есть модель в протеусе. Тоже скидываю.
Не такой уж и коммерческий проект это. Одно устройство от ДМ-Гаджет у меня валяется, с которого я хотел сдернуть прошивку и тупо повторить. Но не поддалось.
И у меня до сих порт эту приблуду не забрали, значит не сильно нужна, а значит хрен продашь. )))) Хотелось бы конечно, на чем-нибудь заработать, т.к. с недавнего времени сижу без работы теперь...
Добавлено after 3 minutes 38 seconds:
Да. И плата под устройство со всеми формирователями четкого импульса, с выходным транзистором, со стабилизатором и защитами отправляется полностью на ваше усмотрение. ))) Автомобиль довольно жесткая среда для эксплуатации электроники. Тут надо от правильной разводки до элементарной базы подходить серьезнее.
Добавлено after 22 minutes 55 seconds:
Не дописал. Тестил только в Протеусе. А там не знаю как сделать не меандр.... (
Добавлено after 18 minutes 27 seconds:
В Тини13 нету таймера с захватом, как я понимаю, но есть вход для внешнего прерывания. А он, если мне память не изменяет, тоже может передний и задний фронт отслеживать, чего будет вполне достаточно.
Добавлено after 8 minutes 10 seconds:
И надо сделать, чтобы дробные корректно мог. А у меня все переменные целые... Тоже пока не соображаю как их в действительные, а потом как это выводить?. )
- Вложения
-
- AAPR.zip
- (40.65 КБ) 146 скачиваний
Станислав
в МК совсем необязательно иметь ЯВНЫЕ дроби (или плавающую точку). всё можно делать в целых числах.
когда нужен коэффициент меньше единицы, представляем его в виде целого числа х, деленного на степень числа 2.
если нужна большая точность коэффициента, то берем для коэффициента двухбайтовое число и для делителя число 65536.
в целых числах умножаем наше число на целое число х и из произведения отбрасываем 2 младших байта - это равноценно делению на 65536.
в результате получаем произведение числа на дробь.
а если не нужна высокая точность, то можно коэффициент представить однобайтовым числом и делить на 256 (отбрасывание одного младшего байта).
также операцию деления можно заменить на такое же умножение на число меньше единицы.
когда нужен коэффициент меньше единицы, представляем его в виде целого числа х, деленного на степень числа 2.
если нужна большая точность коэффициента, то берем для коэффициента двухбайтовое число и для делителя число 65536.
в целых числах умножаем наше число на целое число х и из произведения отбрасываем 2 младших байта - это равноценно делению на 65536.
в результате получаем произведение числа на дробь.
а если не нужна высокая точность, то можно коэффициент представить однобайтовым числом и делить на 256 (отбрасывание одного младшего байта).
также операцию деления можно заменить на такое же умножение на число меньше единицы.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
- Реклама
Спасибо. )) Ничиего не понял, правда, но сейчас почитаю про это еще где-нибудь.
Станислав
навряд ли ты где-то еще сможешь почитать про эту программистскую хитрость.
и что тут непонятного?
допустим, тебе нужно исходное число умножить на дробное число 0,6875.
предварительно умножаем 0,6875 на 65536 и получаем целое число 45056.
теперь твое исходное число умножаем на целое число 45056, и у произведения отбрасываем 2 младших байта (делим на 65536).
в результате получаем произведение на 0,6875.
и что тут непонятного?
допустим, тебе нужно исходное число умножить на дробное число 0,6875.
предварительно умножаем 0,6875 на 65536 и получаем целое число 45056.
теперь твое исходное число умножаем на целое число 45056, и у произведения отбрасываем 2 младших байта (делим на 65536).
в результате получаем произведение на 0,6875.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
А если у меня коэффициент 4,5, то получится уже больше двух байт. ) А как АВР умножает на 0,6575? Там же тоже переменные целые. Мои мозги в этом жутко тупят.
Да и думаю, что прямо так точно не надо. достаточно до десятых все округлить.
И следующий момент, ввод значения для деления/умножения производится переключателями. Пусть 8 штук на весь порт. Их комбинацией надо выставлять любое значение от 1 до 8 с точностью до десятых. Потом считанное значение закидывать в рабочую переменную, которой пользоваться в расчетах.
Да и думаю, что прямо так точно не надо. достаточно до десятых все округлить.
И следующий момент, ввод значения для деления/умножения производится переключателями. Пусть 8 штук на весь порт. Их комбинацией надо выставлять любое значение от 1 до 8 с точностью до десятых. Потом считанное значение закидывать в рабочую переменную, которой пользоваться в расчетах.
Станислав
если тебе не нужна большая точность, то дробную часть можно представить, как х/256. это получится дискретность примерно по 0,004 (1/256).
и для чисел больше 1 тоже нет проблем.
представляем коэффициент, как двухбайтовое число, где старший байт является целой частью, а младший - дробной.
умножаем исходной число на на целое двухбайтовое число, и отбрасываем из произведения 1 младший байт (делим на 256).
в этом случае максимальный коэффициент будет равен 255 плюс 255/256 = 255,996.
и для чисел больше 1 тоже нет проблем.
представляем коэффициент, как двухбайтовое число, где старший байт является целой частью, а младший - дробной.
умножаем исходной число на на целое двухбайтовое число, и отбрасываем из произведения 1 младший байт (делим на 256).
в этом случае максимальный коэффициент будет равен 255 плюс 255/256 = 255,996.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3803209#p3803209"]... сейчас почитаю про это еще где-нибудь.[/uquote]

Для примера https://radiokot.ru/forum/viewtopic.php ... 7#p1420427Starichok51 писал(а):навряд ли ты где-то еще сможешь почитать про эту программистскую хитрость.
Долго мудрил и думал. Думал умножать и заранее на известный коэффициент типа 10. Думал сделать заранее вычисленные таблицы. Всякую фигню возможную и не возможную .
Потом тупо подключил библиотеку с флоат для атмеги8. И забил на все. В протеусе работает.
Потом тупо подключил библиотеку с флоат для атмеги8. И забил на все. В протеусе работает.
Станислав
правильное решениеСКАЗОЧНИК писал(а):подключил библиотеку с флоат для атмеги8. И забил на все.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Перетащил весь проект на ТИНИ2313. Решил использовать весь порт Б под переключатели, которыми коэффициент выбирать. Из которых крайний бит (восьмой) отвечает за деление или умножение, три следующих за единицы, остальные четыре за десятые доли.
Вот так:
8 бит - включен = умножение, сброшен = деление.
----------------------------------------------------------------
7 бит = 4 (это все выставляет единицы)
6 бит = 2
5 бит = 1
ЗАПЯТАЯ
4 бит = 8 (это все выставляет десятые)
3 бит = 4
2 бит = 2
1 бит = 1
Вот набрал я на нем типа 1,6. Как теперь это значение 0b00010110 преобразовать в 1,6? Простыми условиями проверять? Как-то много их получится.
З.Ы. самый левый бит проверяем сразу, потом сбрасываем его, чтобы не мешал. Остается только переменная с числом, которое надо переделать в флоат.
Вот так:
8 бит - включен = умножение, сброшен = деление.
----------------------------------------------------------------
7 бит = 4 (это все выставляет единицы)
6 бит = 2
5 бит = 1
ЗАПЯТАЯ
4 бит = 8 (это все выставляет десятые)
3 бит = 4
2 бит = 2
1 бит = 1
Вот набрал я на нем типа 1,6. Как теперь это значение 0b00010110 преобразовать в 1,6? Простыми условиями проверять? Как-то много их получится.
З.Ы. самый левый бит проверяем сразу, потом сбрасываем его, чтобы не мешал. Остается только переменная с числом, которое надо переделать в флоат.
Станислав
есть несколько вариантов... поскольку у вас по сути BCD-представление числа, можно использовать извращения с BCD-математикой...
но я сделал бы тупее, но проще:
Добавлено after 6 minutes 8 seconds:
только надо помнить, что "десятые" у вас можно задать не только от 0 до 9, но и до 15, что будет уже некорректно - в моём коде проверки на этот случай нет, как вы можете видеть...
но я сделал бы тупее, но проще:
Код: Выделить всё
typedef union{
struct{
uint8_t mul : 1;
uint8_t act: 3;
uint8_t frac : 4;
};
uint8_t data;
} selector_t;
selector_t selector;
selector.data = PINB;
float coefficient = selector.act + selector.frac / 10;только надо помнить, что "десятые" у вас можно задать не только от 0 до 9, но и до 15, что будет уже некорректно - в моём коде проверки на этот случай нет, как вы можете видеть...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
А можно как-то без объединений и структур? Ну плохо я их понимаю в Си.
Зато понял суть последней строчки, где в переменную тупо загоняем единицы к которым прибавили дробную часть тоже как единицы, но разделенные на 10.
Типа 1 + 6 / 10 = 1,6
Добавлено after 1 minute 4 seconds:
Это по сути мне можно сдвигами зафигачить в две переменные сначала первые три бита, потом в другую оставшиеся 4 бита. А после чего уже прибавить одно к другому.
Добавлено after 55 seconds:
Кстати, можно проверку на 15 не делать. Т.к. складывать все равно будет корректно. Просто учитывать это, что можно в десятых набрать больше единицы, но результат все равно будет правильный.
Зато понял суть последней строчки, где в переменную тупо загоняем единицы к которым прибавили дробную часть тоже как единицы, но разделенные на 10.
Типа 1 + 6 / 10 = 1,6
Добавлено after 1 minute 4 seconds:
Это по сути мне можно сдвигами зафигачить в две переменные сначала первые три бита, потом в другую оставшиеся 4 бита. А после чего уже прибавить одно к другому.
Добавлено after 55 seconds:
Кстати, можно проверку на 15 не делать. Т.к. складывать все равно будет корректно. Просто учитывать это, что можно в десятых набрать больше единицы, но результат все равно будет правильный.
Станислав
именно это компилятор за вас и сделает при помощи той самой структуры. оно вам надо - самому париться?СКАЗОЧНИК писал(а):Это по сути мне можно сдвигами зафигачить в две переменные сначала первые три бита, потом в другую оставшиеся 4 бита.
Добавлено after 3 minutes 21 second:
только я вам соврал нечаянно, не сильно задумывался... вот такая структура правильная - предыдущую выбросьте, как страшный сон:
Код: Выделить всё
typedef union{
struct{
uint8_t frac : 4;
uint8_t act: 3;
uint8_t mul : 1;
};
uint8_t data;
} selector_t;прошу прощения за ляп.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Просто пока я не понимаю, как это работает, то этому не доверяю.
Вот когда придет время и разберусь со структурами, буду использовать.
Спасибо, что натолкнули на решение.
Спасибо, что натолкнули на решение.
Станислав
- Сообщения: 1978
- Зарегистрирован: Ср июл 17, 2013 13:55:57
СКАЗОЧНИК, без структур и юниона:
Хотя со структурой и битовыми полями куда удобнее )
Код: Выделить всё
uint8_t data;
data = PINB;
bool mul = (data & 0b10000000) ? true : false;
float coefficient = ((data & 0b1110000) >> 4) + ((float)(data & 0x0F) / 10);
Последний раз редактировалось NStorm Чт мар 12, 2020 09:40:37, всего редактировалось 1 раз.
работает это просто: считайте, что вы объявили переменные frac и act, которые состоят не из 8 битов, а из 4 и 3 соответственно. ну и заодно не просто состоят из меньшего количества битов, но еще и расположены "внутри" байта.СКАЗОЧНИК писал(а):я не понимаю, как это работает
главное - чтобы их положение внутри байта совпало с тем, как вы эти биты вывели на переключатели.
Добавлено after 2 minutes 30 seconds:
кстати, NStorm еще на одну ошибочку
Добавлено after 1 minute 8 seconds:
а поддержка float в attiny2313 помещается?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Всего килобайт лишний сожрала...
Добавлено after 1 hour 29 minutes 35 seconds:
[uquote="NStorm",url="/forum/viewtopic.php?p=3805745#p3805745"]СКАЗОЧНИК, без структур и юниона:[/uquote]
А здесь он с переменной data сначала сделает сдвиг, а потом уже в той же переменной будет толк делать &0x0F? Он же ее запортит?
Добавлено after 1 hour 29 minutes 35 seconds:
[uquote="NStorm",url="/forum/viewtopic.php?p=3805745#p3805745"]СКАЗОЧНИК, без структур и юниона:
Код: Выделить всё
float coefficient = ((data & 0b1110000) >> 4) + ((float)(data & 0x0F) / 10);
А здесь он с переменной data сначала сделает сдвиг, а потом уже в той же переменной будет толк делать &0x0F? Он же ее запортит?
Станислав


