|
Comments and Discussions
|
|
|
Thank you! And thanks for the tip about your interesting article!
|
|
|
|
|
I came across your article because I was searching for ways to speed up my sketch and I was having some problems with digitalWriteFast. I have only been programming for a month and your article was very insightful! When re-labeling the digital pins as DP-1, DP-2, etc., do I also relabel the analogue pins as AP-1, AP-2, etc., in my sketch. Your article does not state this.
Thanks.
|
|
|
|
|
Hi, I suppose you are using the "DIO2" code from the article "Fast digital I/O for Arduino".
If you want to use the analog pins in digital mode (with the digitalRead2f/Write2f functions) use names of pins DP14 to DP19. A0 is DP14, A1 is DP15 and so on. The DIO2 library does not define the analog names like A0, A1, so it is not possible to use them with the new functions.
If you want to use the pins as analog inputs (with analogRead), use standard Arduino names like A0. analogRead is not covered by the DIO2 library, so you are using the normal Arduino functions in this case.
You can find the definition of pins available for the DIO2 functions in pin2_arduino.h file in the board subfolder in the DIO2 library; see the enum GPIO_pin_enum where all available pins are defined.
|
|
|
|
|
 Hi.
Thanks so much for taking the time to answer my email. Your article was clear and very helpful. I have changed my code accordingly, but it still takes almost two seconds to go through it. On the off chance you have a moment to look at the code, I would appreciate your telling me how to speed this up.
It looks at the garage door. When open, it checks the distance to the side wall in the front and back of the car as it pulls in, sets off flashing lights and moves a servo pointer accordingly, and then closes the garage door in 20 minutes if forgotten.
//Single garage door closer, two car parking monitor with graphic display and warning lights
#include <Servo.h>//load the server library
#include <arduino2.h>
const GPIO_pin_t buzzer = DP18;//analog pin A4
const GPIO_pin_t trigPinFront = DP14;//analog pin A0
const GPIO_pin_t echoPinFront=DP10;
const GPIO_pin_t trigPinRear=DP15;
const GPIO_pin_t echoPinRear=DP11;
const GPIO_pin_t dangerGate = DP2;//to turn on red flasher transistor base
const GPIO_pin_t cautionGate = DP1;//to turn on yellow flasher transistor base
const GPIO_pin_t servoControlPin=DP3;
int danger;
const GPIO_pin_t garageSwitch = DP8;//NC when garage is closed
const GPIO_pin_t closeGarage = DP6;//output to close the garage door relay
int timingCounter;//counts the number of times through the program when garage door open
//counts to 40 for each minute
float pingTimeFront;//time for ping to travel to target and return
float targetDistanceFront;//distance from sensor to target
float pingTimeRear;//time for ping to travel to target and return
float targetDistanceRear;//distance from sensor to target
float speedOfSound = 776.5;//speed of sound in mph
float servoAngle;//variable for the angle of the servo
//set up the parameters for the CAUTION range
float maxTargetDistanceFront = 2.0;
float minTargetDistanceFront= 1.0;
float maxTargetDistanceRear = 4.0;
float minTargetDistanceRear = 3.0;
Servo myPointer;//create a servo object called myPointer
void setup(){
pinMode2f(buzzer, OUTPUT);
pinMode2f (trigPinFront, OUTPUT);
pinMode2f(echoPinFront, INPUT);
pinMode2f(trigPinRear, OUTPUT);
pinMode2f(echoPinRear, INPUT);
pinMode2f(dangerGate, OUTPUT);
pinMode2f(cautionGate, OUTPUT);
pinMode2f(servoControlPin, OUTPUT);
pinMode2f(garageSwitch, INPUT);
pinMode2f(closeGarage, OUTPUT);
Serial.begin(9600);
pinMode2f(servoControlPin, OUTPUT);//servo control pin is an output
myPointer.attach(servoControlPin);//tell Arduino where the servo is connected
}
void loop() {
// digitalWrite(garageSwitch, LOW);//not sure this line should be here
digitalWrite2f(dangerGate, LOW);
digitalWrite2f(cautionGate, LOW);
if (digitalRead2f(garageSwitch)== LOW)
{
timingCounter = 0;
}
if (digitalRead2f(garageSwitch) == HIGH)
{
//start the timer code here
timingCounter++;
if (timingCounter>800)
{
digitalWrite2f(garageSwitch, HIGH);
delay(250);
digitalWrite2f(garageSwitch, LOW);
}
digitalWrite2f(trigPinFront, LOW); // set the trigger pin low
delayMicroseconds(200);//pause to let signal settle
digitalWrite2f(trigPinFront, HIGH);// set trigger pin high
delayMicroseconds(15);//pause in high state
digitalWrite2f(trigPinFront, LOW);// bring trig pin back low
pingTimeFront = pulseIn(echoPinFront, HIGH);// measure ping time at echo pin in microseconds
//pingTimeFront = pingTimeFront/1000000.0;//converts pingtime to seconds
//pingTimeFront = pingTimeFront/3600.0;//converts pingtime in seconds to pingtime in hours
pingTimeFront = pingTimeFront/3600000000.0;
targetDistanceFront = speedOfSound * pingTimeFront;//distance equals rate times time to calculate distance in miles
targetDistanceFront = targetDistanceFront/2;//accounts for round trip for ping
targetDistanceFront = targetDistanceFront * 63360.0;//converts target distance to inches (63360 inches in a mile)
digitalWrite2f(trigPinRear, LOW); // set the trigger pin low
delayMicroseconds(200);//pause to let signal settle
digitalWrite2f(trigPinRear, HIGH);// set trigger pin high
delayMicroseconds(15);//pause in high state
digitalWrite2f(trigPinRear, LOW);// bring trig pin back low
pingTimeRear = pulseIn(echoPinRear, HIGH);// measure ping time at echo pin in microseconds
//pingTimeRear = pingTimeRear/1000000.0;//converts pingtime to seconds
//pingTimeRear = pingTimeRear/3600.0;//converts pingtime in seconds to pingtime in hours
pingTimeRear = pingTimeRear/3600000000.0;
targetDistanceRear = speedOfSound * pingTimeRear;//distance equals rate times time to calculate distance in miles
targetDistanceRear = targetDistanceRear/2;//accounts for round trip for ping
/*
Serial.print("The Distance to the Front target is ");
Serial.print(targetDistanceFront);
Serial.print(" inches");
Serial.print("......The Distance to the Rear target is ");
Serial.print(targetDistanceRear);
Serial.println(" inches");
Serial.print("Timing Counter ");
Serial.println(timingCounter);
*/
//looking for danger distances
int danger = 0;//no danger before readings
if (( targetDistanceFront < minTargetDistanceFront) || (targetDistanceRear < minTargetDistanceRear))
{
digitalWrite2f(dangerGate, HIGH);
int danger = 1;
}
//looking for caution distances
if (((targetDistanceFront< maxTargetDistanceFront) && (targetDistanceFront > minTargetDistanceFront)) || ((targetDistanceRear< maxTargetDistanceRear) && (targetDistanceRear > minTargetDistanceRear)) && danger == 0)
{
digitalWrite2f(cautionGate, HIGH);
}
//setting up the pointer for front distances
if (targetDistanceFront>7.0)
{
targetDistanceFront = 7.0;//range pointer cannot be greater than 7
}
servoAngle = (120./7.) * targetDistanceFront + 30;//calculate servoAngle myPointer.write(servoAngle);//write servo angle to myPointer 30 to 150 every 17 degrees to 7 inches maximum
delay(1);//delay to slow things down
}
Serial.print(" Timing Counter = ");
Serial.println(timingCounter);
//It takes 800 passes to go through the program in about 20 minutes
if ((timingCounter>750) && (timingCounter<780))
{
tone(DP14, 2000, 10);//A0 output for buzzer does not have to be declared
delay(500); // delay in between reads between 500 (slow) and 100 (fast)
}
if (timingCounter>780)
{
tone(DP14, 2000, 10);
delay(100);
}
}
|
|
|
|
|
Hi.
First, one strange thing I noticed in the code. In the pulseIn and tone you use the DIO2 pin names, such as DP14 . This should not work at all in my opinion. If it works I am puzzled why Because the DP14 definitions only work with the funtions of DIO2. pulseIn and tone are normal Arduino funcitons which expect simple pin number, for example, instead of DP1 they expect just 1. DP1 and 1 is not the same thing. The value of the DP1 symbol is some number which makes no sense to the Arduino funcitons; it is like calling tone with pin number 2515 or so.
This could be one thing to make the program behave strange.
Then I can think of two point which could make the program slow:
1) Use of the float variables. There is quite a lot of calculations with these variables. For the 8-bit CPU in Arduino it is lot of work to handle float variables (real numbers). If you could use integers instead (unsigned long if you need numbers above 65000 which seems to be the case) it would speed up things a lot. Perhaps the calculations could also be optimized, for example, not to convert to miles and hours; if possible chose units where there will be no big numbers. And instead of first dividing by 2 and then multiplying by something do this in one step. So instead of
targetDistanceFront = targetDistanceFront/2;
targetDistanceFront = targetDistanceFront * 63360.0;
use this ( I hope the math is right , the point is not to calculate it in runtime if it can be done beforehand)
targetDistanceFront * (63360.0/2);
2) The code pulseIn (echoPinFront, HIGH); will wait until some pulse arrives on the input. Probably this is OK if the ping sensor is working as expected, but if the program still runs slow you could try to comment out (disable) this code and see if it does not cause the problems.
I think your code does not benefit much from the DIO2 library. There seems to be no points where it would make any difference whether the digitalWrite takes 5 microsecond (standard Arduino) or about 0.5 microsecond (the fast DIO2 version). In other words, the digitalWrite/Read operations have little effect on the execution speeds. There are the points I mentioned above plus many delays, so the speed of these operations is not the "bottleneck" of your program. This does not mean that you should not use them; just if it becomes complicated to deal with two kinds of pin names - the DIO2 names like DP1 and the native Arduino plain numbers or A0 etc., you can just use the normal Arduino digitalWrite/Read without any effect on the speed.
|
|
|
|
|
Thanks so much for taking the time to review this. I will experiment with these changes over the weekend and let you know, but I'm getting the feeling that you're right and the issue is not pin addressing but rather all the running around I'm asking the program to do. Gotta make it more efficient.
Thanks again.
|
|
|
|
|
|
The digitalWriteFast library actually uses the method I call "option 1" in this article - it is the "macro approach". So it will be fast for pin numbers known in compile time (const) but slow for pins stored in variables. As they write on the website "It can speed things up when the pin number is known at compile time... ....On the other hand a loop with digitalWrite(i,HIGH); or a called function with the pin number as a passed argument will not be faster".
My approach will have the same speed as digitalWriteFast for pin numbers known in compile time. For pin numbers not known in compile time it will be faster than digitalWriteFast.
I think digitalWriteFast will at best have the same pros and cons as the Wiring implementation I describe in this article. I say "at best" because I am not sure how/if it handles disabling the interrupts for port registers on Arduino Mega which may be required even for pin numbers known in compile time and using single-copy of the code when the pin is not known in compile time, so that each call to digitalWriteFast does not result in copy of the same code.
Big advantage of digitalWriteFast over Wiring is that it is easy to use in Arduino while using the Wiring library would require changing the IDE, using Eclipse or so.
But I believe my approach is better You get the best possible speed for pins known at compile time and also better speed for pins not known at compile time.
|
|
|
|
|
Hi Jan,
Hope you're doing well!
This is Wanita from ICStation.com. We are an ICs Product retailer and specialized in IC Components, Development Board, DIY PCB Universal Board, Modules, Robots, Sensor and so on.
I'd like to invite you to write reviews for our product. May I have your contact email address? Thanks!
Look forward to your reply,
Thank you & best regards.
Wanita
|
|
|
|
|
Hi Wanita,
Sorry for the late answer, I haven't checked this forum for some time
If you are still interested, please write me an email to jdolinay (at) hotmail.com.
Best regards,
Jan
|
|
|
|
|
Very interesting and clearly written article.
Just because the code works, it doesn't mean that it is good code.
|
|
|
|
|
This is a great inspiring article. I am pretty much pleased with your good work. You put really very helpful information. Keep it up once again.
|
|
|
|
|
|
|
Thanks for the link. It's really interesting. The results for digitalWrite seems to match. 224 writes per millisecond gives 4.5 microseconds per digitalWrite. With direct port read, the bitRead is translated into IN instruction, which takes 1 clock cycle (62.5 ns) to execute as written there. If bitWrite was used, this translates into SBI or CBI instruction which take 2 cycles (125 ns).
|
|
|
|
|
Playing with them at the moment, this article contains many, many gems. Well researched and documented. My favourite kind of article at CodeProject. Bookmarked.
modified 9-Jun-13 14:02pm.
|
|
|
|
|
|
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
|