Генератор Arduino с регулировкой частоты и скважности по двум каналам.
- Войдите на сайт для отправки комментариев
Втр, 21/02/2017 - 14:42
скетч arduino nano генератора на два канала с регулировкой частоты и скважности с библиотекой PWM.h.
Библиотека позволяет начинающему без особых танцев с бубном вокруг регистров выдать по двум каналам регулируемую частоту с регулируемым ШИМом.
Теперь вопрос:
Как сделать, чтобы фронты начала сигналов 1 и второго каналов совпадали по фазе?
// генератор сигналов с регулировкой частоты и скважности по двум каналам. // частота от 0 до 100 кГц, ШИМ от 0 до 255 // //подключение библиотек ********************************************************************* #include <PWM.h> #include <LiquidCrystal.h> LiquidCrystal lcd (2, 12, 4, 5, 6, 7); // назначение пин LCD (rs, enable, d4, d5, d6, d7) //******************************************************************************************** //определение пинов ************************************************************************** #define OK_PIN 8 // кнопка ОК (можно любой пин) #define OUT_1_PIN 9 // пин для генератора сигналов (не менять) #define OUT_2_PIN 10 // пин для генератора сигналов (не менять) #define LEFT_PIN A0 // кнопка ЛЕВО (можно любой пин) #define RIGHT_PIN A1 // кнопка ПРАВО (можно любой пин) //********************************************************************************************* //объявление переменных *********************************************************************** int PWM_1 = 200; // стартовое значение ШИМ_1 от 0 до 255 int PWM_2 = 50; // стартовое значение ШИМ_2 от 0 до 255 int32_t frequency = 10000; // стартовое значение частоты в Гц byte hag = 0; // стартовое значение выбора режима int mnog = 1; // стартовое значение коэф. частоты int flag = 0; // стартовое флага //********************************************************************************************* // ******************************************************************************************** void setup() { InitTimersSafe(); // инициализация таймеров //инициализация lcd ************************************************************************* lcd.begin(16, 2); lcd.clear(); lcd. noCursor(); //******************************************************************************************* // назначение портов ************************************************************************ pinMode(OUT_1_PIN, OUTPUT); pinMode(OUT_2_PIN, OUTPUT); pinMode(LEFT_PIN, INPUT); pinMode(RIGHT_PIN, INPUT); pinMode(OK_PIN, INPUT); // ****************************************************************************************** bool success_1 = SetPinFrequencySafe(OUT_1_PIN, frequency); // первоначальная установка частоты на первом выходе delay(50); bool success_2 = SetPinFrequencySafe(OUT_2_PIN, frequency); // первоначальная установка частоты на втором выходе delay(50); pwmWrite(OUT_1_PIN, PWM_1); // первоначальная установка ШИМ на первом выходе pwmWrite(OUT_2_PIN, PWM_2); // первоначальная установка ШИМ на втором выходе // вывод на экран ***************************************************************************** lcd.setCursor(0, 0); lcd.print(frequency); lcd.print("Hz * "); lcd.setCursor(15, 0); lcd.print(mnog); lcd.setCursor(0, 1); lcd.print("1PWM"); lcd.setCursor(4, 1); lcd.print(PWM_1); lcd.setCursor(9, 1); lcd.print("2PWM"); lcd.setCursor(13, 1); lcd.print(PWM_2); } // ******************************************************************************************** // основной цикл программы ********************************************************************** void loop() { if ((digitalRead(LEFT_PIN) == HIGH) || (digitalRead(RIGHT_PIN) == HIGH) // если нажата любая кнопка || (digitalRead(OK_PIN) == HIGH)) { key(); // то вызов подпрограммы опроса кнопок } bool success_1 = SetPinFrequencySafe(OUT_1_PIN, frequency); // установка частоты на первом выходе delay(10); bool success_2 = SetPinFrequencySafe(OUT_2_PIN, frequency); // установка частоты на втором выходе delay(10); pwmWrite(OUT_1_PIN, PWM_1); // установка ШИМ на первом выходе pwmWrite(OUT_2_PIN, PWM_2); // установка ШИМ на втором выходе } //************************************************************************************************* // подпрограмма опроса кнопок и установки частоты и скважности ************************************ void key() { if (digitalRead(OK_PIN) == HIGH) // если нажата кнопка ОК - перебор коэф. для частоты и ШИМ { switch (hag) { case 0: // выбор множителя частоты (1) lcd.setCursor(12, 0); lcd.print(" 1"); mnog = 1; flag = 0; break; case 1: // выбор множителя частоты (10) lcd.setCursor(12, 0); lcd.print(" 10"); mnog = 10; flag = 0; break; case 2: // выбор множителя частоты (100) lcd.setCursor(12, 0); lcd.print(" 100"); mnog = 100; flag = 0; break; case 3: // выбор множителя частоты (1000) lcd.setCursor(12, 0); lcd.print(" 1K"); mnog = 1000; flag = 0; break; case 4: // выбор множителя частоты (5000) lcd.setCursor(12, 0); lcd.print(" 5K"); mnog = 5000; flag = 0; break; case 5: // выбор 1 канала для регулировки ШИМ lcd.setCursor(12, 0); lcd.print("1PWM"); flag = 1; break; case 6: // выбор 2 канала для регулировки ШИМ lcd.setCursor(12, 0); lcd.print("2PWM"); flag = 2; break; case 7: // перебор параметров по кругу flag = 0; break; } hag = hag + 1; delay(100); // приращение счетчика if (hag == 8) hag = 0; } if (flag == 0) // флаг выборов режима настройки ШИМ или частоты (по умолчанию флаг =0 - настройка частоты) { if (digitalRead(LEFT_PIN) == HIGH) // если нажата кнопка ЛЕВО { frequency = frequency - mnog; // то уменьшение частоты на выбранный коэф. if (frequency < 0) // если частота меньше 0 { frequency = 0; // то частота =0 } delay(100); // защита от дребезга } if (digitalRead(RIGHT_PIN) == HIGH) // если нажата кнопка ПРАВО { frequency = frequency + mnog; // то увеличение частоты if (frequency >= 99999) // если частота больше 99 999 { frequency = 99999; // то частота = 99 999 } delay(100); // защита от дребезга } lcd.setCursor(0, 0); // вывод на экран частоты lcd.print(frequency); lcd.print("Hz * "); // вывод на экран } if (flag == 1) // флаг выборов режима настройки ШИМ 1 { if (digitalRead(LEFT_PIN) == HIGH) // если нажата кнопка ЛЕВО { PWM_1 = PWM_1 - 5; // то уменьшение ШИМ на 5 if (PWM_1 < 10) // если ШИМ меньше 10 { PWM_1 = 10; // то ШИМ = 10 } delay(100); // защита от дребезга } if (digitalRead(RIGHT_PIN) == HIGH) // если нажата кнопка ПРАВО то приращение ШИМ на 5 { PWM_1 = PWM_1 + 5; if (PWM_1 > 255) // если ШИМ больше 255 { PWM_1 = 255; // то ШИМ = 255 } delay(100); //Serial.print("PWM1= "); Serial.println(PWM_1); // защита от дребезга } } if (flag == 2) // флаг выбора режима настройки ШИМ 2 { if (digitalRead(LEFT_PIN) == HIGH) // аналогично ШИМ первого канала { PWM_2 = PWM_2 - 5; if (PWM_2 < 10) { PWM_2 = 10; } delay(100); } if (digitalRead(RIGHT_PIN) == HIGH) { PWM_2 = PWM_2 + 5; if (PWM_2 > 255) { PWM_2 = 255; } delay(100); } } // вывод на экран ШИМ 1,2 *************************************************************************** lcd.setCursor(4, 1); if (PWM_1 < 100) { lcd.print("0"); lcd.print(PWM_1); } else { lcd.print(PWM_1); } lcd.setCursor(13, 1); if (PWM_2 < 100) { lcd.print("0"); lcd.print(PWM_2); } else { lcd.print(PWM_2); } //*************************************************************************************************** }
собрал схему в симуляторе PROTEUS. все работет. если надо приложу к теме.
...генератора на два канала с регулировкой частоты и скважности...
...выдать по двум каналам регулируемую частоту...
Теперь вопрос:
Как сделать, чтобы фронты начала сигналов 1 и второго каналов совпадали по фазе?
Это принципиально невозможно.
При различной частоте фаза между сигналами неизбежно будет меняться.
Если же Вам нужно не два сигнала с регулируемой частотой и скважностью, а строго одну частоту с двумя вариантами скважности, то нужно применить подход противоположный тому, что используется в библиотеке, а именно - брать сигнал не с разных, а с одного и того же таймера.
частота у обоих каналов одна. и регулируется сразу для обоих каналов.
можно сдвинуть фазу второго канала жесткой логикой, но не хочется огород городить
Если же Вам нужно не два сигнала с регулируемой частотой и скважностью, а строго одну частоту с двумя вариантами скважности, то нужно применить подход противоположный тому, что используется в библиотеке, а именно - брать сигнал не с разных, а с одного и того же таймера.
[/quote]
а как брать сигнал не с разных, а с одного и того же таймера? необходимо лезть в библиотеку?
Можно вообще без библиотеки. Прямо таймер запрограмировать. Как раз два канала.
Можно вообще без библиотеки. Прямо таймер запрограмировать. Как раз два канала.
а как таймер без танцев запрограмировать? чтоб 2 канала регулировать по частоте и ШИМу?
этож надо матчасть учить. староват я.
с библиотекой получилось просто. не обладая знаниями работы конроллера.
вопрос только один - как только сдвинуть фронт второго канала?
подозреваю что надо копать бибилиотеку (менять условия сравнения таймеров)
Библиотека позволяет начинающему без особых танцев с бубном вокруг регистров выдать по двум каналам регулируемую частоту с регулируемым ШИМом.
[cut]
Как сделать, чтобы фронты начала сигналов 1 и второго каналов совпадали по фазе?
Выкинуть библу на помойку. Запрограммировать таймер в FAST-PWM режим.
частота у обоих каналов одна. и регулируется сразу для обоих каналов.
можно сдвинуть фазу второго канала жесткой логикой, но не хочется огород городить
сразу так и подумалось - решить аппаратно
судя по всему то да. аппаратно
5335, а что вы сможете аппаратно сделать? Точка отсчёта (т.е. синхронизации) в "Phase Correct" режиме всегда в середине ипульсов, и время, на которое нужно двигать один импульс относительно второго зависит от разницы их скважности, т.е. эта величина не постоянная. Что бы реализовать аппаратно сие придёться делать автоматическую подстройку фазы, а это уже серьёзное устройство. Ну или просто научиться программировать таймеры :)
спасибо добрый человек.
dimax, Phaze Correct - далеко не единственный режим работы таймера. Раз уж надо привязать фронты друг к другу, целесообразно использовать какой-то из режимов, осуществляющих счет по "пиле", а не "треугольнику".
andriano, если вы не заметили, то в #7 я именно про это и написал :) По "пиле" всего два режима. В СТС нет возможности регулировать скважность, остаётся один вариант -FastPWM
dimax, Phaze Correct - далеко не единственный режим работы таймера. Раз уж надо привязать фронты друг к другу, целесообразно использовать какой-то из режимов, осуществляющих счет по "пиле", а не "треугольнику".
вот по этой диаграмме "железо - углерод"?
Посмотрите в интернете. Множество статей например
https://embedderslife.wordpress.com/2012/04/02/%D0%BA%D1%80%D0%B0%D1%82%...
и в даташите. Ничего сложного. Реально четыре строчки в setup и три в loop.
Не так просто.
ТС частоту тоже надо регулировать, а значит есть сложности с использование ДВУХ каналов сравнения у таймера. Частотой придется управлять, используя прерывание переполнения таймера, по которому инициализировать начальное значение таймера не в 0, а в то, что нужно для точной частоты.
Этот подход - самый верный, но требует от программиста аккуратности в обработке граничных случаев. Иначе будет непредсказуемое поведение.
ну все. добили меня.
wdrakula, формально ТС лишь озвучил желание, чтобы можно было регулировать частоту. Но нигде не уточнял, что регулировка должна быть плавной. Можно выбирать предделители. Можно управлять разрядностью...
Ну и, в конце концов, кое-где на таймер приходится по 3 канала сравнения.
wdrakula, не пугайте Т.С., не всё так страшно, "Mode 14" 16-битного таймера в меге позволяет крутить плавно и общую частоту, и скважность для каждого канала без прерываний и хитростей.
wdrakula, не пугайте Т.С., не всё так страшно, "Mode 14" 16-битного таймера в меге позволяет крутить плавно и общую частоту, и скважность для каждого канала без прерываний и хитростей.
А можно поподробнее с этого момента?
Только на меге?
Только на меге?
да, на 328 (уно, нано, мини) нет такой фичи.
только на 2560 и ее линейке (1280, 640).
wdrakula, не пугайте Т.С., не всё так страшно, "Mode 14" 16-битного таймера в меге позволяет крутить плавно и общую частоту, и скважность для каждого канала без прерываний и хитростей.
А можно поподробнее с этого момента?
мастер класс :)
Похоже на вашу картинку? Умеючи работы на 5 минут.. :) Скетч для меги328
вот по этой диаграмме "железо - углерод"?
Да, по этой диаграмме ушли в область чугунов, мой приятель делал аналогичное на жёсткой логике, вытянуть два сигнала на передний фронт
Увидел решение Дмитрия! Красиво!!!
вот по этой диаграмме "железо - углерод"?
Не, по Шеффлера.))))
вот по этой диаграмме "железо - углерод"?
Не, по Шеффлера.))))
Надо же, сие прошло мимо меня, хоть узнал, что и такое есть)))
Ферриты и аустениты )))
А мне импонировали ледебуриты )))
Увидел решение Дмитрия! Красиво!!!
Оно вам ничего не напомнило? :)
мастер класс :)
Похоже на вашу картинку? Умеючи работы на 5 минут.. :) Скетч для меги328
[/quote]
вах! Промежгородняя!
как во всем этом благолепии менять частоту и скважность?
OCRой или ICRой?
5335, ICR -длительность периода в тактах МК. Или герцах = F_CPU/(ICR+1) ; OCR -длительность лог "1" (импульса) на выходе в тактах МК, то бишь скважность. Отсюда сразу главное правило - OCR не должен быть больше чем ICR. Ну и скважность в проценты самостоятельно пересчитаете.
Похоже на вашу картинку? Умеючи работы на 5 минут.. :) Скетч для меги328
Мой косяк! Просто я плохо искал.
Так что на любом есть. Я - наврал. Сорри.
Единственно, что все регистры у таймера1 - по 16 бит и их советуют в скобках cli/sti изменять.
Увидел решение Дмитрия! Красиво!!!
Оно вам ничего не напомнило? :)
конечно напомнило, скетч написан, опробован, потом перевёл с ШИМа на ЦАП, но затею не похоронил, есть проблемы с оцифровкой датчика тока, шумы 50 милливольт, избавляюсь
5335, ICR -длительность периода в тактах МК. Или герцах = F_CPU/(ICR+1) ; OCR -длительность лог "1" (импульса) на выходе в тактах МК, то бишь скважность. Отсюда сразу главное правило - OCR не должен быть больше чем ICR. Ну и скважность в проценты самостоятельно пересчитаете.
вот спасибо!
а мне мне говорили, что программисты народ конкретный.
дадут совет настолько точный, насколько бесполезный!
ан нет, есть порох в пороховницах и Дробь в ягодицах.
если что кому что отковать, милости просим
а мне мне говорили, что программисты народ конкретный. дадут совет настолько точный, насколько бесполезный!
Совершенно верно говорили! У меня готовой шаблон был, поэтому нетрудно было. Иначе бы ограничился фразой из #7.
Пересобрал скетч - все заработало как надо. Миллиард благодарностей.
Аппаратно тоже можно. Отрезается левая часть сигнала TTL логикой 2 элемента И-НЕ и 2 элемента ИЛИ-НЕ. Но не так красиво
а как тоже самое сделать на MEGE 2560?
а как тоже самое сделать на MEGE 2560?
а зачем?
Собрал на 2-х nano электроэрозионный станочек: одна управляет приводом, вторая - генератор - куча соединительных связей между платами наводки от силовых ключей ловит
хочется на одной меге все сделать
Можно мне тоже генератор ардуино ?
А то я как дурак их у китайцев покупаю.
Можно, разрешаем.
смотря для чего генератор. для эрозионки нужно 2 канала с одной частотой и разной скважностью. 1 - на поджиг дуги. 2-й на горение.
таких китайцы не делают
Так можно или нет на меге?
Или на stm
5335, конечно можно. Но не думаю, что кто-то будет писать код за вас :)
А проверить смогут.?
вижу форум превратился - сделай сам.
Я бы по генератору электроэрозии пообщался где то в ЛС (KestGts@GMAIL.COM)
4 канала - излишне
2 - нормально
1 канал формирует сигнал для включения высоковольтного транзистора- поджиг дуги
2 канал формирует сигнал включения низковольтного транзистора но с большей скважностью
оба канала формируют так называемый стульчик для EDM
Здравствуйте уважаемые коллеги.
Помогите разобраться по этому генералу на 2 канала. Спасибо.