Hey Ardiuno Forum users,
I recently purchased an Ardiuno, and was trying to vary brightness of multiple led’s using shiftOut, i soon found its execution time excruciatingly long. After a lot of research i found that it was the long execution time of digitalWrite.
I looked at direct port manipulation but could never get it to work, I then came across this link. http://urbanhonking.com/ideasfordozens/2009/05/18/an_tour_of_the_arduino_interna/
After reading through it multiple times, I broke down digitalWrite into setup and error checking and port addressing.
I then put these into a class I call dWriteF.
#include <Wiring_digital.c>
// included this library mostly to include turnOffPWM function, since it's quite long
class dWriteF
{
public:
dWriteF(uint8_t pin); //constructor (no destructor, the compiler didn't like mine and didn't seem to care if one was given)
void Write(bool val); //contains all the code that needs to repeat to set a digital output after class is constructed
private:
uint8_t timer; // used in disabling PWM, not sure how this part works
uint8_t bitF; //declared as bitF instead of bit to avoid conflict, "bit" lights up like a keyword, so...
uint8_t port; //byte storing pin's port
volatile uint8_t *out; // address of output register
byte error1; // Variable to store possible error if constructor is supplied an invalid pin number,
dWriteF::dWriteF(uint8_t pin)
{ timer = digitalPinToTimer(pin);
bitF = digitalPinToBitMask(pin);
port = digitalPinToPort(pin);
if (port == NOT_A_PIN) error1 = 100; //sets error 100
// If the pin that support PWM output, we need to turn it off before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port); //returns address of port register
}
void dWriteF::Write(bool val)
{
if (error1 == 100) return; //EDIT,RETURNS just like library function
uint8_t oldSREG = SREG; // unknown???
/*cli() was here, but it was related to interrupts???, so I removed it, looks like a constructor to me*/
if (val == LOW) {
*out &= ~bitF; // sends value using bitmask to register
} else {
*out |= bitF;
}
SREG = oldSREG;
}
//end dWriteF declarations
//-----------------------------------------------------------------------------------------------------//
Note that the constructor dWrite(uint8_t pin) cannot be called in loop, i forgot to try making it global, but here is my test code
const byte LEDpin = 13;
void setup()
{
pinMode(LEDpin, OUTPUT);
Serial.begin(115200);
}
void loop(){
dWriteF LED13 (LEDpin);
int time1;
int time2;
time1 = micros();
LED13.Write(LOW);
time2 = micros();
delay(500);
LED13.Write(HIGH);
delay(500);
LED13.Write(LOW);
LED13.Write(HIGH);
Serial.println(time1);
Serial.println(time2);
}
am I doing this right?
I get an execution of 4 microseconds, is this ridiculous or is it truly the execution time of dWriteF::Write()?
from serial monitor
68
72
17356
17360
-30568
-30564
-12928
-12924
4708
4712
22208
22212
-25720
-25716
-8080
-8076
seems int overflowed.
Thanks everyone, just to make sure I’m not confusing anyone, are these numbers fooling me?
And I’d love feedback of the practicality of implementing this more often.