Closed RobTillaart closed 3 years ago
The trivial solution is to give every AD985X device a unique set of pins. By keeping the sets of pins disjunct there will be no interference between devices. It would mean that every device (besides VCC and GND) need 4 lines DATA, CLOCK, FQ_UD and RESET.
(this merely repeats what is said in #9 to keep all remarks together in one issue)
It is possible to share the DATA line without problems as long as these are only clocked in by the right device.
This implies that the CLOCK line should only reach the right device if the device is selected. This can be done by adding a logic port that ANDs the SELECT and the CLOCK.
This AND port effectively acts as a single gate in a multiplexer controlled by the devices SELECT line.
The RESET line can be multiplexed by the devices in the same way
The FQ_UD (frequency update) line can be multiplexed by the devices in the same way.
(update) The DATA line could also be multiplexed in this way, As 2 input AND port e.g. 74HC08 come per 4 in an IC this would mean one IC per device.
In- https://www.analog.com/en/analog-dialogue/articles/introduction-to-spi-interface.html# and other sources, it is described that SELECT LOW normally means that the device is selected / active.
This would imply that we need an INVERTER before applying the select signal to the AND port. As the select line is not really used yet this can be done in software. This way it simulates a SPI device with an active HIGH. This would not break the behavior when controlling a single device use, so acceptable.
It needs to be investigated if the FQ_UD pin really needs to be multiplexed. If a device gets a FQ_UD pulse it will use the frequency as written in the register. As we do not write a new value in the devices (except 1) there is no change expected. The FQ_UD pulse should pulse in sync with the devices select line.
It would make the hardware simpler (which is good) and it would allow some extra functionality
To use this a update() function should be implemented and a way to set the FQ_UD to manual mode.
_This manual mode will be implemented asap as (2) would be interesting for single devices too, and even when you have disjunct devices (trivial solution) that would share the FQUD pin.
~- [ ] add a flag to update() to disable the select lines - to update all.~
~- [ ] add a flag to reset to disable the select lines - to reset all.~
update 2021-06-05
new insights in architecture will not add the flags. Will be discussed here soon.
Hi, Rob, Thank you very much for your method of controlling 3 devices. I followed by your method and code, but I fail to update the frequencys of 3 devices, the wave of which is not continuous, I think is the problem of frequency update wrong. below is my code, I will appreciate if you check it for me.
`#include "AD985X.h"
AD9850 freqGen;
uint32_t freq1 = 25000;
uint32_t freq2 = 30000;
uint32_t freq3 = 40000;
uint32_t prev = 10000;
uint32_t maxFreq = 30000000;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
const long period1 = 0;
const long period2 = 0;
const long period3 = 0;
unsigned long currentMillis = millis();
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
freqGen.begin(2, 9, 10);
freqGen.powerUp();
maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq);
}
void loop()
{
if (currentMillis - previousMillis1 >= period1) {
int select = 2;
if (prev != freq1){
prev = freq1;
freqGen.setFrequencyF(freq1 * 0.01);
Serial.println(freq1);
previousMillis1 = currentMillis;
}
}
if (currentMillis - previousMillis2 >= period2) {
int select = 3;
if (prev != freq2){
prev = freq2;
freqGen.setFrequencyF(freq2 * 0.01);
Serial.println(freq2);
previousMillis2 = currentMillis;
}
}
if (currentMillis - previousMillis3 >= period3) {
int select = 3;
if (prev != freq3){
prev = freq3;
freqGen.setFrequencyF(freq3 * 0.01);
Serial.println(freq3);
previousMillis3 = currentMillis;
}
}
}
updated your post to do syntax highlighting.
@CHEERScheers it is on my todo list to describe it well, but so are many other things. I will try to come back to this issue later this week
@CHEERScheers had a quick look at your code and you use only 1 device that uses 3 different updaters.
You should use 3 devices when you want 3 devices....
Thank you Rob for your quick reply. But I am using 3 devices, I am confused about how to update. What I want to do is to let the 3 devices output 3 different frequency, need I use 3 Arduino?
@CHEERScheers had a quick look at your code and you use only 1 device that uses 3 different updaters.
You should use 3 devices when you want 3 devices....
Hi, Rob, I tried like this. I can get 3 different frequency waves from 3 AD9850, but I have to flash the Arduino 3 times with 3 different frequencys one by one, if I power off the Arduino, then power on the Arduino, only one AD9850 works with the last flashed program. I think there's only one frequency in the register, I cannot control the 3 AD9850 with only one program...
I rewrite the codes, use the codes below can get different frequency waves perfectly.
#include "AD985X.h"
AD9850 freqGen;
uint32_t freq1 = 25000;
uint32_t freq2 = 30000;
uint32_t freq3 = 40000;
uint32_t prev = 0;
uint32_t maxFreq = 30000000;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
freqGen.begin(2, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq1 * 0.01);
freqGen.begin(3, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq2 * 0.01);
freqGen.begin(4, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq3 * 0.01);
maxFreq = freqGen.getMaxFrequency();
Serial.println(maxFreq);
}
void loop(){}
@CHEERScheers you made a step in the right direction
please try this sketch (not tested beyond compilation)
!! disclaimer: I do not expect the code to work yet
//
// FILE: AD985X_multi.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo multi device
// DATE: 2021-06-04
#include "AD985X.h"
// we want to control three hardware devices
// so we declare three software objects
AD9850 freqGen0;
AD9850 freqGen1;
AD9850 freqGen2;
float freq0 = 25000;
float freq1 = 30000;
float freq2 = 40000;
uint32_t maxFreq = 30000000;
uint32_t previousMillis0 = 0;
uint32_t previousMillis1 = 0;
uint32_t previousMillis2 = 0;
uint32_t period0 = 500;
uint32_t period1 = 1000;
uint32_t period2 = 2000;
uint32_t now;
void setup()
{
// OPEN SERIAL for messages and debugging etc
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
// initialize three devices
freqGen0.begin(4, 9, 10);
freqGen0.powerUp();
freqGen1.begin(2, 9, 10);
freqGen1.powerUp();
freqGen2.begin(3, 9, 10);
freqGen2.powerUp();
// MAXFREQ is the same for all devices
maxFreq = freqGen0.getMaxFrequency();
Serial.println(maxFreq);
}
void loop()
{
// get the time
now = millis();
// do we need to update 0
if (now - previousMillis0 >= period0)
{
previousMillis0 = now;
freq0 = freq0 * 0.01;
if (freq0 >= maxFreq) freq0 = 500;
freqGen0.setFrequencyF(freq0 * 0.01);
Serial.println( (uint32_t) freq0);
}
// do we need to update 1
if (now - previousMillis1 >= period1)
{
previousMillis1 = now;
freq1 = freq1 * 0.01;
if (freq1 >= maxFreq) freq1 = 500;
freqGen1.setFrequencyF(freq1 * 0.01);
Serial.println( (uint32_t) freq1);
}
// do we need to update 2
if (now - previousMillis2 >= period2)
{
previousMillis2 = now;
freq2 = freq2 * 0.01;
if (freq2 >= maxFreq) freq2 = 500;
freqGen2.setFrequencyF(freq2 * 0.01);
Serial.println( (uint32_t) freq2);
}
}
// -- END OF FILE --
As you see there is quite some repeating code and variables, To minimize that we can start using array's
@CHEERScheers The array version, not tested beyond compilation
!! disclaimer: I do not expect the code to work yet
//
// FILE: AD985X_array.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo multi device
// DATE: 2021-06-04
#include "AD985X.h"
// three objects in an array
AD9850 freqGen[3];
uint8_t PIN[3] = { 2, 3, 4 };
float freq[3] = { 25000, 30000, 40000 };
uint32_t previous[3] = { 0, 0, 0 };
uint32_t period[3] = { 500, 1000, 2000 };
uint32_t maxFreq = 30000000;
uint32_t now;
void setup()
{
// OPEN SERIAL for messages and debugging etc
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
// initialize three devices
for (int i = 0; i < 3; i++)
{
freqGen[i].begin(PIN[i], 9, 10);
freqGen[i].powerUp();
freqGen[i].setFrequencyF(freq[i]);
}
maxFreq = freqGen[0].getMaxFrequency();
Serial.print("MAXFREQ:\t");
Serial.println(maxFreq);
}
void loop()
{
now = millis();
// update any of the devices?
for (int i = 0; i < 3; i++)
{
if ( now - previous[i] >= period[i] )
{
previous[i] = now;
freq[i] = freq[i] * 0.01;
freqGen[i].setFrequencyF(freq[i] * 0.01);
Serial.print("FREQ ");
Serial.print(i);
Serial.print(" set to: ");
Serial.println( (uint32_t) freq[i]);
}
}
}
// -- END OF FILE --
Note: expect the code only works if the FQ_UD pin is behind an AND port that "opens" the port only for the FQ_UD signal to reach the selected device
Arduino AND AD985X
--------------------------------------------------
+--------+
(2) select ----| A |
| Q |------- FQ_UD AD985X[0]
(9) FQ_UD ----| B |
+--------+
+--------+
(3) select ----| A |
| Q |------- FQ_UD AD985X[1]
(9) FQ_UD ----| B |
+--------+
+--------+
(4) select ----| A |
| Q |------- FQ_UD AD985X[2]
(9) FQ_UD ----| B |
+--------+
This way only the device selected will get an update pulse
@Rob I tried your code, but there's no waves output. The RX led is always twinkling. please see the video.
Two questions:
1) you had it working with this code?
freqGen.begin(2, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq1 * 0.01);
freqGen.begin(3, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq2 * 0.01);
freqGen.begin(4, 9, 10);
freqGen.powerUp();
freqGen.setFrequencyF(freq3 * 0.01);
2) can you post a drawing of your hardware used / how connected?
code missed one + operator therefor all frequencies dropped to zero
please try this version (works here with one device)
//
// FILE: AD985X_array.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo multi device
// DATE: 2021-06-04
#include "AD985X.h"
// three objects in an array
AD9850 freqGen[3];
uint8_t PIN[3] = { 2, 3, 4 };
float freq[3] = { 25000, 30000, 40000 };
uint32_t previous[3] = { 0, 0, 0 };
uint32_t period[3] = { 500, 1000, 2000 };
uint32_t maxFreq = 30000000;
uint32_t now;
void setup()
{
// OPEN SERIAL for messages and debugging etc
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
// initialize three devices
for (int i = 0; i < 3; i++)
{
freqGen[i].begin(PIN[i], 9, 10);
freqGen[i].powerUp();
freqGen[i].setFrequencyF(freq[i]);
}
maxFreq = freqGen[0].getMaxFrequency();
Serial.print("MAXFREQ:\t");
Serial.println(maxFreq);
}
void loop()
{
now = millis();
// update any of the devices?
for (int i = 0; i < 3; i++)
{
if ( now - previous[i] >= period[i] )
{
previous[i] = now;
freq[i] += freq[i] * 0.01;
freqGen[i].setFrequencyF(freq[i]);
Serial.print("FREQ ");
Serial.print(i);
Serial.print(" set to: ");
Serial.println( (uint32_t) freq[i]);
}
}
}
// -- END OF FILE --
Hi, Rob, I used your code, the frequency will increase to a large number with no regulation. So I delet 2 line of your code: freqGen[i].setFrequencyF(freq[i]); // this line is in void setup() freq[i] += freq[i] * 0.01;// this line is is in void loop()
With the code below which is based on your code, the 3 different frequency waves runs perfectly.
#include "AD985X.h"
// three objects in an array
AD9850 freqGen[3];
uint8_t PIN[3] = { 2, 3, 4 };
float freq[3] = { 25000, 30000, 40000 };
uint32_t previous[3] = { 0, 0, 0 };
uint32_t period[3] = { 500, 1000, 2000 };
uint32_t maxFreq = 30000000;
uint32_t now;
void setup()
{
// OPEN SERIAL for messages and debugging etc
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AD985X_LIB_VERSION: \t");
Serial.println(AD985X_LIB_VERSION);
// initialize three devices
for (int i = 0; i < 3; i++)
{
freqGen[i].begin(PIN[i], 9, 10);
freqGen[i].powerUp();
}
maxFreq = freqGen[0].getMaxFrequency();
Serial.print("MAXFREQ:\t");
Serial.println(maxFreq);
}
void loop()
{
now = millis();
// update any of the devices?
for (int i = 0; i < 3; i++)
{
if ( now - previous[i] >= period[i] )
{
previous[i] = now;
freqGen[i].setFrequencyF(0.01*freq[i]);
Serial.print("FREQ ");
Serial.print(i);
Serial.print(" set to: ");
Serial.println( (uint32_t) freq[i]);
}
}
}
updated your post to highlight the syntax
But good to hear you have it working. If there is no related question you may close the issue.
Thank you very much!
reopened as I still need to add some documentation ....
Thanks Rob.
On Fri, Jun 4, 2021 at 8:40 AM Rob Tillaart @.***> wrote:
reopened as I still need to add some documentation ....
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/RobTillaart/AD985X/issues/13#issuecomment-854685987, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAAD54HD75CDW3BWJXPOXLTRDCVJANCNFSM4WQNZ36A .
@CHEERScheers released 0.3.0 including the document about multi device.
Hi RobTillaart I have a project that generates 2 sine signals from 2 AD9850/9851 modules with the same frequency but different phase. Your library doesn't say this. In the AD9850 multi_sync library the solution for the SELECT pin is coupled to which pin? Can you explain it Thank!
Thanks for the question.
You can use any free IO Pin of your processor as SELECT line You control the device with
pinMode(pinDeviceX, OUTPUT);
pinMode(pinDeviceY, OUTPUT);
...
digitalWrite(pinDeviceX, HIGH);
set the deviceX settings
digitalWrite(pinDeviceX, LOW);
...
digitalWrite(pinDeviceY, HIGH);
set the deviceY settings
digitalWrite(pinDeviceY, LOW);
...
For each extra device you need an additional IO pin. Be careful to select only one device at the time.
We use an AND gate to create the SPI interface. But I don't know what pin of the AD9850 will be paired with the SELECT pin to control it. Can you help me explain. Thank you!
It is all explained in the PDF. you MUST at least control the CLOCK pin with an AND port as this prevents that the non addressed devices are clocking in some data not meant for them.
Thank you very much, I will test it and if there is any problem, I hope you can help
Best is to find someone local with electronics experience (student or professional) that can help on-site. That is many times faster than online (and is probably more fun). Furthermore the Arduino forum has way more people on it that have the expertise to help.
But feel free to ask if questions remain.
Tip of the day: https://www.amazon.com/Practical-Electronics-Inventors-Fourth-Scherz/dp/1259587541
Thank you so much!
Vào Th 2, 4 thg 7, 2022 vào lúc 15:22 Rob Tillaart < @.***> đã viết:
Best is to find someone local with electronics experience (student or professional) that can help on-site. That is many times faster than online (and is probably more fun). Furthermore the Arduino forum has way more people on it that have the expertise to help.
But feel free to ask if questions remain.
Tip of the day:
https://www.amazon.com/Practical-Electronics-Inventors-Fourth-Scherz/dp/1259587541
— Reply to this email directly, view it on GitHub https://github.com/RobTillaart/AD985X/issues/13#issuecomment-1173509244, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARUYH7IXRNE5HDGPBUZSUBDVSKNOFANCNFSM4WQNZ36A . You are receiving this because you commented.Message ID: @.***>
-- С уважением, Нгуен Дык Ань, Вьетнамская Военно-Морская Академия Email: @.*** Tel: +84-984.660.342 +7-960.040.7328
In issue #9 (decimals in frequency) a discussion started how to connect multiple AD985X devices to one MCU.
Problem description
The problem identified is that the device does NOT have a Chip Select pin (CS) like many SPI devices do have. So sharing the DATA and CLOCK lines would result in preparing all AD985X devices with a new frequency.
How bad is that? As long as they do not get an update pulse it should not matter, however it is not a nice as an glitch of the FQ_UD line (also not nice) would update to an unexpected frequency. So we need better solutions.
Note the library already has a select pin in the begin() function to be "SPI compatible"