On my Arduino UNO, I have set pin ~3 to run PWM. Is there a way to know when the signal is ON and when it is OFF?
I am trying to eliminate background noise from an LED light intensity reading, also called background subtraction. I am measuring the light with a phototransistor connected to the same Arduino. I am doing the background subtraction by pulse width modulating the LED and then subtracting the light measure in the OFF part of the PWM (This is the ambient light or noise) from the light measure from the ON part of the PWM (This is the LED and the noise). Which should leave only the light measured from the LED.
I've made a "bad" solution where I have connected pin 3 to pin 4. I then use digitalRead on pin 4 and just read the state of the pin that way. But I am hoping for a more internal solution, something where I for example read a register value.
It didn't work to use digitalread on pin 3, it just comes out 0.
AprilDC:
I've made a "bad" solution where I have connected pin 3 to pin 4. I then use digitalRead on pin 4 and just read the state of the pin that way.
Why is that a bad solution? Does it achieve what you want?
I don't think there is any register to read apart from PORTD itself - which is what digitalRead() does. The digitalWriteFast library also has a digitalReadFast().
I wonder would the changing state of the pin cause a pinChange interrupt - I suspect it would.
If not, you could connect a jumper from your PWM pin to one of the external interrupt pins and use attachInterrupt() to call an ISR when the value changes.
@Robin2 - Thank you for your answer. I am not really sure if it is achieving what I want. I am doing some math on the measurements, and I am not certain that the values are right when the pin switches from ON to OFF.
So I would like to make it more certain by checking internally.
The attachInterrupt() sounds interesting, would it be better than connecting a jumper to pin 4 and using digitalread?
AprilDC:
This sounds interesting, would it be better than connecting a jumper to pin 4 and using digitalread?
Would what be better?
If I have a solution that works and then I discover an alternative that also works I cannot say that either is better unless one of them also solves another problem that was getting in the way of a properly working system.
You can use the PIND register directly, and it gives accurate readings.
// Pin 3 is PD3
if ((PIND & 8) == 0)
{
// Output is low
}
if ((PIND & 8) != 0)
{
// Output is high
}
I really thought digitalRead() would have given accurate readings if PIND did. I thought they did the same thing. But my test code on an Arduino UNO falsifies that. digitalRead(3) always returns 0, whereas (PIND & 8 ) returns what I expected. Weird.
Well, here's the code in wiring.c that handles digitalRead():
int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}
So. The digitalRead() function actually has special code to TURN OFF THE PWM TIMER if it was on that pin. And THEN it returns LOW.