I have a Teensy 3.2 and I am using the Arduino IDE to program it. I am trying to generate 8 pulses with the frequency of 40 kHz and this needs to be repeated every second. I have written 3 different codes and none of them is working quite the way I wanted. The duty cycle of the pulses are not always constant (i.e. the falling edge often shifts in the time axis), indicating an inaccuracy with the delay between the analogWrite
commands. There seems to be an issue with delays not being consistent and changing within the 8 pulses and between the 8 pulses. This inaccuracy is different between the 3 different codes, but exists in all of them. Changing the processor speed between 16 MHz and 120 MHz does not appear to change the problem (except in code 3 where NOP is dependent on it). Is there a way to make the cycles more consistent at 40 kHz? Do I need to use an external timer or oscillator? The two images below display the two problems. The first image shows the differences in time delays and output frequency. The red dashed lines are provided to show the discrepancy in the same pulse at successive iterations of the code. The second image shows a recurring issue where the square wave is not in fact a square, and doesn't seem to be caused by software problems.
Image 1:
Image 2:
The codes I have written can be found below:
Code 1:
const uint8_t pin1 = 5;
const uint8_t pin2 = 6;
void setup() {
analogWriteFrequency(pin1, 40000);
analogWriteFrequency(pin2, 40000);
}
void loop() {
analogWrite(pin1,128); //for 50% duty cycle
delayMicroseconds(188); //It takes 187.5us to generate 8 pulses at the given frequency
analogWrite(pin1,0);
delay(1000);
}
Code 2:
const uint8_t pin1 = 5;
const uint8_t pin2 = 6;
void setup() {
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
}
void loop() {
PWMSignal();
delay(1000);
}
void PWMSignal(){
for(int i =0; i<=8; i++){
analogWrite(pin1, 255);
analogWrite(pin2, 0);
delayMicroseconds(10);
analogWrite(pin1, 0);
analogWrite(pin2, 255);
delayMicroseconds(10);
analogWrite(pin2, 0);
}
}
Code 3:
const uint8_t pin1 = 5;
const uint8_t pin2 = 6;
// Variable N determines the length of the delay.
// Execution of NOP corresponds to 62.5ns delay
// when the processor speed is 16 MHz.
const int N = 50;
#define NOP __asm__ __volatile__ ("nop\n\t")
void setup() {
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
}
void loop() {
PWMSignal();
delay(1000);
}
void PWMSignal(){
for(int i =0; i<=8; i++){
analogWrite(pin1, 255);
analogWrite(pin2, 0);
delayNOP();
analogWrite(pin1, 0);
analogWrite(pin2, 255);
delayNOP();
analogWrite(pin2, 0);
}
}
void delayNOP(){
for(int j =0; j<=N; j++){
NOP;
}
}
digitalWrite()
) would give more reliable results. Hint: GPIOx_PTOR will toggle a pin in one single operation. "x" is the port number, and write(1<<p)
to it wherep
is the pin number.