Добрый день! Подскажите как можно красиво на Си сделать такую задачу. Есть симисторный регулятор на ATtiny2313. Обороты регулируются с помощью таймера/счетчика 1 в режиме СТС. Максимальной скорости соответсвует значение равное 9600, минимальной скорости - 1824. Всего есть 28 градаций скорости. В процентах оборотов это от 19 % до 100 %. Сам двигатель работает на оборотах от 8000 об/мин до 35000 об/мин. На регуляторе есть двухразрядный семисегментный индикатор. На нем отображаются обороты в тысячах оборотов в минуту. Задача стоит такая, не используя switch case , при значении 9600 отображать обороты 35, при значении 1824 обороты отображать 08. Вот массивы используемые: обороты в процентах: speed[27] = {19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100}; обороты в значении регистра сравнения: {1824,2112,2400,2688,2976,3264,3552,3840,4128,4416,4704,4992,5280,5568,5856,6144,6432,6720,7008,7296,7584,7872,8160,8448,8736,9024,9312,9600}; обороты отображаемые на экране: {8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35} ЗЫ: А то кроме switch ничего в голову не лезет.
Почему бы вам просто индекс текущего режима (градации) не использовать и по нему доставать из массивов остальные значения ?
_________________ "Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл / "Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Если бы значение таймера было в массиве , а у меня реализовано через прибавление/вычитание дельты с граничным ограничением Спойлер#define control_triac PD1 //Вывод на управляющий электрод симистора #define v_change_speed 288 //Шаг регулировки изменения скорости #define t_pulse_triac 50 //Длительность отпирающего импульса симистора 30 мкс (смотреть по ТУ для конкретного симистора) #define SP_hi 9600 // максимальная скорость #define SP_lo 1824 // минимальная скорость #define SP_m 4992 // средняя скорость
/********************* Обработчик прерывания по переполнению Timer 0 *************** ISR(TIMER0_OVF_vect) { // Перезагрузка значения для Timer 0 // Период Timer0 = 0.125 МГц = 8 МГц / 64. // 2 мс = 8 мкс * 250 // 5 = 255-250 TCNT0 = 5; state_counter++; output_change = 1; // Это флаг для цикла main if (state_counter > 3) state_counter = 0;
Гы, она же линейная, нaфига там массивы. В школе учили как решать систему из 2-х уравнений для нахождения Y = a * X + b? Я как то ардуино научил решать полином 3-го порядка, это когда сильно нелинейная зависимость и кубическое уравнение. Щёлкает как орехи, Y = a* X^3 + b* X^2 + c* X + d;, коэфициенты все пишет и глазом моргнуть не успеваю.
Очепятка. Там 28 значений скорости. Уравнением не получится, мне нужно целочисленные вычисления. Либо все в массивы загонять, либо через switch case присваивать значения. Как по мне что первый вариант, что второй не очень красивы, тем более с 2кб памяти хочется сделать компактно. Между оборотами в процентах и значением таймера/счетчика 1 есть прямая зависимость равна 96. Просто как потом от процентов перейти к индикации оборотов в тысячах оборотов в минуту. Потому здесь и спросил, какие могут быть варианты. Так как конструкция switch case не слишком нравится на 28 значений.
Заголовок сообщения: Re: Вывод значений с подстановкой из массива.
Добавлено: Ср июн 15, 2016 20:34:42
Это не хвост, это антенна
Карма: 20
Рейтинг сообщений: 188
Зарегистрирован: Вс мар 28, 2010 12:52:22 Сообщений: 1368 Откуда: Беларусь
Рейтинг сообщения:0
На tiny13 написан "линеаризатор" для логометра в авто после замены датчика. Из тока 4-20 мА делал ток в 63-270 мА с обратной кубической зависимостью при помощи целочисленной математики. На ассемблере размер кода составил около 600-т байт. Пробуйте, на самом деле здесь (в математическом методе) гораздо больше гибкости - завтра может понадобится продлить Вашу кривую, а памяти уже и нет...
_________________ «Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Уравнением не получится, мне нужно целочисленные вычисления.
Это вы о чём? Уравнение даёт величину, которую можно округлять вниз, вверх или по середине. Тип переменных в самом уравнении определяется требуемой точностью, флоты даблы или интегеры. Хотя забудьте, это слишком сложно для 3-го класса средней школы
На tiny13 написан "линеаризатор" для логометра в авто после замены датчика. Из тока 4-20 мА делал ток в 63-270 мА с обратной кубической зависимостью при помощи целочисленной математики.
Заголовок сообщения: Re: Вывод значений с подстановкой из массива.
Добавлено: Ср июн 15, 2016 21:00:27
Это не хвост, это антенна
Карма: 20
Рейтинг сообщений: 188
Зарегистрирован: Вс мар 28, 2010 12:52:22 Сообщений: 1368 Откуда: Беларусь
Рейтинг сообщения:0
4 мА вычитаются ОУ, давая нулевое значение, дальше что-то около "Ax^0.5+Bx^0.25+Cx". На выходе ШИМ, после RC фильтра второй ОУ в качестве источника тока вместе с полевиком. Для питания ОУ использован программный ШИМ с инверсией напряжения - дает около -3 вольт для отрицательного питания. Как показала практика - достаточно для LM358 и получения выходного напряжения от 0. Формулу точно не скажу, проект на работе. Линеаризация получилась довольно приличная, хозяин конечного устройства доволен.
_________________ «Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Я так понимаю формулу вручную подбирали, некоторые ещё Эксель используют. Т.е. не численные методы. Я в ардуино метод наименьших квадратов приспособил, т.е. АтМега328 мне формулу сама выдаёт на массив исходных данных. Как здесь, например, один массив Х{} другой Y{}, но тут легко - линия, самое простое уравнение какое может быть.
Ну мне нравится форум на коте. Одна вода. Был задан конкретный вопрос. Зачем мне решение МНК если у меня всего 28 значений, каждому соответствует определенное значение скорости. И промежуточные значения не нужны. Максимум, что может потребоваться, это изменить значение таймера/счетчика 1, если оно не будет соответствовать нужной скорости. Зачем мне решать систему линейных уравнений?
То есть самым компактным и быстрым способом будет задавать значения таймера/счетчика 1 в виде матрицы, вот так , например: const unsigned int speed_count[28] = {1824,2112,2400,2688,2976,3264,3552,3840,4128,4416,4704,4992,5280,5568,5856,6144,6432,6720,7008,7296,7584,7872,8160,8448,8736,9024,9312,9600}; Создать массив соответствующих скоростей для вывода на дисплей, вот так: const unsigned char speed_lcd[28] = {8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35}; И при изменении скорости изменять индекс массива для текущей скорости, а не само значение таймера/счетчика 1. И соответственно по индексу массива выводить значение скорости на ЖКИ. ЗЫ: А еще лучше сохранить эти массивы во флеш и обращаться к ним через pgm_read_word. И ничего лучше пока еще для решения такой задачи не придумали? ЗЫ1: просто пару человек советует использовать массивы. А третий особо умный, зачем массивы, лучше систему уравнений. Вот потому и непонятно. Если бы контроллер был ATmega8 я бы не парился. А так как ATtiny2313 то хочется все поместить в нее.
Насчет системы уравнений это я лишнее, на Экселе графически просто решается. Ваша CTC енто переменная, тогда speed = CTC /96 lcd = (CTC +480) * 27 / 7776.
И всё. Массивы или Look-Up-Table (LUT) нужны когда нелинейная зависимость, и решить не получается или лень.
MagicianT, спасибо это именно то что я искал. Просто не знал как это можно реализовать. А не подскажете как подбирается это числа, чтобы получить целый результат? oleg110592, ну матричный способ мне кажется будет более затратный по размеру кода, по сравнению с одной формулой. Но тоже спасибо за помощь.
Какие числа? Результат определяется типом перемменых lcd и speed. Т.е. если lcd декларирована как int / uint8_t / uint16_t, то будет округление вниз. Если поточнее округлить надо, скажем 1.4 -> до 1, а 1.6 -> до 2, то там перед делением прибавьте половину делителя speed = ( CTC + 48 ) /96 lcd = ((CTC +480) * 27 + 3888) / 7776.
А вот это вообще зачем ? Это же номер (индекс) и есть, сделайте его от 0 до 27 (в обычной переменной) и доставайте из других массивов всякие хитрые числа, а на дисплей выводите индекс +8 если надо.
_________________ "Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл / "Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения