├── Readme.md ├── Examples └── PrayerTimes_example │ └── PrayerTimes_example.ino ├── PrayerTimes.h └── PrayerTimes.cpp /Readme.md: -------------------------------------------------------------------------------- 1 | Islamic Prayer Times for Arduino 2 | =========== 3 | Tested on Arduino : 4 | - Mega 2560 5 | - Uno 6 | 7 | Adabted for arduino from this site: http://praytimes.org/manual/ 8 | 9 | to run the example, you need to install this library: https://github.com/PaulStoffregen/Time 10 | -------------------------------------------------------------------------------- /Examples/PrayerTimes_example/PrayerTimes_example.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // get this library from https://github.com/PaulStoffregen/Time 4 | #include 5 | #include "PrayerTimes.h" 6 | 7 | double times[sizeof(TimeName)/sizeof(char*)]; 8 | 9 | void p(char *fmt, ... ){ 10 | char tmp[128]; // resulting string limited to 128 chars 11 | va_list args; 12 | va_start (args, fmt ); 13 | vsnprintf(tmp, 128, fmt, args); 14 | va_end (args); 15 | Serial.print(tmp); 16 | } 17 | 18 | 19 | 20 | void setup() { 21 | Serial.begin(9600); 22 | 23 | } 24 | 25 | void loop() { 26 | 27 | Serial.println("PTimes:"); 28 | 29 | int dst=1; 30 | 31 | set_calc_method(ISNA); 32 | set_asr_method(Shafii); 33 | set_high_lats_adjust_method(AngleBased); 34 | set_fajr_angle(15); 35 | set_isha_angle(15); 36 | 37 | //MEKKA 38 | //float latitude=21.427378; 39 | //float longitude=39.814838; 40 | //get_prayer_times(year(), month(), day(), latitude, longitude, dst, times); 41 | get_prayer_times(2015, 5, 8, 46.9500f, 7.4458f, 2, times); 42 | 43 | Serial.print("YEAR:"); 44 | Serial.println(year()); 45 | Serial.print("MONTH:"); 46 | Serial.println(month()); 47 | Serial.print("DAY:"); 48 | Serial.println(day()); 49 | 50 | for (int i=0;i= currTime) break; 88 | } 89 | if ( (times[i]-currTime) <0 ) { 90 | i=0; 91 | } 92 | pTime=times[i]; 93 | sprintf(pTimeName,"%s",TimeName[i]); 94 | } 95 | -------------------------------------------------------------------------------- /PrayerTimes.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef Morse_h 4 | #define Morse_h 5 | 6 | #include "Arduino.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | static const int NUM_ITERATIONS = 1; // number of iterations needed to compute times 14 | 15 | /* ------------------------------------------------------------------------------------------------- */ 16 | static const char* TimeName[] = 17 | { 18 | "Fajr", 19 | "Sunrise", 20 | "Dhuhr", 21 | "Asr", 22 | "Sunset", 23 | "Maghrib", 24 | "Isha", 25 | "TimesCount" 26 | }; 27 | // Calculation Methods 28 | enum CalculationMethod 29 | { 30 | Jafari, // Ithna Ashari 31 | Karachi, // University of Islamic Sciences, Karachi 32 | ISNA, // Islamic Society of North America (ISNA) 33 | MWL, // Muslim World League (MWL) 34 | Makkah, // Umm al-Qura, Makkah 35 | Egypt, // Egyptian General Authority of Survey 36 | Custom, // Custom Setting 37 | 38 | CalculationMethodsCount 39 | }; 40 | 41 | // Juristic Methods 42 | enum JuristicMethod 43 | { 44 | Shafii, // Shafii (standard) 45 | Hanafi, // Hanafi 46 | }; 47 | 48 | // Adjusting Methods for Higher Latitudes 49 | enum AdjustingMethod 50 | { 51 | None, // No adjustment 52 | MidNight, // middle of night 53 | OneSeventh, // 1/7th of night 54 | AngleBased, // angle/60th of night 55 | }; 56 | 57 | // Time IDs 58 | enum TimeID 59 | { 60 | Fajr, 61 | Sunrise, 62 | Dhuhr, 63 | Asr, 64 | Sunset, 65 | Maghrib, 66 | Isha, 67 | TimesCount 68 | }; 69 | 70 | struct MethodConfig 71 | { 72 | MethodConfig() 73 | { 74 | } 75 | 76 | MethodConfig(double fajr_angle, 77 | bool maghrib_is_minutes, 78 | double maghrib_value, 79 | bool isha_is_minutes, 80 | double isha_value) 81 | : fajr_angle(fajr_angle) 82 | , maghrib_is_minutes(maghrib_is_minutes) 83 | , maghrib_value(maghrib_value) 84 | , isha_is_minutes(isha_is_minutes) 85 | , isha_value(isha_value) 86 | { 87 | } 88 | 89 | double fajr_angle; 90 | bool maghrib_is_minutes; 91 | double maghrib_value; // angle or minutes 92 | bool isha_is_minutes; 93 | double isha_value; // angle or minutes 94 | }; 95 | 96 | struct DoublePair { 97 | double first; 98 | double second; 99 | }; 100 | 101 | 102 | void compute_times(double times[]); 103 | void adjust_times(double times[]); 104 | void day_portion(double times[]); 105 | void set_calc_method(CalculationMethod method_id); 106 | void adjust_high_lat_times(double times[]); 107 | void set_asr_method(JuristicMethod method_id); 108 | void set_high_lats_adjust_method(AdjustingMethod method_id); 109 | void set_calc_method(CalculationMethod method_id); 110 | void set_fajr_angle(double angle); 111 | void set_maghrib_angle(double angle); 112 | void set_isha_angle(double angle); 113 | 114 | double compute_time(double g, double t); 115 | double sun_declination(double jd); 116 | double compute_mid_day(double _t); 117 | double equation_of_time(double jd); 118 | double night_portion(double angle); 119 | 120 | static double fix_angle(double a); 121 | static double deg2rad(double d); 122 | static double rad2deg(double r); 123 | static String int_to_string(int num); 124 | 125 | void get_prayer_times(int year, int month, int day, double _latitude, double _longitude, double _timezone, double times[]); 126 | void get_float_time_parts(double time, int& hours, int& minutes); 127 | 128 | #endif -------------------------------------------------------------------------------- /PrayerTimes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | #include "Arduino.h" 6 | #include "PrayerTimes.h" 7 | 8 | 9 | double latitude; 10 | double longitude; 11 | double timezone; 12 | double julian_date; 13 | 14 | MethodConfig method_params[CalculationMethodsCount]; 15 | CalculationMethod calc_method; // caculation method 16 | JuristicMethod asr_juristic; // Juristic method for Asr 17 | AdjustingMethod adjust_high_lats; // adjusting method for higher latitudes 18 | double dhuhr_minutes; // minutes after mid-day for Dhuhr 19 | 20 | /* ---------------------- Trigonometric Functions ----------------------- */ 21 | 22 | /* degree sin */ 23 | static double dsin(double d) 24 | { 25 | return sin(deg2rad(d)); 26 | } 27 | 28 | /* degree cos */ 29 | static double dcos(double d) 30 | { 31 | return cos(deg2rad(d)); 32 | } 33 | 34 | /* degree tan */ 35 | static double dtan(double d) 36 | { 37 | return tan(deg2rad(d)); 38 | } 39 | 40 | /* degree arcsin */ 41 | static double darcsin(double x) 42 | { 43 | return rad2deg(asin(x)); 44 | } 45 | 46 | /* degree arccos */ 47 | static double darccos(double x) 48 | { 49 | return rad2deg(acos(x)); 50 | } 51 | 52 | /* degree arctan */ 53 | static double darctan(double x) 54 | { 55 | return rad2deg(atan(x)); 56 | } 57 | 58 | /* degree arctan2 */ 59 | static double darctan2(double y, double x) 60 | { 61 | return rad2deg(atan2(y, x)); 62 | } 63 | 64 | /* degree arccot */ 65 | static double darccot(double x) 66 | { 67 | return rad2deg(atan(1.0 / x)); 68 | } 69 | 70 | /* degree to radian */ 71 | static double deg2rad(double d) 72 | { 73 | return d * M_PI / 180.0; 74 | } 75 | 76 | /* radian to degree */ 77 | static double rad2deg(double r) 78 | { 79 | return r * 180.0 / M_PI; 80 | } 81 | 82 | /* range reduce angle in degrees. */ 83 | static double fix_angle(double a) 84 | { 85 | a = a - 360.0 * floor(a / 360.0); 86 | a = a < 0.0 ? a + 360.0 : a; 87 | return a; 88 | } 89 | 90 | /* range reduce hours to 0..23 */ 91 | static double fix_hour(double a) 92 | { 93 | a = a - 24.0 * floor(a / 24.0); 94 | a = a < 0.0 ? a + 24.0 : a; 95 | return a; 96 | } 97 | 98 | /* ------------------------------------------------------------------------------------------------- */ 99 | /* calculate julian date from a calendar date */ 100 | double get_julian_date(int year, int month, int day) 101 | { 102 | if (month <= 2) 103 | { 104 | year -= 1; 105 | month += 12; 106 | } 107 | 108 | double a = floor(year / 100.0); 109 | double b = 2 - a + floor(a / 4.0); 110 | 111 | return floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524.5; 112 | } 113 | /* compute prayer times at given julian date */ 114 | void compute_day_times(double times[]) 115 | { 116 | double default_times[] = { 5, 6, 12, 13, 18, 18, 18 }; // default times 117 | for (int i = 0; i < TimesCount; ++i) 118 | times[i] = default_times[i]; 119 | 120 | for (int i = 0; i < NUM_ITERATIONS; ++i) 121 | compute_times(times); 122 | 123 | adjust_times(times); 124 | } 125 | 126 | /* compute declination angle of sun and equation of time */ 127 | DoublePair sun_position(double jd) 128 | { 129 | double d = jd - 2451545.0; 130 | double g = fix_angle(357.529 + 0.98560028 * d); 131 | double q = fix_angle(280.459 + 0.98564736 * d); 132 | double l = fix_angle(q + 1.915 * dsin(g) + 0.020 * dsin(2 * g)); 133 | 134 | // double r = 1.00014 - 0.01671 * dcos(g) - 0.00014 * dcos(2 * g); 135 | double e = 23.439 - 0.00000036 * d; 136 | 137 | double dd = darcsin(dsin(e) * dsin(l)); 138 | double ra = darctan2(dcos(e) * dsin(l), dcos(l)) / 15.0; 139 | ra = fix_hour(ra); 140 | double eq_t = q / 15.0 - ra; 141 | DoublePair dp={dd, eq_t}; 142 | return dp; 143 | } 144 | 145 | /* set the juristic method for Asr */ 146 | void set_asr_method(JuristicMethod method_id) 147 | { 148 | asr_juristic = method_id; 149 | } 150 | 151 | /* set adjusting method for higher latitudes */ 152 | void set_high_lats_adjust_method(AdjustingMethod method_id) 153 | { 154 | adjust_high_lats = method_id; 155 | } 156 | 157 | /* compute declination angle of sun */ 158 | double sun_declination(double jd) 159 | { 160 | return sun_position(jd).first; 161 | } 162 | 163 | /* compute equation of time */ 164 | double equation_of_time(double jd) 165 | { 166 | return sun_position(jd).second; 167 | } 168 | 169 | /* compute mid-day (Dhuhr, Zawal) time */ 170 | double compute_mid_day(double _t) 171 | { 172 | double t = equation_of_time(julian_date + _t); 173 | double z = fix_hour(12 - t); 174 | return z; 175 | } 176 | 177 | /* compute time for a given angle G */ 178 | double compute_time(double g, double t) 179 | { 180 | double d = sun_declination(julian_date + t); 181 | double z = compute_mid_day(t); 182 | double v = 1.0 / 15.0 * darccos((-dsin(g) - dsin(d) * dsin(latitude)) / (dcos(d) * dcos(latitude))); 183 | return z + (g > 90.0 ? - v : v); 184 | } 185 | /* compute prayer times at given julian date */ 186 | /* compute the time of Asr */ 187 | double compute_asr(int step, double t) // Shafii: step=1, Hanafi: step=2 188 | { 189 | double d = sun_declination(julian_date + t); 190 | double g = -darccot(step + dtan(fabs(latitude - d))); 191 | return compute_time(g, t); 192 | } 193 | 194 | void compute_times(double times[]) 195 | { 196 | day_portion(times); 197 | 198 | times[Fajr] = compute_time(180.0 - method_params[calc_method].fajr_angle, times[Fajr]); 199 | times[Sunrise] = compute_time(180.0 - 0.833, times[Sunrise]); 200 | times[Dhuhr] = compute_mid_day(times[Dhuhr]); 201 | times[Asr] = compute_asr(1 + asr_juristic, times[Asr]); 202 | times[Sunset] = compute_time(0.833, times[Sunset]); 203 | times[Maghrib] = compute_time(method_params[calc_method].maghrib_value, times[Maghrib]); 204 | times[Isha] = compute_time(method_params[calc_method].isha_value, times[Isha]); 205 | } 206 | /* compute the difference between two times */ 207 | static double time_diff(double time1, double time2) 208 | { 209 | return fix_hour(time2 - time1); 210 | } 211 | 212 | static String int_to_string(int num) 213 | { 214 | return String(num); 215 | } 216 | 217 | /* add a leading 0 if necessary */ 218 | static String two_digits_format(int num) 219 | { 220 | char tmp[16]; 221 | tmp[0] = '\0'; 222 | sprintf(tmp, "%2.2d", num); 223 | return String(tmp); 224 | } 225 | /* the night portion used for adjusting times in higher latitudes */ 226 | double night_portion(double angle) 227 | { 228 | switch (adjust_high_lats) 229 | { 230 | case AngleBased: 231 | return angle / 60.0; 232 | case MidNight: 233 | return 1.0 / 2.0; 234 | case OneSeventh: 235 | return 1.0 / 7.0; 236 | default: 237 | // Just to return something! 238 | // In original library nothing was returned 239 | // Maybe I should throw an exception 240 | // It must be impossible to reach here 241 | return 0; 242 | } 243 | } 244 | /* adjust Fajr, Isha and Maghrib for locations in higher latitudes */ 245 | void adjust_high_lat_times(double times[]) 246 | { 247 | double night_time = time_diff(times[Sunset], times[Sunrise]); // sunset to sunrise 248 | 249 | // Adjust Fajr 250 | double fajr_diff = night_portion(method_params[calc_method].fajr_angle) * night_time; 251 | if (isnan(times[Fajr]) || time_diff(times[Fajr], times[Sunrise]) > fajr_diff) 252 | times[Fajr] = times[Sunrise] - fajr_diff; 253 | 254 | // Adjust Isha 255 | double isha_angle = method_params[calc_method].isha_is_minutes ? 18.0 : method_params[calc_method].isha_value; 256 | double isha_diff = night_portion(isha_angle) * night_time; 257 | if (isnan(times[Isha]) || time_diff(times[Sunset], times[Isha]) > isha_diff) 258 | times[Isha] = times[Sunset] + isha_diff; 259 | 260 | // Adjust Maghrib 261 | double maghrib_angle = method_params[calc_method].maghrib_is_minutes ? 4.0 : method_params[calc_method].maghrib_value; 262 | double maghrib_diff = night_portion(maghrib_angle) * night_time; 263 | if (isnan(times[Maghrib]) || time_diff(times[Sunset], times[Maghrib]) > maghrib_diff) 264 | times[Maghrib] = times[Sunset] + maghrib_diff; 265 | } 266 | /* adjust times in a prayer time array */ 267 | void adjust_times(double times[]) 268 | { 269 | for (int i = 0; i < TimesCount; ++i) 270 | times[i] += timezone - longitude / 15.0; 271 | times[Dhuhr] += dhuhr_minutes / 60.0; // Dhuhr 272 | if (method_params[calc_method].maghrib_is_minutes) // Maghrib 273 | times[Maghrib] = times[Sunset] + method_params[calc_method].maghrib_value / 60.0; 274 | if (method_params[calc_method].isha_is_minutes) // Isha 275 | times[Isha] = times[Maghrib] + method_params[calc_method].isha_value / 60.0; 276 | 277 | if (adjust_high_lats != None) 278 | adjust_high_lat_times(times); 279 | } 280 | /* convert hours to day portions */ 281 | void day_portion(double times[]) 282 | { 283 | for (int i = 0; i < TimesCount; ++i) 284 | times[i] /= 24.0; 285 | } 286 | 287 | /* return prayer times for a given date */ 288 | void get_prayer_times(int year, int month, int day, double _latitude, double _longitude, double _timezone, double times[]) 289 | { 290 | latitude = _latitude; 291 | longitude = _longitude; 292 | timezone = _timezone; 293 | julian_date = get_julian_date(year, month, day) - longitude / (double) (15 * 24); 294 | compute_day_times(times); 295 | } 296 | 297 | void set_calc_method(CalculationMethod method_id) 298 | { 299 | calc_method = method_id; 300 | } 301 | 302 | /* set the angle for calculating Fajr */ 303 | void set_fajr_angle(double angle) 304 | { 305 | method_params[Custom].fajr_angle = angle; 306 | calc_method = Custom; 307 | } 308 | 309 | /* set the angle for calculating Maghrib */ 310 | void set_maghrib_angle(double angle) 311 | { 312 | method_params[Custom].maghrib_is_minutes = false; 313 | method_params[Custom].maghrib_value = angle; 314 | calc_method = Custom; 315 | } 316 | 317 | /* set the angle for calculating Isha */ 318 | void set_isha_angle(double angle) 319 | { 320 | method_params[Custom].isha_is_minutes = false; 321 | method_params[Custom].isha_value = angle; 322 | calc_method = Custom; 323 | } 324 | 325 | /* set the minutes after mid-day for calculating Dhuhr */ 326 | void set_dhuhr_minutes(double minutes) 327 | { 328 | dhuhr_minutes = minutes; 329 | } 330 | 331 | /* set the minutes after Sunset for calculating Maghrib */ 332 | void set_maghrib_minutes(double minutes) 333 | { 334 | method_params[Custom].maghrib_is_minutes = true; 335 | method_params[Custom].maghrib_value = minutes; 336 | calc_method = Custom; 337 | } 338 | 339 | /* set the minutes after Maghrib for calculating Isha */ 340 | void set_isha_minutes(double minutes) 341 | { 342 | method_params[Custom].isha_is_minutes = true; 343 | method_params[Custom].isha_value = minutes; 344 | calc_method = Custom; 345 | } 346 | 347 | /* get hours and minutes parts of a float time */ 348 | void get_float_time_parts(double time, int& hours, int& minutes) 349 | { 350 | time = fix_hour(time + 0.5 / 60); // add 0.5 minutes to round 351 | hours = floor(time); 352 | minutes = floor((time - hours) * 60); 353 | } --------------------------------------------------------------------------------