Управление выходной частотой 3-фазного инвертора SPWM

Сейчас я работаю над проектом трехфазного инвертора SPWM, и я получил этот код из этого статья . Он отлично работает на симуляции. Но проблема в том, что я не могу сделать выходную частоту переменной. Я намерен изменять частоту в диапазоне от 0 до 100 Гц и использовать ее для управления скоростью трехфазного асинхронного двигателя. Кто-нибудь может мне помочь, пожалуйста? Любой совет или, может быть, у вас есть код, который отлично работает для управления частотой инвертора spwm. Вот код 3-фазного инвертора spwm. О, кстати, я использую Arduino Mega.

            int i=0;
            int j=0;
            int k=0;
            int x=0;
            int y=0;
            int z=0;
            int OK=0;
            int OK1=0;
            int OK2=0
            int OK3=0;
            int OK4=0;
            int sinPWM[]={1,2,5,7,10,12,15,17,19,22,24,27,30,32,34,37,39,42,
            44,47,49,52,54,57,59,61,64,66,69,71,73,76,78,80,83,85,88,90,92,94,97,99,
            101,103,106,108,110,113,115,117,119,121,124,126,128,130,132,134,136,138,140,142,144,146,
            148,150,152,154,156,158,160,162,164,166,168,169,171,173,175,177,178,180,182,184,185,187,188,190,192,193,
            195,196,198,199,201,202,204,205,207,208,209,211,212,213,215,216,217,219,220,221,222,223,224,225,226,227,
            228,229,230,231,232,233,234,235,236,237,237,238,239,240,240,241,242,242,243,243,244,244,245,245,246,246,
            247,247,247,248,248,248,248,249,249,249,249,249,255,255,255,255,249,249,249,249,249,248,
            248,248,248,247,247,247,246,246,245,245,244,244,243,243,242,242,241,240,240,239,238,237,237,236,235,234,
            233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,217,216,215,213,212,211,209,208,207,205,204,
            202,201,199,198,196,195,193,192,190,188,187,185,184,182,180,178,177,175,173,171,169,168,166,164,162,160,
            158,156,154,152,150,148,146,144,142,140,138,136,134,132,130,128,126,124,121,119,117,115,113,110,108,106,
            103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,66,64,61,59,57,54,52,49,47,44,42,39,37,34,32,30,
            27,24,22,19,17,15,12,10,7,5,2,1};

            int potinput = A1;
            int potfreq = A2;
            float potinputval;
            float potfreqval;
            float A;
            float F;

            void setup() {
            Serial.begin(9600);

            pinMode(4, OUTPUT);
            pinMode(13,OUTPUT);
            pinMode(9,OUTPUT);
            pinMode(10,OUTPUT);
            pinMode(2,OUTPUT);
            pinMode(5,OUTPUT);

            cli();// остановить прерывания
            TCCR0A=0;//сброс значения
            TCCR0B=0;//сброс значения
            TCNT0=0;//сброс значения
            //0b позволяет мне записывать биты в двоичном формате
            TCCR0A=0b10100001;//корректировка фазы ШИМ
            TCCR0B=0b00000001; // без предделителя



            TCCR2A=0;//сброс значения
            TCCR2B=0;//сброс значения
            TCNT2=0;//сброс значения
            //0b позволяет мне записывать биты в двоичном формате
            TCCR2A=0b10100001;//корректировка фазы ШИМ
            TCCR2B=0b00000001; // без предделителя

            TCCR3A=0;//сброс значения
            TCCR3B=0;//сброс значения
            TCNT3=0;//сброс значения
            //0b позволяет мне записывать биты в двоичном формате
            TCCR3A=0b10100001;//корректировка фазы в режиме ШИМ
            TCCR3B=0b00000001; // без предделителя
            TCCR1A=0;//сброс значения
            TCCR1B=0;//сброс значения
            TCNT1=0;//сброс значения
            OCR1A=509;// сравнить значение совпадения
            TCCR1B=0b00001001; //Бит WGM12 равен 1 для режима CTC и без предделителя

            TIMSK1 |=(1 << OCIE1A);// разрешить прерывания

            sei();//останавливаем прерывания
            }
            ISR(TIMER1_COMPA_vect){// прерывание, когда таймер 1 совпадает со значением OCR1A
            if(i>313 && OK==0){// конечное значение из вектора для контакта 13
            i=0;// переходим к первому значению вектора
            OK=1;//включаем контакт 4
            }
            if(i>313 && OK==1){// конечное значение из вектора для контакта 4
            i=0;//переходим к первому значению вектора
            OK=0;//включаем пин 13
            }
            x = round(A*sinPWM[i]); // x берет значение из вектора, соответствующего позиции i (i нулевой индекс)
            i=i+1;// переходим к следующей позиции
            if(OK==0){
            OCR0B=0;//сделать вывод 4 0
            OCR0A=x;//включаем вывод 13 в соответствующий рабочий цикл
            }
            if(OK==1){
            OCR0A=0;//сделать вывод 13 0
            OCR0B=x;// включаем вывод 4 в соответствующий рабочий цикл
            }

            if ((i==209) || OK1==1){//если i равно 209, включить второй сигнал
            OK1=1;//сохраняем, если функция
            if(j>313 && OK2==0){// конечное значение из вектора для контакта 10
            j=0;// переходим к первому значению вектора
            OK2=1;//включить контакт 9
            }
            if(j>313 && OK2==1){// конечное значение из вектора для контакта 9
            j=0;//переходим к первому значению вектора
            OK2=0;//включить контакт 10
            }
            y = round(A*sinPWM[j]);// y берет значение из вектора, соответствующего позиции j (j нулевой индекс)
            j=j+1;// переходим к следующей позиции
            if(OK2==0){
            OCR2B=0;//сделать вывод 9 0
            OCR2A=y;//включаем вывод 10 в соответствующий рабочий цикл
            }
            if(OK2==1){
            OCR2A=0;//сделать вывод 10 0
            OCR2B=y;//включаем вывод 9 в соответствующий рабочий цикл
            }
            }
            if ((j==209) || OK3==1){//если j равно 209, включить третий сигнал
            OK3=1;//сохраняем, если функция
            if(k>313 && OK4==0){// окончательное значение из вектора для контакта 5
            k=0;// переходим к первому значению вектора
            OK4=1;//включить контакт 2
            }
            if(k>313 && OK4==1){// конечное значение из вектора для контакта 2
            k=0;//переходим к первому значению вектора
            OK4=0;//включить контакт 5
            }
            z=round(A*sinPWM[k]);// z берет значение из вектора, соответствующего позиции k (k имеет нулевой индекс)
            k=k+1;// переходим к следующей позиции
            if(OK4==0){
            OCR3B=0;//сделать вывод 2 0
            OCR3A=z;// включаем вывод 5 в соответствующий рабочий цикл
            }
            if(OK4==1){
            OCR3A=0;//сделать вывод 5 0
            OCR3B=z;// включаем вывод 2 в соответствующий рабочий цикл
        }
        }
        }
        void loop() {

          potinputval = analogRead(potinput);
          A = potinputval/1023;       

          potfreqval = analogRead(potfreq);
          F = map(potfreqval,1023,0,0,50);}

, 👍0


1 ответ


Лучший ответ:

1

В этом скетче значения ШИМ, соответствующие выбранной синусоиде, хранятся в целочисленном массиве sinPWM[]. Значения из sinPWM (1–255) используются без изменений (через промежуточные переменные x, y и z) для установки различных регистров синхронизации (OCR0A/B, OCR2A/B и OCR3A/B), которые управляют широтно-импульсной модуляцией. Таким образом, амплитуда (амплитуды) генерируемой синусоидальной волны (волн) будет постоянной.

Если вы хотите контролировать скорость двигателя, вы должны умножить значения из sinPWM на коэффициент от 0 до 1. Наиболее логично сделать это, когда значения из sinPWM передаются в промежуточные переменные x, у и я. Пример: x=округление(0,8 * sinPWM[i]). Коэффициент 0,8 в этом примере вы, конечно, можете заменить переменной, значение которой получается из AnalogRead() вывода, подключенного к потенциометру или какому-либо датчику. Но не забудьте преобразовать его в значение в диапазоне от 0 до 1, прежде чем использовать его в расчетах.

,

Хорошо.. попробую. Но не могли бы вы сказать мне, почему я должен умножать значение на коэффициент от 0 до 1, пожалуйста?, @Fitrah Hidayat

Вы питаете двигатель тремя синусоидами с взаимной разницей фаз 120 градусов. Амплитуда синусоиды (= половина верхнего значения) определяет скорость двигателя. Я говорю это с некоторой оговоркой, потому что существует множество различных типов электродвигателей. Я предполагаю, что вы используете трехфазный двигатель с короткозамкнутым ротором., @PimV

Спасибо за ваш ответ. Итак, я попробовал формулу, которую вы упомянули выше, сначала без потенциометра (я умножил sinPWM на значение от 0 до 1), и она влияет на значения рабочего цикла. Но когда я подключил потенциометр и улучшил код, это не сработало. Я думаю, что что-то не так с моей формулой аналогового преобразования. Не могли бы вы взглянуть на мой код выше, пожалуйста?, @Fitrah Hidayat

Я постараюсь. Но не могли бы вы сначала рассказать мне подробности о двигателе, который вы используете (есть ли у вас техническое описание или номер производителя и номер детали)?, @PimV

У меня только эти 2 фото. Взгляни, пожалуйста. [Image1](https://drive.google.com/file/d/1Son3hdQbn8HtUav8BKTaY-q71HG5jRrQ/view) [Image2](https://drive.google.com/file/d/1nb-gbeT26wmT9j052lXRBZ-ZfzZIxmJC/view), @Fitrah Hidayat

Спасибо за фотографии. Какая цепь у вас есть между Arduino и двигателем?, @PimV

У меня есть 6 драйверов затворов с выходом 13-14 вольт (я сделал свой собственный драйвер затвора с микросхемой hcpl-3120). Затем у меня есть мост MOSFET с 6 полевыми МОП-транзисторами Irfp460. У меня еще не было фильтра, потому что я думаю сначала контролировать SPWM. И трудно найти ссылки на 3-фазный фильтр нижних частот., @Fitrah Hidayat

Спасибо за информацию. Действительно, вы ошиблись с кодом для обработки значения потенциометра. Во-первых, вам не нужно устанавливать pinMode для этого вывода (дальнейшего влияния это не имеет). Во-вторых, переменная A должна быть числом с плавающей запятой (а не целым числом, потому что целое число не может содержать дроби). Чтобы избежать целочисленного деления и не допустить, чтобы A имело недопустимое промежуточное значение (прерывание может произойти в любой момент вычисления), также сделайте число с плавающей точкой potinputval и выполните вычисление следующим образом: potinputval = AnalogRead(potinput); potinputval = potinputval / 1023; А = потенциометр;, @PimV

Но мой (первоначальный) ответ неверен. У меня сложилось впечатление, что вы использовали небольшой двигатель (например, игрушечный двигатель) аналоговым способом, подключенным к Arduino., @PimV

Я не специалист по моторам. Но судя по табличке на двигателе, он выглядит как трехфазный асинхронный двигатель переменного тока с короткозамкнутым ротором. Если это правильно, двигатель должен иметь 6 электрических точек подключения, некоторые из которых соединены с другими (с помощью металлической «перемычки»). Электродвигатель может быть электрически подключен по схеме «звезда» или «треугольник» (погуглите по этим условиям, если это для вас ново)., @PimV

Скорость вращения этих двигателей зависит от частоты (электрических) фаз. Итак, если вы хотите изменить скорость двигателя, вы должны изменить частоту генерируемых синусоидальных волн. Скорее всего, это связано с другими настройками различных таймеров. Мне потребовалось бы слишком много времени, чтобы понять, как это сделать. Может быть, кто-то еще из Stack Overlow может помочь, или, может быть, парень, управляющий сайтом, был вашим партнером., @PimV

Но когда я ищу метод управления трехфазным асинхронным двигателем. Я обнаружил, что изменение напряжения питания влияет на скорость двигателя. Я думаю, это может быть работой. А вы знаете, как инвертировать массив или как инвертировать ШИМ? Приведенный выше код обеспечивает вывод 6 spwm. Если я соединю 2 выхода вместе, один из них должен быть инвертирован. Поэтому мне нужно 3 обычных выхода и 3 инвертированных выхода. Вы знаете, как это сделать?, @Fitrah Hidayat

Я почти уверен, что вы не можете контролировать скорость этого двигателя, изменяя напряжение питания. Но вы можете попробовать это простым способом: напряжение питания для двигателя подается через ваш драйвер двигателя (H-мост), поэтому его относительно легко изменить. Статья, на которую вы ссылаетесь в 1-й строке вашего вопроса, описывает, как создать положительную и «отрицательную» половины трех фаз. Поскольку Arduino не может генерировать отрицательные сигналы, «отрицательные» половины фаз являются положительными. Инверсия должна выполняться отдельной схемой (которая может быть интегрирована в схему драйвера двигателя)., @PimV

Привет, PimV, ты был прав, мне нужно изменить выходную частоту инвертора. Дело в том, что я не нашел никакого способа контролировать это. Не могли бы вы помочь мне еще раз? Или не могли бы вы дать мне несколько советов или что-то в этом роде, пожалуйста? Заранее спасибо., @Fitrah Hidayat