Skip to content

Instantly share code, notes, and snippets.

@Jamesits
Last active December 25, 2019 14:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jamesits/8d164818946a65d0cafcd6203e3e5049 to your computer and use it in GitHub Desktop.
Save Jamesits/8d164818946a65d0cafcd6203e3e5049 to your computer and use it in GitHub Desktop.
High-accuracy square wave generator (up to 55KHz) based on Arduino UNO, with runtime adjustable frequency, PWM width and offset. https://blog.swineson.me/high-frequency-square-wave-generator-based-on-arduino-uno/
// High-accuracy square wave generator
// based on Arduino UNO
// with runtime adjustable frequency, PWM width and offset
// Output wave at pin 13
// by James Swineson <github@public.swineson.me>, 2017-05
// https://gist.github.com/Jamesits/8d164818946a65d0cafcd6203e3e5049
// See https://blog.swineson.me/high-frequency-square-wave-generator-based-on-arduino-uno/
// for more information (article in Chinese)
// ESP8266 version: https://gist.github.com/Jamesits/92394675c0fe786467b26f90e95d3904
double freq; // Hz
double offset; // percent (0.0 to 1.0)
double width; // percent (0.0 to 1.0)
// unit: microsecond
unsigned long cycle_time;
unsigned long raising_edge;
unsigned long falling_edge;
unsigned long prev_micros;
// compare 2 unsigned value
// true if X > Y while for all possible (X, Y), X - Y < Z
#define TIME_CMP(X, Y, Z) (((X) - (Y)) < (Z))
inline void setHigh() {
// 2 CPU cycles to balance execution time with setLow()
// this is based on measurement on Arduino UNO R3, your mileage may vary
PORTB = B00100000;
PORTB = B00100000;
}
inline void setLow() {
PORTB = B00000000;
}
void setup() {
DDRB = B00100000;
prev_micros = micros();
while(1) {
// read everything from analog input (potentiometer)
// frequency: 0.1-102.4 Hz
// width: 0-100%
// offset: 0-100%
freq = (double)(analogRead(1) + 1) / 10;
width = (double)(analogRead(0) + 1) / 1024;
offset = (double)analogRead(2) / 1024;
// OR manual settings
// max possible frequency is around 55000Hz with <1KHz deviation
// based on measurements on Arduino UNO R3
// you may get to ~77500Hz with significantly larger deviation
// note: please uncomment the next 3 expressions, then
// move the following 6 expressions ahead of while loop
// if you are going to use manual settings, because it is no worth
// to recalculate them.
// freq = 1;
// width = 0.5;
// offset = 0.0;
cycle_time = 1000000 / freq;
raising_edge = (unsigned long)(offset * cycle_time) % cycle_time;
falling_edge = (unsigned long)((offset + width) * cycle_time) % cycle_time;
if (width + offset < 1) {
// raising edge should appear earlier
while (TIME_CMP(micros(), prev_micros + raising_edge, cycle_time)); setHigh();
while (TIME_CMP(micros(), prev_micros + falling_edge, cycle_time)); setLow();
} else {
// falling edge should appear earlier
while (TIME_CMP(micros(), prev_micros + falling_edge, cycle_time)); setLow();
while (TIME_CMP(micros(), prev_micros + raising_edge, cycle_time)); setHigh();
}
prev_micros += cycle_time;
}
}
@Pu240
Copy link

Pu240 commented Oct 27, 2019

支持一下

@littlefish12345
Copy link

可以的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment