Strange PWM Output (4.0)

Groover

New member
Hi! Here is my code:

Code:
#define REAR_DUMP_PWM 7
#define PWM_FREQUENCY_HZ 120
...
analogWriteFrequency(REAR_DUMP_PWM, PWM_FREQUENCY_HZ);
analogWriteResolution(15); // 0 - 32767
analogWrite(REAR_DUMP_PWM, (int)(32767 * 0.50));

And here is what I get - 1kHz with 25% duty cycle. If I change the pin to 1, 3 or 5 then those pins output the expected frequency and duty cycle. What am I missing? I am using Serial5 and not using Serial2, at least not in my code, but I suspect it is Serial2 in some way.

Screenshot 2025-10-01 214709.png


Thanks, Andy
 
4.0

Code:
#include <Arduino.h>
#include <TimerOne.h>

// GPIO pins
#define REAR_DUMP_PWM    7
#define LED              13

#define PWM_FREQUENCY_HZ 120

// how often to toggle the LED
#define LED_FLASH_PERIOD_MS 1000

static uint32_t Ticks = 0;
static uint32_t LEDFlashTimestamp;
static uint8_t LEDState = LOW;

// initialize the hardware
void setup()
{
  Serial5.begin(9600);

  analogWriteFrequency(REAR_DUMP_PWM, PWM_FREQUENCY_HZ);
  analogWriteResolution(15); // 0 - 32767

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LEDState);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(TimerTick);
  Timer1.start();

  LEDFlashTimestamp = GetTime() + LED_FLASH_PERIOD_MS;

  analogWrite(REAR_DUMP_PWM, (int)(32767 * 0.50));
}

// called once a millsecond to keep track of time
static void TimerTick
  (
  void 
  )
{
  Ticks++;
}

// gets the current timestamp
uint32_t GetTime
  (
  void
  )
{
  return Ticks;
}

// checks if a timestamp is in the past
// returns true if timestamps is in the past, false if not
static int IsTimeExpired
  (
  uint32_t Timestamp  // timestamp to check
  )
{
  uint32_t time_now;

  time_now = GetTime();
  if (time_now >= Timestamp)
  {
    if ((time_now - Timestamp) < 0x80000000)
      return true;
    else
      return false;
  }
  else
  {
    if ((Timestamp - time_now) >= 0x80000000)
      return true;
    else
      return false;
  }
}

// main loop
// perform background tasks
void loop
  (
  void
  )
{
  int c;

  // echo serial data
  if (Serial5.available() > 0)
  {
    // read the incoming byte:
    c = Serial5.read();
    Serial5.print((char)c);
  }

  // flash LED
  if (IsTimeExpired(LEDFlashTimestamp))
  {
    LEDFlashTimestamp = GetTime() + LED_FLASH_PERIOD_MS;
    
    if (LEDState == LOW)
    {
      LEDState = HIGH;
    }
    else
    {
      LEDState = LOW;
    }
    digitalWrite(LED, LEDState);
  }
}
 
I'm guessing you're new to Arduino, and if so, I'd like to point a couple of ways to simplify your program.

All Arduino-compatible boards, including Teensy, have a built-in 1-ms timer that you can read via the function millis(), and you can use this instead of your TimerOne. Also, Teensy has a nice helper class called elapsedMillis. If you create a variable of this type, its value is the number of milliseconds since creation. You can also reset its value to 0 (or to any other value), which makes it easy to use for delays like the one you want for blinking the LED. Finally, Teensy, and I think all Arduino, have not only digitalWrite(), but also digitalToggle(), which you can use to eliminate your LED state variable and all of the logic associated with toggling.

With those changes, the program below is equivalent to yours. I've changed Serial5, which is a UART, to Serial (USB) for my own testing.

Here is a capture of the output of pin 7 with the correct 120 Hz and 50% duty cycle. I ran this on T4.1, but it should be the same on T4.0

EDIT: One last thought, please double-check which pin you're measuring. Teensy's pin numbering is not the standard 1-N. In the case of T4.x, pin 7 is the 9th pin from the end with the USB connector.

1759438936989.png


Code:
#include <Arduino.h>

// GPIO pins
#define REAR_DUMP_PWM       (7)
#define LED                 (13)
#define PWM_FREQUENCY_HZ    (120)
#define LED_FLASH_PERIOD_MS (1000)

elapsedMillis ms;

// initialize the hardware
void setup()
{
  Serial.begin(9600);
  while (!Serial && millis() < 3000) {}

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  analogWriteFrequency(REAR_DUMP_PWM, PWM_FREQUENCY_HZ);
  analogWriteResolution(15); // 0 - 32767
  analogWrite(REAR_DUMP_PWM, (int)(32767 * 0.50));
 
  ms = 0;
}

// main loop -- perform background tasks
void loop(void)
{
  // echo serial data
  if (Serial.available() > 0) {
    // read the incoming byte:
    int c = Serial.read();
    Serial.print((char)c);
  }

  // flash LED
  if (ms >= LED_FLASH_PERIOD_MS) {
    digitalToggle(LED);
    ms -= LED_FLASH_PERIOD_MS;
  }
}
 
Back
Top