Осциллограф програмный, через звуковуху? На меньшей частоте 1-2 кГц тоже самое?
Ослик DSO-2150 USB
dimax пишет:
3dmax -код в шапке слишком примитивен, на длительность фронтов влияет прерывание таймера0. Если нужен сигнал стабильной формы - к вашим услугам три аппаратных таймера.
Дня доброго всем. Такой вопрос, залил этот скетч в уно через ардуино иде 1,06. На более новых(1,6-1,8) вообще этот код компилироваться отказывается. Короче запустил, подключил, на экране только надпись ардуино пушпулл. Подключил осцил - на фото всё видно, ничего не регулируется переменниками((( Кто-нибудь может ещё раз проверить данный скетч на правильность или у меня одного ардуина какая-то не правильная))
renoshnik пишет:
Вот полный скетч...
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц),
volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92
byte uk=0;
int f_val, d_val;
float rpm, dtm;
// ********************************************************************
// ********************************************************************
void setup() {
DDRD = B11111000; // нужные пины на выход
PORTD = B00000100; // на втором пине устанавливаем "единицу"
TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры
// TCCR1A=0; TIMSK=0;
TCCR1B=0; // мало ли что arduino IDE туда записало
TCNT1=0; // сбрасываем счетный регистр таймера 1
OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота
TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A
// TIMSK|=(1<<OCIE1A);
// Скетч будет работать на дуинах с atmega168/328.
// При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу).
TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС
lcd.begin(16, 2);
lcd.print("arduino PushPull");
}
// ********************************************************************
// ********************************************************************
void loop(){
if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0
}
// ********************************************************************
// ********************************************************************
ISR(TIMER1_COMPA_vect) {
(*mas[uk])(); // вызываем функцию по указателю
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
void poluper1(void) {
PORTD&=~(1<<5); // на пин 5 лог 0
PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод
if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет
else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту
}
void dead_time1(void) {
PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=2;
}
void poluper2(void) {
PORTD&=~(1<<4); // на пин 4 лог 0
PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод
if(dead_time<92) {OCR1A=val_fr; uk=0;}
else {OCR1A=val_fr-dead_time; uk=3;}
}
void dead_time2(void) {
PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=0;
}
// ********************************************************************
// ********************************************************************
void l_c_d() {
// работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
// работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
f_val = analogRead(A3);
val_fr = map(f_val, 0, 1023, 533, 266);
rpm = 16000000.0/val_fr/2.0; // частота в Герцах
// работаем со скважностью
// пауза между периодами, не должна быть меньше 92 и больше val_fr-91
d_val = analogRead(A2);
int max_dt = val_fr-92;
dead_time = map(d_val, 0, 1023, 91, max_dt);
dtm = dead_time/(val_fr/100.0); // скважность в процентах
if (dead_time < 92) dtm=0;
lcd.setCursor(0, 0);
lcd.print("freq Hz");
lcd.setCursor(5, 0);
lcd.print(rpm);
lcd.setCursor(0, 1);
lcd.print("dead time %");
lcd.setCursor(10, 1);
lcd.print(dtm, 1);
//delay(400);
}
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Evgen, спасибо всё понял, а то, что-то запутался....
ещё.
я немного изменил строки с массивом функций, всё работает но хочется узнать на сколько это правильно.
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
int uk=0;
вчера взял осцилограф (не Бог весть что, но лучше чем прога в компе)... Вот что получается.
volatile int val_fr = 900;
volatile int dead_time = 500;
volatile int val_fr = 900;
volatile int dead_time = 250;
теперь нормально видно, что "мёртвая зона" отрабатывается правильно, с двух сторон от полупериода.
Только при изменении дедтайма изменяется частота...
Думаю, что частоту (полупериод) и скважность (дедтайм) нужно расчитывать от одного числа. Тоесть "полупериод" плюс "дедтайм" должно быть равно при изменении одного из слагаемых.
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
нее, не совсем то, мне нужно 2 выхода работающих в противофазе, с небольшой задержной относительно друг друга, дабы Н-мост не спалить, в идеале deadTime регулировать как и частоту, наверника это уже гдето реализовано, велосипед изобретать не есть хорошо
4KLIN4, дидтайм аппаратно умеют платы: дижиспарк, микро, про-микро, леонардо. Примеров и ардуино-френдли библиотек для лёгкой реализации вашей задумки нет(или мне не встречалось).
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
нее, не совсем то, мне нужно 2 выхода работающих в противофазе, с небольшой задержной относительно друг друга, дабы Н-мост не спалить, в идеале deadTime регулировать как и частоту, наверника это уже гдето реализовано, велосипед изобретать не есть хорошо
На осцилограммах видно, что тут дедтайм регулируется...
Evgen, спасибо всё понял, а то, что-то запутался....
ещё.
я немного изменил строки с массивом функций, всё работает но хочется узнать на сколько это правильно.
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
int uk=0;
вчера взял осцилограф (не Бог весть что, но лучше чем прога в компе)... Вот что получается.
volatile int val_fr = 900;
volatile int dead_time = 500;
volatile int val_fr = 900;
volatile int dead_time = 250;
теперь нормально видно, что "мёртвая зона" отрабатывается правильно, с двух сторон от полупериода.
Только при изменении дедтайма изменяется частота...
Думаю, что частоту (полупериод) и скважность (дедтайм) нужно расчитывать от одного числа. Тоесть "полупериод" плюс "дедтайм" должно быть равно при изменении одного из слагаемых.
В хороших руках техника хорошо сохраняется )))
Эпоха перестройки, годы так 1980-1986 )))
Я на таком отлаживал схему генератора трёх уровневого стробирующего импульса (для декодеров PAL)
для TDA4510
Здравствуйте, знаю что это не спортивно, но не мог бы кто-то из знатоков дать пример кода для управлением пуш-пулл на фиксированной частоте с дедтаймом. Нашел вот такой костыль, но он создает дедтайм только "с одной стороны".
void setup ()
{
TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted
int val = 100 ;
int dead = 2 ;
analogWrite (9, val) ;
analogWrite (10, val+dead) ;
}
void loop ()
{}
Регулировать нужно только скважность, никаких дополнительных наворотов кроме дедтайма не нужно. Спасибо.
Здравствуйте, знаю что это не спортивно, но не мог бы кто-то из знатоков дать пример кода для управлением пуш-пулл на фиксированной частоте с дедтаймом. Нашел вот такой костыль, но он создает дедтайм только "с одной стороны".
void setup ()
{
TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted
int val = 100 ;
int dead = 2 ;
analogWrite (9, val) ;
analogWrite (10, val+dead) ;
}
void loop ()
{}
Регулировать нужно только скважность, никаких дополнительных наворотов кроме дедтайма не нужно. Спасибо.
Проблема моя в том что программист я никакой( это если коротко.
А если расширенно, то в коде из этой темы много лишних, ненужных мне функций, а т.к. почти вся программа сводится к управлению регистрами, вычленить оттуда нужную мне часть - сложно.
А пример, ссылку на который я скинул выше - гораздо более прост для понимания. Вот изготовленный мной огрызок данного кода, рабочий, проверенный на осциллографе:
//~9 TL, PH1, TMR1, PWM data value
//~10 TH, PH1, TMR1, PWM data value
const int dead_time = 10;//10 = 0.625 us
const int half_dead_time = dead_time / 2;//
int PWM = 0;
void setup()
{
pinMode(9, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit
pinMode(10, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit
}
void update_pwm(void)
{
//Limit the pwm_phx so it take the dead time into account so it not will swap over when reach end limit of workable PWM range
if (PWM > (255 - half_dead_time))
{
PWM = (255 - half_dead_time);
}
if (PWM < half_dead_time)
{
PWM = half_dead_time;
}
//All The PWM will run from 0xFF to 0x00 and up again to TOP 0xFF
//The OCRnx will automatic update when TCNTn is on TOP 0xFF by hardware
//Therefor it is sutible to change both OCRnx pair on a place where TCNT not update to ensure that the hardware automatic update NOT occur exact when only one of the two OCRnx have changed by this code
while (TCNT1 > 0x7F)
{
}
//Now it's safe to update OCR1x pair (connect to same transistor pair)
OCR1A = (255 - PWM + half_dead_time); //~9 TL PH1 TMR1
OCR1B = (PWM - half_dead_time); //~10 TH PH1 TMR1
}
void loop()
{
TCCR1A = 0xE1;//PWM, Phase Correct 8-bit TOP at 0xFF
TCCR1B = 0x01;//clkI/O/1 (No prescaling) 31.25kHz PWM frequency
update_pwm();
pinMode(9, OUTPUT); //PWM output
pinMode(10, OUTPUT); //PWM output
while (1)
{
PWM ++;
if(PWM>128)PWM=0;
update_pwm();
delay(100);//delay timer scale is screwd up by the new PWM TMR settings
}
}
Делает вроде бы ровно то что мне нужно. Посмотрите пожалуйста нет ли в нем подводных камней, вроде возможности отказа стандартных ардуиновских функций и библиотек. И можно ли в нем изменить частоту на 62кГц? Что-то подсказывает что нужно заменить строчки 39,40, но вот на что?) Спасибо
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц),
volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92
byte uk=0;
int f_val, d_val;
float rpm, dtm;
// ********************************************************************
// ********************************************************************
void setup() {
DDRD = B11111000; // нужные пины на выход
PORTD = B00000100; // на втором пине устанавливаем "единицу"
TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры
// TCCR1A=0; TIMSK=0;
TCCR1B=0; // мало ли что arduino IDE туда записало
TCNT1=0; // сбрасываем счетный регистр таймера 1
OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота
TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A
// TIMSK|=(1<<OCIE1A);
// Скетч будет работать на дуинах с atmega168/328.
// При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу).
TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС
lcd.begin(16, 2);
lcd.print("arduino PushPull");
}
// ********************************************************************
// ********************************************************************
void loop(){
if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0
}
// ********************************************************************
// ********************************************************************
ISR(TIMER1_COMPA_vect) {
(*mas[uk])(); // вызываем функцию по указателю
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
void poluper1(void) {
PORTD&=~(1<<5); // на пин 5 лог 0
PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод
if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет
else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту
}
void dead_time1(void) {
PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=2;
}
void poluper2(void) {
PORTD&=~(1<<4); // на пин 4 лог 0
PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод
if(dead_time<92) {OCR1A=val_fr; uk=0;}
else {OCR1A=val_fr-dead_time; uk=3;}
}
void dead_time2(void) {
PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=0;
}
// ********************************************************************
// ********************************************************************
void l_c_d() {
// работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
// работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
f_val = analogRead(A3);
val_fr = map(f_val, 0, 1023, 533, 266);
rpm = 16000000.0/val_fr/2.0; // частота в Герцах
// работаем со скважностью
// пауза между периодами, не должна быть меньше 92 и больше val_fr-91
d_val = analogRead(A2);
int max_dt = val_fr-92;
dead_time = map(d_val, 0, 1023, 91, max_dt);
dtm = dead_time/(val_fr/100.0); // скважность в процентах
if (dead_time < 92) dtm=0;
lcd.setCursor(0, 0);
lcd.print("freq Hz");
lcd.setCursor(5, 0);
lcd.print(rpm);
lcd.setCursor(0, 1);
lcd.print("dead time %");
lcd.setCursor(10, 1);
lcd.print(dtm, 1);
//delay(400);
}
Гуру, подскажите почему этот код не компилируется в IDE 1.8.9 ?
Гуру, подскажите почему этот код не компилируется в IDE 1.8.9 ?
потому что любая функция должна быть описана до первого обращения к ней. А у вас ваши функции полу_пер и прочие описаны в строчках 42-62, а первое обращение к ним - в строчке 3
Поместите сами функции или их обьявление до третьей строчки - ошибки исчезнут
Гуру, подскажите почему этот код не компилируется в IDE 1.8.9 ?
потому что любая функция должна быть описана до первого обращения к ней. А у вас ваши функции полу_пер и прочие описаны в строчках 42-62, а первое обращение к ним - в строчке 3
Поместите сами функции или их обьявление до третьей строчки - ошибки исчезнут
Спасибо за подсказку. Но самое интересное что в IDE 1.5.7 компилируется.
Вот переделал
// 27-11-2019 переделал методом переноса текста , компилируется в IDE 1.8.9
// в железе надо проверить
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц),
volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92
byte uk=0;
int f_val, d_val;
float rpm, dtm;
// ********************************************************************
// ********************************************************************
void poluper1(void) {
PORTD&=~(1<<5); // на пин 5 лог 0
PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод
if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет
else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту
}
void dead_time1(void) {
PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=2;
}
void poluper2(void) {
PORTD&=~(1<<4); // на пин 4 лог 0
PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод
if(dead_time<92) {OCR1A=val_fr; uk=0;}
else {OCR1A=val_fr-dead_time; uk=3;}
}
void dead_time2(void) {
PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=0;
}
// ********************************************************************
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
// ********************************************************************
// ********************************************************************
void setup() {
DDRD = B11111000; // нужные пины на выход
PORTD = B00000100; // на втором пине устанавливаем "единицу"
TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры
// TCCR1A=0; TIMSK=0;
TCCR1B=0; // мало ли что arduino IDE туда записало
TCNT1=0; // сбрасываем счетный регистр таймера 1
OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота
TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A
// TIMSK|=(1<<OCIE1A);
// Скетч будет работать на дуинах с atmega168/328.
// При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу).
TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС
lcd.begin(16, 2);
lcd.print("arduino PushPull");
}
// ********************************************************************
// ********************************************************************
void loop(){
if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0
}
// ********************************************************************
// ********************************************************************
ISR(TIMER1_COMPA_vect) {
(*mas[uk])(); // вызываем функцию по указателю
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
void l_c_d() {
// работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
// работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
f_val = analogRead(A3);
val_fr = map(f_val, 0, 1023, 533, 266);
rpm = 16000000.0/val_fr/2.0; // частота в Герцах
// работаем со скважностью
// пауза между периодами, не должна быть меньше 92 и больше val_fr-91
d_val = analogRead(A2);
int max_dt = val_fr-92;
dead_time = map(d_val, 0, 1023, 91, max_dt);
dtm = dead_time/(val_fr/100.0); // скважность в процентах
if (dead_time < 92) dtm=0;
lcd.setCursor(0, 0);
lcd.print("freq Hz");
lcd.setCursor(5, 0);
lcd.print(rpm);
lcd.setCursor(0, 1);
lcd.print("dead time %");
lcd.setCursor(10, 1);
lcd.print(dtm, 1);
//delay(400);
}
#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,10,11,12,13);
volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц),
volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92
byte uk=0;
int f_val, d_val;
float rpm, dtm;
// ********************************************************************
// ********************************************************************
void poluper1(void) {
PORTD&=~(1<<5); // на пин 5 лог 0
PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод
if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет
else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту
}
void dead_time1(void) {
PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=2;
}
void poluper2(void) {
PORTD&=~(1<<4); // на пин 4 лог 0
PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод
if(dead_time<92) {OCR1A=val_fr; uk=0;}
else {OCR1A=val_fr-dead_time; uk=3;}
}
void dead_time2(void) {
PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу
OCR1A=dead_time; uk=0;
}
// ********************************************************************
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций
// ********************************************************************
// ********************************************************************
void setup() {
DDRD = B11111000; // нужные пины на выход
PORTD = B00000100; // на втором пине устанавливаем "единицу"
TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры
// TCCR1A=0; TIMSK=0;
TCCR1B=0; // мало ли что arduino IDE туда записало
TCNT1=0; // сбрасываем счетный регистр таймера 1
OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота
TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A
// TIMSK|=(1<<OCIE1A);
// Скетч будет работать на дуинах с atmega168/328.
// При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу).
TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС
lcd.begin(16, 2);
lcd.print("arduino PushPull");
}
// ********************************************************************
// ********************************************************************
void loop(){
if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0
}
// ********************************************************************
// ********************************************************************
ISR(TIMER1_COMPA_vect) {
(*mas[uk])(); // вызываем функцию по указателю
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
void l_c_d() {
// работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
// работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2)
f_val = analogRead(A3);
val_fr = map(f_val, 0, 1023, 533, 266);
rpm = 16000000.0/val_fr/2.0; // частота в Герцах
// работаем со скважностью
// пауза между периодами, не должна быть меньше 92 и больше val_fr-91
d_val = analogRead(A2);
int max_dt = val_fr-92;
dead_time = map(d_val, 0, 1023, 91, max_dt);
dtm = dead_time/(val_fr/100.0); // скважность в процентах
if (dead_time < 92) dtm=0;
lcd.setCursor(0, 0);
lcd.print("freq Hz");
lcd.setCursor(5, 0);
lcd.print(rpm);
lcd.setCursor(0, 1);
lcd.print("dead time %");
lcd.setCursor(10, 1);
lcd.print(dtm, 1);
//delay(400);
}
Люди ДОБРЫЕ ! ПОМОЖИТЕ! Как этот скеч сделать под регулировку тремя кнопками?
Пытаюсь слямзить с этого скеча управление , да вот мозги дымятся !!!
// генератор сигналов с регулировкой частоты и скважности по двум каналам.
// частота от 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);
}
//***************************************************************************************************
}
Осциллограф програмный, через звуковуху? На меньшей частоте 1-2 кГц тоже самое?
Ослик DSO-2150 USB
3dmax -код в шапке слишком примитивен, на длительность фронтов влияет прерывание таймера0. Если нужен сигнал стабильной формы - к вашим услугам три аппаратных таймера.
то есть таким способом проблемму не решить ? :(
Дня доброго всем. Такой вопрос, залил этот скетч в уно через ардуино иде 1,06. На более новых(1,6-1,8) вообще этот код компилироваться отказывается. Короче запустил, подключил, на экране только надпись ардуино пушпулл. Подключил осцил - на фото всё видно, ничего не регулируется переменниками((( Кто-нибудь может ещё раз проверить данный скетч на правильность или у меня одного ардуина какая-то не правильная))
Вот полный скетч...
#include <LiquidCrystal.h> LiquidCrystal lcd(8,9,10,11,12,13); void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц), volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92 byte uk=0; int f_val, d_val; float rpm, dtm; // ******************************************************************** // ******************************************************************** void setup() { DDRD = B11111000; // нужные пины на выход PORTD = B00000100; // на втором пине устанавливаем "единицу" TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры // TCCR1A=0; TIMSK=0; TCCR1B=0; // мало ли что arduino IDE туда записало TCNT1=0; // сбрасываем счетный регистр таймера 1 OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A // TIMSK|=(1<<OCIE1A); // Скетч будет работать на дуинах с atmega168/328. // При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу). TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС lcd.begin(16, 2); lcd.print("arduino PushPull"); } // ******************************************************************** // ******************************************************************** void loop(){ if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0 } // ******************************************************************** // ******************************************************************** ISR(TIMER1_COMPA_vect) { (*mas[uk])(); // вызываем функцию по указателю } // ******************************************************************** // ******************************************************************** // ******************************************************************** void poluper1(void) { PORTD&=~(1<<5); // на пин 5 лог 0 PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту } void dead_time1(void) { PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=2; } void poluper2(void) { PORTD&=~(1<<4); // на пин 4 лог 0 PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод if(dead_time<92) {OCR1A=val_fr; uk=0;} else {OCR1A=val_fr-dead_time; uk=3;} } void dead_time2(void) { PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=0; } // ******************************************************************** // ******************************************************************** void l_c_d() { // работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) // работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) f_val = analogRead(A3); val_fr = map(f_val, 0, 1023, 533, 266); rpm = 16000000.0/val_fr/2.0; // частота в Герцах // работаем со скважностью // пауза между периодами, не должна быть меньше 92 и больше val_fr-91 d_val = analogRead(A2); int max_dt = val_fr-92; dead_time = map(d_val, 0, 1023, 91, max_dt); dtm = dead_time/(val_fr/100.0); // скважность в процентах if (dead_time < 92) dtm=0; lcd.setCursor(0, 0); lcd.print("freq Hz"); lcd.setCursor(5, 0); lcd.print(rpm); lcd.setCursor(0, 1); lcd.print("dead time %"); lcd.setCursor(10, 1); lcd.print(dtm, 1); //delay(400); }>> ничего не регулируется переменниками
Возможно нужно притянуть пин. Строка 33.
Спасибо, заработало!
dimax, предлогаешь использовать таймер1 или таймер2 вместо таймер0?
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Буду ОЧЕНЬ благодарен за ответ.
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Буду ОЧЕНЬ благодарен за ответ.
А выше написанное чем не подходит ?
https://www.drive2.ru/b/572409/
Evgen, спасибо всё понял, а то, что-то запутался....
ещё.
я немного изменил строки с массивом функций, всё работает но хочется узнать на сколько это правильно.
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций int uk=0;вчера взял осцилограф (не Бог весть что, но лучше чем прога в компе)... Вот что получается.
volatile int val_fr = 900;
volatile int dead_time = 500;
volatile int val_fr = 900;
volatile int dead_time = 250;
теперь нормально видно, что "мёртвая зона" отрабатывается правильно, с двух сторон от полупериода.
Только при изменении дедтайма изменяется частота...
Думаю, что частоту (полупериод) и скважность (дедтайм) нужно расчитывать от одного числа. Тоесть "полупериод" плюс "дедтайм" должно быть равно при изменении одного из слагаемых.
В общем есть чем заниматься на выходных...
Ещё раз ОГРОМНОЕ СПАСИБО !!! за помощь...
ОГО - Это жеж ОМЛ-2М или ОМЛ-3М, я прав?
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Буду ОЧЕНЬ благодарен за ответ.
А выше написанное чем не подходит ?
https://www.drive2.ru/b/572409/
нее, не совсем то, мне нужно 2 выхода работающих в противофазе, с небольшой задержной относительно друг друга, дабы Н-мост не спалить, в идеале deadTime регулировать как и частоту, наверника это уже гдето реализовано, велосипед изобретать не есть хорошо
4KLIN4, дидтайм аппаратно умеют платы: дижиспарк, микро, про-микро, леонардо. Примеров и ардуино-френдли библиотек для лёгкой реализации вашей задумки нет(или мне не встречалось).
Люди добрые подскажите пожалуйста а как реализовать двухтактный генератр у которого 2 выхода работают в противофазе, с регулировкой частоты от 40Гц и выше...
Буду ОЧЕНЬ благодарен за ответ.
А выше написанное чем не подходит ?
https://www.drive2.ru/b/572409/
нее, не совсем то, мне нужно 2 выхода работающих в противофазе, с небольшой задержной относительно друг друга, дабы Н-мост не спалить, в идеале deadTime регулировать как и частоту, наверника это уже гдето реализовано, велосипед изобретать не есть хорошо
На осцилограммах видно, что тут дедтайм регулируется...
Evgen, спасибо всё понял, а то, что-то запутался....
ещё.
я немного изменил строки с массивом функций, всё работает но хочется узнать на сколько это правильно.
void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций int uk=0;вчера взял осцилограф (не Бог весть что, но лучше чем прога в компе)... Вот что получается.
volatile int val_fr = 900;
volatile int dead_time = 500;
volatile int val_fr = 900;
volatile int dead_time = 250;
теперь нормально видно, что "мёртвая зона" отрабатывается правильно, с двух сторон от полупериода.
Только при изменении дедтайма изменяется частота...
Думаю, что частоту (полупериод) и скважность (дедтайм) нужно расчитывать от одного числа. Тоесть "полупериод" плюс "дедтайм" должно быть равно при изменении одного из слагаемых.
В общем есть чем заниматься на выходных...
Ещё раз ОГРОМНОЕ СПАСИБО !!! за помощь...
ОГО - Это жеж ОМЛ-2М или ОМЛ-3М, я прав?
Помоему да ... :-))
В хороших руках техника хорошо сохраняется )))
Эпоха перестройки, годы так 1980-1986 )))
Я на таком отлаживал схему генератора трёх уровневого стробирующего импульса (для декодеров PAL)
для TDA4510
Здравствуйте, знаю что это не спортивно, но не мог бы кто-то из знатоков дать пример кода для управлением пуш-пулл на фиксированной частоте с дедтаймом. Нашел вот такой костыль, но он создает дедтайм только "с одной стороны".
void setup () { TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted int val = 100 ; int dead = 2 ; analogWrite (9, val) ; analogWrite (10, val+dead) ; } void loop () {}Регулировать нужно только скважность, никаких дополнительных наворотов кроме дедтайма не нужно. Спасибо.
Здравствуйте, знаю что это не спортивно, но не мог бы кто-то из знатоков дать пример кода для управлением пуш-пулл на фиксированной частоте с дедтаймом. Нашел вот такой костыль, но он создает дедтайм только "с одной стороны".
void setup () { TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted int val = 100 ; int dead = 2 ; analogWrite (9, val) ; analogWrite (10, val+dead) ; } void loop () {}Регулировать нужно только скважность, никаких дополнительных наворотов кроме дедтайма не нужно. Спасибо.
бесполезно
Tolik4, лучше взять МК с аппаратной поддержкой дид-тайма, Tiny85 например.
Есть диджиспарк, его можно заставить генерировать ШИМ с дедтаймом средствани Ардуино ИДЕ?
Tolik4, возможно что "средства" Arduino IDE будут как раз мешать, нужно проверять. Есть примерчик под "голую" тини85.
https://gist.github.com/ollewelin/4afcf202a6ff267aa70e5b289724abc2 вот нашел пример для трех фаз, можно ли из него повыбрасывать лишнее и дальше писать свой недокод как для обычного ардуино?
https://gist.github.com/ollewelin/4afcf202a6ff267aa70e5b289724abc2 вот нашел пример для трех фаз, можно ли из него повыбрасывать лишнее и дальше писать свой недокод как для обычного ардуино?
Tolik4, я не пойму в чем проблема у вас проблема ? Выше есть рабочий скетч с регулировкой дедтайма !
Вот работа этого скетча...
https://www.youtube.com/watch?v=gz3YcAGV678
https://www.youtube.com/watch?v=rQ368CWKoCU
https://www.youtube.com/watch?v=3VD1KAxJrA0
Проблема моя в том что программист я никакой( это если коротко.
А если расширенно, то в коде из этой темы много лишних, ненужных мне функций, а т.к. почти вся программа сводится к управлению регистрами, вычленить оттуда нужную мне часть - сложно.
А пример, ссылку на который я скинул выше - гораздо более прост для понимания. Вот изготовленный мной огрызок данного кода, рабочий, проверенный на осциллографе:
//~9 TL, PH1, TMR1, PWM data value //~10 TH, PH1, TMR1, PWM data value const int dead_time = 10;//10 = 0.625 us const int half_dead_time = dead_time / 2;// int PWM = 0; void setup() { pinMode(9, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit pinMode(10, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit } void update_pwm(void) { //Limit the pwm_phx so it take the dead time into account so it not will swap over when reach end limit of workable PWM range if (PWM > (255 - half_dead_time)) { PWM = (255 - half_dead_time); } if (PWM < half_dead_time) { PWM = half_dead_time; } //All The PWM will run from 0xFF to 0x00 and up again to TOP 0xFF //The OCRnx will automatic update when TCNTn is on TOP 0xFF by hardware //Therefor it is sutible to change both OCRnx pair on a place where TCNT not update to ensure that the hardware automatic update NOT occur exact when only one of the two OCRnx have changed by this code while (TCNT1 > 0x7F) { } //Now it's safe to update OCR1x pair (connect to same transistor pair) OCR1A = (255 - PWM + half_dead_time); //~9 TL PH1 TMR1 OCR1B = (PWM - half_dead_time); //~10 TH PH1 TMR1 } void loop() { TCCR1A = 0xE1;//PWM, Phase Correct 8-bit TOP at 0xFF TCCR1B = 0x01;//clkI/O/1 (No prescaling) 31.25kHz PWM frequency update_pwm(); pinMode(9, OUTPUT); //PWM output pinMode(10, OUTPUT); //PWM output while (1) { PWM ++; if(PWM>128)PWM=0; update_pwm(); delay(100);//delay timer scale is screwd up by the new PWM TMR settings } }Делает вроде бы ровно то что мне нужно. Посмотрите пожалуйста нет ли в нем подводных камней, вроде возможности отказа стандартных ардуиновских функций и библиотек. И можно ли в нем изменить частоту на 62кГц? Что-то подсказывает что нужно заменить строчки 39,40, но вот на что?) Спасибо
Вот изготовленный мной огрызок данного кода, рабочий, проверенный на осциллографе:
Можно картинку, что показывает осцилограф ?
https://ibb.co/me1Qpn
Пробовал вставить гиф в сообщение - не хочет(
https://ibb.co/me1Qpn
Пробовал вставить гиф в сообщение - не хочет(
думаете такой сигнал подойдет для пуш-пула ?
смотрите тут в теме есть осцилограммы...
Я, как вы уже догадались, не специалист) Вдохновлялся этим:
https://www.youtube.com/watch?v=bYGeAu6_c6w
Доброго дня, а каким образом можно обратную связь по напряжению осуществить?
Вот полный скетч...
#include <LiquidCrystal.h> LiquidCrystal lcd(8,9,10,11,12,13); void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц), volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92 byte uk=0; int f_val, d_val; float rpm, dtm; // ******************************************************************** // ******************************************************************** void setup() { DDRD = B11111000; // нужные пины на выход PORTD = B00000100; // на втором пине устанавливаем "единицу" TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры // TCCR1A=0; TIMSK=0; TCCR1B=0; // мало ли что arduino IDE туда записало TCNT1=0; // сбрасываем счетный регистр таймера 1 OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A // TIMSK|=(1<<OCIE1A); // Скетч будет работать на дуинах с atmega168/328. // При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу). TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС lcd.begin(16, 2); lcd.print("arduino PushPull"); } // ******************************************************************** // ******************************************************************** void loop(){ if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0 } // ******************************************************************** // ******************************************************************** ISR(TIMER1_COMPA_vect) { (*mas[uk])(); // вызываем функцию по указателю } // ******************************************************************** // ******************************************************************** // ******************************************************************** void poluper1(void) { PORTD&=~(1<<5); // на пин 5 лог 0 PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту } void dead_time1(void) { PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=2; } void poluper2(void) { PORTD&=~(1<<4); // на пин 4 лог 0 PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод if(dead_time<92) {OCR1A=val_fr; uk=0;} else {OCR1A=val_fr-dead_time; uk=3;} } void dead_time2(void) { PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=0; } // ******************************************************************** // ******************************************************************** void l_c_d() { // работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) // работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) f_val = analogRead(A3); val_fr = map(f_val, 0, 1023, 533, 266); rpm = 16000000.0/val_fr/2.0; // частота в Герцах // работаем со скважностью // пауза между периодами, не должна быть меньше 92 и больше val_fr-91 d_val = analogRead(A2); int max_dt = val_fr-92; dead_time = map(d_val, 0, 1023, 91, max_dt); dtm = dead_time/(val_fr/100.0); // скважность в процентах if (dead_time < 92) dtm=0; lcd.setCursor(0, 0); lcd.print("freq Hz"); lcd.setCursor(5, 0); lcd.print(rpm); lcd.setCursor(0, 1); lcd.print("dead time %"); lcd.setCursor(10, 1); lcd.print(dtm, 1); //delay(400); }Ругается на строку 3
Arduino: 1.8.9 (Windows 7), Плата:"Arduino/Genuino Uno"
push_pull:3:24: error: 'poluper1' was not declared in this scope
push_pull:3:34: error: 'dead_time1' was not declared in this scope
push_pull:3:46: error: 'poluper2' was not declared in this scope
push_pull:3:56: error: 'dead_time2' was not declared in this scope
exit status 1
'poluper1' was not declared in this scope
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"
Not declared - не заданна переменная (не задекларирована - если дословно)
Гуру, подскажите почему этот код не компилируется в IDE 1.8.9 ?
потому что любая функция должна быть описана до первого обращения к ней. А у вас ваши функции полу_пер и прочие описаны в строчках 42-62, а первое обращение к ним - в строчке 3
Поместите сами функции или их обьявление до третьей строчки - ошибки исчезнут
Гуру, подскажите почему этот код не компилируется в IDE 1.8.9 ?
потому что любая функция должна быть описана до первого обращения к ней. А у вас ваши функции полу_пер и прочие описаны в строчках 42-62, а первое обращение к ним - в строчке 3
Поместите сами функции или их обьявление до третьей строчки - ошибки исчезнут
Спасибо за подсказку. Но самое интересное что в IDE 1.5.7 компилируется.
Вот переделал
// 27-11-2019 переделал методом переноса текста , компилируется в IDE 1.8.9 // в железе надо проверить #include <LiquidCrystal.h> LiquidCrystal lcd(8,9,10,11,12,13); volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц), volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92 byte uk=0; int f_val, d_val; float rpm, dtm; // ******************************************************************** // ******************************************************************** void poluper1(void) { PORTD&=~(1<<5); // на пин 5 лог 0 PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту } void dead_time1(void) { PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=2; } void poluper2(void) { PORTD&=~(1<<4); // на пин 4 лог 0 PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод if(dead_time<92) {OCR1A=val_fr; uk=0;} else {OCR1A=val_fr-dead_time; uk=3;} } void dead_time2(void) { PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=0; } // ******************************************************************** void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций // ******************************************************************** // ******************************************************************** void setup() { DDRD = B11111000; // нужные пины на выход PORTD = B00000100; // на втором пине устанавливаем "единицу" TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры // TCCR1A=0; TIMSK=0; TCCR1B=0; // мало ли что arduino IDE туда записало TCNT1=0; // сбрасываем счетный регистр таймера 1 OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A // TIMSK|=(1<<OCIE1A); // Скетч будет работать на дуинах с atmega168/328. // При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу). TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС lcd.begin(16, 2); lcd.print("arduino PushPull"); } // ******************************************************************** // ******************************************************************** void loop(){ if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0 } // ******************************************************************** // ******************************************************************** ISR(TIMER1_COMPA_vect) { (*mas[uk])(); // вызываем функцию по указателю } // ******************************************************************** // ******************************************************************** // ******************************************************************** void l_c_d() { // работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) // работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) f_val = analogRead(A3); val_fr = map(f_val, 0, 1023, 533, 266); rpm = 16000000.0/val_fr/2.0; // частота в Герцах // работаем со скважностью // пауза между периодами, не должна быть меньше 92 и больше val_fr-91 d_val = analogRead(A2); int max_dt = val_fr-92; dead_time = map(d_val, 0, 1023, 91, max_dt); dtm = dead_time/(val_fr/100.0); // скважность в процентах if (dead_time < 92) dtm=0; lcd.setCursor(0, 0); lcd.print("freq Hz"); lcd.setCursor(5, 0); lcd.print(rpm); lcd.setCursor(0, 1); lcd.print("dead time %"); lcd.setCursor(10, 1); lcd.print(dtm, 1); //delay(400); }самое интересное что в IDE 1.5.7 компилируется.
ничего "интересного" в этом нет, это печально. Просто IDE 1.5.7 делает за вас эту работу, расслабляя новичков.
Правильно - как требует IDE 1.8.9 - то есть описывать функции до их использования
Для разрешения регулировки частоты и дедтайма я так понял пин 2 на общий провод замыкать?
И какие номиналы потенциометров использовать для регулировки частоты и дедтайма?
как обычно, стандартные 10 кОм
Что поменять в скетче чтобы пределы регулирования по частоте от 1Гц до 500Гц было?
#include <LiquidCrystal.h> LiquidCrystal lcd(8,9,10,11,12,13); volatile int val_fr = 533; // длительность полупериода f=18000000/val_fr/2(Гц), volatile int dead_time = 91; // пауза между периодами, не должна быть меньше 92 и больше val_fr-92 byte uk=0; int f_val, d_val; float rpm, dtm; // ******************************************************************** // ******************************************************************** void poluper1(void) { PORTD&=~(1<<5); // на пин 5 лог 0 PORTD|=(1<<4); // на пин 4 лог 1, формируем первый полупериод if(dead_time<92) {OCR1A=val_fr; uk=2;} // если пауза меньше 92 тогда она формироваться не будет else {OCR1A=val_fr-dead_time; uk=1;} // иначе уменьшаем полупериод на длительность паузы чтоб сохранить частоту } void dead_time1(void) { PORTD&=~(1<<4); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=2; } void poluper2(void) { PORTD&=~(1<<4); // на пин 4 лог 0 PORTD|=(1<<5); // на пин 5 лог 1, формируем второй полупериод if(dead_time<92) {OCR1A=val_fr; uk=0;} else {OCR1A=val_fr-dead_time; uk=3;} } void dead_time2(void) { PORTD&=~(1<<5); // на пинах 4 и 5 лог 0, формируем dead_time паузу OCR1A=dead_time; uk=0; } // ******************************************************************** void (*mas[4]) (void)={poluper1, dead_time1, poluper2, dead_time2}; // массив указателей функций // ******************************************************************** // ******************************************************************** void setup() { DDRD = B11111000; // нужные пины на выход PORTD = B00000100; // на втором пине устанавливаем "единицу" TCCR1A=0; TIMSK1=0; // сбрасываем на всякий эти регистры // TCCR1A=0; TIMSK=0; TCCR1B=0; // мало ли что arduino IDE туда записало TCNT1=0; // сбрасываем счетный регистр таймера 1 OCR1A=0; // задаем частоту, в Гц, по формуле f=F_CPU/OCR1A/2 где F_CPU тактовая частота TIMSK1|=(1<<OCIE1A); // разрешаем генерацию прерывания таймера 1, по совпадению с регистром OCR1A // TIMSK|=(1<<OCIE1A); // Скетч будет работать на дуинах с atmega168/328. // При использовании atmega8 меняем все TIMSK1 на TIMSK (убираем еденицу). TCCR1B|=((1<<CS10)|(1<<WGM12)); // запускаем таймер 1 без предделителя в режиме СТС lcd.begin(16, 2); lcd.print("arduino PushPull"); } // ******************************************************************** // ******************************************************************** void loop(){ if ((PIND&(1<<2)) == 0) l_c_d(); // если на пин 2 лог 0 } // ******************************************************************** // ******************************************************************** ISR(TIMER1_COMPA_vect) { (*mas[uk])(); // вызываем функцию по указателю } // ******************************************************************** // ******************************************************************** // ******************************************************************** void l_c_d() { // работаем с частотой от 15009(533) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) // работаем с частотой от 20000(400) Гц до 30075(266) Гц (f=F_CPU/OCR1A/2) f_val = analogRead(A3); val_fr = map(f_val, 0, 1023, 533, 266); rpm = 16000000.0/val_fr/2.0; // частота в Герцах // работаем со скважностью // пауза между периодами, не должна быть меньше 92 и больше val_fr-91 d_val = analogRead(A2); int max_dt = val_fr-92; dead_time = map(d_val, 0, 1023, 91, max_dt); dtm = dead_time/(val_fr/100.0); // скважность в процентах if (dead_time < 92) dtm=0; lcd.setCursor(0, 0); lcd.print("freq Hz"); lcd.setCursor(5, 0); lcd.print(rpm); lcd.setCursor(0, 1); lcd.print("dead time %"); lcd.setCursor(10, 1); lcd.print(dtm, 1); //delay(400); }Люди ДОБРЫЕ ! ПОМОЖИТЕ! Как этот скеч сделать под регулировку тремя кнопками?
Пытаюсь слямзить с этого скеча управление , да вот мозги дымятся !!!
// генератор сигналов с регулировкой частоты и скважности по двум каналам. // частота от 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); } //*************************************************************************************************** }