прошу помочь ускорить работу скетча программный шим 6 каналов
- Войдите на сайт для отправки комментариев
Втр, 14/01/2020 - 00:08
Добрый день!
Прошу помощи в ускорении работы для реализации программного шим для частотного регулятора.
Собрал плату на irams10up60b. Управление хочу выполнить на ардуино нано v3.
Нужно синус на 6 каналов для управления трехфазным двигателем. Скетч сделал, полностью рабочий, но скорость только до 100 герц. Помогите построить более быстрый программный шим.
#include <avr/io.h> #include <avr/interrupt.h> #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) byte prog_pwm=0; byte prog_prev=0; byte num=1; byte mnogitel=0; byte k=0; int steep1=32; int steep2=32; int steep3=32; int steep4=32; int steep5=32; int steep6=32; int sensorValue ; int flag_led_1=0; int readsens=0; int pinIn = A0; // Пин аналогового входа byte sin_1_h[36]={0 , 45, 88,128,164,196,221,240,252,255,252,240,221,196,164,128, 88, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte sin_2_h[36]={221,196,164,128, 88, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 88,128,164,196,221,240,252,255,252,240}; byte sin_3_h[36]={0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 88,128,164,196,221,240,252,255,252,240,221,196,164,128, 88, 45, 0, 0, 0, 0, 0, 0}; byte sin_1_l[36]={0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 88,128,164,196,221,240,252,255,252,240,221,196,164,128, 88, 45}; byte sin_2_l[36]={0 , 0, 0, 0, 0, 0, 0, 45, 88,128,164,196,221,240,252,255,252,240,221,196,164,128, 88, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte sin_3_l[36]={221,240,252,255,252,240,221,196,164,128, 88, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 88,128,164,196}; //byte sin_1_h[13]={ 0 ,127,221,255,221,127, 0 , 0 , 0 , 0 , 0 , 0 , 0 }; //byte sin_2_h[13]={ 221,127, 0, 0, 0 , 0 , 0 , 0 , 0 ,127,221,255,221}; //byte sin_3_h[13]={ 0 , 0, 0, 0, 0 ,127,221,255,221,127, 0 , 0 , 0 }; //byte sin_1_l[13]={ 0 , 0, 0, 0, 0 , 0 , 0 ,127,221,255,221,128, 0 }; //byte sin_2_l[13]={ 0 , 0, 0,127,221,255,221,127, 0 , 0 , 0 , 0 , 0 }; //byte sin_3_l[13]={ 221,255,221,127, 0 , 0 , 0 , 0 , 0 , 0, 0,127,221}; ISR (TIMER1_COMPA_vect ) { flag_led_1++; prog_pwm++; } void setup() { pinMode(pinIn, INPUT); ADCSRA |= (1 << ADPS1); //Биту ADPS2 присваиваем единицу - коэффициент деления 16 ADCSRA &= ~ ((1 << ADPS2) | (1 << ADPS0)); //Битам ADPS1 и ADPS0 присваиваем нули pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); cli(); // отключить глобальные прерывания TCCR1A = 0x00; TCCR1B = (0 << CS12)| (1 << CS11)|(0 << CS10)|(1 << WGM12); //предделитель clk/0, режим таймера СТС TCNT1 = 0x00; OCR1A =10; // максимальный предел счета TIMSK1 |= (1 << OCIE1A); // разрешение прерывания по совпадению sei(); } void loop() { if (prog_pwm>=32){prog_pwm=0;} if (flag_led_1>=1){flag_led_1=0;} steep1=(sin_1_h[num]/4)-prog_pwm-k;if (steep1> prog_pwm){PORTD |= 1<<2;}else{PORTD &= ~(1<<2);} steep2=(sin_2_h[num]/4)-prog_pwm-k;if (steep2> prog_pwm){PORTD |= 1<<3;}else{PORTD &= ~(1<<3);} steep3=(sin_3_h[num]/4)-prog_pwm-k;if (steep3> prog_pwm){PORTD |= 1<<4;}else{PORTD &= ~(1<<4);} steep4=(sin_1_l[num]/4)-prog_pwm-k;if (steep4> prog_pwm){PORTD |= 1<<5;}else{PORTD &= ~(1<<5);} steep5=(sin_2_l[num]/4)-prog_pwm-k;if (steep5> prog_pwm){PORTD |= 1<<6;}else{PORTD &= ~(1<<6);} steep6=(sin_3_l[num]/4)-prog_pwm-k;if (steep6> prog_pwm){PORTD |= 1<<7;}else{PORTD &= ~(1<<7);} mnogitel++; if ( mnogitel>=(9+sensorValue/8)){mnogitel=0;num++;if (num>=36){num=0;sensorValue=analogRead(pinIn);if (sensorValue>=500){k=sensorValue/16;}else{k=0;} } } }
А чем аппаратный (на таймерах) ШИМ не устраивает?
Может конечно я что и не непонял, но, первое - как на аврке сделать аппаратный синус через шим? Это непонятно вообще.
И второе, как??? сделать програмный шим??? И тем более, как его ускорить? Это вооще нипанятьчиго.
********** занавес ***********
Лично я делал синус-шим на авр таким способом: 0-м таймером генерим синхру (тобишь скорость). 1 и 2 таймеры по 8 бит в фасте оба. 0-м таймером "бегаем" по таблице синуса со сдвигом в 120гр. и "кормим" таймеры 1 и 2. Всё.
может я и ошибаюсь ноу ардуино нано всего три таймера на каждом по две ноги. Если использовать один для прерываний то остается 2 таймера, 4 канала шим, а нужно 6. на мегу я скется уже написал все отлично работает. Идея сделать дешевое устройство плавного пуска электродвигателя. 2 доллара ардуино нано, 4 доллара игбт модуль, и на 4 доллара деталей. Всего 10 долларов и насосная станция или другой асинхронный двигатель стартует плавно.
Дешевое устройство плавного пуска.
1.8 доллара блюпилл. Из коробки с одним первым таймером шестифазный генератор с дедтаймами и простой удобной регулировкой.
nik182, сюда постоянно приходют много людей, хотящих странного, и не слушающих ничьих советов. Им говорят, что железо надо подбирать под задачу, а оне всеми копытами упираются, мол, нет, у меня уже есть вот это, как бы мне теперь это поудобнее натянуть, как глаз на жопу.
Может конечно я что и не непонял, но, первое - как на аврке сделать аппаратный синус через шим? Это непонятно вообще.
Отвечаю: я не просил помочь сделать аппаратный синус. сам не пойму что это такое :)
И второе, как??? сделать програмный шим???
Ответ: сделать программный шим на ногах без поддержки аппаратного шим. Он уже реализован в скетче и работает например на PD 2,3,4,5,6,7 порту.
И тем более, как его ускорить? Это вооще нипанятьчиго. Согласен очепятался .Прошу помощи в ускорении работы скетча.
____________________________________________________________
Лично я делал синус-шим на авр таким способом: 0-м таймером генерим синхру (тобишь скорость). 1 и 2 таймеры по 8 бит в фасте оба. 0-м таймером "бегаем" по таблице синуса со сдвигом в 120гр. и "кормим" таймеры 1 и 2.
На меге я так и сделал там таймеров и ног с запасом. Но идея сделать дешевое устройство плавного пуска ценой до 10-12 долларов.
0 и 2 таймер на нане 8 бит. на каждом по две ноги = 4 канала шим. ШИМ: 3, 5, 6, и 11. поскольку таймером 1 мы бегаем по таблице синуса каналы 9, 10, не могут быть задействованы? или я ошибаюсь?
"бегаем" по таблице синуса со сдвигом в 120гр. В данном скетче я сделал шесть массивов, что бы в скетче не пересчитывать сдвиг, это занимает время.
не нужна регулировка. Это устройство плавного пуска.
Дедтайм реализован аппаратно в модуле игбт.
так ведь работает уже, почему не получится? могу видео работы снять. Прошу помощи в ускорении работы скетча а не неестественных задач.
Это предделитель /8
Для /1 (no prescaling) нужно выставлять CS10, а не CS11
не нужна регулировка это устройство плавного пуска, дедтайм реализован аппаратно в игбт модуле.
На меге я так и сделал там таймеров и ног с запасом. Но идея сделать дешевое устройство плавного пуска ценой до 10-12 долларов.
Слушайте, Мега стоит 480 руб, Нано - 180. Вы свое устройство собираетесь выпускать миллионными тиражами, что для вас так принципиальна разница в 300 рублей?
Если да - я вас разочарую, на Али есть готовые частотные модули за копейки
Плавный пуск делают на симисторах, а это уже частотный преобразователь.
За 10 долларов частотник не сделать, потому что в реальном мире против фантазии нужны защитные устройства, нужно охлаждение ключей, нужен не абы какой монтаж, нужно вложить много времени, и так далее.
я пробовал менять предделитель, но форма сигнала искажается видимо потому, что прерывание наступает слишком часто , несколько раз пока идет скетч.
Поэтому прошу посмотреть void loop, что можно ускорить, оптимизировать, упростить.
Плавный пуск делают на симисторах, а это уже частотный преобразователь.
За 10 долларов частотник не сделать, потому что в реальном мире против фантазии нужны защитные устройства, нужно охлаждение ключей, нужен не абы какой монтаж, нужно вложить много времени, и так далее.
1 почему на симисторах, это кто так решил?
2 вот вам частотник за 10 баксов: https://youtu.be/He5ISCiuVcw
не заметил модулей на али за копейки, киньте пожалуйста ссылку в личку. Буду очень благодарен.
Прошу Вас о помощи, увеличить скорость работы скетча, а именно цикла void loop
как его можно оптимизировать, ускорить, упростить?
Прошу тапками не кидать, все уже реализовано, все работает, хочется ускорить работу.
а схема и полный скетч будет публиковаться?
Только сейчас понял вы предлагаете сменить контроллер. В принципе так и думал сделать, даже купил, но пока только разбираюсь в самых основах программирования stm.
это полный скетч.
вот схема, по ней все собрано, она простейшая. контроль температуры не реализован, en подтянуто к +5 В через 1 кОм резистор.
http://circuits.datasheetdir.com/200/IRAMS10UP60B-circuits.jpg
1. Решили инженеры, которые гораздо умнее нас с вами, и отвечают за свою деятельность финансово.
2. Монтаж 380 на макетке - бомба замедленного действия. Моторы без нагрузки не испытывают.
Все в принципе все получилось ветку можно закрывать.
Устройство плавного пуска собрано, шим работает на частоте где-то 5 кГц. Что хорошо сказывается на модуле, он вообще холодный.
Решением проблемы стало: для ускорения работы скетча уменьшил таблицу синуса до 24 значений. для совсем ленивых могу выложить.
Соответственно скорость работы увеличилась в ущерб форме синуса.
Схема указана выше, будут вопросы спрашивайте.
Есть скетч под мегу могу выложить, если нужно.
daniilguz, позволил себе отформатировать ваш код, а глаза сломать можно.
А теперь посмотрите внимательнее - вы точно не ошиблись? Переход к новой точке синуса num++ действительно должен происходить только внутри условия строки 115 ? -
Это-ж макет? а на чем делают макеты?
Проверил с нагрузкой на насосной станции все работает.
1. Решили инженеры, которые гораздо умнее нас с вами, и отвечают за свою деятельность финансово.
Отвечаю: Плавный пуск можно реализовывать каким угодно способом, в том числе и тиристорами, почему нельзя игбт модулем это сделать если стоимость низкая?
https://eleksun.com.ua/ustroystvo-plavnogo-puska-serii-altistart-01-in3-moshchnost-odnofaznyy-220vtrehfaznyy-380v-03711-kvt
Вот покупайте у этих инженеров сами за 120 баксов.
Все в принципе все получилось ветку можно закрывать.
Устройство плавного пуска собрано, шим работает на частоте где-то 5 кГц
Решением проблемы стало: для ускорения работы скетча уменьшил таблицу синуса до 24 значений
Да ну? - уменьшил таблицу с 36 до 24 значиний - и частота ШИМ сразу выросла со 100 Гц до 5 КГц?
А можете свой код немного пояснить?
1. Зачем, например, на каждом шаге каждое значение таблицы синусов делить на 4? - может стоило сразу в таблицу положить уже поделенные значения? - сэкономили бы 6 делений на каждом шаге - а деление в АВР очень медленное...
2. Что такое к?
(update - один вопрос убрал, вроде сам разобрался)
Простите я не понимаю сути вопроса.
В строке 115 уменьшать статический коэффициент 9?
Вообще конструктивно сейчас все обдумаю.
Простите я не понимаю сути вопроса.
В строке 115 уменьшать статический коэффициент 9?
вопрос снимается. Постепенно разбираюсь, скетч очень не наглядно написан. имена переменных неинформативные... "Множитель" - на самом деле совсем не множитель, а шаг ШИМ, верно?
и еще совет - число точек и ШИМ и синуса лучше выбрать степенью двойки - тогда переход через ноль можно будет делать одной битовой операцией. избавившись от проверки условия на каждом шаге
в таблице синуса делю на 4 потому, что эта талица синуса у меня осталась из скетча меги. переделывать было лень, не знал что деление долго идет. исправлю таблицу.
в таблице синуса делю на 4 потому, что эта талица синуса у меня осталась из скетча меги. переделывать было лень, не знал что деление долго идет. исправлю таблицу.
выложи плс исправленный скетч...
не знал что деление долго идет. исправлю таблицу.
Какая разница, долго оно идет или нет? - У вас скорость всего кода, насколько я понял - определяется именно временем вычисления в цикле ЛУП - а значит именно здесь надо оптимизировать каждую букву. А вы вместо этого зачем-то шесть раз делите то, что можно было бы поделить заранее.
При такой архитектуре все содержимое лупа нужно переносить в обработчик прерывания или прямо в лупе ждать таймер при полном запрете всех прерываний. Я бы выбрал второе, т.к. не было бы издержек на вход/выход в прерывания. Действительно ли steep1-steep6 ли должны быть инт? Однобайтовые переменные быстрей посчитает. analogRead - медленный, заменить на прямую работу с АЦП. Шесть массивов с пошти одинаковыми данными - плохо. Быстрей один массив со смещением с учетом #28. Деление исправляйте конечно.
очень не наглядно написан. так точно
выкладываю две осцилограммы полученного программного шим и синуса.
https://photos.app.goo.gl/WXfSzNEsXLoBQjoLA
https://photos.app.goo.gl/mV4XQxtMzG4b2RiZ8
в таблице синуса делю на 4 потому, что эта талица синуса у меня осталась из скетча меги. переделывать было лень, не знал что деление долго идет. исправлю таблицу.
Деление на 4 идет быстро, потому что это просто сдвиг влево на 2 разряда, но да, зачем дополнительные операции. Еще
prog_pwm - k вычисляется 6 раз. По идее компилятор при оптимизации должен это учесть, но нужно посмотреть получившийся ассемблерный код. Может стоит его вычислить один раз
Вместо того, что бы 6 раз дергать РОRTD (а это на самом деле несколько операций) быстрее будет собрать все нужные биты в одну переменную а потом записать ее в PORTD
Ну и самое медленное это analogRead правда он вызывается не часто, но тем не менее его можно запускать в фоне
А в чем глубокий смысл манипулирования flag_led_1 если он все равно нигде не используется?
Деление на 4 идет быстро, потому что это просто сдвиг влево на 2 разряда
Но только у проца нет такой команды. Есть только на 1 разряд, поэтому повторяет 2 раза, а если надо на 3-6 разрядов то воще цикл.
Вместо того, что бы 6 раз дергать РОRTD (а это на самом деле несколько операций) быстрее будет собрать все нужные биты в одну переменную а потом записать ее в PORTD
Не. Не поможет. Что сбор в переменную будет тоже что и в порт сразу.
Если определить моменты переключения вывода, то можно через PINx выход тогглить - минус несколько операций.
Блин всем вам большое спасибо... я очень благодарен Вам. буду оптимизировать.
analogread ускорена - строка 47, 48.
steep1 заменю на byte
массив поделю сразу.
____________________
Вместо того, что бы 6 раз дергать РОRTD (а это на самом деле несколько операций) быстрее будет собрать все нужные биты в одну переменную а потом записать ее в PORTD
вот это не пойму как сделать, тоже об этом думал
_____________________
осцилограммы выложил
Не. Не поможет. Что сбор в переменную будет тоже что и в порт сразу.
А вот нефига. Спорим на 1000р?
Что сбор в переменную будет тоже что и в порт сразу.
А вот нефига. Спорим на 1000р?
вопрос интересный, хорошо б кто-нить проверил. Склоняюсь к мнению Логика - потому как при сборе в переменную будут ровно те же операции. как и в порт - не вижу. на чем собираетесь выиграть
analogread ускорена - строка 47, 48.
analogread запускает преобразование и ждет пока оно закончится. А можно запустить преобразование и продолжить выполнение основной программы. А как оно закончится - считать результат
при сборе в переменную будут ровно те же операции. как и в порт - не вижу. на чем собираетесь выиграть
Видимо на чтении из порта.
вопрос интересный, хорошо б кто-нить проверил. Склоняюсь к мнению Логика - потому как при сборе в переменную будут ровно те же операции. как и в порт - не вижу. на чем собираетесь выиграть
Ну можно посмотреть по ассемблерному коду, а можно замерять время выполнения. Ну что подключаешься к спору? Будет у меня 2000р
Ну что подключаешься к спору? Будет у меня 2000р
не-а, я люблю выигрывать :)
0. У Вас в программе есть ошибка - корректирующий член prog_pwm увеличивается в одном месте (в прерывании), прокручивается в другом (начале цикла), а используется в третьем (теле цикла). Если прерывание произойдет в теле цикла, то оставшиеся ШИМы отработают с значением 33, что явно не планировалось.
Теперь о быстродействии - Вы в теле цикла делаете много ненужной работы.
1. Прокручивание prog_pwm и
flag_led_1 (кстати, а зачем он)
следует убрать из цикла в прерывание.2. В таблице сразу разместить синусы / 4
3. Изменить условие ШИМ - вместо
steep1=sin_1_h[num]-prog_pwm-k; if (steep1> prog_pwm) ...
сделать
border=2*-prog_pwm+k;
....
steep1=sin_1_h[num]; if (steep1> border) ...
4. Вместо / 8 лучше явно писать >> 3.
5. Следует быть уверенным, что операция сброса и установки бита выполняется за такт, иначе лучше воспользоваться советом из предыдущего коммента о группировке битов.
7. Вместо индекса лучше использовать указатель
8. Если массив реорганизовать по 6 байт одного отсчета рядом, то с указателем будет совсем быстро.
короче мне еще работать и работать над кодом, спасибо всем, на неделю разбираться.
и еще совет - число точек и ШИМ и синуса лучше выбрать степенью двойки - тогда переход через ноль можно будет делать одной битовой операцией. избавившись от проверки условия на каждом шаге
____________________________________
вот это не понял.
analogread ускорена - строка 47, 48.
analogread запускает преобразование и ждет пока оно закончится. А можно запустить преобразование и продолжить выполнение основной программы. А как оно закончится - считать результат
я новичок, суть я понял а как сделать не знаю.
Это предделитель /8
Для /1 (no prescaling) нужно выставлять CS10, а не CS11
я в курсе, но тогда пока один раз проходит луп 8 раз срабатывает прерывание.
я новичок, суть я понял а как сделать не знаю.
Если ты новичок, какого ж хрена сразу за частотник схватился?