Управление выходной частотой 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);}
@Fitrah Hidayat, 👍0
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, прежде чем использовать его в расчетах.
- Как разделить входящую строку?
- Как использовать SPI на Arduino?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Arduino Due vs Mega 2560
- Как получить уникальный идентификатор для всех плат Arduino?
- Почему я получаю avrdude: stk500v2_ReceiveMessage(): timeout error when uploading to Arduino Mega?
- Тайм-аут связи Arduino Mega с ошибкой программатора
Хорошо.. попробую. Но не могли бы вы сказать мне, почему я должен умножать значение на коэффициент от 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