Генератор с регулируемоей частотой на ардуино.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Могу посоветовать библиотеку CyberLib. Попробуйте, почитайте про неё, может и выйдет каменный цветок :-)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Ruzveld, на высоких частотах практически невозможно регулировать скважность, число градаций очень мало = F_CPU/2/1000000 для частоты 1 МГц

Ruzveld
Offline
Зарегистрирован: 27.12.2018

dimax, можно без регулировки скважности. Мне главное чтобы задать нужную частоту в какой-нибудь переменной и загрузить скетч. Нужен генератор без экрана, кнопок, и т.д.

Если не затруднит, Вы можете отредактировать скетч для такого упрощённого варианта?

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

Ruzveld, прочтите, там ответ на ваши вопросы: http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-blink-i-bez-delay-i-bez-millis

Mavlid
Offline
Зарегистрирован: 28.11.2018

Alexsandr пишет:

 Если у кого-то будет желание подсоединить кнопки для выбора и изменения частоты и длительности а также LCD дисплей -  этот скетч-генератор хорошее подспорье?

С уважением!

я уже написал,вытавил плату,проверил в железе,нажимаю кнопку (частота+ или частота-) частота меняется на экране,а на выходе частота пропадает через раз,где косяк не пойму...

#define pwm2_polar 0 //полярность выхода PWM2
#define DDSMAX 1E7 //максимальная частота для генератора DDS (удесятерённая)
#define dds_mpl_72 835.05327478167234049174700635502 //множитель DDS для частоты F_CPU 72МГц
//для пересчёта множителя необходимо: частоту на экране * текущий множитель и разделить на фактически измеренную частоту
  #define dds_mpl_128 469.7191655978919104715512499704  //множитель DDS для  частоты F_CPU 128Mhz

#include <LiquidCrystal.h>
LiquidCrystal lcd(PB1, PB0, PB5, PB6, PB7, PB8);
volatile int enc_tic=0, duty_in=50, mon_flag, divider, modebit=1;
      volatile int mode=1;// 0- GEN_si5351, 1-PWM, 2-Duty, 3..7 DDS, 8-Freqmeter 
      volatile int encstep=10; //шаг изменения частоты по умолчанию (желаемый *10)
     volatile int32_t freq=10000; //частота по умолчанию (желаемая *10)
uint8_t wave[512]; //массив для DDS синтеза


     
void setup() {
  Serial.end();// дефолтовый сериал не нужен
  lcd.begin(16, 2);
  lcd.print("hello");
  lcd.setCursor(0, 1);
  lcd.print("geektimes.ru");
  delay(100);// пауза для дисплея
  lcd.clear();  
  nvic_irq_disable_all();//отключить все прерывания 
  systick_disable(); // отключить системный таймер
  RCC_BASE->APB1ENR|= (1<<2)|(1<<1)|(1<<0); //включить тактирование tim-2,3,4
  RCC_BASE->APB2ENR|= (1<<3)|(1<<11)|(1<<2)|(1<<0)|(1<<4);////включить тактирование port-a-b-c,tim1
  AFIO_BASE->MAPR|=(1<<8)|(1<<6); //tim 1 && tim 2 Partial remap
  pinMode(PB15,INPUT_PULLUP); attachInterrupt(PB15, key_enc_int1, RISING);// частота минус
  pinMode(PB14,INPUT_PULLUP); attachInterrupt(PB14, key_enc_int2, RISING);//частота плюс
  pinMode(PB13,INPUT_PULLUP); attachInterrupt(PB13, key_enc_int3, RISING);//шаг -
  pinMode(PB12,INPUT_PULLUP); attachInterrupt(PB12, key_enc_int4, RISING);//шаг +
  pinMode(PB11,INPUT_PULLUP); attachInterrupt(PB11, key_enc_int5, RISING);//режим  
  if (mode==1){ timer_set(0); }

}

void loop() {
  static int old_mode_loop=-1;
  if (mode!=old_mode_loop) {
  old_mode_loop=mode; mon_flag=1;}
   
 if (mon_flag==1) {//
  if (mode==1){ timer_set(0); }
  if (mode >2 && mode<8) { mon_out();  dds_set(); } // запуск DDS режимов
  mon_out();
  mon_flag=0; //флаг вывода на дисплей
  //delay(300);
  }  
}

void key_enc_int1() // частота минус
 { //timer_set(-1);
   switch(mode){ //если сейчас идёт изменение частоты
     case 0:   break;
     case 1:   timer_set(-1); break;
     case 2:    timer_set(-1);  break;  
     case 8:   break; // в частотометре не реагировать на вращение энкодера 
     default: if (freq<encstep ) {freq=1;key_enc_int3();}
              if (freq==encstep ) {freq=1;key_enc_int3();}
              if (freq>encstep ) {freq=freq-encstep;} 
     
}
   mon_flag=1; //флаг вывода на дисплей 
}
void key_enc_int2() // частота плюс
{   //timer_set(1);  
    switch(mode){ //если сейчас идёт изменение частоты
     case 0:   break;
     case 1:   timer_set(1); break;
     case 2:   timer_set(1);  break;  
     case 8:   break; // в частотометре не реагировать на вращение энкодера 
     default: freq=freq+encstep; if (freq>DDSMAX) {freq=DDSMAX;}  mon_flag=1; //DDS режимы  
}
    mon_flag=1; //флаг вывода на дисплей 
}
void key_enc_int3() // шаг минус
{
   encstep=encstep/10;
   enc_step_control();  
}
void key_enc_int4() // шаг плюс
{
    encstep=encstep*10;
    enc_step_control();
//mon_flag=1; //флаг вывода на дисплей  
}
void key_enc_int5() // режим
{
     mode++; //меняем режим
     if(mode>7){mode=1;}
     if (mode==1 || mode==2 ){timer_set(0);}
     if (mode >2 ) {if (freq>DDSMAX) {freq=DDSMAX;} }
     mon_flag=1; //флаг вывода на дисплей  
}
/////////*********** ВЫВОД НА ДИСПЛЕЙ************//////////////////////////
///////////////////////////////////////////////////////////////////////////
void mon_out()
{
char mybuf[15];//lcd.clear();  
//************** Вывод первой строчки*****************************
 lcd.setCursor(0, 0); //  вперёд, вниз
   switch(mode){ 
       case 0: lcd.print("Clock Gen ");  break;       
       case 1: lcd.print(" PWM Mode "); break;
       case 2: lcd.print(" Duty Mode"); break;
       case 3: lcd.print("  Sinus   "); break;
       case 4: lcd.print(" Triangle "); break;
       case 5: lcd.print("Pila1 DDS "); break;
       case 6: lcd.print("Pila2 DDS "); break;
       case 7: lcd.print("Meandr DDS"); break;
       case 8: lcd.print("Freq.meter"); break;
       }
//*****************Вывод второй строчки*****************************
lcd.setCursor(0, 1); 
 if (freq>=1E8) {lcd.print("            ");lcd.setCursor(0, 1);   }    
     if (freq<10) {sprintf(mybuf,"      0,%ld    ", freq );}                //9 -> 0,9
else if (freq<100){sprintf(mybuf,"    %ld,%ld    ", freq/10, freq%10 );}   //99 -> 9,9                
else if (freq<1E3){sprintf(mybuf,"     %ld,%ld   ", freq/10, freq%10 );}    //999 -> 99,9           
else if (freq<1E4){sprintf(mybuf,"     %ld,%ld   ", freq/10, freq%10 );}    //9999 -> 999,9             
else if (freq<1E5){sprintf(mybuf,"   %ld %03ld   ", freq/10000, (freq/10)%1000 );} //99999 -> 9.999               
else if (freq<1E6){sprintf(mybuf,"    %ld %03ld  ", freq/10000, (freq/10)%1000 );}  //999999 -> 99.999                       
else if (freq<1E7){sprintf(mybuf,"    %ld %03ld  ", freq/10000, (freq/10)%1000 );} //999999 -> 999.999                       
else if (freq<1E8){sprintf(mybuf," %ld %03ld %03ld ", freq/10000000, (freq%10000000)/10000, (freq%10000)/10  );} //9999999 -> 9.999.999                       
else              {sprintf(mybuf,"%3ld %03ld %03ld ", freq/10000000, (freq%10000000)/10000, (freq%10000)/10  );} //99999999 -> 99.999.999                       

lcd.print(mybuf);    //вывод частоты
// выводим шаг
lcd.setCursor(10, 0);
       switch (encstep) { 
       /*  case 1:lcd.print(" 0,1"); break;
         case 10: lcd.print("   1"); break;
        case 100: lcd.print("  10"); break;
       case 1E3: lcd.print(" 100");break;
       case 1E4: lcd.print(" 1E3");break;
      case 1E5:  lcd.print(" 1E4");break;
      case 1E6:  lcd.print(" 1E5");break;
      case 1E7:  lcd.print(" 1E6");break;*/
         case 1:lcd.print("0,1 Hz"); break;
       case 10: lcd.print("  1 Hz"); break;
      case 100: lcd.print(" 10 Hz"); break;
      case 1E3: lcd.print("100 Hz");break;
      case 1E4: lcd.print(" 1 kHz");break;
      case 1E5: lcd.print("10 kHz");break;
      case 1E6: lcd.print("100kHz");break;
      case 1E7: lcd.print(" 1 MHz");break;
 }
mon_flag=0; //флаг вывода на дисплей
}
void enc_step_control(){ //ограничение шага в зависимости от режимов и частот
// для CLOCK режима если  шаг более 1 МГц то шаг сбросить на 0,1 или 1 Герц (зацикливание переключений)
if (encstep==0) {encstep=1;} //нет такого шага
if (mode==1 && encstep >1E5) {encstep=1E5;} //для PWM макс шаг 10 000 Гц
if (mode>2 &&  encstep >1E6) {encstep=1E6;} //для DDS  макс шаг 100 000 Гц
if (encstep==1 && freq >=10000 ) encstep=10;// менять шаг 0,1 Гц -> 1Гц  на частотах выше 1кГц для всех режимов
mon_flag=1; //флаг вывода на дисплей  
}
////////////////НАСТРОЙКА ТАЙМЕРА-ГЕНЕРАТОРА/////////////////////////////////////////////
void timer_set(int in){ //принимает +1 -1 или 0
int tim_arr; uint32_t imp_long, imp_hi; 
//общие настройки таймера1
GPIOA_BASE->CRL=0xB4444444; //PA7 alt_output
 GPIOA_BASE->CRH=0x4444444B; //PA8 alt_output
  TIMER1_BASE->CR1=0;
   TIMER1_BASE->CCMR2=0;TIMER1_BASE->PSC=0; TIMER1_BASE->CCR2=0; 
    TIMER1_BASE->CCER=(1<<0)|(1<<2)|(pwm2_polar<<3);//cc1e/cc1ne enable 
     //TIMER1_BASE->BDTR=(1<<15)| 255 ;// dead time sample
       TIMER1_BASE->CCMR1=(1<<6)|(1<<5)|(1<<3);//PWM mode 1
         if(freq < 84850){ //изменение частоты таймера по заданной частоте
          if (in) {freq+=(encstep*in);}//если передавалось изменение частоты, то рассчитать
           if (freq<1){freq=1;}  if (freq>(F_CPU/2*10)) {freq=F_CPU/2*10;}// ограничение макс. частоты *10
           tim_arr = F_CPU*10/freq; 
          divider=1; while ( (tim_arr/divider) > 65535) {divider++;} 
         TIMER1_BASE->PSC=divider-1;
        TIMER1_BASE->ARR=(tim_arr/divider)-1;
       } //end f (freq < 84850)
     else { // изменение частоты таймера инкрементом регистра ARR
    tim_arr=TIMER1_BASE->ARR; //снять тукущее состояния регистра     
   if (tim_arr<1000 && encstep > 1000) encstep=1000; // уменьшать шаг с ростом частоты
 if (tim_arr<100 && encstep > 100) encstep=100; // уменьшать шаг с ростом частоты
if (tim_arr<10 && encstep > 10) encstep=10;   // уменьшать шаг с ростом частоты    
in*=(encstep/10);
 tim_arr-=in;
  if (tim_arr<1) {tim_arr=1;} if (tim_arr>65535) {tim_arr=65535;}
   TIMER1_BASE->ARR=tim_arr;
    } // END  изменение частоты таймера инкрементом регистра ARR
     // установка заданного DUTY
      if(duty_in>99){duty_in=99;} if(duty_in<1){duty_in=1;} 
       if (mode==1 && TIMER1_BASE->ARR<100){ TIMER1_BASE->CCR1=(TIMER1_BASE->ARR+1)/2 ; duty_in=50;} //сбрасывать duty на 50% на высоких частотах 
        else{TIMER1_BASE->CCR1= (float) (TIMER1_BASE->ARR+1)* duty_in/100.0 ;} //или рассчитать 
         freq= F_CPU*10 /((TIMER1_BASE->ARR+1)*divider);// рассчёт фактической частоты
          //duty_out=  (float) TIMER1_BASE->CCR1 / ((TIMER1_BASE->ARR+1) / 100.0) ; //расчёт фактического duty
          //duty_out= floorf(duty_out); //округление
         imp_long=(uint32_t) ((TIMER1_BASE->ARR+1)*divider); //длина периода в тактах
       imp_hi=(uint32_t)  ((TIMER1_BASE->CCR1)*divider); // длина импульса в тактах
     //t_low= (imp_long-imp_hi) /(F_CPU/1E6) ; //время LOW
   //t_hi=  imp_hi /(F_CPU/1E6); //время HI
 TIMER1_BASE->CR1=1;
mon_flag=1;
}//end timer_set

// КОНФИГУРАЦИЯ DDS РЕЖИМОВ
void dds_set(){
 static byte oldmode=255;
   TIMER1_BASE->CCER=0; //timer output pins disable
    GPIOA_BASE->CRL = 0x33333333;// pa0-pa7  выход
      if (oldmode !=mode) {
       if (mode==3) {for(uint16_t n=0; n<512; n++){wave[n]=255*(sin(TWO_PI*float(n)/512)+1)/2 ;}}// синус
       else if (mode==4){ for(uint16_t n=0; n<512; n++){if (n<256){ wave[n]=n;} else {wave[n]=(511-n);}}}//треугол
      else if (mode==5){ for(uint16_t n=0; n<512; n++){ wave[n]=(n>>1);}}                               //пила1
     else if (mode==6){ for(uint16_t n=0; n<512; n++){ wave[n]=((~n)>>1);}}                            //пила2
    else if (mode==7){ for(uint16_t n=0; n<512; n++){if (n<256){ wave[n]=0;} else {wave[n]=255;}}}    //меандр
  oldmode=mode; } 
uint32_t dds_shag= (double)freq/10 * ((F_CPU==72E6)? dds_mpl_72 : dds_mpl_128) ;//  шаг= частота*коэффициент
asm volatile (
"mov   R9, %[port];"  "\n\t" // записать в r9 адресс порта "A"-ODR 
 "mov   R8, %[wave];"       "\n\t" //адресс массива положить в r8  
 "mov   R7, %[shag];"   "\n\t" // значение шага в r7
  "dds_loop:"                  "\n\t"
   "add R6, r7;"               "\n\t"  //(1)добавить к аккумулятору шаг
    "lsrs r2, r6, #23;"         "\n\t"  //(1) положить в R2 сдвинутый на 23 бита аккумулятор
   "ldrb r2, [r8, r2];"        "\n\t"  //(2)загрузить в R2 выбранный байт из массива
   "strb  r2, [r9];"           "\n\t"  //(2) запиcать этот байт в PORTA-ODR
  "ldr  R2, [%[flag]];"       "\n\t"  //(2) подгрузить в  R2 флаг 
 "cmp r2, 1;"                "\n\t"  //(1) сравнить 
"bne dds_loop;"              "\n\t"  //(1) перейти в цикл
: : [wave]"r" (&wave),[shag]"r"(dds_shag),[port]"r"(&GPIOA_BASE->ODR),[flag]"r"(&mon_flag)
: "r9","r8","r7","r6","r2" 
);
  GPIOA_BASE->CRL=0x44444444;// все пины в Z
}//END DDS set()
//

 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

А почему все зациклились на АВР? Ну не может она этого. Mavlid сразу пошёл правильным путём - СТМ32 - а то, что программа подглючивает - это со времем поправится. Если нужен простой генератор без регулировок, так почему его не собрать на какой-нибудь логике, нафига там контроллер? Если очень хочется ШИМ на 1-2 МГц, так используйте СТМ32, пост 27 - очень прилично работает. Цена вопроса - на уровне пачки сигарет, разве что с АЛИ ждать с месяц, а если в городе есть соответствующие магазны - дороже, зато быстро.

Mavlid
Offline
Зарегистрирован: 28.11.2018

И еще-вывод PA1 не работает-в режиме DDS на этом выводе нет никаких сигналов (только пульсации),кз нет...(я про свой вариант на 1602)

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Mavlid пишет:

И еще-вывод PA1 не работает-в режиме DDS на этом выводе нет никаких сигналов (только пульсации),кз нет...(я про свой вариант на 1602)

При отладке данного генератора V3.2 при программировании из Ардуино ИДЕ через ST-LINK у контроллера не работали некоторые ноги, а при прошивке через USB всё было в норме. Как объяснил Dimax, это вызвано разной конфигурацией контроллера в зависимости от режима прошивки (наподобие установки Фьюз-бита JTAGEN в некоторых контроллерах AVR). Может и у Вас там собака порылась?

Alexsandr
Offline
Зарегистрирован: 24.02.2019

dimax пишет:

jeka_tm, вот, модифицировал основной код. Эта версия с регулировкой скважности. Частоту ограничивать в итоге не стал, скважность регулируется на всех частотах, просто начиная с какого-то значения регулируется всё бОльшими рывками. На мегагерце например всего 8 градаций.  Но энкодер всё равно везде счёлкает 100 градаций (в процентах).Некоторое неудобство, но избавится от него малыми силами не выйдет. Хочешь, сам повозись, можно по идее ввести разрядность регулировки скважности в зависимости от частоты.

/* Генератор 1 Hz..4 MHz. С регулировкой скважности. Энкодер регулировки частоты 
подключен к пинам A0 и A1, кнопка  энкодера подключена к A2. 
Энкодер регулировки скважности  подключен к пинам 8 и 10
Его кнопка не задействована.
Требуется использовать конденсаторы  0,01..0,1uf  относительно земли 
на каждый вывод обоих энкодеров.
Скетч для ардуино на мк atmega328 (UNO,Nano, MiniPro)
*/
#define set_duty() { OCR1A=(uint32_t)ICR1*duty/100; }
uint8_t duty=50;
float freq; 
void setup() {
Serial.begin(9600);
pinMode (9,OUTPUT); // выход генератора PB2
pinMode(A0,INPUT); // PC0 вывод энкодера "частота"
pinMode(A1,INPUT); // PC1 вывод энкодера "частота"
pinMode(A2,INPUT_PULLUP);  // PC2 кнопка энкодера 
pinMode(8,INPUT);  // PB0 вывод энкодера "скважность"
pinMode(10,INPUT); // PB2 вывод энкодера "скважность"
PCICR=(1<<PCIE1)|(1<<PCIE0); //разрешить прерывания PCINT 0, 1
PCMSK1=1<<PCINT9;// По сигналу на А1 создавать прерывание (устновка частоты)
PCMSK0=1<<PCINT0;// По сигналу на pin8 создавать прерывание (скважность)
TCCR1A=1<<COM1A1; //подключить выход OC1A первого таймера
TCCR1B=0;//
}

ISR (PCINT1_vect){
static boolean gen_mode=0; //флаг режима управления
static uint32_t enc=1; //переменная счёта энкодера
uint32_t icr=ICR1;
uint16_t divider=1; //переменная коэфф. деления прескалера

byte n=PINC&3; //считать значение энкодера частоты
boolean knopka = PINC&(1<<2); // 0-кнопка нажата, 1-кнопка НЕ нажата.
if (freq<2848) gen_mode=0; //переключение режима управления по частоте
if (freq>=2848) gen_mode=1; //переключение режима управления по OCR

// Если  увеличение частоты
if (n==3||n==0){ 
 if (gen_mode){if (knopka){ if(icr>2) {icr--; } } else {  if(icr>12)icr-=10; }   }
 else knopka?  enc++ : enc+=100; // в нч режиме
 } //end GetUP

// Если уменьшение частоты
if (n==2||n==1){ 
 if (gen_mode){ if (knopka){ if(icr<65535) {icr++; } } else {  if(icr<=65525)icr+=10; }   }
 else {if (knopka) { if (enc>=2)enc--;  } else { if (enc>100) enc-=100; }  }
 } //end GetDown


if(gen_mode){ ICR1=icr; set_duty(); freq= (float)F_CPU/2 / ICR1;  } 
else { //расчёт прескалера и ICR по нужной частоте
divider=1; icr = F_CPU / enc /2 /divider;
if (icr >65536) { divider=8; icr = F_CPU / enc /2 /divider;
    if (icr >65536) { divider=64; icr = F_CPU / enc /2 /divider;
        if (icr >65536)  {divider=256; icr = F_CPU / enc /2 /divider;
            if (icr >65536) { divider=1024; icr = F_CPU / enc /2 /divider;
                if (icr >65536){icr=65536; }}}}} ICR1=icr-1; set_duty();
//запись в регистр прескалера            
switch (divider) {
  case 1: TCCR1B=1|(1<<WGM13); break;
   case 8: TCCR1B=2|(1<<WGM13); break;
    case 64: TCCR1B=3|(1<<WGM13); break;
     case 256: TCCR1B=4|(1<<WGM13); break;
      case 1024: TCCR1B=5|(1<<WGM13); break;  }

    freq= (float) F_CPU/2 / (ICR1+1) /divider;
  } //конец "если  работа в НЧ режиме"
}

ISR (PCINT0_vect){ //обработчик энкодера "скважность"
byte m=PINB&B00000101; //считать значение энкодера2
if (m==0||m==5){ if(duty<100) {duty++; }  }
if (m==1||m==4){ if(duty>0) {duty--; }  }
set_duty();
}

void loop() {
if (freq <10000) { Serial.print(freq,1);Serial.print(" Hz "); }
if (freq >10000) { Serial.print(freq/1000,3);Serial.print(" kHz");}
Serial.print("<br>"); 
Serial.print("Duty="); Serial.print(duty); Serial.print("%");
Serial.println();
delay(100);
}

 

Здесь Вы использовали 2 энкодера. Первый энкодер -для регулировки частоты (задействована  также КНОПКА энкодера), второй энкодер-для реглировки скважности (КНОПКА не задействована).  Не подскажите, как скорректировать скетч (задействовав КНОПКУ второго энкодера)  чтобы получать на 9 и 10 пине частоту от 8 кгц до 200кгц, с раздельным регулированием скважности. 

                         С уважением!!

(Hex tel  14BB0AAC8E‬)

Mavlid
Offline
Зарегистрирован: 28.11.2018

Получилось вот так,с портом PA1 так и не азобрался,стм менял-то же самое

Alexsandr
Offline
Зарегистрирован: 24.02.2019
КРАСИВО........
else { //расчёт прескалера и ICR по нужной частоте
060
 icr = (F_CPU / enc /2 /divider);
061
 byte shifts[] = {3,3,2,2};
062
   for(byte i = 0; i < 4; i++){
063
      if (icr > 65536) {
064
          divider <<= shifts[i];
065
          icr = F_CPU / enc /2 /divider;
066
         }
067
    else {  //запись в регистр прескалера
068
        TCCR1B = (i+1)|(1<<WGM13);  break;
069
         }
070
    }
071
ICR1=icr-1; set_duty();
072
freq= (float) F_CPU/2 / (ICR1+1) /divider;
073
  } //конец "если  частота менее 2848 герц)



ТОЖЕ САМОЕ.......симпатично,  но первая красивее

067
else { //расчёт прескалера и ICR по нужной частоте
068
divider=1; icr = F_CPU / enc /2 /divider;
069
if (icr >65536) { divider=8; icr = F_CPU / enc /2 /divider;
070
    if (icr >65536) { divider=64; icr = F_CPU / enc /2 /divider;
071
        if (icr >65536)  {divider=256; icr = F_CPU / enc /2 /divider;
072
            if (icr >65536) { divider=1024; icr = F_CPU / enc /2 /divider;
073
                if (icr >65536){icr=65536; }}}}} ICR1=icr-1; set_duty();
074
//запись в регистр прескалера           
075
switch (divider) {
076
  case 1: TCCR1B=1|(1<<WGM13); break;
077
   case 8: TCCR1B=2|(1<<WGM13); break;
078
    case 64: TCCR1B=3|(1<<WGM13); break;
079
     case 256: TCCR1B=4|(1<<WGM13); break;
080
      case 1024: TCCR1B=5|(1<<WGM13); break;  }
081
 
082
    freq= (float) F_CPU/2 / (ICR1+1) /divider;
083
  } //конец "если  не Gen_mode (частота менее 2848 герц)

Хотя я только-только делаю первые шаги в программировании - но я восхищен!  Восхищен виртуозностью!  Красоту видно.  

Мне бы понять смысл одной строки:    byte shifts[] = {3,3,2,2};      

Я собрал, и у меня заработало!  И это мне приятно!! Хотя энкодер считает только на увеличение (правильность подключения проверял но осциллографе, по всплескам на двух выводах........возможно энкодеры не те, а возможно резисторы-подтяжки 12к виноваты, хотя в одну сторону, на увеличеие, считает  по 2гц)

Постараюсь  доработать "под себя", чтоб и на 10 пине получать меандр с возможностью регулировки длительности (типа PWM10=const - PWM9).  . То, что 10 пин надо направить на выход - я понял. Но как связать OCR1A  c OCR1B,  чтоб при уеличении первого -второе  уменьшалось....... не могу сообразить. На сколько я понимаю, они в сумме дают ICR. Но как эту  закономерность закодить..

С уважением!

 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Alexsandr пишет:

 Хотя энкодер считает только на увеличение (правильность подключения проверял но осциллографе, по всплескам на двух выводах........возможно энкодеры не те, а возможно резисторы-подтяжки 12к виноваты, хотя в одну сторону, на увеличеие, считает  по 2гц)

Встречаются энкодеры, у которых подвижный контакт не по центру, а один из крайних. Всплески на экране будут, в любом случае там что-то замыкается-размыкается, но правильно или нет? Сам на такие грабли разок наступал. Долго не мог понять, что за хрень творится, пока даташит не посмотрел. Энкодеры были PEC16, перепаял проводки и до сих пор работают. А 12к вполне нормально, и от них на землю по 0.047-0.1 мкФ.

michaeltex
Offline
Зарегистрирован: 20.02.2019

MAG-N пишет:

Энкодер - это тот, который сверху, а с кучей ног - это потенциометры. Типа вот такого

https://www.chipdip.ru/product/rk-1412g-a100k

Спасибо, за ответ. 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Не за что, а далее делайте регулировки уровня, сдвига от нуля и т.д. на этих многоножках.

wpd123
Offline
Зарегистрирован: 24.03.2019

Здравствуйте знающие люди! Ни где не нашёл на просторах интернета схемы генератора сигналов без энкодера вот в такой комплектации, что бы управлять кнопками. Есть много схем и скетчей с AD9850 и c AD9833 c разными дисплеями, без шилда 1602 и без кнопок, а просто с энкодерами, есть много самодельных плат, а вот именно с шилдом 1602A, готовым, для ардуино UNO и ген. AD9833 нет. Может у кого есть схема подключения и скетч именно для этой конфигурации. Или я может что то не допонимаю. простите балбеса за такие вопросы. Просто хотел собрать геныч на готовых модулях которые есть у меня в наличии. Во таких как на картинке.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

wpd123 пишет:

Здравствуйте знающие люди! Ни где не нашёл на просторах интернета схемы генератора сигналов без энкодера вот в такой комплектации, что бы управлять кнопками.

Логично что нету, это же величайшее извращение тыкаться между 5-6ю кнопками , когда всё удобно регулировать одним(!) энкодером, никакой здавомыслящий разработчик не станет такое делать :)

wpd123
Offline
Зарегистрирован: 24.03.2019

dimax пишет:

wpd123 пишет:

Здравствуйте знающие люди! Ни где не нашёл на просторах интернета схемы генератора сигналов без энкодера вот в такой комплектации, что бы управлять кнопками.

Логично что нету, это же величайшее извращение тыкаться между 5-6ю кнопками , когда всё удобно регулировать одним(!) энкодером, никакой здавомыслящий разработчик не станет такое делать :)

Ну это смотря для каких целей использовать генератор. Если цель - использовать только один сигнал - синусоиду, выставить определённую частоту на которой он будет работать и забыть,  то почему бы один раз и не потыкать.))) Да и кстати видел схемы генераторов с шилдом 1602 только на AD9850, выходит это не извращение, а вот на AD9833 с шилдом 1602 это извращение. Просто энкодера нет под рукой, а заказывать, надо ждать 2 месяца, а шилд 1602 имеется, поэтому и поинтересовался.

Ihor
Offline
Зарегистрирован: 10.11.2017

wpd123 пишет

Ну это смотря для каких целей использовать генератор. Если цель - использовать только один сигнал - синусоиду, выставить определённую частоту на которой он будет работать и забыть,  то почему бы один раз и не потыкать.))) Да и кстати видел схемы генераторов с шилдом 1602 только на AD9850, выходит это не извращение, а вот на AD9833 с шилдом 1602 это извращение. Просто энкодера нет под рукой, а заказывать, надо ждать 2 месяца, а шилд 1602 имеется, поэтому и поинтересовался.

[/quote]

А что мешает взять пример из библиотеки на AD9833 и пользоваться?

asam
Offline
Зарегистрирован: 12.12.2018

wpd123 пишет:
Да и кстати видел схемы генераторов с шилдом 1602 только на AD9850, выходит это не извращение, а вот на AD9833 с шилдом 1602 это извращение. Просто энкодера нет под рукой, а заказывать, надо ждать 2 месяца, а шилд 1602 имеется, поэтому и поинтересовался.

Ну, а кто мешает взять этот скетч от AD9850 и переделать его на AD9833?

wpd123
Offline
Зарегистрирован: 24.03.2019

asam пишет:

Ну, а кто мешает взять этот скетч от AD9850 и переделать его на AD9833?

Мешает недостаточность знаний. С ардуино вообще не работал никогда и программа для неё для меня тёмный лес. Саму плату с ардуино уно я запустил, подключил к ней ген 9833, залил проверочную прошивку. Генератор запустился. На осцилографе виден периодически меняющийся сигнал синусоида, треугольный и меандр. Меандр выдаёт амплитуду аж 5 вольт. Вот пока на это меня и хватило. Почему спросил про шилд 1602, потому что то такой нашёл у себя в закромах. Энкодерера нет в наличии. Позтому и хотел его приклячить к ардуинке, хоть чтоб как то переключать режимы.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

wpd123 пишет:

Меандр выдаёт амплитуду аж 5 вольт. Вот пока на это меня и хватило. Почему спросил про шилд 1602, потому что то такой нашёл у себя в закромах. Энкодерера нет в наличии. Позтому и хотел его приклячить к ардуинке, хоть чтоб как то переключать режимы.

Меандр так и должен быть, а синус и треугольник менее вольта. Ну и по поводу шилда - он толи 6, толи 8  выводов УНО занимает, хватит ли свободных ног на генератор? На 9833 хватит, там всего три ноги надо, а вот если ЦАП R-2R - Х его З.

Ihor
Offline
Зарегистрирован: 10.11.2017

wpd123 пишет:

asam пишет:

Ну, а кто мешает взять этот скетч от AD9850 и переделать его на AD9833?

Мешает недостаточность знаний. С ардуино вообще не работал никогда и программа для неё для меня тёмный лес. Саму плату с ардуино уно я запустил, подключил к ней ген 9833, залил проверочную прошивку. Генератор запустился. На осцилографе виден периодически меняющийся сигнал синусоида, треугольный и меандр. Меандр выдаёт амплитуду аж 5 вольт. Вот пока на это меня и хватило. Почему спросил про шилд 1602, потому что то такой нашёл у себя в закромах. Энкодерера нет в наличии. Позтому и хотел его приклячить к ардуинке, хоть чтоб как то переключать режимы.

А что мешает взять пример на 1602 и AD9833 и из суммы получить желаемое. Включить на несколько минут мозги и подключить кнопки шилда для управления.

 

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

А кто мешает из обычного потенциометра сделать энкодер (без кнопки)? Крайние концы - на +5В и Gnd, средний - на аналоговый вход. А дальше в функцию map установливаешь нужный диапазон и вставляешь значение с аналогового  входа. 

/* 
 Potentiometer - > to Encoder
 A1 - input from Potentiometer
*/
int potPin = 1;

void setup()
{
  pinMode(potPin, INPUT);
  Serial.begin(9600);
}
void loop()
{
   int Val = map(analogRead(potPin), 0, 1023, 0, 1000);
   Serial.print(F("Val = "));
   Serial.println(Val);
} 

 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

AlexanderNO пишет:

А кто мешает из обычного потенциометра сделать энкодер (без кнопки)? Крайние концы - на +5В и Gnd, средний - на аналоговый вход. А дальше в функцию map установливаешь нужный диапазон и вставляешь значение с аналогового  входа. 

/* 
 Potentiometer - > to Encoder
 A1 - input from Potentiometer
*/
int potPin = 1;

void setup()
{
  pinMode(potPin, INPUT);
  Serial.begin(9600);
}
void loop()
{
   int Val = map(analogRead(potPin), 0, 1023, 0, 1000);
   Serial.print(F("Val = "));
   Serial.println(Val);
} 

Вообще-то аналоговые входы УНО имеют нумерацию А0-А5 или 14-19, так что Ваш скетч нерабочий.

Должно быть int potPin = 15;

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

MAG-N, Вы это теоретически (что скетч не рабочий) или практически? http://arduino.ru/Reference/AnalogRead

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

AlexanderNO пишет:

MAG-N, Вы это теоретически (что скетч не рабочий) или практически? http://arduino.ru/Reference/AnalogRead

И так и эдак :-) 0-13 - это цифровые входы-выходы. По той ссылке, что Вы дали, ерунда написана, но там в самой первой строчке есть ещё ссылка - вот там всё правильно:

Функция считывает значение с указанного аналогового входа.

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

MAG-N, Вы сами пробовали или это просто Ваши теоретические умозаключения? У меня скетч работает. А по поводу "ерунды" - это к автору(-ам). 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Видимо IDE порт 1 при обращении к нему с аналоговым чтением объявляет его правильно, как А1

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

Если нужно читать с А1 как с цифрового канала, нужно писАть digitalRead(A1), если как с аналогового, - можно  и analogRead(A1), где А1 - имя пина, и analogRead(1), где 1 - номер аналового канала - это не имеет значения. Но чтобы не было путаницы с номерами аналоговых и цифровых входов-выходов обычно используются буквенно-цифровые обозначения по именам пинов. 

Alchimy91
Offline
Зарегистрирован: 28.07.2018

Мне очень подходит Ваш проект (пост#8) есть у меня екраны 16*2 с платой  I2C пожайлуста переправте код под ети екраны. В программировании чайник выручайте . Буду очень благодарен за помощь. 

240265
240265 аватар
Offline
Зарегистрирован: 12.08.2015

Alchimy91 пишет:

Мне очень подходит Ваш проект (пост#8) есть у меня екраны 16*2 с платой  I2C пожайлуста переправте код под ети екраны. В программировании чайник выручайте . Буду очень благодарен за помощь. 

А еще лучше под ВСЕ экраны которые продаются на Алиэкпрессе и ВСЕ экраны которые используются в мобильных телефонах. :)))

 

Alchimy91
Offline
Зарегистрирован: 28.07.2018

240265 пишет:

А еще лучше под ВСЕ экраны которые продаются на Алиэкпрессе и ВСЕ экраны которые используются в мобильных телефонах. :)))

 

Мне на всё не надо!!!

Не хочете помочь не надо но и ерничать с меня не надо разберусь потихоньку не святые горшки лепят! 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

AlexanderNO пишет:

Если нужно читать с А1 как с цифрового канала, нужно писАть digitalRead(A1), если как с аналогового, - можно  и analogRead(A1), где А1 - имя пина, и analogRead(1), где 1 - номер аналового канала - это не имеет значения. Но чтобы не было путаницы с номерами аналоговых и цифровых входов-выходов обычно используются буквенно-цифровые обозначения по именам пинов. 

не надо отсебятины )))

AlexanderNO
Онлайн
Зарегистрирован: 08.11.2018

The analog input pins can be used as digital pins, referred to as A0, A1, etc.

Хотя написание digitalRead() для А0, А1 ... как 14, 15 ... тоже является верным.

Но речь шла о правильности написания analogRead(1) для пина А1, т.к. мой оппонент решил, что для аналогового чтения с пинов А надо использовать те же порядковые номера, что и при цифровом, т.е. 14, 15... . 

 

Ванька79
Offline
Зарегистрирован: 15.04.2019

Выкладываю свою печатку в LAY,вариант на голой атмега328р,весия 2.4,в железе проверена

Предусмотрена зарядка на LTC4054 аккумулятора от сотового и USB разъем для зарядки

https://yadi.sk/d/oF1lFfxWapnwxQ

Спасибо!

 

в ардуино 1.8.8 не мог победить расположение массивов,в 1.6.5 все норм но убрал 6 "0х00"

Также энкодер наоборот (исправляется программно)

Ванька79
Offline
Зарегистрирован: 15.04.2019

(контрастность снизил после фотографирония)