Микроконтроллер для БТГ
Начертил как на макетке собратьAbadiya пишет: Посмотри на этот код.
2 канала; 30-60 кГц с шагом 1 Гц; 2-й канал с синхронизацией; управление- 3 кнопки; Все параметры выводятся на PC терминал.
1. Выход на Push-pull - аппаратный ШИМ ATMega: регулировка частоты + ширина импульса
2. Этот же выход идёт на 2 аппаратных прерывания, по подъёму и спаду для 2-х полупериодов, так же сигнал на для Tesla. Регулируется смещение от начала фронта основного сигнала (Push-pull), регулируется ширина импульса+ пачки импульсов 1-** если включена пачка импульса, то отдельно регулируется пауза между импульсами.
3. Включить / отключить пачки импульсов в противофазе на втором полупериоде
ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ] [ Нажмите, чтобы скрыть ]
/*
Copyright release under LGPL (GNU General Public License), as well as a non-commercial use.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
For legal advice on subjects of Copyright, Trademarks and Patents please consult
legal counsel at myattorneyusa.com
*/
#include "CyberLib.h"
#include <PWM.h>
//byte pin1=4, pin2=5, pin3=6; // pin кнопок
bool p1, p2, p3;
int pwm = 9; // pwm out Push-pull
int32_t f=100;
int duty=128;
int shift=1;
int dutyTT=1;
int packet=1;
int packet_del=1;
int pac=0;
int cycle=0;
bool success;
int mode=1;
// 1 - частота ШИМ
// 2 - ширина ШИМ
// 3 - Сдвиг 2-го импульса
// 4 - Ширина 2-го импульса
// 5 - Количество импульсов
// 6 - пауза между импульсами
// 7 - вкл/выкл противофазы
void setup()
{
Serial.begin(115200);
Serial.println("Init device");
Serial.println("mode: PWM Frequency HZ");
InitTimersSafe();
bool success = SetPinFrequencySafe(pwm, f);
D10_Out; //Настраиваем pin D10 на выход
D9_Out;
D4_In;
D5_In;
D6_In;
D2_In;
D2_High;
D4_High;
D5_High;
D6_High;
//pinMode(2, INPUT_PULLUP);
attachInterrupt(0, Kick,RISING );
}
void loop()
{
label:
p3=D4_Read;
p2=D5_Read;
p1=D6_Read;
if (p1==LOW && p2==HIGH && p3==HIGH) {mode++;
if (mode>9)
{
mode=1;
}
switch (mode) {
case 1:
Serial.println("mode: PWM Frequency HZ"); // Частота основного сигнала
break;
case 2:
Serial.println("mode: PWM Duty %"); // Ширина оснеовного сигнала
break;
case 3:
Serial.println("mode: Shift TT impulse uS"); // сдвиг второго импульча относительно первого
break;
case 4:
Serial.println("mode: Duty TT impulse uS"); // ширина второго импульса
break;
case 5:
Serial.println("mode: Impulses packet"); // пачкоген. количество импульсов
break;
case 6:
Serial.println("mode: Pause between impulses uS"); // пауза между импульсами в пакете
break;
case 7:
Serial.println("mode: Second cycle ON/OFF"); // включение импульса во втором полупериоде
break;
case 8:
Serial.println("mode: Save Data"); // включение импульса во втором полупериоде
break;
case 9:
Serial.println("mode: Load Data"); // включение импульса во втором полупериоде
break;
// default:
}
delay_ms(300);
}
if (p3==LOW && p2==HIGH && p1==HIGH)
{
switch (mode){
case 1:
f++;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
break;
case 2:
duty++;
if (duty>255) duty=255;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(duty);
break;
case 3:
shift++;
Serial.println(shift);
break;
case 4:
if (dutyTT==0){
detachInterrupt(0);
attachInterrupt(0, Kick,RISING );
}
dutyTT++;
Serial.println(dutyTT);
break;
case 5:
packet++;
Serial.println(packet);
break;
case 6:
packet_del++;
Serial.println(packet_del);
break;
case 7:
cycle=1;
attachInterrupt(1, KickInv,FALLING );
Serial.println("Second cycle ON!");
break;
case 8:
WriteEEPROM_Long(0, f);
WriteEEPROM_Byte(10, duty);
WriteEEPROM_Long(15, shift);
WriteEEPROM_Long(25, dutyTT);
WriteEEPROM_Byte(35, packet);
WriteEEPROM_Byte(36, packet_del);
WriteEEPROM_Byte(37, cycle);
Serial.println("Data saved!");
break;
case 9:
f = ReadEEPROM_Long(0);
duty = ReadEEPROM_Byte(10);
shift = ReadEEPROM_Long(15);
dutyTT = ReadEEPROM_Long(25);
packet = ReadEEPROM_Byte(35);
packet_del = ReadEEPROM_Byte(36);
cycle = ReadEEPROM_Byte(37);
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
if (cycle==1) attachInterrupt(1, KickInv,FALLING );
else detachInterrupt(1);
Serial.println("Data loaded!");
break;
}
delay_ms(100);
}
if (p2==LOW && p1==HIGH && p3==HIGH)
{
switch (mode){
case 1:
f--;
if (f<50)f=50;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
break;
case 2:
duty--;
if (duty<0) duty=0;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(duty);
break;
case 3:
shift--;
if (shift<=0)shift=1;
Serial.println(shift);
break;
case 4:
dutyTT--;
if(dutyTT<=0){dutyTT=0;
detachInterrupt(0);
attachInterrupt(0, Kick1,RISING );
Serial.println(dutyTT);
}
break;
case 5:
packet--;
if (packet<1)packet=1;
Serial.println(packet);
break;
case 6:
packet_del--;
if (packet_del<0)packet_del=0;
Serial.println(packet_del);
break;
case 7:
cycle=0;
detachInterrupt(1);
Serial.println("Second cycle OFF!");
break;
case 8:
WriteEEPROM_Long(0, f);
WriteEEPROM_Byte(10, duty);
WriteEEPROM_Long(15, shift);
WriteEEPROM_Long(25, dutyTT);
WriteEEPROM_Byte(35, packet);
WriteEEPROM_Byte(36, packet_del);
WriteEEPROM_Byte(37, cycle);
Serial.println("Data saved!");
break;
case 9:
f = ReadEEPROM_Long(0);
duty = ReadEEPROM_Byte(10);
shift = ReadEEPROM_Long(15);
dutyTT = ReadEEPROM_Long(25);
packet = ReadEEPROM_Byte(35);
packet_del = ReadEEPROM_Byte(36);
cycle = ReadEEPROM_Byte(37);
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
if (cycle==1) attachInterrupt(1, KickInv,FALLING );
else detachInterrupt(1);
Serial.println("Data loaded!");
break;
}
delay_ms(100);
}
if (p3==LOW && p2==HIGH && p1==LOW && mode==1)
{
f=f+100;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
delay_ms(100);
}
if (p2==LOW && p1==HIGH && p3==LOW && mode==1)
{
f=f-100;
if (f<50)f=50;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
delay_ms(100);
}
//analogWrite(9,30);
goto label;
}
void Kick()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
delay_us(dutyTT);
D10_Low;
if(packet_del>0)delay_us(packet_del);
pac++;
}
}
void Kick1()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
D10_Low;
pac++;
}
}
void KickInv()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
delay_us(dutyTT);
D10_Low;
if(packet_del>0)delay_us(packet_del);
pac++;
}
}
Есть желание? помоги дороботать! Частота от 1,0 до 2,0 МГЦ не реализована. Нужно подключать модуль AD9850
Эх не дочертил выходы, сейчас доделаю и выложу.
Если враги отечества не заблокируют.
Т.к. нашлась в рюкзаке DUE - переписываю скетч и схему подключения для DUE.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
VOYAGE пишет: Парни, треба полноценный генератор меандра и синуса с независимой регулировкой каналов. Три канала нужно. С выходом прямиком на ключи типа ирф. Слыхивал кто то ваяет на счетчиках. Частота до 2мгц. Если кто готов спаять плату пишите в приват. Наличие дисплея не обязательно но не откажусь =).
На счетчиках делать не буду. А вот на микроконтроллере с LCD + 3 модуля на AD9850 + усилители на выходах сделать могу. Что-то подобное , только на 3 канала.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Ага на счетчиках -еще бы на вакуумных приборах в XXI век предложил спаятьAlexeySh пишет:
VOYAGE пишет: Парни, треба полноценный генератор меандра и синуса с независимой регулировкой каналов. Три канала нужно. С выходом прямиком на ключи типа ирф. Слыхивал кто то ваяет на счетчиках. Частота до 2мгц. Если кто готов спаять плату пишите в приват. Наличие дисплея не обязательно но не откажусь =).
На счетчиках делать не буду. А вот на микроконтроллере с LCD + 3 модуля на AD9850 + усилители на выходах сделать могу. Что-то подобное , только на 3 канала.
А зачем Вы хотите на синтезаторе частот с частотой до 40 MHz делать, Ваша установка будет работать на частоте выше 2 MHz? Скважность на AD9850 как будете регулировать?
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
И враги ОТЕЧЕСТВА заблокировали дедушку.Mining пишет:
Начертил как на макетке собратьAbadiya пишет: Посмотри на этот код.
2 канала; 30-60 кГц с шагом 1 Гц; 2-й канал с синхронизацией; управление- 3 кнопки; Все параметры выводятся на PC терминал.
1. Выход на Push-pull - аппаратный ШИМ ATMega: регулировка частоты + ширина импульса
2. Этот же выход идёт на 2 аппаратных прерывания, по подъёму и спаду для 2-х полупериодов, так же сигнал на для Tesla. Регулируется смещение от начала фронта основного сигнала (Push-pull), регулируется ширина импульса+ пачки импульсов 1-** если включена пачка импульса, то отдельно регулируется пауза между импульсами.
3. Включить / отключить пачки импульсов в противофазе на втором полупериоде
ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ] [ Нажмите, чтобы скрыть ]
/*
Copyright release under LGPL (GNU General Public License), as well as a non-commercial use.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
For legal advice on subjects of Copyright, Trademarks and Patents please consult
legal counsel at myattorneyusa.com
*/
#include "CyberLib.h"
#include <PWM.h>
//byte pin1=4, pin2=5, pin3=6; // pin кнопок
bool p1, p2, p3;
int pwm = 9; // pwm out Push-pull
int32_t f=100;
int duty=128;
int shift=1;
int dutyTT=1;
int packet=1;
int packet_del=1;
int pac=0;
int cycle=0;
bool success;
int mode=1;
// 1 - частота ШИМ
// 2 - ширина ШИМ
// 3 - Сдвиг 2-го импульса
// 4 - Ширина 2-го импульса
// 5 - Количество импульсов
// 6 - пауза между импульсами
// 7 - вкл/выкл противофазы
void setup()
{
Serial.begin(115200);
Serial.println("Init device");
Serial.println("mode: PWM Frequency HZ");
InitTimersSafe();
bool success = SetPinFrequencySafe(pwm, f);
D10_Out; //Настраиваем pin D10 на выход
D9_Out;
D4_In;
D5_In;
D6_In;
D2_In;
D2_High;
D4_High;
D5_High;
D6_High;
//pinMode(2, INPUT_PULLUP);
attachInterrupt(0, Kick,RISING );
}
void loop()
{
label:
p3=D4_Read;
p2=D5_Read;
p1=D6_Read;
if (p1==LOW && p2==HIGH && p3==HIGH) {mode++;
if (mode>9)
{
mode=1;
}
switch (mode) {
case 1:
Serial.println("mode: PWM Frequency HZ"); // Частота основного сигнала
break;
case 2:
Serial.println("mode: PWM Duty %"); // Ширина оснеовного сигнала
break;
case 3:
Serial.println("mode: Shift TT impulse uS"); // сдвиг второго импульча относительно первого
break;
case 4:
Serial.println("mode: Duty TT impulse uS"); // ширина второго импульса
break;
case 5:
Serial.println("mode: Impulses packet"); // пачкоген. количество импульсов
break;
case 6:
Serial.println("mode: Pause between impulses uS"); // пауза между импульсами в пакете
break;
case 7:
Serial.println("mode: Second cycle ON/OFF"); // включение импульса во втором полупериоде
break;
case 8:
Serial.println("mode: Save Data"); // включение импульса во втором полупериоде
break;
case 9:
Serial.println("mode: Load Data"); // включение импульса во втором полупериоде
break;
// default:
}
delay_ms(300);
}
if (p3==LOW && p2==HIGH && p1==HIGH)
{
switch (mode){
case 1:
f++;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
break;
case 2:
duty++;
if (duty>255) duty=255;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(duty);
break;
case 3:
shift++;
Serial.println(shift);
break;
case 4:
if (dutyTT==0){
detachInterrupt(0);
attachInterrupt(0, Kick,RISING );
}
dutyTT++;
Serial.println(dutyTT);
break;
case 5:
packet++;
Serial.println(packet);
break;
case 6:
packet_del++;
Serial.println(packet_del);
break;
case 7:
cycle=1;
attachInterrupt(1, KickInv,FALLING );
Serial.println("Second cycle ON!");
break;
case 8:
WriteEEPROM_Long(0, f);
WriteEEPROM_Byte(10, duty);
WriteEEPROM_Long(15, shift);
WriteEEPROM_Long(25, dutyTT);
WriteEEPROM_Byte(35, packet);
WriteEEPROM_Byte(36, packet_del);
WriteEEPROM_Byte(37, cycle);
Serial.println("Data saved!");
break;
case 9:
f = ReadEEPROM_Long(0);
duty = ReadEEPROM_Byte(10);
shift = ReadEEPROM_Long(15);
dutyTT = ReadEEPROM_Long(25);
packet = ReadEEPROM_Byte(35);
packet_del = ReadEEPROM_Byte(36);
cycle = ReadEEPROM_Byte(37);
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
if (cycle==1) attachInterrupt(1, KickInv,FALLING );
else detachInterrupt(1);
Serial.println("Data loaded!");
break;
}
delay_ms(100);
}
if (p2==LOW && p1==HIGH && p3==HIGH)
{
switch (mode){
case 1:
f--;
if (f<50)f=50;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
break;
case 2:
duty--;
if (duty<0) duty=0;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(duty);
break;
case 3:
shift--;
if (shift<=0)shift=1;
Serial.println(shift);
break;
case 4:
dutyTT--;
if(dutyTT<=0){dutyTT=0;
detachInterrupt(0);
attachInterrupt(0, Kick1,RISING );
Serial.println(dutyTT);
}
break;
case 5:
packet--;
if (packet<1)packet=1;
Serial.println(packet);
break;
case 6:
packet_del--;
if (packet_del<0)packet_del=0;
Serial.println(packet_del);
break;
case 7:
cycle=0;
detachInterrupt(1);
Serial.println("Second cycle OFF!");
break;
case 8:
WriteEEPROM_Long(0, f);
WriteEEPROM_Byte(10, duty);
WriteEEPROM_Long(15, shift);
WriteEEPROM_Long(25, dutyTT);
WriteEEPROM_Byte(35, packet);
WriteEEPROM_Byte(36, packet_del);
WriteEEPROM_Byte(37, cycle);
Serial.println("Data saved!");
break;
case 9:
f = ReadEEPROM_Long(0);
duty = ReadEEPROM_Byte(10);
shift = ReadEEPROM_Long(15);
dutyTT = ReadEEPROM_Long(25);
packet = ReadEEPROM_Byte(35);
packet_del = ReadEEPROM_Byte(36);
cycle = ReadEEPROM_Byte(37);
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
if (cycle==1) attachInterrupt(1, KickInv,FALLING );
else detachInterrupt(1);
Serial.println("Data loaded!");
break;
}
delay_ms(100);
}
if (p3==LOW && p2==HIGH && p1==LOW && mode==1)
{
f=f+100;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
delay_ms(100);
}
if (p2==LOW && p1==HIGH && p3==LOW && mode==1)
{
f=f-100;
if (f<50)f=50;
success = SetPinFrequencySafe(pwm, f);
pwmWrite(pwm, duty);
Serial.println(f);
delay_ms(100);
}
//analogWrite(9,30);
goto label;
}
void Kick()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
delay_us(dutyTT);
D10_Low;
if(packet_del>0)delay_us(packet_del);
pac++;
}
}
void Kick1()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
D10_Low;
pac++;
}
}
void KickInv()
{ pac=0;
delay_us(shift);
while(pac<packet)
{
D10_High;
delay_us(dutyTT);
D10_Low;
if(packet_del>0)delay_us(packet_del);
pac++;
}
}
Есть желание? помоги дороботать! Частота от 1,0 до 2,0 МГЦ не реализована. Нужно подключать модуль AD9850
Эх не дочертил выходы, сейчас доделаю и выложу.
Если враги отечества не заблокируют.
Т.к. нашлась в рюкзаке DUE - переписываю скетч и схему подключения для DUE.
Вот так будет компактнее
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
там компаратор быстродействующий стоит на получение квадратного сигнала
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Или вместо R13 поставить digital potentiometer. И управлять с контроллера.ua4yhz пишет:
Легко.zeleniy пишет: как вы будете программировать эту скважность если нужно точное значение.?
там компаратор быстродействующий стоит на получение квадратного сигнала
Что такое квадратный сигнал ? Меандр что-ли ?
Если подстроечник стоит на одном из входов компаратора и задаёт какое-то опорное напряжение,то вообще проблем нет.
Шим 100% - 5в. Шим 50% - 2.5в. А если совсем супер точность нужна, от колебаний температуры например или питания,то заводите этот вывод в АЦП как обратную связь, и меряете с точностью 0.01в. после корректируете шим уже программно.Ресурсов у меги достаточно,она ведь загружает данные в AD9850 только при изменении настроек частоты или фазы,а так в холостую практически молотит.
Вложение не найдено
Согласно схеме речь про подстроечник R13 10ком.
Больше интересует сбои при загрузке 5 пакетов по 8 байт.Если что-то сбойнёт, то кранты вашему преобразователю(пуш-пулу) вместе с мегой и AD-шкой.Так же интересует защита,если например вход пуш-пула сунут в выход синуса генератора. Народ тут практически не различает синус от меандра,так,что это очень даже возможно...Для гальванической развязки оптрончики нужны как минимум на 10 Мгц.Это спасёт генератор,но не спасёт пуш-пул.Так же интересует синхронизация двух опорных генераторов обеих AD-шек (125 Мгц однако, и подстройки никакой нет).Например в моей плате опорничек стоит вряд ли лучше чем 10ррм*12.5=125Гц уход частоты, на практике примерно так оно и есть.
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
digital potentiometer- программируемый потенциометр. Пост на руском.ua4yhz пишет:
Если охота лишнюю крутилку иметь,то тогда уж лучше вместо резистора валкодер поставить.tesla-nsk пишет: Или вместо R13 поставить digital potentiometer. И управлять с контроллера.
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Это как пример я написал. В зависимости от точности применять можно любой доступный от 5 до 10 бит (от 32 до 1024 шагов). То в цене до $0,5-1.ua4yhz пишет:
Я бы не стал такое применять по нескольким причинам.ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ] [ Нажмите, чтобы скрыть ]tesla-nsk пишет:
digital potentiometer- программируемый потенциометр. Пост на руском.ua4yhz пишет:
Если охота лишнюю крутилку иметь,то тогда уж лучше вместо резистора валкодер поставить.tesla-nsk пишет: Или вместо R13 поставить digital potentiometer. И управлять с контроллера.
1. Что у этого потенциометра,что у ардуины одинаковое 8-ми битное АЦП.Так,что большей точности вы не добьётесь.
2. С потенциометром вам придётся задействовать вывод Аref МК для подключения внешнего АЦП.
3.Усложниться программа и добавится в схему дополнительная дорогая деталь.
Ваша идея мне тоже понравилась. К сожалению не скоро буду в своей лаборатории что бы попробовать Arduino c AD9850..
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Да этих решений тьма тьмущая в internet. Отчего свой sketch не показали? И почему регулировка с клавиатуры, энкодера со встроенной кнопкой нет? Кнопкой выбирать последовательно меню и экодером менять параметры.ua4yhz пишет: Для простого примера написал за 5 мин.не большой тестовый скетч регулировки контрастности дисплея с помощью внутреннего ШИМ (на меге32 их всего 4,на меге48 их 6 ) вместо подстроечного резистора,что ставят на вывод 3 строчных LCD . В иттоге получилось 255 шагов по 0.02в. Надеюсь точность установки выходного напряжения устроит очень даже многих.
Сейчас "примострячу" регулировку с клавиатуры и положу скетч в копилку для будущих проектов.
Видео работы:
Правда есть один не достаток, контрастность дисплея регулируется не линейно,думаю об этом все ардуинщики в курсе.За перевёрнутый дисплей звиняйте,из-за этого недостатка новое видео снимать не буду...
Я вот осмысливаю Вашу идею для управления скважностью AD9850. Не вижу памяти в AD9850 и вот получается Arduino все время будет нагружен для формирования ШИМ. Или Вы как то иначе хотите реализовать?
/Сократ/
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.