I have a first solution myself, but i could not test the reliability as the hardware is not finished jet.
First I added oldPins and tickCount as global variables:
static byte oldPins = 0;
volatile unsigned int tickCount[4] = { 0, 0, 0, 0 };
And thats how I solved the ISR at the moment. Better solutions are more than welcome.
ISR( PCINT2_vect ) {
//Read values from digital pins 2 to 7
const byte actPins = PIND;
//Match this values agaist the oldPins bitmask (XOR and AND for raising edge)
const byte setPins = (oldPins ^ actPins) & actPins;
if (setPins & 0b00000100)
tickCount[0]++;
if (setPins & 0b00001000)
tickCount[1]++;
if (setPins & 0b00010000)
tickCount[2]++;
if (setPins & 0b00100000)
tickCount[3]++;
oldPins = actPins;
}
Taking a look at the Arduino Uno's schematic explains this, if I understand the schematic correctly. I don't own an Arduino Uno, so I can't verify with a multimeter, so I might be wrong.
As I understand from the schematic, pin 13 of the arduino, the SCK pin, is connected to an op amp buffer. When you (or anyone) upload a program that doesn't do anything to pin 13, it's default state is an input without a pullup.
When a digital pin is configured as an input without a pullup resistor, it has a high impedance (high-Z) and unspecified voltage. It can be 0V, but might be something like 1.5V as well. The measurement will depend on the impedance of your meter, among other things. Upload an empty sketch and check the voltage on the pins - you'll find they're pretty random and not always 0V.
Now, a high-Z input pin with, say, a few volts will not be able to power an LED. However, this voltage is buffered by the Uno's op amp, and repeated on the output. This op amp will be able to power up an LED, and apperently, it does.
I think the Arduino team should add a high ohmage pulldown resistor (e.g. 50kOhm) to make this less confusing.
Best Answer
Relax. Don't worry. These pins are called
PWM
and are the same as the other pins, except they have an "added bonus."Some uses from Arduino's Website:
How it works:
The PWM pins are controlled by on-chip timers which toggle the pins automatically at a rate of about 490Hz. The "Pulse Width Modulation" (PWM) is how long the pin stays on or off for a single cycle of that frequency. This can dim a LED by giving the illusion it is at half the brightness as before, where it is really flashing very quickly.
When there is a 25% duty cycle, it is on one-forth of the time. If you used for a LED, it would appear about 1/4th as bright [give or take]. (Note: as some people pointed out this isn't truly proportional but let's leave it this way for simplicity. EX: 25% isn't always 1/4th the brightness.)
(If you are really electrical savvy, you could probably add a capacitor to make it also an analog output.)
How to use these pins to output:
First, you need to define the pin as output. Then, you use
analogWrite(ledPin, 128);
to start it. TheledPin
is the PWM pin that you want to start PWM and128
should be replaced with a number between0
and255
;0
:0% duty cycle
(turns the pin completely off) and255
:100% duty cycle
. (turns the pin on completely)Source: http://www.arduino-tutorials.com/arduino-pwm/
Why can't I just turn the light on and off really fast in my code?:
Technically, you can, however, there are some problems:
It's not really going to make that much of a difference if the Arduino's sole purpose is to generate PWM signals. However, if you put any delays longer than 50 MS in the main loop, it will mess up the timing. With the software approach you would want to eliminate any "delay" functions since the Arduino only runs on one thread (it can only do one thing at one time). If you know what you're doing, it won't make that much of a difference dimming the light, but if you have an extra pin with PWM, you're just wasting your time with a software approach.
As others have pointed out:
You still need a resistor for your circuits to limit current and voltage. You cannot skip this.