Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Problema con classe per far funzionare ARDUINODUE con AD9833

Progetti, interfacciamento, discussioni varie su questa piattaforma.

Moderatori: Foto UtenteWALTERmwp, Foto Utentexyz

0
voti

[1] Problema con classe per far funzionare ARDUINODUE con AD9833

Messaggioda Foto Utentefabio75 » 24 nov 2025, 19:05

Sto collegando ARDUINODUE a due aD9833 per generare dei segnali audio.
Riporto il codice che ho trovato qui ---> https://forum.arduino.cc/t/program-mult ... pi/1098217
Codice: Seleziona tutto
#include "Wire.h"
int FSYNC = 10; //in my example OR ANY PIN 0-13
int FSYNC2 = 31;
int SDATA = 11;
int SCLK = 13;
int i;
int k ;
unsigned long freq;     
//byte wave=1;
void setup() {
  freq=1; // start with frequency 1HZ as an example
//Application Note AN-1070 from Analog Devices
 UpdateRegister(0x2100);  UpdateRegister(0x50C7); UpdateRegister(0x4000); 
 UpdateRegister(0xC000); UpdateRegister(0x2000);
 UpdateRegister2(0x2100);  UpdateRegister2(0x50C7); UpdateRegister2(0x4000); 
 UpdateRegister2(0xC000); UpdateRegister2(0x2000);
 UpdateRegister3(0x2100);  UpdateRegister3(0x50C7); UpdateRegister3(0x4000); 
 UpdateRegister3(0xC000); UpdateRegister3(0x2000);
 
for(k=0;k<32;k++)  pinMode(k, OUTPUT);

  for (i=0;i<32;i++)  digitalWrite(i,HIGH); // put pins 0-13 (FSYNC's) as output HIGH
  
 // pinMode(FSYNC, OUTPUT);  pinMode(SDATA, OUTPUT); pinMode(SCLK, OUTPUT);
 //digitalWrite(FSYNC, HIGH);digitalWrite(SDATA, LOW);digitalWrite(SCLK, HIGH);
  }

void loop() {
   UpdateFreq(2300, 0x2020);  // for every FSYNC pins 0-13 we update a desired frequency, 0x2000 is for sine wave, 0x2020 is for square etc
   UpdateFreq2(200, 0x2020);
   UpdateFreq3(800, 0x2020);
   delay(500); // a delay to measure your desired programmed frequencies with a scope
}

void UpdateFreq(unsigned int freq, int form){
// function to program the frequency into registers - no touch
long FreqReg;
unsigned int MSB, LSB;
  FreqReg = (freq * pow(2, 28)) / 25000000; // 25MHz Quarz
  if (form == 0x2020) FreqReg = FreqReg << 1; 
  MSB = (int)((FreqReg & 0xFFFC000) >> 14);
  LSB = (int)(FreqReg & 0x3FFF);
  LSB |= 0x4000;
  MSB |= 0x4000;
  UpdateRegister(0x2100); // Control Register, Reset Bit DB8
  UpdateRegister(LSB);    // Frequency Register 0 LSB
  UpdateRegister(MSB);    // Frequency Register 0 MSB
  UpdateRegister(0xC000); // Phase Register
  UpdateRegister(form);   // Exit Reset
}
void UpdateRegister(unsigned int data)
{ // function to program registers - no touch
  unsigned int pointer = 0x8000;
  digitalWrite(FSYNC, LOW);
  for (int i=0; i<16; i++){
    if ((data & pointer) > 0) {
      digitalWrite(SDATA, HIGH);
    }
    else {
      digitalWrite(SDATA, LOW);
    }
    digitalWrite(SCLK, LOW);
    digitalWrite(SCLK, HIGH);
    pointer = pointer >> 1 ;
  }
  digitalWrite(FSYNC, HIGH);
}

void UpdateFreq2(unsigned int freq, int form){
// function to program the frequency into registers - no touch
long FreqReg;
unsigned int MSB, LSB;
  FreqReg = (freq * pow(2, 28)) / 25000000; // 25MHz Quarz
  if (form == 0x2020) FreqReg = FreqReg << 1; 
  MSB = (int)((FreqReg & 0xFFFC000) >> 14);
  LSB = (int)(FreqReg & 0x3FFF);
  LSB |= 0x4000;
  MSB |= 0x4000;
  UpdateRegister2(0x2100); // Control Register, Reset Bit DB8
  UpdateRegister2(LSB);    // Frequency Register 0 LSB
  UpdateRegister2(MSB);    // Frequency Register 0 MSB
  UpdateRegister2(0xC000); // Phase Register
  UpdateRegister2(form);   // Exit Reset
}
void UpdateRegister2(unsigned int data)
{ // function to program registers - no touch
  unsigned int pointer = 0x8000;
  digitalWrite(FSYNC2, LOW);
  for (int i=0; i<16; i++){
    if ((data & pointer) > 0) {
      digitalWrite(SDATA, HIGH);
    }
    else {
      digitalWrite(SDATA, LOW);
    }
    digitalWrite(SCLK, LOW);
    digitalWrite(SCLK, HIGH);
    pointer = pointer >> 1 ;
  }
  digitalWrite(FSYNC2, HIGH);
}


Quel codice sopra l'ho esteso per due moduli AD9833 e funziona riesco a generare due segnali distinti in due moduli (uno da 200Hz ed uno da 2300Hz sinusoidali), allego le tracce dell'oscilloscopio con i segnali di uscita.
La mia idea è quella di estendere il codice per 10 moduli AD9833, quindi la cosa giusta da fare
sarebbe creare una classe e dalla classe ricavare 10 oggetti come nel codice che riporto sotto:
Codice: Seleziona tutto
#include "Wire.h"
#include "ad9833.h"
#include <SPI.h>
int FSYNC = 10; //in my example OR ANY PIN 0-13
int SDATA = 11;
int SCLK = 13;
int i;
int k ;
unsigned int freq;
Gen gen[10];
//byte wave=1;
void setup() {
  freq=1; // start with frequency 1HZ as an example
//Application Note AN-1070 from Analog Devices
gen[1].UpdateRegister(0x2100);  gen[1].UpdateRegister(0x50C7); gen[1].UpdateRegister(0x4000);
gen[1].UpdateRegister(0xC000); gen[1].UpdateRegister(0x2000);
for(k=0;k<32;k++)  pinMode(k, OUTPUT);

  for (i=0;i<32;i++)  digitalWrite(i,HIGH); // put pins 0-13 (FSYNC's) as output HIGH
 
// pinMode(FSYNC, OUTPUT);  pinMode(SDATA, OUTPUT); pinMode(SCLK, OUTPUT);
//digitalWrite(FSYNC, HIGH);digitalWrite(SDATA, LOW);digitalWrite(SCLK, HIGH);
  }

void loop() {
   gen[1].UpdateFreq(1000, 0x2020);  // for every FSYNC pins 0-13 we update a desired frequency, 0x2000 is for sine wave, 0x2020 is for square etc
   
   delay(1);     
   //FSYNC=0; //start FSYNC (AD9833 chip select ) from the beginning
   
   delay(500); // a delay to measure your desired programmed frequencies with a scope
}

void Gen::UpdateFreq(unsigned int freq, int form){
// function to program the frequency into registers - no touch
  long FreqReg;
  unsigned int MSB, LSB;
  FreqReg = (freq * pow(2, 28)) / 25000000; // 25MHz Quarz
  if (form == 0x2020) FreqReg = FreqReg << 1; 
  MSB = (int)((FreqReg & 0xFFFC000) >> 14);
  LSB = (int)(FreqReg & 0x3FFF);
  LSB |= 0x4000;
  MSB |= 0x4000;
  gen[1].UpdateRegister(0x2100); // Control Register, Reset Bit DB8
  gen[1].UpdateRegister(LSB);    // Frequency Register 0 LSB
  gen[1].UpdateRegister(MSB);    // Frequency Register 0 MSB
  gen[1].UpdateRegister(0xC000); // Phase Register
  gen[1].UpdateRegister(form);   // Exit Reset
}

void Gen::UpdateRegister(unsigned int data)
{ // function to program registers - no touch
  //unsigned int pointer = 0x8000;
  digitalWrite(FSYNC, LOW);
  for (int i=0; i<16; i++){
    if ((data & pointer) > 0) {
      digitalWrite(SDATA, HIGH);
    }
    else {
      digitalWrite(SDATA, LOW);
    }
    digitalWrite(SCLK, LOW);
    digitalWrite(SCLK, HIGH);
    gen[1].pointer = gen[1].pointer >> 1 ;
  }
  digitalWrite(FSYNC, HIGH);
}


ed il relativo file header:
Codice: Seleziona tutto
class Gen
{
  public:
    void UpdateFreq(unsigned int , int);
    void UpdateRegister(unsigned int);
  private:
    //unsigned int FreqReg;
    //unsigned int MSB, LSB;
    unsigned int pointer = 0x8000;
  };


Dopo aver compilato e trasferito il codice noto che non funziona nemmeno per un modulo infatti io imposto da programma una freq. di 1000Hz ad onda quadra ed invece misuro una frequenza di 8.25Mhz con una forma d'onda assurda.
Allego la traccia.
Non capisco perché la generazione del segnale utilizzando la classe e l'oggetto da essa generato non funziona.
Scusate la mia igoranza con il C++ ma conosco poco questo linguaggio.
Mi potete aiutare a capire cosa ho sbagliato in quest'ultimo codice? #-o
Allegati
traccia_con_la_classe.png
tracce.jpg
Avatar utente
Foto Utentefabio75
0 3
 
Messaggi: 3
Iscritto il: 24 nov 2025, 13:42

1
voti

[2] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto Utentexyz » 24 nov 2025, 19:50

Riporta lo schema elettrico delle connessioni. Il pin FSYNC ha anche la funzione di Chip Select, nel primo codice è usato il pin 10 (FSYNC) e pin 31 (FSYNC2).
Il secondo codice è scritto male, riporto i primi problemi che ho notato. Fai il loop con più oggetti instanziati ma tutti usano il pin 10 (FSYNC). Il loop conta da 0 a 15 ma array è di soli 10 elementi, usi come indice la variabile i ma poi usi 1 (uno) il quale salva il programma da un buffer overflow ma è un errore. Mi fermo qui a elencare i problemi di programmazione che vedo.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

1
voti

[3] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto UtenteEtemenanki » 24 nov 2025, 19:54

Premetto che non uso mai le classi (lo considero come andarsi a cercare i problemi anche dove non ci sono), e non ho una DUE (per cui potrei sbagliare), ma credo possano funzionare come con la UNO, quindi perche' fare una cosa del genere ? ... non puoi pilotarli semplicemente in una funzione dedicata ?

Ti crei un paio di array dove metti i numeri dei pin collegati ai pin sync e via ... tanto i moduli AD9833 sono "3wire SPI", li attivi uno alla volta in ricezione portando il relativo pin fsync basso, scrivi i valori per frequenza, forma d'onda e fase (se ti serve anche quella) e riporti il fsync alto ... quindi puoi passare ad ognuno di loro i dati in qualsiasi momento anche solo usando comandi "wire", in modo indipendente sia come frequenze che come forme d'onda.

Oppure ho capito male io, e ti serve una modalita' di funzionamento differente ?
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.
Avatar utente
Foto UtenteEtemenanki
9.507 3 6 10
Master
Master
 
Messaggi: 5935
Iscritto il: 2 apr 2021, 23:42
Località: Dalle parti di un grande lago ... :)

0
voti

[4] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto Utentefabio75 » 24 nov 2025, 20:32

Nota di moderazione: evita di citare integralmente i post, in questo caso non serviva proprio citare.

Scelgo la soluzione di Etemenanki e riporto il codice modificato:
Codice: Seleziona tutto
#include "Wire.h"
int FSYNC = 10; //in my example OR ANY PIN 0-13
int FSYNC2 = 31;
int FSYNC3 = 32;
int FSYNC4 = 33;
int SDATA = 11;
int SCLK = 13;
int i;
int k ;
unsigned long freq;     
//byte wave=1;
void setup() {
  freq=1; // start with frequency 1HZ as an example
//Application Note AN-1070 from Analog Devices
UpdateRegister(0x2100, FSYNC);  UpdateRegister(0x50C7, FSYNC); UpdateRegister(0x4000, FSYNC);
UpdateRegister(0xC000, FSYNC); UpdateRegister(0x2000, FSYNC);
UpdateRegister(0x2100, FSYNC2);  UpdateRegister(0x50C7, FSYNC2); UpdateRegister(0x4000, FSYNC2);
UpdateRegister(0xC000, FSYNC2); UpdateRegister(0x2000, FSYNC2);
UpdateRegister(0x2100, FSYNC3);  UpdateRegister(0x50C7, FSYNC3); UpdateRegister(0x4000, FSYNC3);
UpdateRegister(0xC000, FSYNC3); UpdateRegister(0x2000, FSYNC3);
UpdateRegister(0x2100, FSYNC4);  UpdateRegister(0x50C7, FSYNC4); UpdateRegister(0x4000, FSYNC4);
UpdateRegister(0xC000, FSYNC4); UpdateRegister(0x2000, FSYNC4);
for(k=0;k<34;k++)  pinMode(k, OUTPUT);

  for (i=0;i<34;i++)  digitalWrite(i,HIGH); // put pins 0-13 (FSYNC's) as output HIGH
 
// pinMode(FSYNC, OUTPUT);  pinMode(SDATA, OUTPUT); pinMode(SCLK, OUTPUT);
//digitalWrite(FSYNC, HIGH);digitalWrite(SDATA, LOW);digitalWrite(SCLK, HIGH);
  }

void loop() {
   UpdateFreq(2300, 0x2000,  FSYNC);  // for every FSYNC pins 0-13 we update a desired frequency, 0x2000 is for sine wave, 0x2020 is for square etc
   UpdateFreq(200, 0x2000,  FSYNC2);
   UpdateFreq(1000, 0x2020,  FSYNC3);
   UpdateFreq(2700, 0x2000,  FSYNC4);
   delay(500); // a delay to measure your desired programmed frequencies with a scope
}

void UpdateFreq(unsigned int freq, int form, int sc){
// function to program the frequency into registers - no touch
long FreqReg;
unsigned int MSB, LSB;
  FreqReg = (freq * pow(2, 28)) / 25000000; // 25MHz Quarz
  if (form == 0x2020) FreqReg = FreqReg << 1; 
  MSB = (int)((FreqReg & 0xFFFC000) >> 14);
  LSB = (int)(FreqReg & 0x3FFF);
  LSB |= 0x4000;
  MSB |= 0x4000;
  UpdateRegister(0x2100, sc); // Control Register, Reset Bit DB8
  UpdateRegister(LSB, sc);    // Frequency Register 0 LSB
  UpdateRegister(MSB, sc);    // Frequency Register 0 MSB
  UpdateRegister(0xC000, sc); // Phase Register
  UpdateRegister(form, sc);   // Exit Reset
}
void UpdateRegister(unsigned int data, int sc)
{ // function to program registers - no touch
  unsigned int pointer = 0x8000;
  digitalWrite(sc, LOW);
  for (int i=0; i<16; i++){
    if ((data & pointer) > 0) {
      digitalWrite(SDATA, HIGH);
    }
    else {
      digitalWrite(SDATA, LOW);
    }
    digitalWrite(SCLK, LOW);
    digitalWrite(SCLK, HIGH);
    pointer = pointer >> 1 ;
  }
  digitalWrite(sc, HIGH);
}


Funziona con 4 moduli! :ok:
Nel tutorial non è spiegato che valore mettere per ottenere un' onda triangolare.
Allego lo schemino.
Ultima modifica di Foto Utenteclaudiocedrone il 25 nov 2025, 0:01, modificato 1 volta in totale.
Motivazione: Eliminata inutile citazione integrale del post immediatamente precedente
Avatar utente
Foto Utentefabio75
0 3
 
Messaggi: 3
Iscritto il: 24 nov 2025, 13:42

0
voti

[5] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto Utentefabio75 » 24 nov 2025, 20:55

Avatar utente
Foto Utentefabio75
0 3
 
Messaggi: 3
Iscritto il: 24 nov 2025, 13:42

0
voti

[6] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto UtenteEtemenanki » 24 nov 2025, 23:04

fabio75 ha scritto:non è spiegato che valore mettere per ottenere un' onda triangolare

Triangolare 0x2002 , quadra 0x2028 , sinusoidale 0x2000

Pensavo ad una soluzione un po diversa, ma se ti funziona cosi, va bene pure quella ;-)
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.
Avatar utente
Foto UtenteEtemenanki
9.507 3 6 10
Master
Master
 
Messaggi: 5935
Iscritto il: 2 apr 2021, 23:42
Località: Dalle parti di un grande lago ... :)

1
voti

[7] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto Utenteclaudiocedrone » 25 nov 2025, 0:29

Foto Utentefabio75 o Foto Utentealien75 :?:
Scegli quale dei due account vuoi mantenere, gli account multipli non sono ammessi dal regolamento.
Poi rispetta le regole del forum, dovresti conoscerle bene dato che lo frequenti da lungo tempo (addirittura da prima di me).
Alla prossima violazione scatteranno provvedimenti.
"Non farei mai parte di un club che accettasse la mia iscrizione" (G. Marx)
Avatar utente
Foto Utenteclaudiocedrone
21,3k 4 7 9
Master EY
Master EY
 
Messaggi: 15300
Iscritto il: 18 gen 2012, 13:36

0
voti

[8] Re: Problema con classe per far funzionare ARDUINODUE con AD

Messaggioda Foto Utenteclaudiocedrone » 4 dic 2025, 1:36

Ok, visto che non hai scelto tu scegliamo noi di disattivare questo tuo nuovo account.
"Non farei mai parte di un club che accettasse la mia iscrizione" (G. Marx)
Avatar utente
Foto Utenteclaudiocedrone
21,3k 4 7 9
Master EY
Master EY
 
Messaggi: 15300
Iscritto il: 18 gen 2012, 13:36


Torna a Arduino

Chi c’è in linea

Visitano il forum: Nessuno e 5 ospiti