Pages: 1 [2] 3   Go Down
Author Topic: How much can 328p handle?  (Read 1908 times)
0 Members and 1 Guest are viewing this topic.
Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

..instead of the freq calcs just add the step (when you do a linear sweep)..
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 517
Posts: 26268
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh yeah - way faster
add this
#include <SPI.h>
Code:
Get rid of all these
 #define W_CLK 8       // Pin 8 - connect to AD9850 module word load clock pin (CLK)
 #define FQ_UD 9       // Pin 9 - connect to freq update pin (FQ)
 #define DATA 10       // Pin 10 - connect to serial data load pin (DATA)
 #define RESET 11      // Pin 11 - connect to reset pin (RST).

use this:
// pin 13 to clock
// pin 12 to devices data out pin if you will read anything back
// pin 11 to devices data in pin that you are sending data to
 #define FQ_UD 10       // Pin 10 - connect to freq update pin (FQ)
 #define RESET 9      // Pin 9 - connect to reset pin (RST).

Put your 5 bytes in an array, and add this in place of the bit banging you have now"

PORTB = PORTB & B11111011; // clear pin 10
SPI.transfer(dataArray[0]);
SPI.transfer(dataArray[1]);
SPI.transfer(dataArray[2]);
SPI.transfer(dataArray[3]);
SPI.transfer(dataArray[4]);
PORTB = PORTB | B00000100; // set pin 10
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

0
Offline Offline
Full Member
***
Karma: 2
Posts: 226
#include˂baby.h˃™
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, it compiles, but it seems to hang somewhere ?

I was also wondering if the array is needed, instead of dataArray = (freq & 0xFF);, just sending the data byte in the for loop?

Code:
#include <SPI.h>
#define W_CLK 13     // Pin 13 - connect to AD9850 module word load clock pin (CLK)
#define DATA 11      // Pin 11 - connect to serial data load pin (DATA)
#define FQ_UD 10     // Pin 10 - connect to freq update pin (FQ)
#define RESET 9      // Pin 9 - connect to reset pin (RST)
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }

// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {
  byte dataArray[5];
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850
  for (int b=0; b<4; b++, freq>>=8) {
    dataArray[b] = (freq & 0xFF);
  }
  dataArray[4] = 0x000;   // Final control byte, all 0 for 9850 chip
  PORTB = PORTB & B11111011; // clear pin 10
  SPI.transfer(dataArray[0]);
  SPI.transfer(dataArray[1]);
  SPI.transfer(dataArray[2]);
  SPI.transfer(dataArray[3]);
  SPI.transfer(dataArray[4]);
  PORTB = PORTB | B00000100; // set pin 10
  pulseHigh(FQ_UD);  // Done!  Should see output
}
 
void setup() {
  Serial.begin(115200);
  Serial.println("DDS Sweep");
  // configure arduino data pins for output
  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT);
  pulseHigh(RESET);
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);  // this pulse enables serial mode - Datasheet page 12 figure 10
}
 
void loop() {
  long F1 = 1;
  long F2 = 10;
  long long freq = 1;
  Serial.print("Start Frequency: ");
  Serial.print(long (freq));
  Serial.println(" Hz");
  long timeStart = micros();
  while (freq <= F2) {
    sendFrequency(freq);  // freq
    freq++;
  }
  long timeStop = micros();
  Serial.print("Start Time: ");
  Serial.print(timeStart);
  Serial.println(" us");
  Serial.print("Stop Frequency: ");
  Serial.print(long (freq));
  Serial.println(" Hz");
  Serial.print("Stop Time: ");
  Serial.print(timeStop);
  Serial.println(" us");
  Serial.print("Sweep Time: ");
  Serial.print(timeStop - timeStart);
  Serial.println(" us");
  Serial.print("Switching Time: ");
  Serial.print((timeStop - timeStart) / long(freq));
  Serial.println(" us/pt");
  Serial.println("");
}
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

..
int32_t freq_start = (frequency1 * 4294967296LL)/125000000;
int32_t freq_stop = (frequency2 * 4294967296LL)/125000000;
int32_t freq_step = (frequency3 * 4294967296LL)/125000000;
..

and then something like this:

for (f=freq_start; f<=freq_stop; f=f+freq_step) {
sendDDSword(f);
}

PS: shall it be 4294967295 or 4294967296 ?? smiley
« Last Edit: May 06, 2013, 05:19:57 pm by pito » Logged

Offline Offline
Edison Member
*
Karma: 43
Posts: 1551
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int32_t freq = frequency * 4294967295/125000000;
I doubt that that will work. It would have a better chance if you force the size of the integers and get 2^32 right:
Code:
int32_t freq = frequency * 4294967296LL/125000000L;

Pete

Logged

Where are the Nick Gammons of yesteryear?

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
You need to do this calculation in 64-bit integer arithmetic (which makes using the Due look better!)

This works on the Uno:

Code:
unsigned long long DDSword, freq, DDSclock;
DDSclock = 125000000LL;
freq = 50000000LL;  // required freq
DDSword = (0x100000000LL) * freq ;
DDSword = DDSword / DDSclock;
The above works smiley
You may do a check with:
Code:
Serial.println((long)DDSword, 16);
against:
http://designtools.analog.com/dt/dds/ad9850.html
« Last Edit: May 06, 2013, 05:20:34 pm by pito » Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 226
#include˂baby.h˃™
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Folks. Thanks a lot for the inputs! I'm still digesting how to use the code snip-its provided.

I also noticed the 2^32 calculation and sent the update (int32_t freq = frequency * 4294967296LL/125000000L;). My freq counter is limited to 10 Hz resolution , so perhaps I am just not able to measure the difference - the output is 9,999,96 Hz when set to 10 MHz output. I'll have to dig out another counter...

I see what you're saying pito, thanks.

I'm still trying to get the faster code to run, and also played with putting the sendfreq call in an encoder interrupt, and that did nothing?
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 517
Posts: 26268
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf

"This is the 8-bit data port for iteratively loading the 32-bit frequency and the 8-bit phase/control word."

I don't see that you have an control word being created in the array data.
See pages 9-10 of the data sheet.

I think your formula is not correct
int32_t freq = frequency * 4294967295/125000000;

page 8 says Freq out = (tuning word * clock in(MHz))/2^32
                                     = (32-bit word*125,000,000)/0xFFFFFFFF
                                     = (32-bit word * 125,000,000) >> 32
so you probably need a 64 bit to start with for the multiplication, that gets shifted down for the 2^32 divide.
125,000,000 = 0x0773,5940
So it would seem that the the tuning word would have to be some minimum amount to avoid getting divided down to 0, yes?
Like 23 or more:
0x0773 5940 x 22 = 0xFD51 DA80 >> 32 = 0
0x773 5940 * 23 = 0x1 04C5 33C0 >> 32 = 1
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

0
Offline Offline
Full Member
***
Karma: 2
Posts: 226
#include˂baby.h˃™
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, this is like the opening scene with Mr. Roarke and Tattoo...

Is this not the control word in the array: dataArray[4] = 0x000;   // Final control byte, all 0 for 9850 chip

The formula does seem messed up, not only the value. I'm surprised I'm getting output. I'll change that tonight and see how it pans out, but, is it not this way because we are calculating the tuning word value based on frequency? And there was something about the largest 32-bit integer value being 2^32-1.

I know decimal math, if I plug in a tuning word value of "1", I get a frequency value of 0.0291, which is the minimum frequency resolution of the DDS (spec). If the tuning word value is 34.35974, the frequency value is 1. If the tuning word value is 0, then I suspect DC output?
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Again, simply verify your DDSword calculation (see my post above). When it is correct (it MUST be the same as the calc result on the ADI page above), try to pass it to the DDS chip.

Do NOT expect you will see an accurate DDS output frequency on the freqmeter, because you do NOT know the actual frequency of your 125MHz DDSclock. It could be 125.009.447,786 Hz - this DDSclock needs to be

a) measured by the freqmeter and its value has to be changed in the code accordingly, or,

b) "calibration mode": set the DDSfreq to ie. 10.000.000Hz output, pass it to DDS chip, do measure the DDS output freq (you may see something like "9.997.234Hz"), and do change the DDSclock value such until you see "10.000.000Hz" on the freqmeter (provided your freqmeter is precise enough), and do save the new DDSclock value somewhere.

I used that "calibration" mode with my DDS stuff I did long time back (so I did not care what the actual DDSclock freq was like, and, the actual DDSclock hex value was saved into an EEPROM after the calibration - btw. you can do the calibration anytime then, even when your DDS generator is already built into a nice shiny case smiley )..
« Last Edit: May 06, 2013, 03:54:54 pm by pito » Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 517
Posts: 26268
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

See bottom of page 12.
You may have to flip the SPI bit order:
http://arduino.cc/en/Reference/SPISetBitOrder
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://sourceforge.net/projects/k3ngarduinaddds/files/
http://www.ad7c.com/projects/ad9850-dds-vfo/
http://code.google.com/p/ad9850-arduino/
http://www.theladderline.com/node/10
http://arduino.alhin.de/index.php?n=7
http://webshed.org/wiki/AD9850_Arduino
http://code.google.com/p/rocketnumbernine/source/browse/trunk/AVR/AD9851/ad9851-spi.pde

http://www.knology.net/~gmarcus/
http://www.elecfreaks.com/2110.html
http://www.kerrywong.com/2012/11/06/dds-function-generator-build/#more-7090
https://gist.github.com/raivisr/3861473
http://rockingdlabs.dunmire.org/home/ad-9850ddssynthesizer
https://gist.github.com/raivisr/3861473
http://www.tarapippo.net/arduino/sweep.ino
http://www.ad7c.com/2013/02/
http://wsprnet.org/drupal/node/3834

PS: the 9851 and 9850 are identical except 1 bit..


« Last Edit: May 06, 2013, 05:14:12 pm by pito » Logged

Offline Offline
Edison Member
*
Karma: 43
Posts: 1551
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For a serial load, the relevant information is Table IV on page 12.

The formula I gave is correct:
Code:
int32_t freq = frequency * 4294967296LL/125000000L;
This calculates the tuning word (given the misleading variable name "freq" here) from the desired frequency. The tuning word is then sent to the device.

Pete
Logged

Where are the Nick Gammons of yesteryear?

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
int32_t freq = frequency * 4294967296LL/125000000L;
To be safe:
int32_t freq = (frequency * 0x100000000LL)/125000000L;
PS: Mind the 125000000L is not the correct number with those cheap modules..
« Last Edit: May 06, 2013, 05:44:48 pm by pito » Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 226
#include˂baby.h˃™
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Folks! I'd seen some of those sites before, and interesting that the same 2^32 number comes up incorrectly in the code in a few different places.

That is a pretty clever way to calibrate the DDS clock. I was thinking of adjusting the sent frequency value with a cal variable in the sendfrequency module.

I think I'm armed with enough to get something done now. smiley-confuse
Logged

Pages: 1 [2] 3   Go Up
Jump to: