Kód Arduina na generátor funkcií pomocou AD9833

Sekcia určená pre Arduino nadšencov

Moderátor: Moderátori

feriak
Okoloidúci
Okoloidúci
Príspevky: 5
Dátum registrácie: 03 Máj 2023, 18:19

Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa feriak » 03 Máj 2023, 18:26

Dobrý, chcel by som od vás či by ste sa nemohli pozrieť na kód arduina na generovanie vĺn. Ako sami viete modul AD9833 dokáže generovať sinus, pilovite a obdlžnikove priebehy. Ale u mňa nastal taký problem že keď si merám prístroj pri obdlžnikovom priebehu my vždycky ukazuje iba polovičnú hodnotu. napr. nastavím 500Hz tak na osciloskope ukáže iba 250.


Kód: Vybrať všetko

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <Encoder_Polling.h>
 
#define FSYNC 6 //Definícia PIN-u D6 - FSYNC AD9833
#define POSITIVE 0 
// ĎALŠIE PIN-Y POUŽITÉ PRE AD9833 Z ARDUINO NANO V3
// D11 - MOSI(MasterOut, SlaveIn) - SDATA
// D13 - SCK (Serial Peripheral Interface) - SCLK
// PINY PRE I2C
// A4 - SDA
// A5 - SCL
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define Light 3                 // podsvietenie - pin 3
 
//********** definícia pin-ov encoder-a
int encoderPin_A = 4;
int encoderPin_B = 3;
int PushButt = 2;      // pin encoder-a PushButton
 
//********** spúšťacie parametre a premenné
long cas = 500000;      // nastavenie počiatočnej frekvencie
String frekvencia;
long krok = 10;             // počiatočný krok
int sinus = 0x2000;          
int trojhol = 0x2002;
int obdl = 0x2020;
int typchodu;
int znacka = 10;           // pomocná značka – používa sa pre MENU
 
void setup()
{
    lcd.begin ();                     // def. LCD
    lcd.setBacklight(HIGH);               // zapnúť podsvietenie LCD
    pinMode(FSYNC, OUTPUT);               // konfigurácia pinu FSYNC
    SPI.begin();                          // start SPI
    digitalWrite(FSYNC, HIGH);            // nastavenie pinu FSYNC
    SPI.setDataMode(SPI_MODE2);           // prevádzkový režim SPI
 
    encoder_begin(encoderPin_A, encoderPin_B); // start Encoder
    pinMode(PushButt, INPUT);            // konfigurácia pinu PushButtona
    typchodu = sinus;                // začnite s priebehom SINUS
   
}
 
//*********************** Hlavná slučka programu *********************
void loop()
{
    obsluha_buttona();                  // skontrolujte tlačidlo v Encoder-i
    obsluha_encodera();                 // skontrolujte rotáciu v Encoder-i
    WriteFrequencyAD9833(cas);     // uložiť/obnoviť f v AD9833
    prezentacia();                      // zobraziť všetko na LCD
    delay(100);                         // pauza, aby LCD neblikal
                                        
                                        
    }
 
//*********************** Koniec hlavnej slučky *********************
 
 
 
 
 
 
//***********************  Postupy  ******************************
 
void obsluha_encodera()
{
 
    if (znacka == 10)   // značka 10 zmení signál sin/odbl/trohol
    {
              int dir = encoder_data();     // skontrolujte Encoder
              if(dir > 0)                   // Kontrolujem len správne
              {
                      if(typchodu == sinus)    // ak je typ chodu SINUS zmeň ho
                          {typchodu = trojhol; // na trojholník
                           delay(80);}             // počkaj
 
                      else if (typchodu == trojhol) //ak je typ chodu trojhol zmeň ho
                          {typchodu = obdl;delay(80);} // na obdĺžnik
                               
                      else if (typchodu == obdl)//ak je typ chodu obdĺžnik zmeň ho
                          {typchodu = sinus;delay(80);} // na SINUS
                      else
                      {}   
              }
              else
              {}
    } //*****************koniec podmienky pre značku == 10
 
 
 
               
    if (znacka == 20)    // podmienka pre značku 20 - kroková zmena
    {
             int dir = encoder_data();     // skontrolujte Encoder
             if(dir > 0)                   // ak spravne tak...
               {
                  if (krok < 1000000)      // ak je krok menší ako 1 MHz
                  {krok = krok * 10;delay(100);} // zvýšte krok násobenia o 10
                   
                  else                     // ak 1MHz neurobí nič
                  {}
               }
             else if (dir <0 )             // ak zostane potom...
                  {
                    if (krok >= 10)        // dodatočná podmienka
                                           // skontrolujte, či to nie je 0
                       {krok = krok / 10;  // znížiť krok - delenie 10
                        delay(100); 
                       } 
                        
                    else
                      {krok = 1;delay(100);}          // nastavte na krok 1 Hz
                       
                  }
              else
                  {}
       
    } //****************koniec podmienky pre značku == 20
     
 
    else if (znacka == 30) // podmienka pre značku 30 - zmena frekvencie
    {
                 
           int dir = encoder_data();              // skontrolujte Encoder
           if(dir > 0)                            // ak spravne tak...
                  {cas = cas + krok;}   // zvýšiť f o jeden krok
           else if (dir <0 )                      // ak zostane potom...
                if ((cas-krok) >= 0)
                  {
                  {cas = cas - krok;}   // znížiť f o krok
                  }
                  else
                  {}
                   
           else
                  {}
     } //********************koniec podmienky pre značku == 30
    else
        {}
   
} //****************koniec postupu obsluhy encoder-a
 
 
 
void obsluha_buttona()
{
   if (digitalRead(PushButt))
   {}                              // nestlačené - výstup
    
   else
   {                               // stlačený - určím ktorý
                                   //  položky ponuky a čo zmeniť
    if (znacka == 10)            // ak značka = 10 ...
      {znacka = 20;delay(120);}  // ...zmena na 20
    else if (znacka == 20)       // ak značka = 20 ...
      {znacka = 30;delay(120);}  // ...zmena na 30
    else
      {znacka = 10;delay(120);}  // ak nie 10 a nie 20, tak musí
                                   // byť 30, tak ho znova nastavte na 10
   }
}
 
 
 
 
 
void prezentacia()                 // zobraziť všetky hodnoty
{
  lcd.clear();                     // čistý LCD
  if(znacka == 10)               // značka = 10
    {lcd.print("*");}              // ... zobrazí pred ním znak „*“.
  else
    {lcd.print(" ");}              //tznačka <> 10 - medzera
 
  if(typchodu == sinus)        // aký je náš aktuálny priebeh
    {lcd.print("sinus");}            // ak sínus - zobraz
  else if (typchodu == obdl)
    {lcd.print("obdlz");}            // ak obdĺžnik - zobraz
   else if (typchodu == trojhol)
    {lcd.print("trojh");}            // ak trojuholník - zobraz
   else
    {}
 
  if(znacka == 20)               // ak značka = 20
    {
    lcd.print(" *");}
  else
    {lcd.print("  ");}
     
  lcd.print("K=");
 
  if(krok == 1000000)
    {
      lcd.print(krok / 1000000);
      lcd.print("MHz");
    }
  else if(krok >= 1000)
    {
      lcd.print(krok / 1000);
      lcd.print("KHz");
    }
  else
  {
    lcd.print(krok);
    lcd.print("Hz");
  }
   
  lcd.setCursor(0, 1);
 
 
  if(znacka == 30)               // ak značka = 30
    {
        lcd.print("*");
    }
  else
    {
        lcd.print(" ");
    }
 


 
 
  frekvencia = String(cas); //prevod dátového typu na reťazec
  int dlzka = frekvencia.length(); //Nastavil som dĺžku
   
  if (dlzka == 6) // ak dĺžka 6 - menej ako 1 MHz
     {
       frekvencia = "0" + frekvencia; // dajte pred ňu nulu
     }
   else if(dlzka == 5) // ak dĺžka 5 - desiatky KHz
     {
       frekvencia = "00" + frekvencia;
     }
   else if(dlzka == 4) // ak dĺžka 4 - kHz jednotky
     {
       frekvencia = "000" + frekvencia;
     }
 
    else if(dlzka == 3) // ak dĺžka 3 - stovky Hz
     {
       frekvencia = "0000" + frekvencia;
     }
    else if(dlzka == 2) // ak dĺžka 2 - desiatky Hz
     {
       frekvencia = "00000" + frekvencia;
     }
 
    else if(dlzka == 1) // ak dĺžka 1 - Hz jednotky
     {
       frekvencia = "000000" + frekvencia;
     }
    else
    {}
 
 
      
   
  lcd.print(" F=" + frekvencia.substring(0,1) + "." + frekvencia.substring(1,4) + "." + frekvencia.substring(4,7) + " Hz");
   
   
 
}
 
 
// Postupy obsluhy AD9833 - prevzatá zo siete 
// 
 
void WriteFrequencyAD9833(long frequency)
{
int MSB;
int LSB;
int phase = 0;
long calculated_freq_word;
float AD9833Val = 0.00000000;
AD9833Val = (((float)(frequency)) / 25000000); // 25 MHz DDS hodiny
calculated_freq_word = AD9833Val * 0x10000000;
MSB = (int)((calculated_freq_word & 0xFFFC000) >> 14);
LSB = (int)(calculated_freq_word & 0x3FFF);
LSB |= 0x4000;
MSB |= 0x4000;
phase &= 0xC000;
WriteRegisterAD9833(0x2100);
WriteRegisterAD9833(LSB);
WriteRegisterAD9833(MSB);
WriteRegisterAD9833(phase);
WriteRegisterAD9833(typchodu);
}
 
void WriteRegisterAD9833(int dat)
{
digitalWrite(FSYNC, LOW);
SPI.transfer(highByte(dat));
SPI.transfer(lowByte(dat));
digitalWrite(FSYNC, HIGH);
}
0
Naposledy upravil/-a feriak v 03 Máj 2023, 22:34, upravené celkom 1 krát.

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 540
Dátum registrácie: 21 Feb 2022, 12:06

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa balu » 03 Máj 2023, 22:29

Když sem dáváš kód programu, nebylo by od věci uzavřít ho do tagu <code> (je v menu nahoře, když píšeš příspěvek : </>). Když to uděláš, budou zachované i odsazení atd. Takhle aby se v tom prase vyznalo ...

Je vidět, že s programováním teprve začínáš :
1. Máš tam tolikrát delay, že procesor v podstatě nedělá nic jinýho ...
2. Proč tam máš tohle :

Kód: Vybrať všetko

else
{}
1
Obrázok 1

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 540
Dátum registrácie: 21 Feb 2022, 12:06

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa balu » 03 Máj 2023, 22:39

Super - takhle to vypadá mnohem lépe.

Tu poloviční frekvenci to dělá jenom u obdélníkového průběhu ?
0

feriak
Okoloidúci
Okoloidúci
Príspevky: 5
Dátum registrácie: 03 Máj 2023, 18:19

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa feriak » 03 Máj 2023, 22:55

balu napísal:
03 Máj 2023, 22:29
ano
0

feriak
Okoloidúci
Okoloidúci
Príspevky: 5
Dátum registrácie: 03 Máj 2023, 18:19

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa feriak » 03 Máj 2023, 22:55

balu napísal:
03 Máj 2023, 22:39
Super - takhle to vypadá mnohem lépe.

Tu poloviční frekvenci to dělá jenom u obdélníkového průběhu ?
ano
0

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 540
Dátum registrácie: 21 Feb 2022, 12:06

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa balu » 03 Máj 2023, 23:12

feriak napísal:
03 Máj 2023, 18:26

Kód: Vybrať všetko

AD9833Val = (((float)(frequency)) / 25000000); // 25 MHz DDS hodiny
calculated_freq_word = AD9833Val * 0x10000000;
MSB = (int)((calculated_freq_word & 0xFFFC000) >> 14);
LSB = (int)(calculated_freq_word & 0x3FFF);
Výpočty v 64-bitech na 8-bitovém jednočipu je teda docela brutální nápad, ale budiž ...

Nemohla by ta poloviční frekvence souviset s tímhle :
MSB of the DAC Data

The MSB of the DAC data can be output from the AD9833. By setting the OPBITEN (D5) control bit to 1, the MSB of the DAC data is available at the VOUT pin. This is useful as a coarse clock source. This square wave can also be divided by 2 before being output. The DIV2 (D3) bit in the control register controls the frequency of this output from the VOUT pin.
obrazek.png
Upraveno : No jasně - 0x2020 je pro obdélník s poloviční frekvencí - zkontroluj si ještě jednou bity v control registru.
0

feriak
Okoloidúci
Okoloidúci
Príspevky: 5
Dátum registrácie: 03 Máj 2023, 18:19

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa feriak » 04 Máj 2023, 00:10

balu napísal:
03 Máj 2023, 23:12
feriak napísal:
03 Máj 2023, 18:26

Kód: Vybrať všetko

AD9833Val = (((float)(frequency)) / 25000000); // 25 MHz DDS hodiny
calculated_freq_word = AD9833Val * 0x10000000;
MSB = (int)((calculated_freq_word & 0xFFFC000) >> 14);
LSB = (int)(calculated_freq_word & 0x3FFF);
Výpočty v 64-bitech na 8-bitovém jednočipu je teda docela brutální nápad, ale budiž ...

Nemohla by ta poloviční frekvence souviset s tímhle :
MSB of the DAC Data

The MSB of the DAC data can be output from the AD9833. By setting the OPBITEN (D5) control bit to 1, the MSB of the DAC data is available at the VOUT pin. This is useful as a coarse clock source. This square wave can also be divided by 2 before being output. The DIV2 (D3) bit in the control register controls the frequency of this output from the VOUT pin.
obrazek.png
Upraveno : No jasně - 0x2020 je pro obdélník s poloviční frekvencí - zkontroluj si ještě jednou bity v control registru.
takže my vlastne stačí len prepísať 0x2020 na 0x2028 ?
0

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 540
Dátum registrácie: 21 Feb 2022, 12:06

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa balu » 04 Máj 2023, 06:44

Správně. 👍
0

feriak
Okoloidúci
Okoloidúci
Príspevky: 5
Dátum registrácie: 03 Máj 2023, 18:19

Re: Kód Arduina na generátor funkcií pomocou AD9833

Príspevok od používateľa feriak » 04 Máj 2023, 12:03

balu napísal:
04 Máj 2023, 06:44
Správně. 👍
Ďakujem funguje :applause:
0

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok