Официальный сайт компании Arduino по адресу arduino.cc
Arduino Push-pull
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Сб, 29/06/2013 - 19:10
Нужна помощь. Если где-то уже есть решения подскажите пожалуйста.
за основу было взято http://www.kerrywong.com/2010/03/12/a-power-inverter-with-arduino-pulse-source/
изменил немного скетч
void setup() { DDRD = B11111110; PORTD = B00000000; } void loop() { PORTD = B00010000; delayMicroseconds(25); // 19.36 кГц PORTD = B00100000; delayMicroseconds(25); }
получилось запустить устройство
http://www.youtube.com/watch?v=gz3YcAGV678
В перспективе добавить обратную связь для автоподстройки частоты на резонансе. Но проблема в том, что очень большой шаг изменения частоты.
25 = 19,36 кГЦ
26 = 18,62 кГц
27 = 17,93 кГц
28 = 17,29 кГц
смотрел темы :
http://cxem.net/arduino/arduino62.php
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
https://sites.google.com/site/vanyambauseslinux/arduino/tajmery-sceetcik...
но что-то не могу понять как сделать двухтактный выход ....
так, шаг уменьшился до 100 Гц, уже лучше но недостаточно...
Даже при использований прерываний и таймера 1 в режиме СТС, шаг регулировки частоты, при 19.36 кГц, будет около 50 Гц, и чем выше частота тем он будет больше. Соответственно чем ниже частота тем шаг меньше. Так что 100 Гц это нормальный шаг.
вот такой код получился
изменение частоты производится переменным резистором тоько при низком уровне на 3 пине...
если бы сделать как-то расчёт частоты для отображения на экране, но пока не придумал как....
Кароч всетаки придется использовать прерывания и таймер 1 в режиме СТС. Объясняю почему. В строке 16 100 раз подряд будет выполняться команда PORTD=B00010100. Пока она выполняется на pin4 высокий уровень, формируется первый полупериод. В 17 строке 100 раз выполняется команда PORTD=B00100100, на pin5 высокий уровень, формируется второй полупериод. И вот формироваться он будет пока не отработает 18 строка, а она вызывает функцию l_c_d(), а в ней есть задержка пол секунды. Надеюсь понятно , что второй полупериод будет слишком долгий.
Вот пример как получить генерацию заданной частоты используя прерывания и таймер 1 в режиме СТС:
Значения меньше 30 в OCR1A лучше не записывать. Так как были изменены значения регистров по умолчанию, функция analogWrite() будет работать неправильно. Скетч будет работать на дуинах с atmega168/328. При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу).
--- что-то не хочет компилироваться ...
sketch_jun30a.ino: In function 'void __vector_11()':
sketch_jun30a:19: error: 'PD4' was not declared in this scope
--- на счёт второго полупериода вы правы, недосмотрел. Хотя в моём случае это не критично. Во время генерации мерял прибором отдельно полупериоды, показания идентичны. При удержании кнопки на 5 пине держится единица пока кручу резистор но на работу устройства это особо не влияет (хотя можно попробовать обнулить этот пин).
больше напрягает настройка и индикация частоты..... хочу попробовать запустить ваш вариант, но что-то запутался в этих таймерах....
--- что-то не хочет компилироваться ...
Замените в 19 строке PD4 на 4.
всё, запустил !!!!
у вас просто опечатка... if(PORTD & (1<<PIND4))PORTD = B00100100;
Отлично, шаг тут получается 30 Гц .....
Теперь нужно прикрутить регулировку и индикацию - продолжаю мучать прерывания.
попытался сделать так
при нажатии кнопки включается индикатор и показывает изменение val_fr но потом изменённое значение НЕ передаётся в генератор...
подскажите как изменить OCR1A=val_fr; ?????
Регистр OCR1A лучше изменять в обработчике прерывания
Evgen, с меня пиво, всё работает отлично !!!!!!!!!!
прицепил на 4 и 5 пины прибор мерять частоту, посмотрел при замкнутой и разомкнутой кнопке на пин 3, частота не уходит. возможно настройку частоты можно поместит в loop() без "нулевого" прерывания. проверю это на готовом изделии.
Не сочтите за наглость, но может ещё подскажете как сюда добавить регулировку скважности ...
пока только в качестве идеи - delayMicroseconds() в обработчике прерывания с пропорциональным увеличением частоты, но что-то в цифрах запутался....
Вы хотите задавать разную длительность первого и второго полупериода?
Не не, так делать нельзя, работать не будет.
Вы хотите задавать разную длительность первого и второго полупериода?
несовсем. нужно сделать dead time - задержки между полупериодами
На рис. 4 показана форма импульсов с малой скважностью, на рис. 5 - с большей скважностью, а на рис. 6 - с максимальной скважностью.
только просто сделать задержку между полупериодами наверное не получится т.к. за время переполнения таймера будеет разное колличество импульсов (будет меняться частота).
нужно сохранять частоту при изменении скважности .
Вот реализация того, что сделано насегодня...
http://www.youtube.com/watch?v=rQ368CWKoCU&feature=youtu.be
Вот. Можно регулировать скважность переменной dead_time.
Огромное спасибо !!!!
если я правильно понял, то переменные
можно просто изменять в основной программе.
тоесть как раньше сделать прерывание на кнопку и двумя переменниками устанавливаем значения на аналоговых пинах, затем читаем их и используем в генераторе...
Да, все так. Только я этот код не проверял, пробуйте сами.
Проверил, но что-то не то получается....
вопервых при значении val_fr = 500 в "базовом" варианте реальная частота равна 16 кГц и соответствует расчётам f=16000/500/2
в новом скетче, с частотой что-то не понятное и скважность ведёт себя странно...
На последних двух скриншотах пауза между периодами задана не правильно. Я же писал там в комментах, она не должна быть больше чем (val_fr*2)-100. А вот почему остальное не работает счас буду думать.
А что за программа осциллогрф? Дайте ссылочку где скачать можно.
не помню где я её скачал, вот залил на обменник.
http://zalil.ru/34619125
а щуп делал такой http://www.illari.ru/electro/osc/
только какая-то фигня с этим осцилографом, цепляю один щуп на пин, второй на массу а на осцилографе всёравно ДВЕ полуволны.....
А если вот так попробывать ??? Только сейчас не могу проверить на железе...
Разобрался я почему неправильно работало. У дуины банально не хватает быстродействия.
Значения этих переменных, если другими словами, это такты процессора. Если какаянить из переменных равна 500, то таймер 1 отсчитает 500 тактов проца и вызовет прерывание, если 300 значит 300 тактов. Это значит что, то что написано в обработчике прерывания должно выполнится за меньшее количество тактов, а вот это как раз делаться не успевалось. Только один вход в обработчик это, я думаю, 20-30 тактов, да плюс еще там операция деления присутствует (если пауза между периодами формируется), а она много времени отнимает. К тому-же у дуины еще свои прерывания есть, например функции millis() и micros() используют таймер 0.
Для повышения быстродействия можно заменить операцию деления на два, на сдвиг вправо на один разряд (сдвиг вправо на один разряд это деление на два, сдвиг влево на один разряд это умножение на два).
Ну и нужно задать другие ограничения для переменных val_fr и dead_time. В общем вот немного подправленный скетч.
Теперь вопрос. Вы откуда осциллограммы снимаете, с пинов ардуины? С четвертого и пятого или только одного? У вас на осциллограммах только один канал показан, должно быть два. Вы второй специально отключили? Должно быть вот так:
у меня штекер "моно" ....
подключался к пин 4 и пин 5 ... хотя ессли цеплял пин+масса картинка не менялась...
А, почему у вас разная чувствительность на каналах на первом 1000, а на втором 500 ?
Так было по умолчанию при включении программы, я не трогал эту настройку.
Если вы будете снимать сигнал только с одного пина то, при формировании паузы между полупериодами, осциллограф будет неправильно высчитывать частоту. Он будет считать частоту, замеряя длительность периода, вот так
А в конечном устройстве период будет вот такой
Самое странное, что у меня картинка сигнала НЕ меняется хоть с одного пина снимаю, хоть с двух ?!?!?!
вот пример, с двух пинов ....
вот с одного пина и массы
Запустил последний скетч, вот что получилось (сигнал снимал с двух пинов)
с такими настройками на картинке колличество импульсов не меняется, а частота (в цифрах) скачет.
Но непонятно другое !!!!! почему "мёртвая зона" только с одной стороны ????
по идее и по правилам "мёртвая зона" должна быть сдвух сторон каждой полуволны...
Вы каим оброзом осциллограммы снимаете? Надо один канал линейного входа звуковой карты подключить к четвертому пину, другой к пятому. Я подключал через резисторы 100 Ом (можно побольше поставить) и ничего не сгорело. Для этого нужен разъем мини-джек "стерео". Дуину нужно от того-же компа запитывать которым осциллограммы снимаете.
У меня джек "моно" поэтому входы карты объеденены, и получается, что пин 4 на входы, пин 5 на массу.
Помогите, я кажется запутался...
выполняется функция 1 (дедтайм) по её завершении таймеру задаётся значение OCR1A=dead_time; тогда получается, что следующая функция 2 (формирование полупериода) будет выполняться в течении таймера "мёртвой зоны"...
Немного не так. Строка OCR1A=dead_time задает сколько будет длиться пауза между полупериодами. Эта функция не выполняется сколько-то долго, она просто устанавливает лог 0 на пинах 4 и 5 (ну в данном случае только на пине 4 потому, что 5 пин и так в нуле), потм задает через сколько тактов процессора должно вызваться это-же прерывание (OCR1A=dead_time) и изменяет переменную uk=2, чтобы в следующий раз в обработчике прерывания вызвалась не опять она-же, а уже другая функция, которая формирует полупериод.
Evgen, спасибо всё понял, а то, что-то запутался....
ещё.
я немного изменил строки с массивом функций, всё работает но хочется узнать на сколько это правильно.
вчера взял осцилограф (не Бог весть что, но лучше чем прога в компе)... Вот что получается.
volatile int val_fr = 900;
volatile int dead_time = 500;
volatile int val_fr = 900;
volatile int dead_time = 250;
теперь нормально видно, что "мёртвая зона" отрабатывается правильно, с двух сторон от полупериода.
Только при изменении дедтайма изменяется частота...
Думаю, что частоту (полупериод) и скважность (дедтайм) нужно расчитывать от одного числа. Тоесть "полупериод" плюс "дедтайм" должно быть равно при изменении одного из слагаемых.
В общем есть чем заниматься на выходных...
Ещё раз ОГРОМНОЕ СПАСИБО !!! за помощь...
В первой строке вы явно указали размер массива. Если все элементы массива указаны, а в данном случае они указаны в фигурных скобках, то компилятор выставит размер массива сам. Так что можно указывать, а можно не указывать, правильно и так и так.
Во второй стрчке лучше оставить тип byte. Зачем отводить под переменную два байта когда хватит и одного? Хотя конечно работать будет, но старший байт будет не задействован.
А вот на счет ухода частоты это надо подумать.
Подумал:) Получается, что-бы частота не уходила, пауза дедтайма должна полностью вычитаться из полупериода. Тогда изменим функцию формирования полупериода вот так
Это значит что дедтайм не может быть меньше 200 и больше длительности полупериода - 200
Как-то так.
Пока не могу проверить в "железе" ....
Это значит что дедтайм не может быть меньше 200 и больше длительности полупериода - 200volatile int dead_time; // пауза между периодами, не должна быть меньше 200 и больше val_fr-200
Как-то так.
Вот как-то так ....
Вот полный скетч...
Ну вроде все так. Должно работать.
Это уже проверено - работает.... СПАСИБО ЗА ПОМОЩЬ !!!!!!!
минимальный дедтайм равен 92 - установлено экспериментально .
не помню где я её скачал, вот залил на обменник.
http://zalil.ru/34619125
а щуп делал такой http://www.illari.ru/electro/osc/
Можешь перезалить?
не помню где я её скачал, вот залил на обменник.
http://zalil.ru/34619125
а щуп делал такой http://www.illari.ru/electro/osc/
Можешь перезалить?
http://radioradar.net/programms/radiomeasurements/osc.html
Спасибо, но уже нашёл получше http://www.x-io.co.uk/serial-oscilloscope/
В принципе неплохо рабтает:
http://www.youtube.com/watch?v=zDzTNyC4qJQ
Ну вроде все так. Должно работать.
Здравствуйте, вы могли бы подсказать как запустить этот скейтч на Arduino DUE ? Спасибо.
Никак. На Arduino DUE стоит совсем другой микроконтроллер на базе ARM Cortex-M3. Там совсем другие регистры и работа с портами ввода-вывода, аппаратными таймерами и прерываниями отличается от AVR.
Получается нужно с нуля писать код под DUE? А я обрадовался... Я только начинаю с ардуино, поэтому пока для меня тёмный лес.
Получается нужно с нуля писать код под DUE?
Да, код будет практически с нуля.
Спасибо. Не подскажите как правильно начать обучаться программированию именно DUE?
Сложный вопрос. Приведенный выше код выходит за рамки концепции Arduino (скажем так, ардуино это упрощение для новчиков). Там идёт работа с микроконтроллером на более низком уровне. Поэтому нужно изучать не ардуино, а сам микроконтроллер. На Arduino DUE стоит микроконтроллер фирмы Atmel, а именно SAM3X8E. Чтобы писать подобный код, как выше - надо качать даташит на микроконтроллер (который, к слову, на английском языке) и читать, изучать. Можно ещё поискать какие-нибудь книжки или статьи на русском, но по МК на базе ARM Cortex-M от Atmel я практически ничего не встречал... Для начала научитесь программировать как Ардуино, без низкоуровневого обращения к микроконтроллеру. Потому как освоить это будет очень тяжело с наскоку.
Вам проще будет взять другую ардуину, где МК ATmega (ядро AVR). Они кстати тоже разные бывают и не всегда совместимы по низкоуровневому коду. Код выше вроде подходит для МК ATmega328P, который стоит на Arduino UNO, NANO, Pro Mini.
Ну или найти/написать другой код, который не будет использовать низкоуровневую работу с микроконтроллером.
Спасибо вам.
Всем привет. Вопрос: заметил что фронты иногда скачут, то тут то там, увеличивая и уменьшая скважность От этого как можно избавиться или это обычное дело ?
я так понял, никто не в курсе ???
вот даже снял видео, https://youtu.be/ET0zkCjuRsg
скрипт по сути тот же что в шапке.
Осциллограф програмный, через звуковуху? На меньшей частоте 1-2 кГц тоже самое?
3dmax -код в шапке слишком примитивен, на длительность фронтов влияет прерывание таймера0. Если нужен сигнал стабильной формы - к вашим услугам три аппаратных таймера.