Последний код надо серьёзно тестить без силовой. Запускается с разгоном нормально, во время работы убавил частоту переменником и нажимал кнопку - появился высокий уровень на нескольких пинах, а это взрыв силовой сразу. По осциллографу смотрел без подключения силовой. andryn, проверьте у себя на осциле динамическую регулировку частоты и нажатие кнопки в разных комбинациях.
Последний код надо серьёзно тестить без силовой. Запускается с разгоном нормально, во время работы убавил частоту переменником и нажимал кнопку - появился высокий уровень на нескольких пинах, а это взрыв силовой сразу. По осциллографу смотрел без подключения силовой. andryn, проверьте у себя на осциле динамическую регулировку частоты и нажатие кнопки в разных комбинациях.
Да, был такой косячек. При остановке не останавливались ШИМ, поэтому при нажатии на кнопу для остановки могла оставться генерация на ключах из разных фаз. Сейчас это убрал. Под нагрузкой из мотора винчестера проверил, мотор крутится, но работает кривовато, больше 70Гц не раскручивается. Еще мне не нравится механизм плавного увеличения частоты по 1Гц, наверно переделаю.
Изменения такие:
@@ -314,6 +324,13 @@
Serial.print("Button press");
if ((run & B00000010)) { //Надо остановить
TIMSK2 &= ~(1<<TOIE2); //остановка таймера
+ //Установить все PWM в 0
+ OCR0A = 0;
+ OCR0B = 0;
+ OCR1A = 0;
+ OCR1B = 0;
+ OCR2A = 0;
+ OCR2B = 0;
//Вывод на экран F + частота
disp.display(0,15);
disp.display(1,(dfreq_set%1000)/100);
Для всех интересующихся темой: провел небольшие испытания в железе.
Описание стенда: Arduino Uno, Переменный резистор 10К(подключен к A0), Кнопка без фиксации(подключена к А1), дисплей 1602 с I2C(подключен к A4, A5), силовая часть на ir2101+2SK3569, моторчик от FDD 3''(обмотки соединены звездой). Питание драйверов 12В, питание мотора тоже 12В, питание arduino 5В.
Основной результат испытаний: работает. Покрутил моторчик частотами от 10 до 200Гц - работает стабильно.
Есть некоторые особенности, которе не проявляется на эмуляторах:
После запуска таймера с генерацией нельзя ничего перерисовать на дисплее, для этого нужно таймер остановить, перерисовать, потом таймер запустить. Это плохо сказывается на работе мотора. Может это особенность работы LiquidCrystal_I2C, но пока разбираться неохота.
Частота увеличивается по +5Гц примерно 2 раза в секунду, т.е. 50Гц набирает где-то за 5 секунд.
Кнопка старт/стоп работает. Если покрутить резистор в процессе работы мотора, то генерация останавливается принудительно.
Свежий код:
/* Main.ino
*
* Created: AVS, 2018-06-06
* Processor: Arduino Uno
* Compiler: Arduino AVR
*/
#include "TM1637.h"
#include "LiquidCrystal_I2C.h"
const byte PROGMEM sineP4[] = { //Константа для первой четверти синуса. 256 значений.
//Для реализации Dead Time при переключении с Hight pin на Low pin добавим несколько нулевых значений.
//Для частоты 125Гц значений должно быть 2, т.к. описана 1/4 периода. Сделаем 3 значения, этого точно хватит :)
0,0,
0,2,3,5,6,8,9,11,13,14,16,17,19,20,22,24,25,27,28,30,31,33,34,36,38,39,41,42,44,45,47,48,50,51,53,55,56,58,59,61,62,64,65,67,68,70,71,73,74,76,77,79,80,82,83,85,86,88,89,91,92,94,95,96,
98,99,101,102,104,105,107,108,109,111,112,114,115,116,118,119,121,122,123,125,126,128,129,130,132,133,134,136,137,138,140,141,142,143,145,146,147,149,150,151,152,154,155,156,157,159,160,161,162,164,165,166,167,168,169,171,172,173,174,175,176,178,179,180,
181,182,183,184,185,186,187,188,190,191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,206,207,208,209,210,211,212,213,213,214,215,216,217,218,218,219,220,221,222,222,223,224,225,225,226,227,228,228,229,230,230,231,232,232,233,234,234,235,235,
236,237,237,238,238,239,239,240,241,241,242,242,243,243,243,244,244,245,245,246,246,247,247,247,248,248,248,249,249,249,250,250,250,251,251,251,251,252,252,252,252,253,253,253,253,253,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255
};
// const double refclk=31372.549; // =16MHz / 510
const unsigned int refclk = 31374; // Реальная внутренняя частота
volatile unsigned long phaccu; // аккумулирующая переменная, 32 бит
volatile unsigned long delta; // переменная, расчитывающаяся на основе refclk и желаемой частоты работы
volatile unsigned int incr; // переменная для вычисления итерации(10 бит = 2 бит + 8 бит)
volatile byte dfreq; //Текущая Частота, Гц
volatile byte dfreq_set; //Установленная частота, Гц
byte inctmr; // переменная для реализации таймера в loop
//Управление частотой
const int deltafreq=10; // deltafreq пунктов изменения аналогового входа дают изменение частоты на 2Гц. Если deltafreq=20, то изменение до 110Гц
unsigned int setfreq=1024+deltafreq; // переменная для хранения предыдущего измерения заначения пина. По умолчанию гарантированно больше 1023 на deltafreq.
//******************************************************************
//Для регулировки частоты переменным резистором
#define ADJ_PIN A0 // Пин, к которому подключен переменный резистор, регулирующий частоту
int adj; // переменная для чтения значения с переменного резистора
//*******************************************************************
//Кнопка старт/стоп
#define BTN_START_PIN A1 // Пин, к которому подключена кнопка старта
byte run = B00000000; //младший бит(B00000001) - нажата ли кнопка, старший(B00000010) на до ли запускать
//******************************************************************
//Индикатор TM1637
#define CLK 8
#define DIO 7
TM1637 disp(CLK, DIO);
//******************************************************************
//Дисплей LiquidCrystal_I2C
LiquidCrystal_I2C lcd(0x27,16,2); // Задаем адрес и размерность дисплея.
//******************************************************************
// Настройка таймеров
void Setup_timer() {
// TIMER0
TCCR0A |= (1<<COM0A1); // COM0A1, COM0A0: 1 0 - None-inverted mode для OC0A, для инверсного режима ШИМ нужно 1 1
TCCR0A &= ~(1<<COM0A0);
TCCR0A |= (1<<COM0B1); // COM0B1, COM0B0: 1 0 - None-inverted mode для OC0B, для инверсного режима ШИМ нужно 1 1
TCCR0A &= ~(1<<COM0B0);
TCCR0A |= (0<<WGM01); // WGM02, WGM01, WGM00: 0 1 1 - Fast PWM
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<CS02); // CS02, CS01, CS00: 0 0 1 - тактовый генератор CLK
TCCR0B &= ~(1<<CS01);
TCCR0B |= (1<<CS00);
TCCR0B &= ~(1<<WGM02);
// TIMER1
TCCR1A |= (1<<COM1A1); // COM1A1, COM1A0: 1 0 - None-inverted mode для OC1A, для инверсного режима ШИМ нужно 1 1
TCCR1A &= ~(1<<COM1A0);
TCCR1A |= (1<<COM1B1); // COM1B1, COM1B0: 1 0 - None-inverted mode для OC1B, для инверсного режима ШИМ нужно 1 1
TCCR1A &= ~(1<<COM1B0);
TCCR1A &= ~(0<<WGM11); // WGM13, WGM12, WGM11, WGM10: 0 1 0 1 - Fast PWM, 8bit
TCCR1A |= (1<<WGM10);
TCCR1B &= ~(1<<CS12); // CS12, CS11, CS10: 0 0 1 - тактовый генератор CLK
TCCR1B &= ~(1<<CS11);
TCCR1B |= (1<<CS10);
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12);
// TIMER2
TCCR2A |= (1<<COM2A1); // COM2A1, COM2A0: 1 0 - None-inverted mode для OC2A, для инверсного режима ШИМ нужно 1 1
TCCR2A &= ~(1<<COM2A0);
TCCR2A |= (1<<COM2B1); // COM2B1, COM2B0: 1 0 - None-inverted mode для OC2B, для инверсного режима ШИМ нужно 1 1
TCCR2A &= ~(1<<COM2B0);
TCCR2A |= (1<<WGM21); // WGM22, WGM21, WGM20: 0 1 1 - Fast PWM
TCCR2A |= (1<<WGM20);
TCCR2B &= ~(1<<CS22); // CS22, CS21, CS20: 0 0 1 - тактовый генератор CLK
TCCR2B &= ~(1<<CS21);
TCCR2B |= (1<<CS20);
TCCR2B &= ~(1<<WGM22);
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Разрешить/запретить прерывания по таймерам
TIMSK0 &= ~(1<<TOIE0); //Запретить прерывания на таймер 0
TIMSK1 &= ~(1<<TOIE1); //Запретить прерывания на таймер 1
TIMSK2 &= ~(1<<TOIE2); //Запретить прерывания на таймер 2
}
//******************************************************************
//Прерывание по таймеру 2 (TIMER2)
//Работает с частотой
ISR(TIMER2_OVF_vect) {
PIND |= (1 << 2); //Для замера скорости
//Таймер 0 | выводы 5 и 6 | OC0B, OC0A
//Таймер 1 | выводы 9 и 10 | OC1A, OC1B
//Таймер 2 | выводы 3 и 11 | OC2B, OC2A
//Для теста
//ШИМ 0, pins 6, 5
//OCR0A = 128;
//OCR0B = 128;
//ШИМ 1, pins 9, 10
//OCR1A = 128;
//OCR1B = 128;
//ШИМ 2, pins 11, 3
//OCR2A = 128;
//OCR2B = 128;
phaccu = phaccu + delta; // Добавляем дельту(рассчитна по частоте) в аккумулирующую переменную 32 бит
//Фаза 1
incr = (phaccu >> 22); //10 бит. Старщие 2 бита(incr & 0x300) - номер четверти, младшие 8 бит(incr & 0xFF) - номер значения из таблицы констант
switch (incr & 0x300) { //B1100000000=0x300
case 0x0: //Первая четверть, выбрать константу из массива в пин A.
{
OCR0B = 0;
OCR0A = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x100: //Вторая четверть, выбрать обратнную константу из массива в пин A
{
OCR0B = 0;
OCR0A = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
case 0x200: //Третья четверть, выбрать константу из массива в пин B
{
OCR0A = 0;
OCR0B = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x300: //Четвертая четверть, выбрать обратнную константу из массива в пин B
{
OCR0A = 0;
OCR0B = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
default:
{
OCR0A = 0;
OCR0B = 0;
break;
}
}
//Фаза 2. Смещена относительно фазы 1 на 120. 1/2*Pi = 512; 120 = 2/3*Pi = 512*4/3 = 683. Сдвинем фазу на 683 деления
incr = incr + 683;
//Уберем биты выще 10го B001111111111=0x3FF, чтобы попасть в массив констант
incr &= 0x3FF;
switch (incr & 0x300) { //B1100000000=0x300
case 0x0: //Первая четверть, выбрать константу из массива в пин A.
{
OCR1B = 0;
OCR1A = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x100: //Вторая четверть, выбрать обратнную константу из массива в пин A
{
OCR1B = 0;
OCR1A = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
case 0x200: //Третья четверть, выбрать константу из массива в пин B
{
OCR1A = 0;
OCR1B = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x300: //Четвертая четверть, выбрать обратнную константу из массива в пин B
{
OCR1A = 0;
OCR1B = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
default:
{
OCR1A = 0;
OCR1B = 0;
break;
}
}
//Фаза 3. Смещена относительно фазы 2 на 120. 1/2*Pi = 512; 120 = 2/3*Pi = 512*4/3 = 683. Сдвинем фазу на 683 деления
incr = incr + 683;
//Уберем биты выще 10го B001111111111=0x3FF, чтобы попасть в массив констант
incr &= 0x3FF;
switch (incr & 0x300) { //B1100000000=0x300
case 0x0: //Первая четверть, выбрать константу из массива в пин A.
{
OCR2B = 0;
OCR2A = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x100: //Вторая четверть, выбрать обратнную константу из массива в пин A
{
OCR2B = 0;
OCR2A = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
case 0x200: //Третья четверть, выбрать константу из массива в пин B
{
OCR2A = 0;
OCR2B = pgm_read_byte_near(sineP4 + (incr & 0xFF));
break;
}
case 0x300: //Четвертая четверть, выбрать обратнную константу из массива в пин B
{
OCR2A = 0;
OCR2B = pgm_read_byte_near(sineP4 + 255 - (incr & 0xFF));
break;
}
default:
{
OCR2A = 0;
OCR2B = 0;
break;
}
}
}
void setup()
{
Serial.begin(115200); // connect to the serial port
Serial.println("Test begin");
DDRD = 0xFC; // весь порт D - выход, кроме RX TX
DDRB = 0xFF; // весь порт B - выход
//Настройка и остановка таймеров
Setup_timer();
dfreq = 9; //минимальнач частота
//Дя регулировки частоты
pinMode(ADJ_PIN, INPUT);
//Кнопка старта
pinMode(BTN_START_PIN, INPUT_PULLUP);
//Индикатор
disp.init();
disp.point(false);
disp.set(BRIGHT_TYPICAL); //яркость
disp.clearDisplay(); //Очистить
//LCD дисплей
lcd.init(); // Инициализация lcd
lcd.backlight(); // Включаем подсветку
// Курсор находится в начале 1 строки
lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
lcd.print("3phase generator"); // Выводим текст
lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
lcd.print("Stop "); // Выводим текст
}
void loop() {
//PIND |= (1 << 2); //Для замера скорости
//Реализация для изменения частоты переменным резистором
if ((inctmr++) % 2048 == 0) { //Обрабатывается каждый 512-й вызов loop. Можно, наверно, увеличить.
adj = (analogRead(ADJ_PIN)+analogRead(ADJ_PIN)+analogRead(ADJ_PIN))/3; //Усредненное значение на пине регулировки частоты
if ( abs(adj - setfreq) >= deltafreq ){
//Значение аналогового входа изменилось на deltafreq и более.
//Сначала останавливаем прерывания по таймеру 2, иначе не работает
TIMSK2 &= ~(1<<TOIE2);
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Переведем значение analogRead в частоту
setfreq = adj;
dfreq_set = 10 + 2*(setfreq/deltafreq); // Минимальная частота 10Гц, на каждые 15 пунктов частота увеличивается на 2Гц
//Заполнить значение для LCD частотой dfreq_set. Вывод: Set freq: + частота
lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
lcd.print("Set freq: "); // Выводим текст
lcd.setCursor(10, 0); // Устанавливаем курсор в 10 позицию
lcd.print(dfreq_set); // Выводим текст
lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
lcd.print("Stop "); // Выводим текст
run = B00000000; //Изменение состояния на выкл и запрет обработки кнопки
run |= B00000001; //Кнопку можно снова обрабатывать
}
}
if (inctmr % 256 == 0) { //Обрабатывается каждый 256-й вызов loop. Можно, наверно, увеличить.
//Нажатие кнопки
if ( digitalRead(BTN_START_PIN) == LOW && (run & B00000001) ){ //Нажата кнопка и нужно менять состояние
if ((run & B00000010)) { //Надо остановить
TIMSK2 &= ~(1<<TOIE2); //остановка таймера
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Вывод на экран F + частота
/*disp.display(0,15);
disp.display(1,(dfreq_set%1000)/100);
disp.display(2,(dfreq_set%100)/10);
disp.display(3,dfreq_set%10);
*/
//Заполнить значение для LCD частотой dfreq_set. Вывод: Set freq: + частота
lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
lcd.print("Stop ");// Выводим текст
run = B00000000; //Изменение состояния на выкл и запрет обработки кнопки
}
else {
phaccu = 0;
dfreq = 4; //Минимальная частота для увеличения до рабочей
//Заполнить значение для LCD частотой dfreq_set. Вывод: Set freq: + частота
lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
lcd.print("Running ");// Выводим текст
run = B00000010; //Изменение состояния на вкл и запрет обработки кнопки
}
}
else if (digitalRead(BTN_START_PIN) == HIGH) { //кнопка отпущена
run |= B00000001; //Кнопку можно снова обрабатывать
}
}
if (dfreq < dfreq_set && (run & B00000010) && inctmr % 1048576/2 == 0) { //Плавное увеличение частоты, если нужная частота больше текущей. Резкое изменение, если меньше
dfreq++; //Увеличение частоты
if (dfreq % 5 == 0 || dfreq == dfreq_set) { //Увеличиваем каждые 5Гц
delta = 0x100000000 * dfreq / refclk; // Новое вычисление дельты
TIMSK2 |= (1<<TOIE2); //Запуск таймера
}
//delta = 0x100000000 * dfreq / refclk; // Новое вычисление дельты
//TIMSK2 |= (1<<TOIE2); //Запуск таймера
}
}
Дальнейшие планы:
1. Сделать реверс
2. Испытать на чем-то более силовом, вольт на 40. Есть идеи?
3. Сделать токовую защиту. Пока простенькую, типа датчика тока по линии питания мотора.
После запуска таймера с генерацией нельзя ничего перерисовать на дисплее, для этого нужно таймер остановить, перерисовать, потом таймер запустить. Это плохо сказывается на работе мотора. Может это особенность работы LiquidCrystal_I2C, но пока разбираться неохота.
Частота увеличивается по +5Гц примерно 2 раза в секунду, т.е. 50Гц набирает где-то за 5 секунд.
Кнопка старт/стоп работает. Если покрутить резистор в процессе работы мотора, то генерация останавливается принудительно.
Экран по 6 проводам пробовали подключать, результат тот же? Тоесть динамическая регулировка частоты отсутствует?
Не придумали как динамическую регулировку частоты сделать?
Проблема не в динамической регулировке частоты, ее сдеать можно. Проблема в отображении на дисплее текущей частоты. В библиотеке LiquidCrystal_I2C встречается 10 delay. В библиотеке TM1637 тоже есть delay.
Поэтому сейчас искуственно введена остановка генерации сигнала при изменении частоты.
Возможно перепишу либу TM1637, но может это и не нужно.
step64 пишет:
На другой контроллер не планируете свой проект переводить?
Нет, не планирую. На других, более мощных контроллерах, есть куча готовых решений. Сам проект сделан специально на Arduino, т.к. когда я искал готовый начитался много ерунды, типа "ардуина так не сможет".
andryn , Рад что проект развивается. Вы двигатель на 220 тестировали, силовую сразу на движок цепляли без фильтров? Вч ШИМ 62кГц может похерить изоляцию обмоток движка, да и будут большие динамические потери на таких частотах в МОЩНЫХ игбт, не зря в пром частотниках частота шим ДО десятка кГц +/- единицы кГц. А вы не хотите как опцию тормозной резистор приделать? Команда стоп -> лог.1 на свободный порт-> ключ-> Резистор. Рекомендую простенькую но эффективную схему защиты от перегруза и кз, повторялась не однократно, есть печатка если надо.
Вы двигатель на 220 тестировали, силовую сразу на движок цепляли без фильтров? Вч ШИМ 62кГц может похерить изоляцию обмоток движка, да и будут большие динамические потери на таких частотах в МОЩНЫХ игбт, не зря в пром частотниках частота шим ДО десятка кГц +/- единицы кГц.
Подключал напрямую, без фильтров. Про пробой изоляции не задумывался. Пока не понимаю физику пробоя при высокой частоте. Почитаю про это.
step64 пишет:
А вы не хотите как опцию тормозной резистор приделать? Команда стоп -> лог.1 на свободный порт-> ключ-> Резистор. Рекомендую простенькую но эффективную схему защиты от перегруза и кз, повторялась не однократно, есть печатка если надо.
Для борьбы с перегрузом и КЗ думал поставить измеритель тока после выпрямителя 220В. Тогда можно программно регулировать максимальную мощность.
b707 пишет:
мощность мотора падает, потому что амплитуда генерируемого синуса должна расти с частотой, как я понимаю, а в коде этого нет.
Амплитуда у меня постоянна и равна выпрямленному напряжению 220В. Т.е. повышать ее не куда, если не делать повышающий преобразователь вольт на 500. Можно было бы уменьшать скважность обратно пропорционально частоте, но тогда на номинальных 50Гц будет не полная мощность. В общем я считаю, что обычные 3-х фазные моторы не предназначены и не рассчитаны для вращения со скоростями в 4 раза, превышающими номинальную.
b707 пишет:
А можно подробнее. какие косяки выявились на испытаниях? - думаю, многим будет интересно, если конечно это не простые описки..
Функция генерации работает нормально, в нее исправлений не вносил. Основной косяк был в том, что при работе analogRead начинает прыгать на 25-30 пунктов, в связи с чем мотор останавливался, т.к. алгоритм считал, что повернули ручку регулировки. Еще переделал индикацию на TM1637, т.к. использовать большой экран бессмысленно, потому что не получается его динамически рефрешить. Ну и описки были, конечно :)
Для борьбы с перегрузом и КЗ думал поставить измеритель тока после выпрямителя 220В. Тогда можно программно регулировать максимальную мощность.
Идея конечно отличная, поставить хотя бы один модуль например ACS712 20A на шину питания и смотреть/контролировать ток на дисплее, тогда и напряжение шины питания надо выводить на дисплей, что бы всё по взрослому было) Интересно, меге 328 это по силам будет всё сразу делать, да ещё успевать мгновенно среагировать на КЗ.
Интересно, меге 328 это по силам будет всё сразу делать, да ещё успевать мгновенно среагировать на КЗ.
не, я конечно понимаю, что чисто из спортивного интереса это классно делать на атмеге328... но вообще практически любой stm32... даже самый банальный stm32f103 - справится с этим в разы лучше и будет загружен задачей процентов на 20.
1. Заглянул на данную ветку. На работе занимаюсь ремонтом (модульно) промышленных станций - частотников. Возможно, я что то упустил, но думаю так: не имеет смысла в таблице синусов первыми выборками назначать 0-0-0. Это всего лишь искривит вашу амлитуду при переходе через 0. Дит-тайм - это пауза в шим-сигнале. Подробнее так: методом шима формируется импульс ( определенной (расчетной) длины в заданное время), после каждого импульса устанавливается Дит-тайм (для IGBT-модулей которые мы применяем 3-3,3 mks) и только после этого может включиться нижний ключ или ключ другой фазы. В промышленных установках часто используют камни TMSxxx где все это реализовано аппаратно. Как сделать это программно на атмеге пока не представляю.
2. Недавно прочитал, правильно использовать "геометрический синус" - или как то так.. Взяв из сети 220В по простой таблице синуса вы обратно не отдадите теже 220/3ф. Как он работает - проще посмотреть картину в гугле. В настоящее время на коленке пишу 3-х фазный генератор синуса (срочно попросили). Если кому нужно - выложу то что получилось...
P/S быть может.. фазный шим поможет (заполнение не должно превышать ~ 99%) . Но кто даст гарантии что все таймеры запустятся синхронно и синронность работы PWM не нарушится... И с другой стороны, в гугле попадались частотники на простеньких камнях - и схемы рабочии (но там точно были драйверы с защитой от сквозных токов). Шим в установках 2500 - 5000 Гц с L-C фильтром. 1500 Гц без фильтра что бы АД не грелся...
По поводу ШИМ для двигателя может быть еще несколько проблем.
Первая - как уже писалось Если верхний транзистор открыт мы сначала подаем сигнал на закрытие верхнего транзистора. Ждем когда он закроется. И после этого только подаем сигнал на открытие нижнего транзистора. Так сделано в типовой схеме компьютерного блока питания на микросхеме TL494. Иначе пойдет ток короткого замыкания через 2 одновременно открытых транзистора и они сгорят. Время закрытого состояния обоих транзисторов около 4% длительности.
Второе - Допустим мы подаем идеальный ШИМ на двигатель.Но двигатель имеет неидеальные характеристики. Напимер индуктивность одной фазы на 0.0001% больше чем другой. В итоге сердечник двигателя войдет в насыщение по этой фазе и переодически ток насышения будет по этой фазе нарастать (например 1 раз в секунду для одного периода импульса) гораздо быстрее чем на остальных. Допустим частота ШИМ = 1 кгц. ток по истечении 0.5 мс с момента начала импульса ток должен быть 10 А. Но из за насыщения сердечника 1 раз в несколько секунд ток по истечении 0.5 мс будет 100 А. После этого насыщение убирается и все повторяется заново. Так вот этот ток и палит транзисторы IGBT. Либо ставить транзисторы с импульсным током гораздо большим среднего тока. Либо как то бороться с этим. Но бороться специальными схемными решениями. Контроллер в этом не поможет. Врят ли он сумеет обработать датчик тока и закрыть транзистор. При использовании двигателей маленькой мошности средний ток около 0.5А. Импульсный ток может быть 10А. Такой режим в основном держат все мощные полевые транзисторы или IGBT. При этом проблем не будет. Проблемы будут при мощных движках. Если не делать защит то транзисторы надо будет выбирать на импульсные токи 300 - 500А.
Да и посмотрите какой материал используется в двигателе. Обычно пластинчатое железо. У него на большой частоте свойства сильно падают.
вот вот, подскажи ссылку на частотник где PWM реализован программно, что-то не могу найти, там еще силовая на IRAMS10UP60B была сделана - "ЩАЖЖЭ!!!" )))
Вот только одно из видео не понял - частотник на 1 или 3 фазы?
из одной в три , меня интересует схемные решения , вы мой косяк видели ? сегодня удалось снизить до 1 миллисекунды больше не могу , вот и подбираю драйвер чтобы был с защитой и ноги совпадали , насчет похвастаться , да понты корявые , у котов меня забанили
нашел IR2308 но активный уровень высокий , схему управления изменил , микруху 540 заменил на 245 , если есть предложения по драйверам тогда предлагайте буду ОШЕНЬ благодарен
Кстати по поводу предложений, под управление трёхфазными двигателями, вернее под формирование трёхфазной синусоиды больше заточена Attiny861, у неё есть таймер счётчик работающий на частоте до 64 МГц (есть внутри ФАПЧ), есть 3 канала шим с 2 выходами каждый, с возможностью установки мёртвого времени между закрытием верхнего ключа и открытием нижнего и наоборот.
Кстати, в этом контроллере есть одна хитрость, связанная с включением каналов. Если мы моделируем в Протеусе, то каналы A, B и D работают как надо, в железе запускается только канал A. Некоторое время пришлось поламать голову над этой задачкой, но все три канала запустил, причём это связано не с тем что чип китайский якобы и это не является глюком контроллера (не описано в erratasheet). Тут скорее как говорил Козьма Прутков: "Зри в даташник."
Добрый день! Загрузил код в ардуино, синус не меняется
Его частота на порте а0 и кнопка старт стоп только работает, реверс просто выключает шимм, у меня на осциллографе дсо лес из шимм сигналов , с конденсатором появляется половина синуса но 20 мс развёртка там полу период на целую секунду растянут
Господа, не могу не вмешаться. Только что сын защитил диплом, собрали учебный стенд с трёхфазным векторным ШИМ с контроллером Arduino UNO. Пусть вас не пугают "двугорбые верблюды", "титьки" или "жопы", как их называют специалисты по электроприводу, это математически единственно верный метод создания трёхфазного векторного ШИМ.
Программу варганил профи. Начальная частота пуска 5 Гц, Максимальная частота 50 Гц. Разгон и торможение в функции U/f, зависимость линейная. Частота ШИМ 5 кГц. Задание частоты потенциометром, кнопки пуск и стоп. назначение входов в программе подписаны: #define key_stop A1 //вывод для кнопки стоп: #define key_start A2 //вывод для кнопки старт: #define f_zad_pin A3 //вход для задатчика выходной частоты.
//расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
faza=faza+dt*(f_out>>16);//(фаза увеличивается как интеграл частоты)
if(faza>0x00FFFFFF){//если угол вышел за сектор в 60град
faza=faza-0x00FFFFFF;//находим угол вектора в новом секторе
sector++;//увеличиваем номер сектора на 1
if(sector>6)sector=1;//если сектор больше 6, то начинаем с первого
}
//расчет времени импульсов управления ключами
unsigned int t1=pgm_read_byte_near(time1+(faza>>16));//считываем из таблицы Т1
unsigned int t2=pgm_read_byte_near(time2+(faza>>16));//считываем из таблицы Т2
//умножаем Т1 и Т2 на относительную амплитуду напряжения
t1=(t1*u_out)>>8;
t2=(t2*u_out)>>8;
byte t0=255-t1-t2;//расчет времени нулевого вектора
byte fa,fb,fc;//временные переменные для компараторов фазы А,В,С
//в зависимости от сектора, в котором формируется вектор выходного напряжения, готовим необходимые значения для компараторов
//см.рис.20.5
switch (sector) {
case 1:{ //t1-100 t2-110 t0-111
PORTD |= (1 << 4); //Для контроля вых.частоты
fa=255;
fb=t0+t2;
fc=t0;
break;
}
case 2:{ //t1-110 t2-010 t0-111
fb=255;
fa=t0+t1;
fc=t0;
break;
}
case 3:{ //t1-010 t2-011 t0-111
fb=255;
fc=t0+t2;
fa=t0;
break;
}
case 4:{ //t1-011 t2-001 t0-111
PORTD &= ~(1 << 4); //Для контроля вых.частоты
fc=255;
fb=t0+t1;
fa=t0;
break;
}
case 5:{ //t1-001 t2-101 t0-111
fc=255;
fa=t0+t2;
fb=t0;
break;
}
case 6:{ //t1-101 t2-100 t0-111
fa=255;
fc=t0+t1;
fb=t0;
break;
}
}
if(!start){//стоп - формируем ноль на выход
if(f_out<f_zad_min){
fa=255;fb=255;fc=255;
}
}
//запись значений в компараторы
OCR0A = fa;
OCR0B = fa;
OCR1A = fb;
OCR1B = fb;
OCR2A = fc;
OCR2B = fc;
//приращение счетчика времени
tim++;
}
следующий вариант этой проги для тех, кто имеет МКИ на базе TM1638 с двумя четырёхразрядными индикаторами семисегментного кода с общим катодом LED & KEY
/расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
как книга называется?
vahnik60@mail.ru пошли мне пробное письмо, я тебе перешлю все материалы, какие пожелаешь, а там вставляй куда хочешь сам. Надоела эта ребятня с пацанскими манерами, мало мне полторашку к пенсии добавили, ещё ваши выпендроны выслушивать. Возьми на себя распространение.
/расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu как книга называется?
В. Мелешин Д. Овчинников
Управление транзисторными преобразователями электроэнергии
стр. 460
но вам лучше в эти дебри не лезть, лучше воткните первую прогу в Arduino UNO и наслаждайтесь. Не забудьте про задержки на включение ключей (в моём IGBT-модуле время открытия IGBT-транзистора 0,4 мксек, а время закрытия - 3,4 мксек при 50 А 600 В), сквозной ток, однако!!!
У кого есть МКИ указанного типа (индикаторы с общим катодом ТМ1638, если индикаторы с общим анодом - замучаетесь программировать, нестандартный вариант), запускайте вторую прогу, ещё приятнее.
Если нужны исходники для Arduino UNO (R3) или схемы - запрос на почту vahnik60@mail.ru
Есть файл маткада с наглядным пояснением, как из двух двугорбых верблюдов получается синусоида линейного напряжения, это классическая раскладка 3-фазного векторного ШИМ (извините за повторения).
/*
Программу варганил профи. Начальная частота пуска 5 Гц, Максимальная частота 50 Гц. Разгон и торможение в функции U/f, зависимость линейная. Частота ШИМ 5 кГц.
Задание частоты потенциометром, кнопки пуск и стоп. назначение входов в программе подписаны: #define key_stop A1 //вывод для кнопки стоп:
#define key_start A2 //вывод для кнопки старт: #define f_zad_pin A3 //вход для задатчика выходной частоты.
*/
//расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
#include "LiquidCrystal_I2C.h"
//раздел 20.1
//таблица времени T1
//по формуле 20.1.6 - cos(a+30) в относительных единицах (0-1 соотв. 0-255)
const unsigned int PROGMEM time1[] = {
220,220,219,219,218,218,217,217,216,215,215,214,214,213,213,212,212,211,210,210,209,209,208,207,207,206,206,205,204,204,203,202,202
,201,201,200,199,199,198,197,197,196,195,195,194,193,193,192,191,191,190,189,188,188,187,186,186,185,184,183,183,182,181,181,180,179
,178,178,177,176,175,175,174,173,172,172,171,170,169,168,168,167,166,165,164,164,163,162,161,160,160,159,158,157,156,156,155,154,153
,152,151,151,150,149,148,147,146,145,145,144,143,142,141,140,139,139,138,137,136,135,134,133,132,131,131,130,129,128,127,126,125,124
,123,122,122,121,120,119,118,117,116,115,114,113,112,111,110,109,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92
,91,90,89,88,87,86,85,84,83,82,81,80,79,78,78,77,76,75,74,73,72,71,70,69,68,67,65,64,63,62,61,60,59,58,57,56,55,54,53
,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,24,23,22,21,20,19,18,17,16,15,14,13
,12,11,10,9,8,7,6,5,4,3,2,1 };
//таблица времени T2
//по формуле 20.1.7 - sin(a) в относительных единицах (0-1 соотв. 0-255)
const unsigned int PROGMEM time2[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41
,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,78,79,80
,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,109,110,111,112,113,114,115
,116,117,118,119,120,121,122,122,123,124,125,126,127,128,129,130,131,131,132,133,134,135,136,137,138,139,139,140,141,142,143,144,145
,145,146,147,148,149,150,151,151,152,153,154,155,156,156,157,158,159,160,160,161,162,163,164,164,165,166,167,168,168,169,170,171,172
,172,173,174,175,175,176,177,178,178,179,180,181,181,182,183,183,184,185,186,186,187,188,188,189,190,191,191,192,193,193,194,195,195
,196,197,197,198,199,199,200,201,201,202,202,203,204,204,205,206,206,207,207,208,209,209,210,210,211,212,212,213,213,214,214,215,215
,216,217,217,218,218,219,219,220 };
//по предварительным опытам частота шим получилась 7692,30769Гц
volatile unsigned long f_zad=0x00FFFFFF;//задание на частоту в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long f_zad_max=0x00FFFFFF;//максимум задание на частоту в отн.единицах, что соотв. 50 Гц
const unsigned long f_zad_min=0x19999A;//минимум задание на частоту в отн.единицах, что соотв. 5 Гц
volatile unsigned long f_out;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long df=218;//шаг приращения вых.частоты до задания, подобрать для получения разгона 50Гц/10сек
volatile byte u_out=1;//амплитуда на выход в отн.единицах 0-255, что соотв. 0-100%
//делим полный оборот вектора напряжения на сектора
//в каждом секторе отдельно накапливаем фазу до максимума и переходим к след.сектору
//при накоплении до 6 сектора начинаем с начала
volatile unsigned long faza=0; //угол вектора в секторе 0..0x00FFFFFF
volatile byte sector=1;//сектор 1..6
const unsigned long dt=2566;//коэф.интегрирования частоты для получения фазы. подобрать для получения 50Гц при f_zad=0x00FFFFFF
volatile boolean start=false; //разрешение работы инвертора
volatile unsigned int tim=0;//счетчик времени
unsigned long f=5;//задание частоты
volatile unsigned long f_old;
unsigned long fz;//задание частоты для шим
unsigned int ttim;//временная tim
unsigned int tims;//таймер подачи силового питания
volatile unsigned long fout;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
#define key_stop A1 //вывод для кнопки стоп
#define key_start A2 //вывод для кнопки старт
#define f_zad_pin A3 //вход для задатчика выходной частоты
LiquidCrystal_I2C lcd(0x27,16,2); // Задаем адрес и размерность дисплея.
//процедура выполняется перед основным циклом
void setup()
{
Serial.begin(9600); // connect to the serial port
Serial.println("Test begin");
//настройка выхода для управления подачей силового питания
pinMode(A0, OUTPUT); digitalWrite(A0,LOW);
//настройка входов кнопок с подтяжкой к +5
pinMode(key_stop, INPUT_PULLUP);
pinMode(key_start, INPUT_PULLUP);
//настройка портов вывода
DDRD = 0xFC; // весь порт D - выход, кроме RX TX
DDRB = 0xFF; // весь порт B - выход
//задание начальных значений частоты и таймера питания
f_out=f_zad_min;
tims=0;
//Настройка шим и прерываний
Setup_timer();
lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
lcd.print("Freq: "); // Выводим текст
lcd.setCursor(6, 0); // Устанавливаем курсор в 6 позицию
lcd.print(f); // Выводим текст
Serial.println( f);
}
//основной цикл программы, исполняется бесконечно
void loop(){
//считываем значение времени во временную переменную
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
ttim=tim;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
//если прошло полсекунды, то делаем опрос кнопок, обновление индикации
if(ttim>3500){//каждые 0.5сек
//читаем задание частоты
int f_pin=analogRead(f_zad_pin);
//изменяем задание на частоту
f=f_pin/20;
if(f<5)f=5; //если получилось меньше 5, то установить 5
if(f>50)f=50; //если больше 50, то установить 50
//пересчет задания частоы из Гц в относительные единицы
fz=f*20*0x4189;
//запись нового задания частоты и обнуление счетчика времени
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
f_zad=fz; //новое задание..............................................................
if( f!= f_old){f_old=f;
lcd.setCursor(6, 0); // Устанавливаем курсор в 6 позицию
lcd.print(f); // Выводим текст
Serial.println(f);
}
tim=0;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
//проверяем нажатие кнопок старт и стоп
if(digitalRead(key_start)==LOW){// если старт
start=true; //устанавливаем флаг разрешения работы
}
if(digitalRead(key_stop)==LOW){// если стоп
start=false;//сбрасываем флаг разрешения работы
}
//счет выдержки для подачи силового питания
tims++; //увеличить счетчик на 1
if(tims>4){//если прошло 2 сек
tims=0;
digitalWrite(A0,HIGH); //лог.1 на выход управления питанием
}
}
}
//******************************************************************
// Настройка таймеров
void Setup_timer() {
//настройка регистров таймеров и шим согласно документации на контроллер
//за каждую фазу отвечает свой таймер (0-ф.А,1-ф.В,2-ф.С)
// у каждого таймера два компаратора А и В, которые отвечают каждый за свой ключ в фазе (А-верх, В-нижн.)
//т.к. ключи в одном плече работают противофазно, то сомпараторы А настраиваем в неинвертирующий режим, В - в инвертирующий
//таймеры настраиваем в режим Fast PWM, 8bit
// TIMER0
TCCR0A |= (1<<COM0A1); // COM0A1, COM0A0: 1 0 - None-inverted mode для OC0A, для инверсного режима ШИМ нужно 1 1
TCCR0A &= ~(1<<COM0A0);
TCCR0A |= (1<<COM0B1); // COM0B1, COM0B0: 1 0 - None-inverted mode для OC0B, для инверсного режима ШИМ нужно 1 1
TCCR0A |= (1<<COM0B0);
TCCR0A |= (0<<WGM01); // WGM02, WGM01, WGM00: 0 1 1 - Fast PWM
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<CS02); // CS02, CS01, CS00: 0 0 1 - тактовый генератор CLK
TCCR0B &= ~(1<<CS00);
TCCR0B |= (1<<CS01);
TCCR0B &= ~(1<<WGM02);
// TIMER1
TCCR1A |= (1<<COM1A1); // COM1A1, COM1A0: 1 0 - None-inverted mode для OC1A, для инверсного режима ШИМ нужно 1 1
TCCR1A &= ~(1<<COM1A0);
TCCR1A |= (1<<COM1B1); // COM1B1, COM1B0: 1 0 - None-inverted mode для OC1B, для инверсного режима ШИМ нужно 1 1
TCCR1A |= (1<<COM1B0);
TCCR1A &= ~(0<<WGM11); // WGM13, WGM12, WGM11, WGM10: 0 1 0 1 - Fast PWM, 8bit
TCCR1A |= (1<<WGM10);
TCCR1B &= ~(1<<CS12); // CS12, CS11, CS10: 0 0 1 - тактовый генератор CLK
TCCR1B &= ~(1<<CS10);
TCCR1B |= (1<<CS11);
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12);
// TIMER2
TCCR2A |= (1<<COM2A1); // COM2A1, COM2A0: 1 0 - None-inverted mode для OC2A, для инверсного режима ШИМ нужно 1 1
TCCR2A &= ~(1<<COM2A0);
TCCR2A |= (1<<COM2B1); // COM2B1, COM2B0: 1 0 - None-inverted mode для OC2B, для инверсного режима ШИМ нужно 1 1
TCCR2A |= (1<<COM2B0);
TCCR2A |= (1<<WGM21); // WGM22, WGM21, WGM20: 0 1 1 - Fast PWM
TCCR2A |= (1<<WGM20);
TCCR2B &= ~(1<<CS22); // CS22, CS21, CS20: 0 0 1 - тактовый генератор CLK
TCCR2B &= ~(1<<CS20);
TCCR2B |= (1<<CS21);
TCCR2B &= ~(1<<WGM22);
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;// инверс
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Разрешить/запретить прерывания по таймерам
TIMSK0 &= ~(1<<TOIE0); //Запретить прерывания на таймер 0
TIMSK1 &= ~(1<<TOIE1); //Запретить прерывания на таймер 1
TIMSK2 |= (1<<TOIE2); //Разрешить прерывания на таймер 2
}
//******************************************************************
//Прерывание по таймеру 2 (TIMER2)
//Работает с частотой шим
//оформляется отдельной блок-схемой, т.к. работает параллельно основной программе
ISR(TIMER2_OVF_vect) {
//Таймер 0 | выводы 5 и 6 | OC0B, OC0A
//Таймер 1 | выводы 9 и 10 | OC1A, OC1B
//Таймер 2 | выводы 3 и 11 | OC2B, OC2A
//расчет выходной частоты (реализация разгона и торможения по рампе с заданным темпом)
if(start){//если есть разрешение работы
if(f_out<f_zad_min)f_out=f_zad_min;//если частота ниже минимума, то ставим минимум
if(f_out<f_zad){//если частота меньше заданной, то
f_out=f_out+df;//увеличиваем с заданным темпом
if(f_out>f_zad)f_out=f_zad;//если превысили задание, то ставим частоту равной заданию
}
if(f_out>f_zad){//если частота больше заданной, то
f_out=f_out-df;//уменьшаем частоту с заданным темпом
if(f_out<f_zad)f_out=f_zad;//если стало меньше задания, то ставим частоту равной заданию
}
}else{//иначе нет разрешения работы (стоп)
if(f_out<f_zad_min){f_out=0;}//если выходная частота меньше минимума, то ставим ноль
else{f_out=f_out-df;}//иначе тормозим с заданным темпом
}
//расчет амплитуды выходного напряжения пропорционально частоте
//т.к. принята линейная зависимость, то в относительных единицах они равны
//просто приводим к размеру представления амплитуды
u_out=(byte)(f_out>>16);
//расчет угла обобщенного вектора выходного напряжения
faza=faza+dt*(f_out>>16);//(фаза увеличивается как интеграл частоты)
if(faza>0x00FFFFFF){//если угол вышел за сектор в 60град
faza=faza-0x00FFFFFF;//находим угол вектора в новом секторе
sector++;//увеличиваем номер сектора на 1
if(sector>6)sector=1;//если сектор больше 6, то начинаем с первого
}
//расчет времени импульсов управления ключами
unsigned int t1=pgm_read_byte_near(time1+(faza>>16));//считываем из таблицы Т1
unsigned int t2=pgm_read_byte_near(time2+(faza>>16));//считываем из таблицы Т2
//умножаем Т1 и Т2 на относительную амплитуду напряжения
t1=(t1*u_out)>>8;
t2=(t2*u_out)>>8;
byte t0=255-t1-t2;//расчет времени нулевого вектора
byte fa,fb,fc;//временные переменные для компараторов фазы А,В,С
//в зависимости от сектора, в котором формируется вектор выходного напряжения, готовим необходимые значения для компараторов
//см.рис.20.5
switch (sector) {
case 1:{ //t1-100 t2-110 t0-111
PORTD |= (1 << 4); //Для контроля вых.частоты
fa=255;
fb=t0+t2;
fc=t0;
break;
}
case 2:{ //t1-110 t2-010 t0-111
fb=255;
fa=t0+t1;
fc=t0;
break;
}
case 3:{ //t1-010 t2-011 t0-111
fb=255;
fc=t0+t2;
fa=t0;
break;
}
case 4:{ //t1-011 t2-001 t0-111
PORTD &= ~(1 << 4); //Для контроля вых.частоты
fc=255;
fb=t0+t1;
fa=t0;
break;
}
case 5:{ //t1-001 t2-101 t0-111
fc=255;
fa=t0+t2;
fb=t0;
break;
}
case 6:{ //t1-101 t2-100 t0-111
fa=255;
fc=t0+t1;
fb=t0;
break;
}
}
if(!start){//стоп - формируем ноль на выход
if(f_out<f_zad_min){
fa=255;fb=255;fc=255;
}
}
//запись значений в компараторы
OCR0A = fa;
OCR0B = fa;
OCR1A = fb;
OCR1B = fb;
OCR2A = fc;
OCR2B = fc;
//приращение счетчика времени
tim++;
}
Уважаемый Oleg.normalniy, недоумеваю от Ваших коментариев в роликах по поводу сравнения потребления тока при векторном (двугорбые полусинусоиды) и при самопальном (одногорбые полусинусоиды). Для двигателя разницы в способе формирования синусоиды напряжения нет, а вот амплитуда модулируемого напряжения синусоиды для него имеет значение, в первом случае формируются линейные напряжения 3-х фазной сети чуть не в два раза выше, чем при втором при "одинаковой", вроде бы, амплитуде на RC-цепочке. Первый классический способ гарантируется 100% использования ресурса постоянного напряжения источника, а второй менее 70%. Вы можете в этом убедиться, если подцепите на силовые выходы инвертора "звезду" из 3-х RC-цепей (например 1 мкф, 30k), образующих искусственную среднюю точку. Увидите фвзные напряжения в масштабе в обоих случаях. Успехов в экспериментах, берегите себя.
При не запущенном ШИМ открыты три верхние ключи, нижние отключены. При включении ШИМ в каждом плече один из ключей включен, второй выключен и наоборот. Вероятно, у Вас неверный код программы. Пришлитемне письмо на почту vahnik60mail.ru , я вышлю исходники для двух вариантов программы. Первый вариант с заданием частоты резистивным задатчиком, второй - с МКИ на TM1638.
Вариант и LCD-дисплеем не смотрел (не моя переделка), он оказался недоделанным в плане индикации.
Последний код надо серьёзно тестить без силовой. Запускается с разгоном нормально, во время работы убавил частоту переменником и нажимал кнопку - появился высокий уровень на нескольких пинах, а это взрыв силовой сразу. По осциллографу смотрел без подключения силовой. andryn, проверьте у себя на осциле динамическую регулировку частоты и нажатие кнопки в разных комбинациях.
Последний код надо серьёзно тестить без силовой. Запускается с разгоном нормально, во время работы убавил частоту переменником и нажимал кнопку - появился высокий уровень на нескольких пинах, а это взрыв силовой сразу. По осциллографу смотрел без подключения силовой. andryn, проверьте у себя на осциле динамическую регулировку частоты и нажатие кнопки в разных комбинациях.
Да, был такой косячек. При остановке не останавливались ШИМ, поэтому при нажатии на кнопу для остановки могла оставться генерация на ключах из разных фаз. Сейчас это убрал. Под нагрузкой из мотора винчестера проверил, мотор крутится, но работает кривовато, больше 70Гц не раскручивается. Еще мне не нравится механизм плавного увеличения частоты по 1Гц, наверно переделаю.
Изменения такие:
Для всех интересующихся темой: провел небольшие испытания в железе.
Описание стенда: Arduino Uno, Переменный резистор 10К(подключен к A0), Кнопка без фиксации(подключена к А1), дисплей 1602 с I2C(подключен к A4, A5), силовая часть на ir2101+2SK3569, моторчик от FDD 3''(обмотки соединены звездой). Питание драйверов 12В, питание мотора тоже 12В, питание arduino 5В.
Основной результат испытаний: работает. Покрутил моторчик частотами от 10 до 200Гц - работает стабильно.
Есть некоторые особенности, которе не проявляется на эмуляторах:
После запуска таймера с генерацией нельзя ничего перерисовать на дисплее, для этого нужно таймер остановить, перерисовать, потом таймер запустить. Это плохо сказывается на работе мотора. Может это особенность работы LiquidCrystal_I2C, но пока разбираться неохота.
Частота увеличивается по +5Гц примерно 2 раза в секунду, т.е. 50Гц набирает где-то за 5 секунд.
Кнопка старт/стоп работает. Если покрутить резистор в процессе работы мотора, то генерация останавливается принудительно.
Свежий код:
Дальнейшие планы:
1. Сделать реверс
2. Испытать на чем-то более силовом, вольт на 40. Есть идеи?
3. Сделать токовую защиту. Пока простенькую, типа датчика тока по линии питания мотора.
После запуска таймера с генерацией нельзя ничего перерисовать на дисплее, для этого нужно таймер остановить, перерисовать, потом таймер запустить. Это плохо сказывается на работе мотора. Может это особенность работы LiquidCrystal_I2C, но пока разбираться неохота.
Частота увеличивается по +5Гц примерно 2 раза в секунду, т.е. 50Гц набирает где-то за 5 секунд.
Кнопка старт/стоп работает. Если покрутить резистор в процессе работы мотора, то генерация останавливается принудительно.
Экран по 6 проводам пробовали подключать, результат тот же?
Не пробовал. Я всетаки склоняюсь к семисегентнику и паре светодиодов.
Тоесть динамическая регулировка частоты отсутствует?
Да, сейчас так. Не понятно как ее отобразить, если нужно останавливать таймер. Может придумаю что-то.
Добавлена кнопка реверса на пине A2.
Код:
Не придумали как динамическую регулировку частоты сделать? На другой контроллер не планируете свой проект переводить?
andryn какая максимальная частота вами достигнута ?
Не придумали как динамическую регулировку частоты сделать?
Проблема не в динамической регулировке частоты, ее сдеать можно. Проблема в отображении на дисплее текущей частоты. В библиотеке LiquidCrystal_I2C встречается 10 delay. В библиотеке TM1637 тоже есть delay.
Поэтому сейчас искуственно введена остановка генерации сигнала при изменении частоты.
Возможно перепишу либу TM1637, но может это и не нужно.
На другой контроллер не планируете свой проект переводить?
Нет, не планирую. На других, более мощных контроллерах, есть куча готовых решений. Сам проект сделан специально на Arduino, т.к. когда я искал готовый начитался много ерунды, типа "ардуина так не сможет".
andryn какая максимальная частота вами достигнута ?
Гонял до 200Гц, но понял, что больше 100 сильно падает мощность мотора. Поэтому сейчас регулировка от 10 до 110Гц.
Ну и, для интересующихся, вести с полей. Испытал работу на маленьком трехфазном моторчике 220Вольт 40Вт(по-моему). Работает устойчиво.
При испытании выявил несколько косяков. Вот свежий код:
В библиотеку TM1637 добавил несколько символов для индикации в старшем разряде текущего состояния.
andryn , Рад что проект развивается. Вы двигатель на 220 тестировали, силовую сразу на движок цепляли без фильтров? Вч ШИМ 62кГц может похерить изоляцию обмоток движка, да и будут большие динамические потери на таких частотах в МОЩНЫХ игбт, не зря в пром частотниках частота шим ДО десятка кГц +/- единицы кГц. А вы не хотите как опцию тормозной резистор приделать? Команда стоп -> лог.1 на свободный порт-> ключ-> Резистор. Рекомендую простенькую но эффективную схему защиты от перегруза и кз, повторялась не однократно, есть печатка если надо.
Гонял до 200Гц, но понял, что больше 100 сильно падает мощность мотора. Поэтому сейчас регулировка от 10 до 110Гц.
При испытании выявил несколько косяков.
мощность мотора падает, потому что амплитуда генерируемого синуса должна расти с частотой, как я понимаю, а в коде этого нет.
А можно подробнее. какие косяки выявились на испытаниях? - думаю, многим будет интересно, если конечно это не простые описки..
Вы двигатель на 220 тестировали, силовую сразу на движок цепляли без фильтров? Вч ШИМ 62кГц может похерить изоляцию обмоток движка, да и будут большие динамические потери на таких частотах в МОЩНЫХ игбт, не зря в пром частотниках частота шим ДО десятка кГц +/- единицы кГц.
Подключал напрямую, без фильтров. Про пробой изоляции не задумывался. Пока не понимаю физику пробоя при высокой частоте. Почитаю про это.
А вы не хотите как опцию тормозной резистор приделать? Команда стоп -> лог.1 на свободный порт-> ключ-> Резистор. Рекомендую простенькую но эффективную схему защиты от перегруза и кз, повторялась не однократно, есть печатка если надо.
Для борьбы с перегрузом и КЗ думал поставить измеритель тока после выпрямителя 220В. Тогда можно программно регулировать максимальную мощность.
мощность мотора падает, потому что амплитуда генерируемого синуса должна расти с частотой, как я понимаю, а в коде этого нет.
Амплитуда у меня постоянна и равна выпрямленному напряжению 220В. Т.е. повышать ее не куда, если не делать повышающий преобразователь вольт на 500. Можно было бы уменьшать скважность обратно пропорционально частоте, но тогда на номинальных 50Гц будет не полная мощность. В общем я считаю, что обычные 3-х фазные моторы не предназначены и не рассчитаны для вращения со скоростями в 4 раза, превышающими номинальную.
А можно подробнее. какие косяки выявились на испытаниях? - думаю, многим будет интересно, если конечно это не простые описки..
Функция генерации работает нормально, в нее исправлений не вносил. Основной косяк был в том, что при работе analogRead начинает прыгать на 25-30 пунктов, в связи с чем мотор останавливался, т.к. алгоритм считал, что повернули ручку регулировки. Еще переделал индикацию на TM1637, т.к. использовать большой экран бессмысленно, потому что не получается его динамически рефрешить. Ну и описки были, конечно :)
Для борьбы с перегрузом и КЗ думал поставить измеритель тока после выпрямителя 220В. Тогда можно программно регулировать максимальную мощность.
Интересно, меге 328 это по силам будет всё сразу делать, да ещё успевать мгновенно среагировать на КЗ.
не, я конечно понимаю, что чисто из спортивного интереса это классно делать на атмеге328... но вообще практически любой stm32... даже самый банальный stm32f103 - справится с этим в разы лучше и будет загружен задачей процентов на 20.
Подключал напрямую, без фильтров. Про пробой изоляции не задумывался. Пока не понимаю физику пробоя при высокой частоте. Почитаю про это.
тут всё просто, механическое повреждение изоляции (перетирает) )))
Вакуумная пропитка кремнийорганическим лаком с последующей сущкой спасает ситуацию
1. Заглянул на данную ветку. На работе занимаюсь ремонтом (модульно) промышленных станций - частотников. Возможно, я что то упустил, но думаю так: не имеет смысла в таблице синусов первыми выборками назначать 0-0-0. Это всего лишь искривит вашу амлитуду при переходе через 0. Дит-тайм - это пауза в шим-сигнале. Подробнее так: методом шима формируется импульс ( определенной (расчетной) длины в заданное время), после каждого импульса устанавливается Дит-тайм (для IGBT-модулей которые мы применяем 3-3,3 mks) и только после этого может включиться нижний ключ или ключ другой фазы. В промышленных установках часто используют камни TMSxxx где все это реализовано аппаратно. Как сделать это программно на атмеге пока не представляю.
2. Недавно прочитал, правильно использовать "геометрический синус" - или как то так.. Взяв из сети 220В по простой таблице синуса вы обратно не отдадите теже 220/3ф. Как он работает - проще посмотреть картину в гугле. В настоящее время на коленке пишу 3-х фазный генератор синуса (срочно попросили). Если кому нужно - выложу то что получилось...
P/S быть может.. фазный шим поможет (заполнение не должно превышать ~ 99%) . Но кто даст гарантии что все таймеры запустятся синхронно и синронность работы PWM не нарушится... И с другой стороны, в гугле попадались частотники на простеньких камнях - и схемы рабочии (но там точно были драйверы с защитой от сквозных токов). Шим в установках 2500 - 5000 Гц с L-C фильтром. 1500 Гц без фильтра что бы АД не грелся...
По поводу ШИМ для двигателя может быть еще несколько проблем.
Первая - как уже писалось Если верхний транзистор открыт мы сначала подаем сигнал на закрытие верхнего транзистора. Ждем когда он закроется. И после этого только подаем сигнал на открытие нижнего транзистора. Так сделано в типовой схеме компьютерного блока питания на микросхеме TL494. Иначе пойдет ток короткого замыкания через 2 одновременно открытых транзистора и они сгорят. Время закрытого состояния обоих транзисторов около 4% длительности.
Второе - Допустим мы подаем идеальный ШИМ на двигатель.Но двигатель имеет неидеальные характеристики. Напимер индуктивность одной фазы на 0.0001% больше чем другой. В итоге сердечник двигателя войдет в насыщение по этой фазе и переодически ток насышения будет по этой фазе нарастать (например 1 раз в секунду для одного периода импульса) гораздо быстрее чем на остальных. Допустим частота ШИМ = 1 кгц. ток по истечении 0.5 мс с момента начала импульса ток должен быть 10 А. Но из за насыщения сердечника 1 раз в несколько секунд ток по истечении 0.5 мс будет 100 А. После этого насыщение убирается и все повторяется заново. Так вот этот ток и палит транзисторы IGBT. Либо ставить транзисторы с импульсным током гораздо большим среднего тока. Либо как то бороться с этим. Но бороться специальными схемными решениями. Контроллер в этом не поможет. Врят ли он сумеет обработать датчик тока и закрыть транзистор. При использовании двигателей маленькой мошности средний ток около 0.5А. Импульсный ток может быть 10А. Такой режим в основном держат все мощные полевые транзисторы или IGBT. При этом проблем не будет. Проблемы будут при мощных движках. Если не делать защит то транзисторы надо будет выбирать на импульсные токи 300 - 500А.
Да и посмотрите какой материал используется в двигателе. Обычно пластинчатое железо. У него на большой частоте свойства сильно падают.
Всем привет. Ну как ? Работает схема??
Выкладывай что получилось.. и продублируй мне на почту пожалуйста! spgazsystem@yandex.ru
ты забыл ключевое слово "ЩАЖЖЭ!!!"
Я тама прописал.. Пажалуйста !!
ты забыл ключевое слово "ЩАЖЖЭ!!!"
вот вот, подскажи ссылку на частотник где PWM реализован программно, что-то не могу найти, там еще силовая на IRAMS10UP60B была сделана - "ЩАЖЖЭ!!!" )))
подскажи ссылку на частотник где PWM реализован программно, что-то не могу найти, там еще силовая на IRAMS10UP60B была сделана - "ЩАЖЖЭ!!!" )))
держи
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/proshu-pomoch-uskorit-rabotu-sketcha-programmnyi-shim-6-kana
подскажи ссылку на частотник где PWM реализован программно, что-то не могу найти, там еще силовая на IRAMS10UP60B была сделана - "ЩАЖЖЭ!!!" )))
держи
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/proshu-pomoch-uskorit-rabotu-sketcha-programmnyi-shim-6-kana
данке щён
Что-то по проекту больше никакой информации!?
Добрый день! Как успехи по проекту ?В протеусе посмотрел работу программы на ардуино 5 и 6 порты не выдают импульсы шимм
Добрый день! Как успехи по проекту ?В протеусе посмотрел работу программы на ардуино 5 и 6 порты не выдают импульсы шимм
делайте на СТМ32
привет народ , замутил свой частотник на XMEGA32D4
https://studio.youtube.com/video/fY6xBOhNq6Q/edit
Ну кто так ссылки то выкладывает.
Правильно вот так: https://www.youtube.com/watch?v=fY6xBOhNq6Q
ну и ссылки на кота можно было тоже привести, а то ни схемы ни прошивки, как будто похвастаться:
https://radiokot.ru/forum/viewtopic.php?p=3814020#p3814020
https://radiokot.ru/forum/viewtopic.php?p=3851152#p3851152
Вот только одно из видео не понял - частотник на 1 или 3 фазы?
Ну кто так ссылки то выкладывает.
Правильно вот так: https://www.youtube.com/watch?v=fY6xBOhNq6Q
ну и ссылки на кота можно было тоже привести, а то ни схемы ни прошивки, как будто похвастаться:
https://radiokot.ru/forum/viewtopic.php?p=3814020#p3814020
https://radiokot.ru/forum/viewtopic.php?p=3851152#p3851152
Вот только одно из видео не понял - частотник на 1 или 3 фазы?
из одной в три , меня интересует схемные решения , вы мой косяк видели ? сегодня удалось снизить до 1 миллисекунды больше не могу , вот и подбираю драйвер чтобы был с защитой и ноги совпадали , насчет похвастаться , да понты корявые , у котов меня забанили
нашел IR2308 но активный уровень высокий , схему управления изменил , микруху 540 заменил на 245 , если есть предложения по драйверам тогда предлагайте буду ОШЕНЬ благодарен
привед народ , выкладываю новые приключения моторчика с датчиком тока ACS758
https://youtu.be/aoLlJcYoZYQ
всем привеД , выкладываю не правильное видео , народ говорит так делать не льзя
https://youtu.be/QnE6-JBv4kQ
Кстати по поводу предложений, под управление трёхфазными двигателями, вернее под формирование трёхфазной синусоиды больше заточена Attiny861, у неё есть таймер счётчик работающий на частоте до 64 МГц (есть внутри ФАПЧ), есть 3 канала шим с 2 выходами каждый, с возможностью установки мёртвого времени между закрытием верхнего ключа и открытием нижнего и наоборот.
Кстати, в этом контроллере есть одна хитрость, связанная с включением каналов. Если мы моделируем в Протеусе, то каналы A, B и D работают как надо, в железе запускается только канал A. Некоторое время пришлось поламать голову над этой задачкой, но все три канала запустил, причём это связано не с тем что чип китайский якобы и это не является глюком контроллера (не описано в erratasheet). Тут скорее как говорил Козьма Прутков: "Зри в даташник."
XMEGA и не надо искать профильный проц , XMEGA A1 если верить DATE держит 128 мгц , а таймеров на 5 движков
Добрый день! Загрузил код в ардуино, синус не меняется
Его частота на порте а0 и кнопка старт стоп только работает, реверс просто выключает шимм, у меня на осциллографе дсо лес из шимм сигналов , с конденсатором появляется половина синуса но 20 мс развёртка там полу период на целую секунду растянут
Господа, не могу не вмешаться. Только что сын защитил диплом, собрали учебный стенд с трёхфазным векторным ШИМ с контроллером Arduino UNO. Пусть вас не пугают "двугорбые верблюды", "титьки" или "жопы", как их называют специалисты по электроприводу, это математически единственно верный метод создания трёхфазного векторного ШИМ.
Программу варганил профи. Начальная частота пуска 5 Гц, Максимальная частота 50 Гц. Разгон и торможение в функции U/f, зависимость линейная. Частота ШИМ 5 кГц. Задание частоты потенциометром, кнопки пуск и стоп. назначение входов в программе подписаны: #define key_stop A1 //вывод для кнопки стоп: #define key_start A2 //вывод для кнопки старт: #define f_zad_pin A3 //вход для задатчика выходной частоты.
//расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
//раздел 20.1
//таблица времени T1
//по формуле 20.1.6 - cos(a+30) в относительных единицах (0-1 соотв. 0-255)
const unsigned int PROGMEM time1[] = {
220,220,219,219,218,218,217,217,216,215,215,214,214,213,213,212,212,211,210,210,209,209,208,207,207,206,206,205,204,204,203,202,202
,201,201,200,199,199,198,197,197,196,195,195,194,193,193,192,191,191,190,189,188,188,187,186,186,185,184,183,183,182,181,181,180,179
,178,178,177,176,175,175,174,173,172,172,171,170,169,168,168,167,166,165,164,164,163,162,161,160,160,159,158,157,156,156,155,154,153
,152,151,151,150,149,148,147,146,145,145,144,143,142,141,140,139,139,138,137,136,135,134,133,132,131,131,130,129,128,127,126,125,124
,123,122,122,121,120,119,118,117,116,115,114,113,112,111,110,109,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92
,91,90,89,88,87,86,85,84,83,82,81,80,79,78,78,77,76,75,74,73,72,71,70,69,68,67,65,64,63,62,61,60,59,58,57,56,55,54,53
,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,24,23,22,21,20,19,18,17,16,15,14,13
,12,11,10,9,8,7,6,5,4,3,2,1 };
//таблица времени T2
//по формуле 20.1.7 - sin(a) в относительных единицах (0-1 соотв. 0-255)
const unsigned int PROGMEM time2[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41
,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,78,79,80
,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,109,110,111,112,113,114,115
,116,117,118,119,120,121,122,122,123,124,125,126,127,128,129,130,131,131,132,133,134,135,136,137,138,139,139,140,141,142,143,144,145
,145,146,147,148,149,150,151,151,152,153,154,155,156,156,157,158,159,160,160,161,162,163,164,164,165,166,167,168,168,169,170,171,172
,172,173,174,175,175,176,177,178,178,179,180,181,181,182,183,183,184,185,186,186,187,188,188,189,190,191,191,192,193,193,194,195,195
,196,197,197,198,199,199,200,201,201,202,202,203,204,204,205,206,206,207,207,208,209,209,210,210,211,212,212,213,213,214,214,215,215
,216,217,217,218,218,219,219,220 };
//по предварительным опытам частота шим получилась 7692,30769Гц
volatile unsigned long f_zad=0x00FFFFFF;//задание на частоту в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long f_zad_max=0x00FFFFFF;//максимум задание на частоту в отн.единицах, что соотв. 50 Гц
const unsigned long f_zad_min=0x19999A;//минимум задание на частоту в отн.единицах, что соотв. 5 Гц
volatile unsigned long f_out;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long df=218;//шаг приращения вых.частоты до задания, подобрать для получения разгона 50Гц/10сек
volatile byte u_out=1;//амплитуда на выход в отн.единицах 0-255, что соотв. 0-100%
//делим полный оборот вектора напряжения на сектора
//в каждом секторе отдельно накапливаем фазу до максимума и переходим к след.сектору
//при накоплении до 6 сектора начинаем с начала
volatile unsigned long faza=0; //угол вектора в секторе 0..0x00FFFFFF
volatile byte sector=1;//сектор 1..6
const unsigned long dt=2566;//коэф.интегрирования частоты для получения фазы. подобрать для получения 50Гц при f_zad=0x00FFFFFF
volatile boolean start=false; //разрешение работы инвертора
volatile unsigned int tim=0;//счетчик времени
unsigned long f=5;//задание частоты
unsigned long fz;//задание частоты для шим
unsigned int ttim;//временная tim
unsigned int tims;//таймер подачи силового питания
volatile unsigned long fout;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
#define key_stop A1 //вывод для кнопки стоп
#define key_start A2 //вывод для кнопки старт
#define f_zad_pin A3 //вход для задатчика выходной частоты
//процедура выполняется перед основным циклом
void setup()
{
//настройка выхода для управления подачей силового питания
pinMode(A0, OUTPUT); digitalWrite(A0,LOW);
//настройка входов кнопок с подтяжкой к +5
pinMode(key_stop, INPUT_PULLUP);
pinMode(key_start, INPUT_PULLUP);
//настройка портов вывода
DDRD = 0xFC; // весь порт D - выход, кроме RX TX
DDRB = 0xFF; // весь порт B - выход
//задание начальных значений частоты и таймера питания
f_out=f_zad_min;
tims=0;
//Настройка шим и прерываний
Setup_timer();
}
//основной цикл программы, исполняется бесконечно
void loop(){
//считываем значение времени во временную переменную
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
ttim=tim;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
//если прошло полсекунды, то делаем опрос кнопок, обновление индикации
if(ttim>3500){//каждые 0.5сек
//читаем задание частоты
int f_pin=analogRead(f_zad_pin);
//изменяем задание на частоту
f=f_pin/20;
if(f<5)f=5; //если получилось меньше 5, то установить 5
if(f>50)f=50; //если больше 50, то установить 50
//пересчет задания частоы из Гц в относительные единицы
fz=f*20*0x4189;
//запись нового задания частоты и обнуление счетчика времени
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
f_zad=fz; //новое задание
tim=0;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
//проверяем нажатие кнопок старт и стоп
if(digitalRead(key_start)==LOW){// если старт
start=true; //устанавливаем флаг разрешения работы
}
if(digitalRead(key_stop)==LOW){// если стоп
start=false;//сбрасываем флаг разрешения работы
}
//счет выдержки для подачи силового питания
tims++; //увеличить счетчик на 1
if(tims>4){//если прошло 2 сек
tims=0;
digitalWrite(A0,HIGH); //лог.1 на выход управления питанием
}
}
}
//******************************************************************
// Настройка таймеров
void Setup_timer() {
//настройка регистров таймеров и шим согласно документации на контроллер
//за каждую фазу отвечает свой таймер (0-ф.А,1-ф.В,2-ф.С)
// у каждого таймера два компаратора А и В, которые отвечают каждый за свой ключ в фазе (А-верх, В-нижн.)
//т.к. ключи в одном плече работают противофазно, то сомпараторы А настраиваем в неинвертирующий режим, В - в инвертирующий
//таймеры настраиваем в режим Fast PWM, 8bit
// TIMER0
TCCR0A |= (1<<COM0A1); // COM0A1, COM0A0: 1 0 - None-inverted mode для OC0A, для инверсного режима ШИМ нужно 1 1
TCCR0A &= ~(1<<COM0A0);
TCCR0A |= (1<<COM0B1); // COM0B1, COM0B0: 1 0 - None-inverted mode для OC0B, для инверсного режима ШИМ нужно 1 1
TCCR0A |= (1<<COM0B0);
TCCR0A |= (0<<WGM01); // WGM02, WGM01, WGM00: 0 1 1 - Fast PWM
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<CS02); // CS02, CS01, CS00: 0 0 1 - тактовый генератор CLK
TCCR0B &= ~(1<<CS00);
TCCR0B |= (1<<CS01);
TCCR0B &= ~(1<<WGM02);
// TIMER1
TCCR1A |= (1<<COM1A1); // COM1A1, COM1A0: 1 0 - None-inverted mode для OC1A, для инверсного режима ШИМ нужно 1 1
TCCR1A &= ~(1<<COM1A0);
TCCR1A |= (1<<COM1B1); // COM1B1, COM1B0: 1 0 - None-inverted mode для OC1B, для инверсного режима ШИМ нужно 1 1
TCCR1A |= (1<<COM1B0);
TCCR1A &= ~(0<<WGM11); // WGM13, WGM12, WGM11, WGM10: 0 1 0 1 - Fast PWM, 8bit
TCCR1A |= (1<<WGM10);
TCCR1B &= ~(1<<CS12); // CS12, CS11, CS10: 0 0 1 - тактовый генератор CLK
TCCR1B &= ~(1<<CS10);
TCCR1B |= (1<<CS11);
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12);
// TIMER2
TCCR2A |= (1<<COM2A1); // COM2A1, COM2A0: 1 0 - None-inverted mode для OC2A, для инверсного режима ШИМ нужно 1 1
TCCR2A &= ~(1<<COM2A0);
TCCR2A |= (1<<COM2B1); // COM2B1, COM2B0: 1 0 - None-inverted mode для OC2B, для инверсного режима ШИМ нужно 1 1
TCCR2A |= (1<<COM2B0);
TCCR2A |= (1<<WGM21); // WGM22, WGM21, WGM20: 0 1 1 - Fast PWM
TCCR2A |= (1<<WGM20);
TCCR2B &= ~(1<<CS22); // CS22, CS21, CS20: 0 0 1 - тактовый генератор CLK
TCCR2B &= ~(1<<CS20);
TCCR2B |= (1<<CS21);
TCCR2B &= ~(1<<WGM22);
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Разрешить/запретить прерывания по таймерам
TIMSK0 &= ~(1<<TOIE0); //Запретить прерывания на таймер 0
TIMSK1 &= ~(1<<TOIE1); //Запретить прерывания на таймер 1
TIMSK2 |= (1<<TOIE2); //Разрешить прерывания на таймер 2
}
//******************************************************************
//Прерывание по таймеру 2 (TIMER2)
//Работает с частотой шим
//оформляется отдельной блок-схемой, т.к. работает параллельно основной программе
ISR(TIMER2_OVF_vect) {
//Таймер 0 | выводы 5 и 6 | OC0B, OC0A
//Таймер 1 | выводы 9 и 10 | OC1A, OC1B
//Таймер 2 | выводы 3 и 11 | OC2B, OC2A
//расчет выходной частоты (реализация разгона и торможения по рампе с заданным темпом)
if(start){//если есть разрешение работы
if(f_out<f_zad_min)f_out=f_zad_min;//если частота ниже минимума, то ставим минимум
if(f_out<f_zad){//если частота меньше заданной, то
f_out=f_out+df;//увеличиваем с заданным темпом
if(f_out>f_zad)f_out=f_zad;//если превысили задание, то ставим частоту равной заданию
}
if(f_out>f_zad){//если частота больше заданной, то
f_out=f_out-df;//уменьшаем частоту с заданным темпом
if(f_out<f_zad)f_out=f_zad;//если стало меньше задания, то ставим частоту равной заданию
}
}else{//иначе нет разрешения работы (стоп)
if(f_out<f_zad_min){f_out=0;}//если выходная частота меньше минимума, то ставим ноль
else{f_out=f_out-df;}//иначе тормозим с заданным темпом
}
//расчет амплитуды выходного напряжения пропорционально частоте
//т.к. принята линейная зависимость, то в относительных единицах они равны
//просто приводим к размеру представления амплитуды
u_out=(byte)(f_out>>16);
//расчет угла обобщенного вектора выходного напряжения
faza=faza+dt*(f_out>>16);//(фаза увеличивается как интеграл частоты)
if(faza>0x00FFFFFF){//если угол вышел за сектор в 60град
faza=faza-0x00FFFFFF;//находим угол вектора в новом секторе
sector++;//увеличиваем номер сектора на 1
if(sector>6)sector=1;//если сектор больше 6, то начинаем с первого
}
//расчет времени импульсов управления ключами
unsigned int t1=pgm_read_byte_near(time1+(faza>>16));//считываем из таблицы Т1
unsigned int t2=pgm_read_byte_near(time2+(faza>>16));//считываем из таблицы Т2
//умножаем Т1 и Т2 на относительную амплитуду напряжения
t1=(t1*u_out)>>8;
t2=(t2*u_out)>>8;
byte t0=255-t1-t2;//расчет времени нулевого вектора
byte fa,fb,fc;//временные переменные для компараторов фазы А,В,С
//в зависимости от сектора, в котором формируется вектор выходного напряжения, готовим необходимые значения для компараторов
//см.рис.20.5
switch (sector) {
case 1:{ //t1-100 t2-110 t0-111
PORTD |= (1 << 4); //Для контроля вых.частоты
fa=255;
fb=t0+t2;
fc=t0;
break;
}
case 2:{ //t1-110 t2-010 t0-111
fb=255;
fa=t0+t1;
fc=t0;
break;
}
case 3:{ //t1-010 t2-011 t0-111
fb=255;
fc=t0+t2;
fa=t0;
break;
}
case 4:{ //t1-011 t2-001 t0-111
PORTD &= ~(1 << 4); //Для контроля вых.частоты
fc=255;
fb=t0+t1;
fa=t0;
break;
}
case 5:{ //t1-001 t2-101 t0-111
fc=255;
fa=t0+t2;
fb=t0;
break;
}
case 6:{ //t1-101 t2-100 t0-111
fa=255;
fc=t0+t1;
fb=t0;
break;
}
}
if(!start){//стоп - формируем ноль на выход
if(f_out<f_zad_min){
fa=255;fb=255;fc=255;
}
}
//запись значений в компараторы
OCR0A = fa;
OCR0B = fa;
OCR1A = fb;
OCR1B = fb;
OCR2A = fc;
OCR2B = fc;
//приращение счетчика времени
tim++;
}
следующий вариант этой проги для тех, кто имеет МКИ на базе TM1638 с двумя четырёхразрядными индикаторами семисегментного кода с общим катодом LED & KEY
http://arduinoprom.ru/obzory-modulej/289-obzor-displeja-led-and-key-na-c...
Слева заданная частота, справа текущая
Интенсивность разгона около 50 сек. до 50 Гц.
сейчас df=100
меняйте и смотрите
А3 - STB
А2 - CLK
А1 - DIO
A0 - готовность появляется через 2 секунды после включения, подача силового питания на ключи.
D6 - HU, D5 - LU фаза А
D10 - HV, D9 - LV фаза В
D11 - HW, D3 - LW фаза С
А4 - меандр, контроль частоты.
Для повышения максимальной частоты менять константы пересчета туда и обратно
const unsigned long dt=2566;//коэф.интегрирования частоты для получения фазы. подобрать для получения 50Гц при f_zad=0x00FFFFFF
fz=f*20*0x4189;
ff=ff/float(0x00FFFFFF); ff=ff*50.0; условия ограничения задания с кнопок
не забудьте добавить в библиотеку TM1638
#include <TM1638.h>
//таблица времени T1
const unsigned int PROGMEM time1[] = {
220,220,219,219,218,218,217,217,216,215,215,214,214,213,213,212,212,211,210,210,209,209,208,207,207,206,206,205,204,204,203,202,202
,201,201,200,199,199,198,197,197,196,195,195,194,193,193,192,191,191,190,189,188,188,187,186,186,185,184,183,183,182,181,181,180,179
,178,178,177,176,175,175,174,173,172,172,171,170,169,168,168,167,166,165,164,164,163,162,161,160,160,159,158,157,156,156,155,154,153
,152,151,151,150,149,148,147,146,145,145,144,143,142,141,140,139,139,138,137,136,135,134,133,132,131,131,130,129,128,127,126,125,124
,123,122,122,121,120,119,118,117,116,115,114,113,112,111,110,109,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92
,91,90,89,88,87,86,85,84,83,82,81,80,79,78,78,77,76,75,74,73,72,71,70,69,68,67,65,64,63,62,61,60,59,58,57,56,55,54,53
,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,24,23,22,21,20,19,18,17,16,15,14,13
,12,11,10,9,8,7,6,5,4,3,2,1 };
//таблица времени T2
const unsigned int PROGMEM time2[] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41
,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,78,79,80
,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,109,110,111,112,113,114,115
,116,117,118,119,120,121,122,122,123,124,125,126,127,128,129,130,131,131,132,133,134,135,136,137,138,139,139,140,141,142,143,144,145
,145,146,147,148,149,150,151,151,152,153,154,155,156,156,157,158,159,160,160,161,162,163,164,164,165,166,167,168,168,169,170,171,172
,172,173,174,175,175,176,177,178,178,179,180,181,181,182,183,183,184,185,186,186,187,188,188,189,190,191,191,192,193,193,194,195,195
,196,197,197,198,199,199,200,201,201,202,202,203,204,204,205,206,206,207,207,208,209,209,210,210,211,212,212,213,213,214,214,215,215
,216,217,217,218,218,219,219,220 };
//по предварительным опытам частота шим получилась 7692,30769Гц
volatile unsigned long f_zad=0x00FFFFFF;//задание на частоту в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long f_zad_max=0x00FFFFFF;//максимум задание на частоту в отн.единицах, что соотв. 50 Гц
const unsigned long f_zad_min=0x19999A;//минимум задание на частоту в отн.единицах, что соотв. 5 Гц
volatile unsigned long f_out;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
const unsigned long df=050;//шаг приращения вых.частоты до задания, подобрать для получения разгона 50Гц/100сек
volatile byte u_out=1;//амплитуда на выход в отн.единицах 0-255, что соотв. 0-100%
//делим полный оборот вектора напряжения на сектора
//в каждом секторе отдельно накапливаем фазу до максимума и переходим к след.сектору
//при накоплении до 6 сектора начинаем с начала
volatile unsigned long faza=0; //угол вектора в секторе 0..0x00FFFFFF
volatile byte sector=1;//сектор 1..6
const unsigned long dt=2566;//коэф.интегрирования частоты для получения фазы. подобрать для получения 50Гц при f_zad=0x00FFFFFF
//TM1638 module(8, 9, 7);// define a module on data pin 8, clock pin 9 and strobe pin 7
TM1638 tm(A1, A2, A3);//подключаем кнопки и индикатор DATA-A1 CLK-A2 STRB-A3
volatile boolean start=false; //разрешение работы инвертора
volatile unsigned int tim=0;//счетчик времени
unsigned long f=5;//задание частоты
unsigned long fz;//задание частоты для шим
unsigned int ttim,tims;
volatile unsigned long fout;//частота на выход в отн.единицах 0..0x00FFFFFF, что соотв. 0-50 Гц
void setup()
{
Serial.begin(115200); // connect to the serial port
Serial.println("Test begin");
//управление подачей силового питания
pinMode(A0, OUTPUT);
digitalWrite(A0,LOW);
DDRD = 0xFC; // весь порт D - выход, кроме RX TX
DDRB = 0xFF; // весь порт B - выход
f_out=f_zad_min;
//Настройка и запуск таймеров
Setup_timer();
tm.clearDisplay();
tims=0;
}
void loop(){
byte keys;
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
ttim=tim;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
if(ttim>3500){//каждые 0.5сек
//читаем кнопки
keys = tm.getButtons();
//Serial.print("keys=");Serial.println(keys);
//читаем задание на частоту
if(keys==4){// уменьшить задание
f--; if(f<5)f=5;
}else{
if(keys==8){// увеличить задание
f++; if(f>50)f=50;
}
}
fz=f*20*0x4189;
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
f_zad=fz; //новое задание
tim=0;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
if(keys==2){// start
start=true;
}
if(keys==1){// stop
start=false;
}
//вывод задания и выхода на индикатор Гц
//tm.setDisplayToDecNumber( f*10000+fout, 0, false);
//tm.setNumber(f,3);
TIMSK2 &= ~(1<<TOIE2);//Сначала останавливаем прерывания по таймеру 2
fout=f_out;
TIMSK2 |= (1<<TOIE2);//Теперь можно запустить прерывания по таймеру 2
//Serial.print("fout_1=");Serial.println(fout);
//fout=fout*50;
//Serial.print("fout_2=");Serial.println(fout);
//fout=fout/0x00FFFFFF;
//Serial.print("fout_3=");Serial.println(fout);
float ff=float(fout);
ff=ff/float(0x00FFFFFF); ff=ff*50.0;
fout=round(ff);
String s1,s2;
s1=String(f);while(s1.length()<4){s1=" "+s1;}
s2=String(fout);while(s2.length()<4){s2=" "+s2;}
s1=s1+s2;
tm.setDisplayToString(s1);
//счет выдержки для подачи силового питания
tims++;
if(tims>4){//2 сек
tims=0;
digitalWrite(A0,HIGH);
}
}
}
//******************************************************************
// Настройка таймеров
void Setup_timer() {
// TIMER0
TCCR0A |= (1<<COM0A1); // COM0A1, COM0A0: 1 0 - None-inverted mode для OC0A, для инверсного режима ШИМ нужно 1 1
TCCR0A &= ~(1<<COM0A0);
TCCR0A |= (1<<COM0B1); // COM0B1, COM0B0: 1 0 - None-inverted mode для OC0B, для инверсного режима ШИМ нужно 1 1
TCCR0A |= (1<<COM0B0);
TCCR0A |= (0<<WGM01); // WGM02, WGM01, WGM00: 0 1 1 - Fast PWM
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<CS02); // CS02, CS01, CS00: 0 0 1 - тактовый генератор CLK
TCCR0B &= ~(1<<CS00);
TCCR0B |= (1<<CS01);
TCCR0B &= ~(1<<WGM02);
// TIMER1
TCCR1A |= (1<<COM1A1); // COM1A1, COM1A0: 1 0 - None-inverted mode для OC1A, для инверсного режима ШИМ нужно 1 1
TCCR1A &= ~(1<<COM1A0);
TCCR1A |= (1<<COM1B1); // COM1B1, COM1B0: 1 0 - None-inverted mode для OC1B, для инверсного режима ШИМ нужно 1 1
TCCR1A |= (1<<COM1B0);
TCCR1A &= ~(0<<WGM11); // WGM13, WGM12, WGM11, WGM10: 0 1 0 1 - Fast PWM, 8bit
TCCR1A |= (1<<WGM10);
TCCR1B &= ~(1<<CS12); // CS12, CS11, CS10: 0 0 1 - тактовый генератор CLK
TCCR1B &= ~(1<<CS10);
TCCR1B |= (1<<CS11);
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12);
// TIMER2
TCCR2A |= (1<<COM2A1); // COM2A1, COM2A0: 1 0 - None-inverted mode для OC2A, для инверсного режима ШИМ нужно 1 1
TCCR2A &= ~(1<<COM2A0);
TCCR2A |= (1<<COM2B1); // COM2B1, COM2B0: 1 0 - None-inverted mode для OC2B, для инверсного режима ШИМ нужно 1 1
TCCR2A |= (1<<COM2B0);
TCCR2A |= (1<<WGM21); // WGM22, WGM21, WGM20: 0 1 1 - Fast PWM
TCCR2A |= (1<<WGM20);
TCCR2B &= ~(1<<CS22); // CS22, CS21, CS20: 0 0 1 - тактовый генератор CLK
TCCR2B &= ~(1<<CS20);
TCCR2B |= (1<<CS21);
TCCR2B &= ~(1<<WGM22);
//Установить все PWM в 0
OCR0A = 0;
OCR0B = 0;
OCR1A = 0;
OCR1B = 0;
OCR2A = 0;
OCR2B = 0;
//Разрешить/запретить прерывания по таймерам
TIMSK0 &= ~(1<<TOIE0); //Запретить прерывания на таймер 0
TIMSK1 &= ~(1<<TOIE1); //Запретить прерывания на таймер 1
TIMSK2 |= (1<<TOIE2); //Разрешить прерывания на таймер 2
}
//******************************************************************
//Прерывание по таймеру 2 (TIMER2)
//Работает с частотой
ISR(TIMER2_OVF_vect) {
PORTD |= (1 << 2); //Для замера скорости
//Таймер 0 | выводы 5 и 6 | OC0B, OC0A
//Таймер 1 | выводы 9 и 10 | OC1A, OC1B
//Таймер 2 | выводы 3 и 11 | OC2B, OC2A
//разгон к заданию
if(start){//работаем
if(f_out<f_zad_min)f_out=f_zad_min;
if(f_out<f_zad){
f_out=f_out+df; if(f_out>f_zad)f_out=f_zad;
}
if(f_out>f_zad){
f_out=f_out-df; if(f_out<f_zad)f_out=f_zad;
}
}else{//стоп
if(f_out<f_zad_min){f_out=0;}
else{f_out=f_out-df;}
}
//амплитуда пропорционально частоте
u_out=(byte)(f_out>>16);
//крутим вектор
faza=faza+dt*(f_out>>16);
if(faza>0x00FFFFFF){
faza=faza-0x00FFFFFF;
sector++;
if(sector>6)sector=1;
}
//расчет времени импульсов
unsigned int t1=pgm_read_byte_near(time1+(faza>>16));
unsigned int t2=pgm_read_byte_near(time2+(faza>>16));
t1=(t1*u_out)>>8;
t2=(t2*u_out)>>8;
byte t0=255-t1-t2;
byte fa,fb,fc;
//выдаем сигналы управления от сектора
switch (sector) {
case 1:{ //t1-100 t2-110 t0-111
PORTD |= (1 << 4); //Для контроля вых.частоты
fa=255;
fb=t0+t2;
fc=t0;
break;
}
case 2:{ //t1-110 t2-010 t0-111
fb=255;
fa=t0+t1;
fc=t0;
break;
}
case 3:{ //t1-010 t2-011 t0-111
fb=255;
fc=t0+t2;
fa=t0;
break;
}
case 4:{ //t1-011 t2-001 t0-111
PORTD &= ~(1 << 4); //Для контроля вых.частоты
fc=255;
fb=t0+t1;
fa=t0;
break;
}
case 5:{ //t1-001 t2-101 t0-111
fc=255;
fa=t0+t2;
fb=t0;
break;
}
case 6:{ //t1-101 t2-100 t0-111
fa=255;
fc=t0+t1;
fb=t0;
break;
}
}
if(!start){//стоп - формируем ноль на выход
if(f_out<f_zad_min){
fa=255;fb=255;fc=255;
}
}
OCR0A = fa;
OCR0B = fa;
OCR1A = fb;
OCR1B = fb;
OCR2A = fc;
OCR2B = fc;
/*
//Для теста
//ШИМ 0, pins 6, 5
OCR0A = 0;
OCR0B = 64;
//ШИМ 1, pins 9, 10
OCR1A = 128;
OCR1B = 255;
//ШИМ 2, pins 11, 3
OCR2A = 3;
OCR2B = 250;
*/
tim++;
PORTD &= ~(1 << 2); //Для замера скорости
}
Когда станете цеплять ключи, не забудьте на выходы ШИМ поставить схемы задержки времени, чтобы избежать сквозных токов через силовые ключи.
Задержка на включение до 3 мксек (в данном случае 2,5 мксек).
Драйвер должен исключать открытие обоих ключей одновременно, самый простой способ – включить оптроны гальванической развязки встречно-параллельно.
К сожалению не умею вставлять рисунки и файлы
Вроде бы всё!!!
К сожалению не умею вставлять рисунки и файлы
а так же код.
Может, прежде чем лезть на форум. правила надо было почитать? или так душа горела "вмешаться" ?:)
ну он же должен был нам причинить радость и нанести щастье. Вот причинил и нанёс, без спроса.
добрый день!
/расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
как книга называется?
добрый день!
/расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu
как книга называется?
vahnik60@mail.ru пошли мне пробное письмо, я тебе перешлю все материалы, какие пожелаешь, а там вставляй куда хочешь сам. Надоела эта ребятня с пацанскими манерами, мало мне полторашку к пенсии добавили, ещё ваши выпендроны выслушивать. Возьми на себя распространение.
/расчет шим и метод формирования по книге \диплом\Помощь\книга с. 460.djvu как книга называется?
Добавил дисплей для первого варианта
https://youtu.be/SyC8uj3og5k
https://youtu.be/RKtLPRaU0Ws
Уважаемый Oleg.normalniy, недоумеваю от Ваших коментариев в роликах по поводу сравнения потребления тока при векторном (двугорбые полусинусоиды) и при самопальном (одногорбые полусинусоиды). Для двигателя разницы в способе формирования синусоиды напряжения нет, а вот амплитуда модулируемого напряжения синусоиды для него имеет значение, в первом случае формируются линейные напряжения 3-х фазной сети чуть не в два раза выше, чем при втором при "одинаковой", вроде бы, амплитуде на RC-цепочке. Первый классический способ гарантируется 100% использования ресурса постоянного напряжения источника, а второй менее 70%. Вы можете в этом убедиться, если подцепите на силовые выходы инвертора "звезду" из 3-х RC-цепей (например 1 мкф, 30k), образующих искусственную среднюю точку. Увидите фвзные напряжения в масштабе в обоих случаях. Успехов в экспериментах, берегите себя.
пост #94
доброго времени . собрал на макетке , прошил код ,
все 3 верхних шим просто включены и не управляются ,
управляются только нижние .
это так специально или у меня при загрузке косяк ?
При не запущенном ШИМ открыты три верхние ключи, нижние отключены. При включении ШИМ в каждом плече один из ключей включен, второй выключен и наоборот. Вероятно, у Вас неверный код программы. Пришлитемне письмо на почту vahnik60mail.ru , я вышлю исходники для двух вариантов программы. Первый вариант с заданием частоты резистивным задатчиком, второй - с МКИ на TM1638.
Вариант и LCD-дисплеем не смотрел (не моя переделка), он оказался недоделанным в плане индикации.
Дипломная работа частотный привод
https://yadi.sk/d/hFfTlAGVB6TIBw