Frequency generator

Status
Not open for further replies.

Gary

Active member
Hi.

I need your help (I'm sorry for my English).

I have bought a Tripple CAN board with a Teensy 4.0 and a display from skpang.

This is a very good board and the CAN connectivity is great and function very good.

But now I need an SPI port to connect an AD9833 frequency generator. This board uses the SPI for the display.

For my project I need a frequency from 0 to 350 hz with a 50/50 frequency length.

Is there an option to get an frequency generator on the software way?

I have searched in Internet but I found nothing..

Greetings

Gary
 
Good morning.

I have taken a look on this site days before. But this isn't a good way. I need a square signal with a length from 50/50. PWM hasn't this length.

Thanks for your idea and reply

Gary
 
If Resolution is set to 8 bits - values range 0-255. Setting an AnalogWrite( pin, 127 ) will give a 50/50 wave.

Something like this should work - picking a higher Resolution ( up to 16 bits ) will work better at low frequencies indicated - the value to write changes accordingly.
Code:
  #define PINx  4  // your pin here
  void setup() {
      analogWriteResolution(8);
      analogWriteFrequency(PINx, 350); // Use this to write the desired frequency
      analogWrite(PINx, 127);
  }
 
Thanks defragster

Just I have tried to take the Teensy from this board. It was possible. I thought that the Teensy was soldered.

Now there is an option to use the SPI port 2 on the backside.

I have not much knowledge in this boards. Is it possible to use the second port, if the first one is already used? In this case I could use the AD9833.

Nevertheless I will try your code.

Greetings
 
Hi defragster.

Sorry for the late reply. We have a lot of problems with the Corona virus in my federal state of Germany.

I have tried your code and this runs well with your frequency. But if I try other frequencies like for example 20, I dont have a duty about 50/50.
This is very difficult for me. ;-)

Thanks

Gary
 
Yep it works better if you go to higher resolution... Here is a quick and dirty that verified using Logic Analyzer:
Code:
#define PINx  12  // your pin here
void setup() {
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
  Serial.println("Will start at 350, enter new if desired...");

  analogWriteResolution(10);
  analogWriteFrequency(PINx, 350); // Use this to write the desired frequency
  analogWrite(PINx, 511);
  pinMode(13, OUTPUT);
}

void loop() {
  int ch;
  if (Serial.available()) {
    uint16_t val = 0;
    while ((ch = Serial.read()) != -1) {
      if (ch >= '0' && ch <= '9') val = val * 10 + ch - '0';
    }
    digitalWriteFast(13, !digitalReadFast(13));
    analogWriteFrequency(PINx, val); // Use this to write the desired frequency
    analogWrite(PINx, 511);
  }
}
And you can see the change with the entering in 20...
screenshot.jpg

At the 8 bit resolution, the value 20hz gave a value of maybe 40% duty due to limitations of rounding and the like. You can also go up to 12 bit resolution,
Again would need to change the analogWrite to something like 2047...
 
Thank KurtE.

I haved tried to use your code. The frequencies between 18 and 350 are ok. But the lower frequencies are not possible.

The 40% daty are ok. But I Need a frequency near by 0.

Greetings and thanks
 
Again it may depend on all of your other requirements and how exactly you need it. You could simply use an intervalTimer to do it. Or you could use the timerTools by @luni...

Example: hacked up previous example:
Code:
#define PINx  12  // your pin here
IntervalTimer it;

void it_handler() {
  digitalWriteFast(PINx, !digitalReadFast(PINx));
  asm("dsb");
}

void setup() {
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
  Serial.println("Will start at 350, enter new if desired...");

  //analogWriteResolution(10);
  //analogWriteFrequency(PINx, 350); // Use this to write the desired frequency
  //analogWrite(PINx, 511);
  pinMode(PINx, OUTPUT);
  it.begin(&it_handler, 500000l/350);
  pinMode(13, OUTPUT);
}


void loop() {
  int ch;
  if (Serial.available()) {
    uint16_t val = 0;
    while ((ch = Serial.read()) != -1) {
      if (ch >= '0' && ch <= '9') val = val * 10 + ch - '0';
    }
    digitalWriteFast(13, !digitalReadFast(13));
    //analogWriteFrequency(PINx, val); // Use this to write the desired frequency
    //analogWrite(PINx, 511);
    it.update(500000l/val);

  }
}
 
Thanks a lot

At this time it is too much for my brain. I will test the new code in the evening.

I dont need an exact square wave but it should be nearly 50/50. 60/40 isn't a problem. The first zulignal should be near 0 and it's not important that the signals are exactly for example 5.0 Hz.

Thanks for helping me...

Greetings
 
Thanks KurtE

This runs perfectly. I dont know why but it works. ;-)

Now I go a big step to the end of my Project.

Your help is great…. Thanks also to the rest of this forum.


Greetings
 
Status
Not open for further replies.
Back
Top