0

The code below should generate a PWM signal on digital pin 3. But know I want to see if it is even working. I was thinking about a Event triggering method like ISR. But somehow it does not work. I guess a ISR needs to a Input Pin, e.g. it would work, when I would've a PWM signal coming from somewhere.

Is it even possible to generate a PWM signal and read it to see some results on the serial monitor?

edited code:

byte const PWM_PIN = 3;

volatile unsigned long pwm_value = 0;
volatile unsigned long prev_time = 0;

void setup() {
  pinMode(PWM_PIN, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), rising, RISING);
}

void loop() {
  digitalWrite(PWM_PIN, HIGH);
  delay(400);
  digitalWrite(PWM_PIN, LOW);
  delay(1600);
}

void rising() {
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), falling, FALLING);
  prev_time = millis();
}

void falling() {
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), rising, RISING);
  pwm_value = millis()-prev_time;
  Serial.println(pwm_value);
}
7
  • wire the pin to other pin and read the other pin. what you generate is not PWM. you don't attach any interrupt in setup. use CHANGE interrupt
    – Juraj
    Commented Dec 23, 2018 at 17:15
  • 1
    If a digitalWrite is not working for an output pin, then you should not use that arduino board anymore. You create a extra code that can have bugs to test something very simple, it is therefor more likely that the extra code is wrong. It is allowed to do a digitalRead for an output pin, you can therefor make the pin high, and read if it is really high. But please don't do that. If that fails, then something else is very wrong. When you assign a value to a variable (for example int i = 3 ;), how do you know that does work? Do you want to add extra tests to check if the variables do work?
    – Jot
    Commented Dec 23, 2018 at 18:19
  • 1
    With your current code the delays are so long, that you can see the code working by connecting a LED to the output pin. An on time of 400ms is well noticable by eye. Though I wouldn't call this slow signal PWM.
    – chrisl
    Commented Dec 23, 2018 at 19:04
  • @Juraj Yes right. I tried to do it without Serial.println(); in loop() and I also added attachInterrupt to setup(). I set both delays to 1000 (which should be in ms). But the pwm_value is only 16984, which are micro seconds. ---> 16,9ms
    – Gamdschiee
    Commented Dec 23, 2018 at 20:26
  • But that makes no sense, the right pwm_value should be 1000000 us right?
    – Gamdschiee
    Commented Dec 23, 2018 at 20:27

2 Answers 2

1

You are declaring the variables prev_time and pwm_value as int, which has (on a standard Arduino) 16 bits. Since you use the signed variant, you get a range of values from -32768 to 32767. But micros() is returning an unsigned long, which has 4 bytes (32 bits) and is not signed. With int there are only 32.767 ms (since it represents microseconds here), without letting the variable overflow. Even the full range would give you only about 65 ms. It simply cannot hold a value like 1000000. If you assign this value to an int, it will directly overflow (which - I think - would give you the value modulo 2^16), effectively loosing big parts of the information. You cannot get meaningful results with this in such a high time scale.

When measuring time (with millis() or micros()) you should always be sure to use unsigned long as type to prevent these problems.


Apart from the variable type, why do you use micros() here? You are measuring times in the hundreds of milliseconds, so why not use millis()? This would keep the values lower.

2
  • Yes! It works now. I've edited the code above. So you can attach an interrupt to both input and output. Through @leoc7 I probably even found an easier way to create a PWM signal with: playground.arduino.cc/code/timer1
    – Gamdschiee
    Commented Dec 24, 2018 at 13:51
  • If it works now, please consider to accept the answer as correct.
    – chrisl
    Commented Dec 24, 2018 at 17:07
0
  1. You aren’t generating a correct PWM, because Serial.println introduces a delay. The right way for generating PWM is to use analogWrite function.

  2. You can’t use attachInterrupt function for detecting rising and falling edge of an output pin.

  3. In order to detect the rising and falling edge of a PWM signal, you have to use the timer interrupt of PWM module. For doing this, You have to write/read directly ATmega registers without using Arduino libraries. What version of Arduino are you using?

7
  • 1. there is a delay(1200) and you nitpick the Serial println()? 3. what?
    – Juraj
    Commented Dec 23, 2018 at 19:18
  • 3. I mean Timer Overflow Interrupt
    – leoc7
    Commented Dec 23, 2018 at 19:27
  • 2
    2. is incorrect. You can. Commented Dec 23, 2018 at 19:43
  • @leoc7 Arduino 1.8.8
    – Gamdschiee
    Commented Dec 23, 2018 at 20:10
  • @Gamdschiee Sorry, I meant what model of Arduino
    – leoc7
    Commented Dec 23, 2018 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.