Nano Every Square wave generator

Hello Everyone,

This has been handled before but not with a Nano Every (That I could Find), I have read through this thread top to bottom.
Using digitalWrite to create a square wave of a specific frequency.

What I surmised was the following code which does work very well except for: Min frequency is 31Hz and max seems to be about 80KHz. I am designing an Electronic DC Load, I would like to go from 1Hz to around 1Khz @50% duty cycle to test power supply curve responses with.

Here is the code I am using I will be using a multiturn trim pot later on to set the frequency with, the same nano will also be used to monitor current draw and load voltage via an external ADC an ADS1115..


int frequency = 100; //Set frequency in Hertz

double delayTime = 1000UL*1000UL / (frequency * 2);

void setup() 
{
pinMode(13, OUTPUT);  
pinMode(11, OUTPUT);
}

void loop() 
{
 digitalWrite(11, LOW);
 digitalWrite(13, HIGH);
 delayMicroseconds(delayTime);

 digitalWrite(13, LOW);
 digitalWrite(11, HIGH);
 delayMicroseconds(delayTime);
}

Any Help will be appreciated.
Bare in mind I am a noob please.

Regards
Charles

You are likely limited by the time to execute digtialWrite().

At higher frequencies, you need a faster way of switching the pins. Have a look at

Also not a great idea to use delay, as you need to account for the other statements in your code for timing. Use micros() to determine when to switch.

Use unsigned long to hold the delayTime.

Hi, thanks for a speedy reply,

I will look at the provided link tomorrow,
NOTE however, my problem is not getting up high into the frequency range but rather lower down closer to 0.

Thank you kindly. I will respond once I have read the provided link and revert back.

Is this your requirement:

from 1Hz to around 1Khz @50% duty cycle

in that case this would probably do it:

const byte pin1 = 11;
const byte pin2 = 13;

byte pin1State = LOW;
byte pin2State = HIGH;
unsigned long halfwave;


void setup()
{
  Serial.begin(115200);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  SetFrequency(50);
}

void loop()
{
  Rectangle();
}

void SetFrequency(int frequ){
  halfwave = 1000000UL / frequ / 2;
}

void Rectangle() {
  static unsigned long lastChange = 0;
  if (micros() - lastChange >= halfwave) {
    lastChange = micros();
    digitalWrite(pin1, pin1State);
    digitalWrite(pin2, pin2State);
    pin1State = !pin1State;
    pin2State = !pin2State;
  }
}

For more accuracy you might look for the use of timer interrupts like shown here
https://create.arduino.cc/projecthub/mircemk/diy-simple-square-wave-generator-up-to-1mhz-231375

You can still use the above code for 1Hz to 5Hz and the timer for the rest ...

Both will allow to do other jobs in between (if carefully designed) which cannot be done with delay() functions .

I should have read more carefully.

Check out the documentation for delayMicros...

In particular...
Currently, the largest value that will produce an accurate delay is 16383;

Hi, thank you for replying,

I will look at the provided code and read the given link tomorrow and revert back.

Thank you kindly.

Good day ec2021.

I tried your code thank you.
It is more than stable enough for my needs.
I should not be going above 1KHz max.

The only thing I found is that connecting an analogRead does induce a lot of noise into the whole circuit, so, one of two options, analog smoothing or an encoder... I am afraid that this might induce more instability as it will take more time to process.

As for timers and interrupts, I am afraid that this is still above my fireplace of understanding.

Regards
Charles

const byte pin1 = 11;
const byte pin2 = 13;

byte pin1State = LOW;
byte pin2State = HIGH;
unsigned long halfwave;


void setup()
{
  Serial.begin(115200);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  SetFrequency(50);
}

void loop()
{
  Rectangle();
}

void SetFrequency(int frequ){
  halfwave = 1000000UL / frequ / 2;
}

void Rectangle() {
  static unsigned long lastChange = 0;
  if (micros() - lastChange >= halfwave) {
    lastChange = micros();
    digitalWrite(pin1, pin1State);
    digitalWrite(pin2, pin2State);
    pin1State = !pin1State;
    pin2State = !pin2State;
  }
}

Hi red_car:

Thank you for helping out.

I was already using the delayMicroseconds in my OP sketch so I understand how that works.

I fear that ec2021 may be correct instating that I may need to use timers and interrupts but I fear that I am still to learn that. The code ec2021 provided works, though as I said to him in my reply that adding analogRead to the mix made it all unstable due to the noise induced, so I will either have to smooth or I'll need to put in an encoder....

Anyway,
Thank you for your input, it is appreciated.

Regards
Charles.

Would you mind to elaborate a little bit more about the noise and instability you encountered?

It may also be helpful if you could also provide a sketch of your hardware setup...

If I cannot help there is a real chance that there are numerous experts around in this forum.

Hi ec2021

I can't draw a diagram now, limited in time I will post one tomorrow as an addendum to this post.

Basically all is on a bread board being powered from the PC's usb.
using the onboard led pin 13 and an external 2.2k resistor from ground to led and then to pin 11.
I have soldered on a 5K linear bourns multiturn panel mount pot. Wiper to pin A0 one end to ground and the other to the 5V pin on the Arduino Nano Every, and am monitoring the A0 via the serial monitor, and frequency via my fluke multimeter.

Your code as written is stable, no fluctuation whatsoever except the last significant digit.
when I comment out your "Frequency'' setup and substitute the analog one then on the serial monitor and my meter there is a lot of fluctuation, as this is present on the A0 input the output also fluctuates, I am sure this has nothing to do with the code but is a by product of noise on the input. The pots wires are only 100mm or 10cm long but I can see noise present on the output from my meter and the serial monitor input from the pot.

Here is my code along with yours.

const byte pin1 = 11;
const byte pin2 = 13;

byte pin1State = LOW;
byte pin2State = HIGH;
unsigned long halfwave;
//int frequ = A0; //analog input 


void setup() {
  Serial.begin(115200);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  SetFrequency (100); //Uncomment for digital set
  
}

void loop() {
  Rectangle();
//SetFrequency (); //Uncomment for analog input
}
                                    ////////// Analog \\\\\\\\\\\\

/*                                   
void SetFrequency() {                             // Create void
  frequ = analogRead(A0);                         // Placeholder A0 Value
  halfwave = 1000000UL / frequ / 2;               // Value to set SetFrequency in void loop with
  //Serial.println (halfwave);                    // Print Value to Serial monitor
  //Serial.println (frequ);                       // Print Value to serial monitor
}
*/

void SetFrequency(int frequ){

  halfwave = 1000000UL / frequ / 2;
}

void Rectangle() {
  static unsigned long lastChange = 0;
  if (micros() - lastChange >= halfwave) {
    lastChange = micros();
    digitalWrite(pin1, pin1State);
    digitalWrite(pin2, pin2State);
    pin1State = !pin1State;
    pin2State = !pin2State;
  }
}

Regards
Charles

I would suggest to use a rotary encoder instead of the linear potentiometer. That will ensure a stable input of the frequency.

Yes,

My train of thought as well..

Will revert as soon as I've had time to test.

Regards
Charles

Don't want to push you but have you been aware of this?

https://forum.arduino.cc/t/analogread-works-on-nano-but-no-the-every/852359/7

Hi ec2021

I mrasured the 5V out, there is 4.6V as the usb is also just under 5V itself, but, the instability is definitely caused by noise. I am relatively sure of that.

Regards
Charles

That's the "beauty" of physics... and a reason to change to digital if possible.

Or a challenge to find the source and a solution to it ... :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.