1

Тема: Генератор AD9833+частотомер 6.5 МГц.

Доброго времени суток. Есть Генератор http://rcl-radio.ru/?p=78387. 
Есть частотомер http://rcl-radio.ru/?p=45077, по отдельности.
Есть ли возможность сделать два в одном с тем-же функционалом,
дисплей по I2C. Энкодер, кнопки сколько надо. У меня не получается.
Заранее благодарен за ответ.

2

Re: Генератор AD9833+частотомер 6.5 МГц.

Я так понимаю что эти два устройства не возможно объединить в одно?

3

Re: Генератор AD9833+частотомер 6.5 МГц.

Можно, подождите немного, я займусь этим вопросом.

4

Re: Генератор AD9833+частотомер 6.5 МГц.

Основная статья - http://rcl-radio.ru/?p=128106

Генератор от 0 до 10 МГц, частотомер от 0 до 6,5 МГц

Скетч совместим с Atmega88 168 328

Скетч использует 5360 байт (16%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 78 байт (3%) динамической памяти, оставляя 1970 байт для локальных переменных. Максимум: 2048 байт.

http://forum.rcl-radio.ru/uploads/images/2022/06/19e051b8698896c3ad054e624a5ade95.png

Вход частотомера D5
Кнопка вкл.выкл генератора D11
Кнопка форма сигнала D12
Энкодер D8 D9 D10 = DT CLK SW
Дисплей LCD1602 I2C
Генератор A0 A1 A2 = CS CLK DATA

Подключение кнопок:

http://forum.rcl-radio.ru/uploads/images/2022/06/807c63ecd47f4d03f29b8a861c21fad7.png

//  ATMEGA328 16 MHz
//  PD5 frequency input

//AD9833
#define CS    PC0
#define MCLK  PC1
#define DATA  PC2
// ENCODER
#define DT    PB0
#define CLK   PB1
#define SW    PB2
// BUTTON
#define G_ON_OFF PB3
#define FORM     PB4


#include <avr/io.h>
#include <util/delay.h>
#include <Wire_low.h>         // http://forum.rcl-radio.ru/viewtopic.php?pid=5521#p5521
#include <Lcd1602_i2c_low.h>  // http://rcl-radio.ru/wp-content/uploads/2022/03/Lcd1602_i2c_low.zip
  Lcd1602_i2c_low lcd(0x27);// адрес I2C

volatile uint8_t _prevValueAB = 0;    
volatile uint8_t _currValueAB = 0;
volatile int16_t newPosition = 0;
int position = -999;
int form;
int timer2,times;
volatile byte x;
unsigned long f;
bool w=1,on;
long fg;
long b,h_bit,l_bit;
float k = 0.995265; // устраним погрешность кварца
const long f25 = 25000000;// частота кварца, если нет эталонного частотомера установите частоту 25000000 Гц
int a[7],i;
 
 
int main(){ 
  PCICR |= (1 << PCIE0);
  PCMSK0 |= (1 << PCINT0)|(1 << PCINT1); 
  PORTB |= (1 << PB3)|(1 << PB4);
  PORTD |= (1<<PD5); // подтягивающий резистор на PD5 (вход T1)
  DDRC |=(1<<CS)|(1<<MCLK)|(1<<DATA);
  PORTC |=(1<MCLK)|(1<<CS)|(1<<DATA);
  _delay_ms(500);
  ad_AD9833();
    cli();
  // TIMER 1  
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B &= ~(1 << CS12)|(1 << CS11)|(1 << CS10); //Внешний тактовый источник на выводе T1. Тактирование по фронту
  TIMSK1 |= (1 << TOIE1); // бит TOIE1 в регистре TIMSK1 взывает прерывание когда таймер переполняется
  // TIMER 2
  TCCR2A = 0;   
  TCCR2B = 0;   
  OCR2A = 155; // 100 Hz 
  TCCR2A |= (1 << WGM21); 
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); 
  TIMSK2 |= (1 << OCIE2A); 
    sei(); 
  wire_set(16000000,100000); // тактовая частота контроллера, частота шины I2C
  lcd.setInit();
  lcd.Clear(); // очистка экрана
  lcd.led(1);  // включение и отключение подсветки экрана
  a[0] = EEPROM_read(0);a[1] = EEPROM_read(1);a[2] = EEPROM_read(2);a[3] = EEPROM_read(3);a[4] = EEPROM_read(4);a[5] = EEPROM_read(5);a[6] = EEPROM_read(6);
  form = EEPROM_read(7);
 
while(1){ 
  if(((PINB >> SW) & 1)==0){i++;if(on==1){w=1;}on=0;if(i>6){i=0;};_delay_ms(300);}
  if(((PINB >> G_ON_OFF) & 1)==0 && on==0){on=1;w=1;i=100;_delay_ms(300);}
  if(((PINB >> G_ON_OFF) & 1)==0 && on==1){on=0;w=1;fg=0;i=0;_delay_ms(300);}
  if(((PINB >> FORM) & 1)==0){form++;if(form>2){form=0;}w=1;fg=0;i=0;_delay_ms(300);}
///////////////////////////////////////////////////
  if(newPosition != position){position = newPosition;
    a[i] = a[i]+newPosition;newPosition=0;
    }  
///////////////////////////////////////////////////  
  if(on==0){fg=0;lcd.Curs(1,11);lcd.PrintString(" ");}
  if(on==1){lcd.Curs(1,11);lcd.PrintString("*");}
  if(w==1){w=0;
  lcd.Curs(1,13);
    switch(form){
  case 0: lcd.PrintString("DAC");WriteAD9833(0x2028);break;
  case 1: lcd.PrintString("SIN");WriteAD9833(0x2000);break;
  case 2: lcd.PrintString("TRI");WriteAD9833(0x2002);break;
  }
  EEPROM_write(0,a[0]);EEPROM_write(1,a[1]);EEPROM_write(2,a[2]);EEPROM_write(3,a[3]);EEPROM_write(4,a[4]);EEPROM_write(5,a[5]);EEPROM_write(6,a[6]);
  EEPROM_write(7,form);
  ad_AD9833();}
/////////////////////////////////////////////////// 
  lcd.Curs(0,0);lcd.PrintString("F ");
  lcd.PrintInt(f/1000000);lcd.PrintString(".");
  lcd.PrintInt(f/100000%10);
  lcd.PrintInt(f/10000%10);
  lcd.PrintInt(f/1000%10);lcd.PrintString(".");
  lcd.PrintInt(f/100%10);
  lcd.PrintInt(f/10%10);
  lcd.PrintInt(f%10);  
  lcd.PrintString("  Hz ");
///////////////////////////////////////////////////  
  if(a[i]<0){a[i]=0;}if(a[i]>9){a[i]=9;}
  lcd.Curs(1,0);lcd.PrintString("G ");
  lcd.Curs(1,2);if(i==0){if(timer2-times<50){lcd.PrintInt(a[0]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[0]);}
  lcd.Curs(1,3);lcd.PrintString(".");
  lcd.Curs(1,4);if(i==1){if(timer2-times<50){lcd.PrintInt(a[1]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[1]);}
  lcd.Curs(1,5);if(i==2){if(timer2-times<50){lcd.PrintInt(a[2]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[2]);}
  lcd.Curs(1,6);if(i==3){if(timer2-times<50){lcd.PrintInt(a[3]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[3]);}
  lcd.Curs(1,7);lcd.PrintString(".");
  lcd.Curs(1,8);if(i==4){if(timer2-times<50){lcd.PrintInt(a[4]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[4]);}
  lcd.Curs(1,9);if(i==5){if(timer2-times<50){lcd.PrintInt(a[5]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[5]);}
  lcd.Curs(1,10);if(i==6){if(timer2-times<50){lcd.PrintInt(a[6]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[6]);}
  fg=a[0]*pow(10,6)+a[1]*pow(10,5)+a[2]*pow(10,4)+a[3]*pow(10,3)+a[4]*pow(10,2)+a[5]*pow(10,1)+a[6];


}}// end main/while
 
ISR (TIMER1_OVF_vect){x++;}// при переполнении увеличить переменную х на 1
ISR (TIMER2_COMPA_vect){
     timer2++;
     if(timer2==1){
     x = 0;TCNT1 = 0; 
     TCCR1B |= (1 << CS12)|(1 << CS11)|(1 << CS10);}
     if(timer2==101){
     TCCR1B &= ~(1 << CS12)|(1 << CS11)|(1 << CS10);
     f = ((x*65535) + TCNT1);timer2=0;}
}  

void WriteAD9833(int data){        // SPI
  PORTC |=(1<<MCLK);PORTC &=~(1<<CS);
     for(int i = 15; i >= 0; i--){
        PORTC |=(1<<MCLK);
       if(((data>>i)&0x01)==1){PORTC |=(1<<DATA);}else{PORTC &=~(1<<DATA);}
        PORTC &=~(1<<MCLK);_delay_ms(1);}
        PORTC |=(1<<CS);
  }

void ad_AD9833(){
  b = (fg*pow(2,28)/f25)*k;
  if(b<16383){l_bit = b + 0x4000 ;h_bit = 0x4000;}
  else{h_bit = (b>>14) + 0x4000;l_bit = b - (h_bit<<14) + 0x4000;}
  WriteAD9833(0x2100);// 0010 0001 0000 0000 - Reset + DB28
  WriteAD9833(l_bit); // 0100 0000 0000 0000 - Freq0 LSB 
  WriteAD9833(h_bit); // 0100 0000 0000 0000 - Freq0 MSB 
  WriteAD9833(0xC000);// 1100 0000 0000 0000 - Phase0 
  WriteAD9833(0x2028);// 0010 0000 0000 0000 - Exit Reset
  } 

ISR(PCINT0_vect){ 
  bool pinA = ((PINB >> DT) & 1);
  bool pinB = ((PINB >> CLK) & 1);
   _currValueAB  = (pinA << 1) | pinB;
   switch(_prevValueAB | _currValueAB){
    case 0b0001: newPosition++;break;
    case 0b0100: newPosition--;break;
  }
  _prevValueAB = _currValueAB << 2;     
  }   

unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EECR |= (1<<EERE);// чтение EEPROM
    return EEDR; // вывод значения
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
  while(EECR & (1<<EEPE)); // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EEDR = ucData; // регистр данных 
    EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
    EECR |= (1<<EEPE); // Запись в EEPROM
}  

5

Re: Генератор AD9833+частотомер 6.5 МГц.

А у меня как раз методом тыка получилось вот так. И оно работает, только при переключении с
частотомера на генератор перестаёт работать энкодер, приходиться делать сброс и тогда можно
переключать частоту энкодером.

#include <SPI.h>
#include <EEPROM.h> 
#include <FreqCount.h>
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <Encoder.h>  // https://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // https://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
  LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
  Encoder myEnc(9, 8);//CLK, DT

float f=9.4;
long b,h_bit,l_bit,f_lcd,f_ust;
const long f25 = 25000000;// частота кварца, если нет эталонного частотомера установите частоту 25000000 Гц
int a[9],i,form,h_g,y;
bool w=1,on;
long oldPosition  = -999,newPosition,times;

unsigned long t_0;float t0;
int x1,n=3,r;
 

void setup() {
    Wire.begin();Serial.begin(9600);
  lcd.init();lcd.backlight();
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  lcd.setCursor(0,0);lcd.print("AD9833 GENERATOR");
  lcd.setCursor(0,1);lcd.print("   FREQ METR    ");delay(3000);lcd.clear();// ЗАСТАВКА
  pinMode(7,INPUT); // sw
  pinMode(2,INPUT_PULLUP);// on/off out
  pinMode(3,INPUT_PULLUP);// dac,sin,tri
  pinMode(4,INPUT_PULLUP);// F = 0
  pinMode(A1,INPUT); // ЧАСТОТОМЕР/ГЕНЕРАТОР
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  a[0] = EEPROM.read(0);a[1] = EEPROM.read(1);a[2] = EEPROM.read(2);a[3] = EEPROM.read(3);a[4] = EEPROM.read(4);a[5] = EEPROM.read(5);
  a[6] = EEPROM.read(6);a[7] = EEPROM.read(7);a[8] = EEPROM.read(8);form = EEPROM.read(9);
  ad();  
}
 void WriteAD9833(uint16_t Data){
  SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
  digitalWrite(SS, LOW);
  delayMicroseconds(1);
  SPI.transfer16(Data);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}
 void ad(){
  b = f*pow(2,28)/f25;
  if(b<16383){l_bit = b + 0x4000 ;h_bit = 0x4000;}
  else{h_bit = (b>>14) + 0x4000;l_bit = b - (h_bit<<14) + 0x4000;}
  SPI.begin();
  WriteAD9833(0x2100);// 0010 0001 0000 0000 - Reset + DB28
  WriteAD9833(l_bit); // 0100 0000 0000 0000 - Freq0 LSB 
  WriteAD9833(h_bit); // 0100 0000 0000 0000 - Freq0 MSB 
  WriteAD9833(0xC000);// 1100 0000 0000 0000 - Phase0 
  WriteAD9833(0x2000);// 0010 0000 0000 0000 - Exit Reset
  } 
void to_Timer(){newPosition = myEnc.read()/4;}

void loop() {
  if(analogRead(1)>600){h_g++;y=0;delay(300);if(h_g>1){h_g=0;}}// ГЕНЕРАТОР/ЧАСТОТОМЕР (ПО УМОЛЧАНИЮ ПЕРВЫЙ ГЕНЕРАТОР)
  
   if(h_g==1){ i=0; // ЧАСТОТОМЕР ////////////////////////////////////////////////////////////////////
  if(y==1){FreqCount.begin(1000);}
 
  if(digitalRead(7)==LOW){n++;x1=0;delay(100);}// ВЫБОР ВРЕМЕНИ ИЗМЕРЕНИЯ ПРИ ПОМОЩИ КНОПКИ ЭНКОДЕРА
    lcd.setCursor(0,1);
  if(n==1){x1++;if(x1==1){FreqCount.begin(100);}r=-1;lcd.print("T = 0.1 s ");}
  if(n==2){x1++;if(x1==1){FreqCount.begin(10000);}r=1;lcd.print("T = 10 s ");}
  if(n==3){x1++;if(x1==1){FreqCount.begin(1000);}r=0;lcd.print("T = 1 s  ");}
  if(n>3){n=1;} 
    lcd.setCursor(0,0);
    lcd.print("F = "); // ВЫВОД ЧАСТОТЫ 
  if(t_0>=1000000 && n==3){t0=t_0/1000000.0;lcd.print(t0,6+r);lcd.print(" MHz");}
  if(t_0<1000000 && n==3){t0=t_0/1000.0;lcd.print(t0,3+r);lcd.print(" kHz");}
  if(t_0>=100000 && n==1){t0=t_0/100000.0;lcd.print(t0,6+r);lcd.print(" MHz");}
  if(t_0<100000 && n==1){t0=t_0/100.0;lcd.print(t0,3+r);lcd.print(" kHz");}
  if(t_0>=10000000 && n==2){t0=t_0/10000000.0;lcd.print(t0,6+r);lcd.print("MHz");}
  if(t_0<10000000 && n==2){t0=t_0/10000.0;lcd.print(t0,3+r);lcd.print(" kHz");}
 
  if (FreqCount.available()) { 
 
    t_0 = FreqCount.read(); // ИЗМЕРЕНИЕ ЧАСТОТЫ
 
   lcd.setCursor(10,1);lcd.print("***");// ИНДИКАЦИЯ ИЗМЕРЕНИЯ
  }
   delay(200);
   lcd.clear();
  }

  if(h_g==0){// ГЕНЕРАТОР //////////////////////////////////////////////////////////////////
 
  if(digitalRead(4)==LOW){a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=0;a[6]=0;a[7]=0;a[8]=0;w=1;on=0;delay(300);}
   if(digitalRead(3)==LOW){form++;w=1;on=0;if(form>2){form=0;};delay(300);}
   if(digitalRead(7)==LOW){i++;w=1;on=0;if(i>8){i=0;};delay(300);}
   if(digitalRead(2)==LOW&&on==0){on=1;delay(300);w=1;}
   if(digitalRead(2)==LOW&&on==1){on=0;delay(300);w=1;}
 
   if(on==1){lcd.setCursor(0,1);lcd.print("OUT_ON ");i=100;}else{lcd.setCursor(0,1);lcd.print("OUT_OFF");}
 
   if (newPosition != oldPosition){oldPosition = newPosition;a[i]=a[i]+newPosition;if(a[i]>9){a[i]=9;}if(a[i]<0){a[i]=0;}myEnc.write(0);newPosition=0;} 
   if(a[0]>1){a[0]=1;}if(a[0]==1&&a[1]>2){a[1]=2;}if(a[0]==1&&a[1]==2&&a[2]>5){a[2]=5;}
 
  lcd.setCursor(0,0);lcd.print("F ");
 
if(i==0){if(millis()-times<500){lcd.print(a[0]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[0]);}
if(i==1){if(millis()-times<500){lcd.print(a[1]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[1]);}
lcd.print(".");
if(i==2){if(millis()-times<500){lcd.print(a[2]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[2]);}
if(i==3){if(millis()-times<500){lcd.print(a[3]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[3]);}
if(i==4){if(millis()-times<500){lcd.print(a[4]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[4]);}
lcd.print(".");
if(i==5){if(millis()-times<500){lcd.print(a[5]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[5]);}
if(i==6){if(millis()-times<500){lcd.print(a[6]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[6]);}
if(i==7){if(millis()-times<500){lcd.print(a[7]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[7]);}
lcd.print(",");
if(i==8){if(millis()-times<500){lcd.print(a[8]);}if(millis()-times>=500){lcd.print(" ");}if(millis()-times>1000){times=millis();}}else{lcd.print(a[8]);}
 
  f=a[0]*pow(10,7)+a[1]*pow(10,6)+a[2]*pow(10,5)+a[3]*pow(10,4)+a[4]*pow(10,3)+a[5]*pow(10,2)+a[6]*10+a[7]+float(a[8]*0.1);
  lcd.print("Hz");
  if(on==0){f=0;}
 
  if(w==1){ad(); 
  EEPROM.update(0, a[0]);EEPROM.update(1, a[1]);EEPROM.update(2, a[2]);EEPROM.update(3, a[3]);EEPROM.update(9, form);
  EEPROM.update(4, a[4]);EEPROM.update(5, a[5]);EEPROM.update(6, a[6]);EEPROM.update(7, a[7]);EEPROM.update(8, a[8]);
  lcd.setCursor(11,1);
  switch(form){
  case 0: lcd.print("MEANDR");WriteAD9833(0x2028);break;
  case 1: lcd.print("SINUS ");WriteAD9833(0x2000);break;
  case 2: lcd.print("TRIAQ ");WriteAD9833(0x2002);break;
  }
  w=0;}
 
 }// loop
 
// void WriteAD9833(uint16_t Data){
//  SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
 // digitalWrite(SS, LOW);
 // delayMicroseconds(1);
 // SPI.transfer16(Data);
 // digitalWrite(SS, HIGH);
 // SPI.endTransaction();
}
//void ad(){
//  b = f*pow(2,28)/f25;
//  if(b<16383){l_bit = b + 0x4000 ;h_bit = 0x4000;}
//  else{h_bit = (b>>14) + 0x4000;l_bit = b - (h_bit<<14) + 0x4000;}
//  SPI.begin();
  //WriteAD9833(0x2100);// 0010 0001 0000 0000 - Reset + DB28
//  WriteAD9833(l_bit); // 0100 0000 0000 0000 - Freq0 LSB 
//  WriteAD9833(h_bit); // 0100 0000 0000 0000 - Freq0 MSB 
//  WriteAD9833(0xC000);// 1100 0000 0000 0000 - Phase0 
//  WriteAD9833(0x2000);// 0010 0000 0000 0000 - Exit Reset
//  } 
//void to_Timer(){newPosition = myEnc.read()/4;}

Ваш проект попробую позже, надо схему перебирать. И я так понял частотомер меряет
сигнал генератора AD9833? И конечно тут информативней был бы 1604 или 2004 дисплей.

6

Re: Генератор AD9833+частотомер 6.5 МГц.

И оно работает, только при переключении с
частотомера на генератор перестаёт работать энкодер, приходиться делать сброс и тогда можно
переключать частоту энкодером.

Скорее всего энкодер и частотомер используют один таймер

И я так понял частотомер меряет сигнал генератора AD9833?

Да.

7

Re: Генератор AD9833+частотомер 6.5 МГц.

Да при компиляции он всё ругался на таймер, пока я не перенёс его в верх
и все лупы, воиды. Я не программист и что где кто использует а не знаю
всё делал по аналогии. Есть коментарий-хорошо, а новый скетч вообще
для меня тёмный лес.

8

Re: Генератор AD9833+частотомер 6.5 МГц.

Загрузите новый скетч без изменений и опубликуйте коды ошибок.

9

Re: Генератор AD9833+частотомер 6.5 МГц.

При компиляции выдал это
C:\Users\Admin\Desktop\
генератора+частотомер\gen__AD9833____freq__Arduino_\gen__AD9833____freq__Arduino_.ino:10:0: warning: "CLK" redefined
C:\Users\Admin\Desktop\
генератора+частотомер\gen__AD9833____freq__Arduino_\gen__AD9833____freq__Arduino_.ino:6:0: note: this is the location of the previous definition
Скетч использует 5360 байт (17%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 78 байт (3%) динамической памяти, оставляя 1970 байт для локальных переменных. Максимум: 2048 байт.
Но мне кажется мы говорим о разных скетчах.

10

Re: Генератор AD9833+частотомер 6.5 МГц.

Я поправил скетч, был одинаковый defaine, но у меня это не приводило к ошибкам:

//  ATMEGA328 16 MHz
//  PD5 frequency input

//AD9833
#define CS    PC0
#define MCLK  PC1
#define DATA  PC2
// ENCODER
#define DT    PB0
#define CLK   PB1
#define SW    PB2
// BUTTON
#define G_ON_OFF PB3
#define FORM     PB4


#include <avr/io.h>
#include <util/delay.h>
#include <Wire_low.h>         // http://forum.rcl-radio.ru/viewtopic.php?pid=5521#p5521
#include <Lcd1602_i2c_low.h>  // http://rcl-radio.ru/wp-content/uploads/2022/03/Lcd1602_i2c_low.zip
  Lcd1602_i2c_low lcd(0x27);// адрес I2C

volatile uint8_t _prevValueAB = 0;    
volatile uint8_t _currValueAB = 0;
volatile int16_t newPosition = 0;
int position = -999;
int form;
int timer2,times;
volatile byte x;
unsigned long f;
bool w=1,on;
long fg;
long b,h_bit,l_bit;
float k = 0.995265; // устраним погрешность кварца
const long f25 = 25000000;// частота кварца, если нет эталонного частотомера установите частоту 25000000 Гц
int a[7],i;
 
 
int main(){ 
  PCICR |= (1 << PCIE0);
  PCMSK0 |= (1 << PCINT0)|(1 << PCINT1); 
  PORTB |= (1 << PB3)|(1 << PB4);
  PORTD |= (1<<PD5); // подтягивающий резистор на PD5 (вход T1)
  DDRC |=(1<<CS)|(1<<MCLK)|(1<<DATA);
  PORTC |=(1<MCLK)|(1<<CS)|(1<<DATA);
  _delay_ms(500);
  ad_AD9833();
    cli();
  // TIMER 1  
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B &= ~(1 << CS12)|(1 << CS11)|(1 << CS10); //Внешний тактовый источник на выводе T1. Тактирование по фронту
  TIMSK1 |= (1 << TOIE1); // бит TOIE1 в регистре TIMSK1 взывает прерывание когда таймер переполняется
  // TIMER 2
  TCCR2A = 0;   
  TCCR2B = 0;   
  OCR2A = 155; // 100 Hz 
  TCCR2A |= (1 << WGM21); 
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); 
  TIMSK2 |= (1 << OCIE2A); 
    sei(); 
  wire_set(16000000,100000); // тактовая частота контроллера, частота шины I2C
  lcd.setInit();
  lcd.Clear(); // очистка экрана
  lcd.led(1);  // включение и отключение подсветки экрана
  a[0] = EEPROM_read(0);a[1] = EEPROM_read(1);a[2] = EEPROM_read(2);a[3] = EEPROM_read(3);a[4] = EEPROM_read(4);a[5] = EEPROM_read(5);a[6] = EEPROM_read(6);
  form = EEPROM_read(7);
 
while(1){ 
  if(((PINB >> SW) & 1)==0){i++;if(on==1){w=1;}on=0;if(i>6){i=0;};_delay_ms(300);}
  if(((PINB >> G_ON_OFF) & 1)==0 && on==0){on=1;w=1;i=100;_delay_ms(300);}
  if(((PINB >> G_ON_OFF) & 1)==0 && on==1){on=0;w=1;fg=0;i=0;_delay_ms(300);}
  if(((PINB >> FORM) & 1)==0){form++;if(form>2){form=0;}w=1;fg=0;i=0;_delay_ms(300);}
///////////////////////////////////////////////////
  if(newPosition != position){position = newPosition;
    a[i] = a[i]+newPosition;newPosition=0;
    }  
///////////////////////////////////////////////////  
  if(on==0){fg=0;lcd.Curs(1,11);lcd.PrintString(" ");}
  if(on==1){lcd.Curs(1,11);lcd.PrintString("*");}
  if(w==1){w=0;
  lcd.Curs(1,13);
    switch(form){
  case 0: lcd.PrintString("DAC");WriteAD9833(0x2028);break;
  case 1: lcd.PrintString("SIN");WriteAD9833(0x2000);break;
  case 2: lcd.PrintString("TRI");WriteAD9833(0x2002);break;
  }
  EEPROM_write(0,a[0]);EEPROM_write(1,a[1]);EEPROM_write(2,a[2]);EEPROM_write(3,a[3]);EEPROM_write(4,a[4]);EEPROM_write(5,a[5]);EEPROM_write(6,a[6]);
  EEPROM_write(7,form);
  ad_AD9833();}
/////////////////////////////////////////////////// 
  lcd.Curs(0,0);lcd.PrintString("F ");
  lcd.PrintInt(f/1000000);lcd.PrintString(".");
  lcd.PrintInt(f/100000%10);
  lcd.PrintInt(f/10000%10);
  lcd.PrintInt(f/1000%10);lcd.PrintString(".");
  lcd.PrintInt(f/100%10);
  lcd.PrintInt(f/10%10);
  lcd.PrintInt(f%10);  
  lcd.PrintString("  Hz ");
///////////////////////////////////////////////////  
  if(a[i]<0){a[i]=0;}if(a[i]>9){a[i]=9;}
  lcd.Curs(1,0);lcd.PrintString("G ");
  lcd.Curs(1,2);if(i==0){if(timer2-times<50){lcd.PrintInt(a[0]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[0]);}
  lcd.Curs(1,3);lcd.PrintString(".");
  lcd.Curs(1,4);if(i==1){if(timer2-times<50){lcd.PrintInt(a[1]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[1]);}
  lcd.Curs(1,5);if(i==2){if(timer2-times<50){lcd.PrintInt(a[2]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[2]);}
  lcd.Curs(1,6);if(i==3){if(timer2-times<50){lcd.PrintInt(a[3]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[3]);}
  lcd.Curs(1,7);lcd.PrintString(".");
  lcd.Curs(1,8);if(i==4){if(timer2-times<50){lcd.PrintInt(a[4]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[4]);}
  lcd.Curs(1,9);if(i==5){if(timer2-times<50){lcd.PrintInt(a[5]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[5]);}
  lcd.Curs(1,10);if(i==6){if(timer2-times<50){lcd.PrintInt(a[6]);}if(timer2-times>=50){lcd.PrintString(" ");}if(timer2-times>100){times=timer2;}}else{lcd.PrintInt(a[6]);}
  fg=a[0]*pow(10,6)+a[1]*pow(10,5)+a[2]*pow(10,4)+a[3]*pow(10,3)+a[4]*pow(10,2)+a[5]*pow(10,1)+a[6];


}}// end main/while
 
ISR (TIMER1_OVF_vect){x++;}// при переполнении увеличить переменную х на 1
ISR (TIMER2_COMPA_vect){
     timer2++;
     if(timer2==1){
     x = 0;TCNT1 = 0; 
     TCCR1B |= (1 << CS12)|(1 << CS11)|(1 << CS10);}
     if(timer2==101){
     TCCR1B &= ~(1 << CS12)|(1 << CS11)|(1 << CS10);
     f = ((x*65535) + TCNT1);timer2=0;}
}  

void WriteAD9833(int data){        // SPI
  PORTC |=(1<<MCLK);PORTC &=~(1<<CS);
     for(int i = 15; i >= 0; i--){
        PORTC |=(1<<MCLK);
       if(((data>>i)&0x01)==1){PORTC |=(1<<DATA);}else{PORTC &=~(1<<DATA);}
        PORTC &=~(1<<MCLK);_delay_ms(1);}
        PORTC |=(1<<CS);
  }

void ad_AD9833(){
  b = (fg*pow(2,28)/f25)*k;
  if(b<16383){l_bit = b + 0x4000 ;h_bit = 0x4000;}
  else{h_bit = (b>>14) + 0x4000;l_bit = b - (h_bit<<14) + 0x4000;}
  WriteAD9833(0x2100);// 0010 0001 0000 0000 - Reset + DB28
  WriteAD9833(l_bit); // 0100 0000 0000 0000 - Freq0 LSB 
  WriteAD9833(h_bit); // 0100 0000 0000 0000 - Freq0 MSB 
  WriteAD9833(0xC000);// 1100 0000 0000 0000 - Phase0 
  WriteAD9833(0x2028);// 0010 0000 0000 0000 - Exit Reset
  } 

ISR(PCINT0_vect){ 
  bool pinA = ((PINB >> DT) & 1);
  bool pinB = ((PINB >> CLK) & 1);
   _currValueAB  = (pinA << 1) | pinB;
   switch(_prevValueAB | _currValueAB){
    case 0b0001: newPosition++;break;
    case 0b0100: newPosition--;break;
  }
  _prevValueAB = _currValueAB << 2;     
  }   

unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EECR |= (1<<EERE);// чтение EEPROM
    return EEDR; // вывод значения
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
  while(EECR & (1<<EEPE)); // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EEDR = ucData; // регистр данных 
    EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
    EECR |= (1<<EEPE); // Запись в EEPROM
}  

11

Re: Генератор AD9833+частотомер 6.5 МГц.

Скомпилировался без ошибок но в работе не пробовал.

12

Re: Генератор AD9833+частотомер 6.5 МГц.

Доброго времени суток.
Последний скетч компилируется без ошибок, но в нану грузиться отказывается категорически.
Пишет ошибку:

Arduino: 1.8.19 (Windows 7), Плата:"Arduino Nano, ATmega328P"
Скетч использует 5360 байт (17%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 78 байт (3%) динамической памяти, оставляя 1970 байт для локальных переменных. Максимум: 2048 байт.

Произошла ошибка при загрузке скетча
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x4c
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x4c

И куда толкаться сообразить не могу.
Заранее спасибо.

13

Re: Генератор AD9833+частотомер 6.5 МГц.

Переподключите USB кабель, выберите плату Arduino UNO, проверьте порт, повторите загрузку.

14

Re: Генератор AD9833+частотомер 6.5 МГц.

Это пробовалось: три разных варианта, два разных кабеля и две разные платы nano v3,
+ еще mega168 в формате nano,
+ пробовал на клон с LGT8F328p залить с единым результатом. 
Чуть позже еще попробую комп просто перезагрузить....для чистоты эксперимента.

15

Re: Генератор AD9833+частотомер 6.5 МГц.

Спасибо! Поллитергейст какой-то. Перезагрузился и все зашло.

16

Re: Генератор AD9833+частотомер 6.5 МГц.

При работе последним скетчем не происходит запуск генератора; вернее генератор пускается примерно на полсекунды и уходит в останов.
Единственное что другое, так это модуль генератора: используется модуль CJMCU-9833.
Модуль работает, изменение частоты происходит, изменение формы тож, кратковременно генератор выдает условно заданную частоту. Задано 10кгц на выдаче 10кгц, 100кгц - 100кгц... но нет удержания генерации.

17

Re: Генератор AD9833+частотомер 6.5 МГц.

Вы измеряете частотомером в ардуино? Импульсный сигнал измеряете?

18 (2023-04-02 18:17:46 отредактировано adsms)

Re: Генератор AD9833+частотомер 6.5 МГц.

Да не только: паралельно
- частотометр ардуино
- осциллограф
- и еще пробовался частотомер мультиметра

Измерять пробовал и импульсный сигнал, и пилу и синусоиду. Результат примерно одинаковый.
Частотомер ардуины при подаче на вход сигнала ТТЛ уровня с задающего генератора частоту измеряет вполне адекватно.

И еще, индикатор в виде звездочки на экране при нажатии на кнопку ON/OFF загорается на полсекунды и гаснет, паралельно, когда он еще горит с выхода генератора идет генерируемый сигнал.
Такое ощущение, что не срабатывает на удержание программный триггер. Но программист из меня тяжелый, второй день штудирую скетч построчно,но пока без результата.

19

Re: Генератор AD9833+частотомер 6.5 МГц.

Завтра постараюсь собрать схему и протестировать.

20

Re: Генератор AD9833+частотомер 6.5 МГц.

Доброго времени . По моим ощущениям что то не так в 72-75 строке кода.

  72 #    if(((PINB >> SW) & 1)==0){i++;if(on==1){w=1;}on=0;if(i>6){i=0;};_delay_ms(100);}
  73 #    if(((PINB >> G_ON_OFF) & 1)==0 && on==0){on=1;w=1;i=100;_delay_ms(300);}
  74 #    if(((PINB >> G_ON_OFF) & 1)==0 && on==1){on=0;w=1;fg=0;i=0;_delay_ms(300);}  // on=0
  75 #    if(((PINB >> FORM) & 1)==0){form++;if(form>2){form=0;}w=1;fg=0;i=0;_delay_ms(300);}

Если в 72 строке 'on=0' поменять ноль на 1 то генерация идет постоянно.
Не могу отследить логику включения генератора -
82 строка отвечает за исполнение вывода  * на экран ?
 

 82 #    if(on==1){lcd.Curs(1,11);lcd.PrintString("*");} 

21

Re: Генератор AD9833+частотомер 6.5 МГц.

72 #    if(((PINB >> SW) & 1)==0){i++;if(on==1){w=1;}on=0;if(i>6){i=0;};_delay_ms(100);}

Если нажата кнопка энкодера, то начат перебор изменения разрядов установленной частоты, при это генерация выключается (n=0;)

73 #    if(((PINB >> G_ON_OFF) & 1)==0 && on==0){on=1;w=1;i=100;_delay_ms(300);}
  74 #    if(((PINB >> G_ON_OFF) & 1)==0 && on==1){on=0;w=1;fg=0;i=0;_delay_ms(300);}  // on=0


Кнопка вкл/отк генерацию

82 #    if(on==1){lcd.Curs(1,11);lcd.PrintString("*");}

строка индикации вкл/отк генерации

проверьте кнопку энкодера, а так же наличие 3-х подтягивающих резисторов на платке энкодера по 10кОм

22

Re: Генератор AD9833+частотомер 6.5 МГц.

Доброго времени суток.
На энкодере оказалось что один из подтягивающих резисторов, а именно резистор на кнопку сказал мяу..., подправил, подпаял и все завелось как надо. Спасибо.

23

Re: Генератор AD9833+частотомер 6.5 МГц.

Схема и скетч от проекта генератор + частотомер. Работает только частотомер. Генератор выдает только меандр вместо пилы и синусоиды. Меандр выдает хорошо и частота меняется. Переключение на синус ничего не дает. Выдает только меандр. Пришлось перепаять схему на проект  генератор без частотомера. Слил скетч. Все заработало. Выдает и пилу и синус. Ардуино Nano/ Подскажите в чем проблема? Да, схема работает и без третьей кнопки CLEAR, она по сути и не нужна.

24

Re: Генератор AD9833+частотомер 6.5 МГц.

Уважаемый  taban. Не могли бы Вы выложить схему соединений блоков. Хочу попробовать ваш скетч и схему. Хотелось бы запустить частотомер

25

Re: Генератор AD9833+частотомер 6.5 МГц.

Вечер добрый! При переключении типа волны, выдаёт только прямоугольный импульс. Синус и пилу не выдаёт, частота при этом регулируется. Что посоветуете ?