شاید تا کنون در انجام پروژه هایتان به چالشی با عنوان سنجش زمان، تاریخ و دما برخورد کرده باشید، به طور مثال زمانسنجی مقدار عملکرد دستگاه، انجام یک عملکرد خاص طبق زمانبدی تعیین شده، چک کردن دما و گزارش هفتگی، ماهانه و سالیانه عملکرد دستگاه و…
اما مطمئنا اگر در پروژه هایتان با موارد بالا برخورد کرده باشید. حتما با سوالاتی همچون موارد زیر برخورد کرده اید.
- از چه آیسی باید استفاده کنیم؟ که قابلیت دریافت همزمان تاریخ، زمان و دما را داشته باشد؟
- چطور باید آنرا راهاندازی کنیم؟
در این مقاله از سری پروژه های آردوینو میخواهیم به این سوالات پاسخ دهیم و در نهایت ماژول معرفی شده را توسط برد آردوینو راهاندازی کنیم.
از چه آیسی باید استفاده کنیم؟ که قابلیت دریافت همزمان تاریخ، زمان و دما را داشته باشد؟
در واقع یکی از بزرگترین ضعف های مهندسان الکترونیک، انتخاب قطعه مناسب برای انجام کار مورد نیاز است، که در این بخش میخواهیم با توجه به پروژه ای که تعریف کردهایم، قطعه موردنظر خود را انتخاب کنیم.
خب اگر دقت کنید در مقدمه مقاله گفتیم که نیاز به سنجش زمان، تاریخ و همینطور دما را داریم. برای اینکه بتوانیم قطعه مورد نظر را پیدا کنیم نیاز به یک جستجو با عنوان ماژول یا آیسی ساعت در گوگل را داریم که پس از این جستجو، با آیسی به نام DS3231 آشنا خواهیم شد. البته دقت کنید که آیسی DS1307 هم موجود میباشد که این آیسی دقت کمتری نسبت به DS3231 را دارد.
حال مرحله بعد نیاز به بررسی دیتاشیت این ماژول داریم. که ببینیم قابلیت هایی که مدنظر ما است را دارد یا خیر؟
خب پس از بررسی دیتاشیت ماژول DS3231، مواردی که مدنظر ما در این پروژه بود را از جمله موارد زیر را دارا میباشد.
- تنظیم سال
- تنظیم ماه
- تنظیم روز
- تنظیم روزهای هفته
- تنظیم ساعت
- تنظیم دقیقه
- تنظیم ثانیه
- داشتن یک سنسور داخلی که قابلیت اندازه گیری دما از -40 تا 85 درجه سانتیگراد را دارد.
خب پس از اینکه موفق به انتخاب آیسی موردنظر شدیم. باید آنرا راهاندازی کنیم.
نحوه راهاندازی ماژول DS3231
خب در این بخش قبل از راهاندازی نیاز به یک آشنایی جزئی با این ماژول را داریم. که این آشنایی جز با مراجعه به دیتاشیت بدست نخواهد آمد.
نحوه صحیح دیتاشیت خوانی چیست؟
یکی دیگر از مواردی که مهندسان الکترونیک در آن ضعف دارند، خواندن صحیح دیتاشیت قطعه موردنظر است که در این بخش ابتدا میخواهیم به صورت کاملا مختصر نحوه صحیح خواندن دیتاشیت را توضیح دهیم. و نکته ای که وجود دارد خیلی از دوستان فکر میکنند که حتما باید تسلط کامل به زبان انگلیسی داشته باشند تا بتوانند تسلط کافی را به دیتاشیت داشته باشند و در نهایت بتوانند قطعه موردنظر را راهاندازی کنند. خیر، برای راهاندازی قطعه موردنظر باید نکات کلیدی که نیاز است را از دیتاشیت جمعآوری کرد و در نهایت از آن نکات استفاده کرد البته از این نکته هم غافل نباشیم که تسلط به زبان انگلیسی بسیار میتواند در این روند کمک کننده محسوب شود.
خب فرض کنید ما تا به حال حتی اسم این قطعه را هم نشنیده ایم و فقط تنها برنامهنویسی را میدانیم، حال باید برای راهاندازی، چه کاری را انجام دهیم.
اولین کاری که باید انجام دهیم، این است که بدانیم آیسی موردنظر از چه پروتکلی پشتیبانی میکند. خب اگر به عکسی که در ادامه قرار دارد دقت کنید. این آیسی از پروتکل I2C جهت برقراری با ماژول استفاده میکند.
دومین مرحله یادگیری پروتکل I2C است که دقیقا چه عملیاتی را باید جهت برقراری ارتباط با میکروکنترلر انجام داد.
پروتکل I2C چیست؟
اگر به صورت کاملا مختصر توضیح دهیم. یک راه ارتباطی جهت انتقال دیتا بین میکروکنترلر و آیسی موردنظر است که نحوه عملکرد آن به صورت شکل زیر میباشد.
پروتکل I2C را با پین های زیر میشناسند.
نحوه عملکرد پروتکل I2C
در I2C داده ها به صورت پیام هایی فرستاده میشود که خود این پیام ها خود به چند بخش تقسیم می شوند. هر پیام شامل یک بخش آدرس است، که همان آدرس باینری مربوط به slave موردنظر است. یک یا دو بخش مربوط به دیتا هم در پیام های ارسالی نیز وجود دارد. پیام همچنین شامل شرایط اولیه و پایانی(دستور شروع و پایان پروتکل)، بیت های read/write و بیت های ACK / NACK بین هربخش از پیام است.
حال پس از اینکه یک دید کلی نسبت به پروتکل پیدا کردیم نیاز است که دستورات ماژول DS3231 را مطالعه کنیم و ببینیم که هر دستور دقیقا چه کاربردی دارد و دقیقا کجا مورد استفاده قرار میگیرد.
خب پس از اینکه این دستورات را مورد مطالعه قرار دادیم نوبت به انتقال همین دستورات و انتقال دیتا توسط پروتکل I2C است. که برای این بخش توصیه میکنیم به کتابخانه ای که در جدول پایین توضیح دادیم مراجعه کنید.
در واقع روندی که توضیح داده شد یک حالت کاملا کلی از خواندن دیتاشیت بود که در ادامه نحوه کدنویسی ماژول DS3231 را مورد مطالعه قرار میدهیم.
کدنویسی ماژول DS3231
در این بخش میخواهیم علاوه بر کد آردوینو ماژول، کتابخانه ای هم که از آن استفاده میکنیم مورد مطالعه قرار دهیم و از عملکرد آن مطلع شویم که اگر خودمان نیاز به نوشتن یه کتابخانه به صورت اصولی داشتیم باید چه کاری را انجام دهیم. و صرفا از کتابخانه های آماده استفاده نکنیم.(چون امکانش هست یه جایی گیر کنیم و اگه واقعا همش از توابع آماده استفاده کنیم آخرش به مشکل بخوریم و … پس بهتره که هر چیزی رو اصولی یادبگیریم و بعدش حداقل از توابع آمادش استفاده کنیم)
کتابخانه نوشته شده ماژول DS3231
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | #include <Wire.h> #include <avr/pgmspace.h> #include "Sodaq_DS3231.h" #include "Arduino.h" #define EPOCH_TIME_OFF 946684800 // This is 2000-jan-01 00:00:00 in epoch time #define SECONDS_PER_DAY 86400L این خط ارسال دستور اماده باش به ماژول است که با دستور 0x68 شناخته میشود #define DS3231_ADDRESS 0x68 //I2C Slave address تعریف یک سری دستورات ماکرو که دقیقا از دیتاشیت آیسی انتخاب شده و کاملا مطابق با دستورات دیتاشیت میباشد. که کاملا هم خوانا نوشته شده است. نکته اول: در نوشتن کتابخانه همیشه منظم و خوانا عمل کنید. #define DS3231_SEC_REG 0x00 #define DS3231_MIN_REG 0x01 #define DS3231_HOUR_REG 0x02 #define DS3231_WDAY_REG 0x03 #define DS3231_MDAY_REG 0x04 #define DS3231_MONTH_REG 0x05 #define DS3231_YEAR_REG 0x06 #define DS3231_AL1SEC_REG 0x07 #define DS3231_AL1MIN_REG 0x08 #define DS3231_AL1HOUR_REG 0x09 #define DS3231_AL1WDAY_REG 0x0A #define DS3231_AL2MIN_REG 0x0B #define DS3231_AL2HOUR_REG 0x0C #define DS3231_AL2WDAY_REG 0x0D #define DS3231_CONTROL_REG 0x0E #define DS3231_STATUS_REG 0x0F #define DS3231_AGING_OFFSET_REG 0x10 #define DS3231_TMP_UP_REG 0x11 #define DS3231_TMP_LOW_REG 0x12 //////////////////////////////////////////////////////////////////////////////// // utility code, some of this could be exposed in the DateTime API if needed در این بخش هم به نحوه راهاندازی دستورات ماژول و همینطور نحوه محاسبه زمان و تاریخ و همینطور محاسبه دما پرداخته شده است. static const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; // number of days since 2000/01/01, valid for 2001..2099 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { if (y >= 2000) y -= 2000; uint16_t days = d; for (uint8_t i = 1; i < m; ++i) days += pgm_read_byte(daysInMonth + i - 1); if (m > 2 && y % 4 == 0) ++days; return days + 365 * y + (y + 3) / 4 - 1; } static uint32_t time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { return ((days * 24L + h) * 60 + m) * 60 + s; } static uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } //////////////////////////////////////////////////////////////////////////////// // DateTime implementation - ignores time zones and DST changes // NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second DateTime::DateTime (long t) { ss = t % 60; t /= 60; mm = t % 60; t /= 60; hh = t % 24; uint16_t days = t / 24; uint8_t leap; for (yOff = 0; ; ++yOff) { leap = yOff % 4 == 0; if (days < 365 + leap) break; days -= 365 + leap; } for (m = 1; ; ++m) { uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); if (leap && m == 2) ++daysPerMonth; if (days < daysPerMonth) break; days -= daysPerMonth; } d = days + 1; wday = 0; // FIXME This is not properly initialized } DateTime::DateTime (uint16_t year, uint8_t month, uint8_t date, uint8_t hour, uint8_t min, uint8_t sec, uint8_t wd) { if (year >= 2000) year -= 2000; yOff = year; m = month; d = date; hh = hour; mm = min; ss = sec; wday = wd; } // A convenient constructor for using "the compiler's time": // DateTime now (__DATE__, __TIME__); // NOTE: using PSTR would further reduce the RAM footprint DateTime::DateTime (const char* date, const char* time) { // sample input: date = "Dec 26 2009", time = "12:34:56" yOff = conv2d(date + 9); // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec switch (date[0]) { case 'J': m = date[1] == 'a' ? 1 : date[2] == 'n' ? 6 : 7; break; case 'F': m = 2; break; case 'A': m = date[2] == 'r' ? 4 : 8; break; case 'M': m = date[2] == 'r' ? 3 : 5; break; case 'S': m = 9; break; case 'O': m = 10; break; case 'N': m = 11; break; case 'D': m = 12; break; } d = conv2d(date + 4); hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); wday = 0; // FIXME This is not properly initialized } uint32_t DateTime::get() const { uint16_t days = date2days(yOff, m, d); return time2long(days, hh, mm, ss); } uint32_t DateTime::getEpoch() const { return get() + EPOCH_TIME_OFF; } /* * Format an integer as %0*d * * Arduino formatting sucks. */ static void add0Nd(String &str, uint16_t val, size_t width) { if (width >= 5 && val < 1000) { str += '0'; } if (width >= 4 && val < 100) { str += '0'; } if (width >= 3 && val < 100) { str += '0'; } if (width >= 2 && val < 10) { str += '0'; } str += val; } static inline void add04d(String &str, uint16_t val) { add0Nd(str, val, 4); } static inline void add02d(String &str, uint16_t val) { add0Nd(str, val, 2); } void DateTime::addToString(String & str) const { add04d(str, year()); str += '-'; add02d(str, month()); str += '-'; add02d(str, date()); str += ' '; add02d(str, hour()); str += ':'; add02d(str, minute()); str += ':'; add02d(str, second()); } static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } //////////////////////////////////////////////////////////////////////////////// // RTC DS3231 implementation uint8_t Sodaq_DS3231::readRegister(uint8_t regaddress) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)regaddress); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 1); return Wire.read(); } void Sodaq_DS3231::writeRegister(uint8_t regaddress,uint8_t value) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)regaddress); Wire.write((byte)value); Wire.endTransmission(); } uint8_t Sodaq_DS3231::begin(void) { unsigned char ctReg=0; Wire.begin(); ctReg |= 0b00011100; writeRegister(DS3231_CONTROL_REG, ctReg); //CONTROL Register Address delay(10); // set the clock to 24hr format uint8_t hrReg = readRegister(DS3231_HOUR_REG); hrReg &= 0b10111111; writeRegister(DS3231_HOUR_REG, hrReg); delay(10); return 1; } //set the time-date specified in DateTime format //writing any non-existent time-data may interfere with normal operation of the RTC void Sodaq_DS3231::setDateTime(const DateTime& dt) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)DS3231_SEC_REG); //beginning from SEC Register address Wire.write((byte)bin2bcd(dt.second())); Wire.write((byte)bin2bcd(dt.minute())); Wire.write((byte)bin2bcd((dt.hour()) & 0b10111111)); //Make sure clock is still 24 Hour Wire.write((byte)dt.dayOfWeek()); Wire.write((byte)bin2bcd(dt.date())); Wire.write((byte)bin2bcd(dt.month())); Wire.write((byte)bin2bcd(dt.year() - 2000)); Wire.endTransmission(); } DateTime Sodaq_DS3231::makeDateTime(unsigned long t) { if (t < EPOCH_TIME_OFF) return DateTime(0); return DateTime(t - EPOCH_TIME_OFF); } // Set the RTC using timestamp (seconds since epoch) void Sodaq_DS3231::setEpoch(uint32_t ts) { setDateTime(makeDateTime(ts)); } //Read the current time-date and return it in DateTime format DateTime Sodaq_DS3231::now() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0x00); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 8); uint8_t ss = bcd2bin(Wire.read()); uint8_t mm = bcd2bin(Wire.read()); uint8_t hrreg = Wire.read(); uint8_t hh = bcd2bin((hrreg & ~0b11000000)); //Ignore 24 Hour bit uint8_t wd = Wire.read(); uint8_t d = bcd2bin(Wire.read()); uint8_t m = bcd2bin(Wire.read()); uint16_t y = bcd2bin(Wire.read()) + 2000; return DateTime (y, m, d, hh, mm, ss, wd); } //Enable periodic interrupt at /INT pin. Supports only the level interrupt //for consistency with other /INT interrupts. All interrupts works like single-shot counter //Use refreshINTA() to re-enable interrupt. void Sodaq_DS3231::enableInterrupts(uint8_t periodicity) { unsigned char ctReg=0; ctReg |= 0b00011101; writeRegister(DS3231_CONTROL_REG, ctReg); //CONTROL Register Address switch(periodicity) { case EverySecond: writeRegister(DS3231_AL1SEC_REG, 0b10000000 ); //set AM1 writeRegister(DS3231_AL1MIN_REG, 0b10000000 ); //set AM2 writeRegister(DS3231_AL1HOUR_REG, 0b10000000 ); //set AM3 writeRegister(DS3231_AL1WDAY_REG, 0b10000000 ); //set AM4 break; case EveryMinute: writeRegister(DS3231_AL1SEC_REG, 0b00000000 ); //Clr AM1 writeRegister(DS3231_AL1MIN_REG, 0b10000000 ); //set AM2 writeRegister(DS3231_AL1HOUR_REG, 0b10000000 ); //set AM3 writeRegister(DS3231_AL1WDAY_REG, 0b10000000 ); //set AM4 break; case EveryHour: writeRegister(DS3231_AL1SEC_REG, 0b00000000 ); //Clr AM1 writeRegister(DS3231_AL1MIN_REG, 0b00000000 ); //Clr AM2 writeRegister(DS3231_AL1HOUR_REG, 0b10000000 ); //Set AM3 writeRegister(DS3231_AL1WDAY_REG, 0b10000000 ); //set AM4 break; } } //Enable HH/MM/SS interrupt on /INTA pin. All interrupts works like single-shot counter void Sodaq_DS3231::enableInterrupts(uint8_t hh24, uint8_t mm, uint8_t ss) { unsigned char ctReg=0; ctReg |= 0b00011101; writeRegister(DS3231_CONTROL_REG, ctReg); //CONTROL Register Address writeRegister(DS3231_AL1SEC_REG, 0b00000000 | bin2bcd(ss) ); //Clr AM1 writeRegister(DS3231_AL1MIN_REG, 0b00000000 | bin2bcd(mm)); //Clr AM2 writeRegister(DS3231_AL1HOUR_REG, (0b00000000 | (bin2bcd(hh24) & 0b10111111))); //Clr AM3 writeRegister(DS3231_AL1WDAY_REG, 0b10000000 ); //set AM4 } //Disable Interrupts. This is equivalent to begin() method. void Sodaq_DS3231::disableInterrupts() { begin(); //Restore to initial value. } //Clears the interrrupt flag in status register. //This is equivalent to preparing the DS3231 /INT pin to high for MCU to get ready for recognizing the next INT0 interrupt void Sodaq_DS3231::clearINTStatus() { // Clear interrupt flag uint8_t statusReg = readRegister(DS3231_STATUS_REG); statusReg &= 0b11111110; writeRegister(DS3231_STATUS_REG, statusReg); } //force temperature sampling and converting to registers. If this function is not used the temperature is sampled once 64 Sec. void Sodaq_DS3231::convertTemperature() { // Set CONV uint8_t ctReg = readRegister(DS3231_CONTROL_REG); ctReg |= 0b00100000; writeRegister(DS3231_CONTROL_REG,ctReg); //wait until CONV is cleared. Indicates new temperature value is available in register. do { //do nothing } while ((readRegister(DS3231_CONTROL_REG) & 0b00100000) == 0b00100000 ); } //Read the temperature value from the register and convert it into float (deg C) float Sodaq_DS3231::getTemperature() { float fTemperatureCelsius; uint8_t tUBYTE = readRegister(DS3231_TMP_UP_REG); //Two's complement form uint8_t tLRBYTE = readRegister(DS3231_TMP_LOW_REG); //Fractional part if(tUBYTE & 0b10000000) //check if -ve number { tUBYTE ^= 0b11111111; tUBYTE += 0x1; fTemperatureCelsius = tUBYTE + ((tLRBYTE >> 6) * 0.25); fTemperatureCelsius = fTemperatureCelsius * -1; } else { fTemperatureCelsius = tUBYTE + ((tLRBYTE >> 6) * 0.25); } return (fTemperatureCelsius); } Sodaq_DS3231 rtc; |
خب حالا نوبت به استفاده از این کتابخانه میرسد البته با این دید که میدانیم از چه توابعی استفاده شده و چطور مورد استفاده قرار گرفته شده است.
راهاندازی ماژول DS3231 با آردوینو
خب این بخش به دو قسمت شماتیک و کدنویسی تقسیم میشود.
شماتیک راهاندازی ماژول DS3231 با آردوینو
کدنویسی ماژول DS3231 با آردوینو
ابتدا باید کتابخانه مربوطه را نصب کنیم، که برای اینکار باید طبق شکلهایی که در ادامه میگذاریم عمل نمایید.
حال پس از نصب کتابخانه نوبت به نوشتن کد موردنظر برای راهاندازی ماژول موردنظر است که در این قسمت میخواهیم از مثال های آماده این کتابخانه استفاده کنیم. برای این کار باید به صورت زیر عمل کنیم.
خب همونطوری که میبینید این کتابخانه دارای 4 نمونه کد راهانداز است که میخواهیم کد NOW را امتحان و در نهایت روی سریال مانیتور اطلاعات را نمایش دهیم.
کد مثال NOW
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | // Date and time functions using RX8025 RTC connected via I2C and Wire lib #include <Wire.h> #include "Sodaq_DS3231.h" char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; void setup () { Serial.begin(57600); Wire.begin(); rtc.begin(); } uint32_t old_ts; void loop () { DateTime now = rtc.now(); //get the current date-time uint32_t ts = now.getEpoch(); if (old_ts == 0 || old_ts != ts) { old_ts = ts; Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.date(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.print(' '); Serial.print(weekDay[now.dayOfWeek()]); Serial.println(); Serial.print("Seconds since Unix Epoch: "); Serial.print(ts, DEC); Serial.println(); } delay(1000); } |
در نهایت اگر تمامی مراحلی که توضیح دادیمبه درستی انجام شده باشد باید خروجی سربال مانیتور مطابق اطلاعاتی که در ادامه قرار میدهیم، باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 2002/2/5 7:12:58 Wed Seconds since Unix Epoch: 1012893178 2002/2/5 7:12:59 Wed Seconds since Unix Epoch: 1012893179 2002/2/5 7:13:0 Wed Seconds since Unix Epoch: 1012893180 2002/2/5 7:13:1 Wed Seconds since Unix Epoch: 1012893181 2002/2/5 7:13:2 Wed Seconds since Unix Epoch: 1012893182 2002/2/5 7:13:3 Wed Seconds since Unix Epoch: 1012893183 2002/2/5 7:13:4 Wed Seconds since Unix Epoch: 1012893184 2002/2/5 7:13:5 Wed Seconds since Unix Epoch: 1012893185 2002/2/5 7:13:6 Wed Seconds since Unix Epoch: 1012893186 2002/2/5 7:13:7 Wed Seconds since Unix Epoch: 1012893187 2002/2/5 7:13:8 Wed Seconds since Unix Epoch: 1012893188 2002/2/5 7:13:9 Wed Seconds since Unix Epoch: 1012893189 2002/2/5 7:13:10 Wed Seconds since Unix Epoch: 1012893190 2002/2/5 7:13:11 Wed Seconds since Unix Epoch: 1012893191 2002/2/5 7:13:12 Wed |
امیدوارم که این آموزش هم برای شما مفید واقع شده باشد.
ممنون از آموزش خوب و مفیدتون..
چطوری از حالت 12 ساعته به 24 ساعته یا برعکس تنظیم کنیم؟
با سپاس
سلام دوست عزیز – دقیقا صفحه ۱۲ دیتاشیت این مطلب رو نوشته
Bit 6 of the hours register is defined as the 12- or 24-hour mode select bit
در واقع شما ست و ریست بیت ۶ ام از ریجیستر ۲ حالت های ۱۲ ساعته یا ۲۴ ساعته رو انتخاب کنید.
ممنون از پاسختون..
اما من متوجه نشدم..
امکانش هست کمی بیشتر توضیح بدین؟
خیلی ممنون میشم.
دوست من اگر دیتاشیت رو باز میکردید و اون صفحه ای که اشاره کردم و مطالعه می کردید مشکلتون زودتر حل میشد.
ببینید یه بیت توی یکی از رجیسترها وجود داره که با یک کردن اون بیت به آیسی میگید چطور زمان رو محاسبه (۱۲ ساعته یا ۲۴ ساعته )کنه به همین سادگی
با تشکر،
اما من چون رشتم الکترونیک نیست، خیلی سر در نمیارم..
باسلام و تشکر از توضیحات خوبتون
در صورت امکان نحوه تبدیل تاریخ به شمسی هم به برنامتون اضافه کنید .
ممنونم دوست عزیز
پیشنهاد بدی نیست بررسی میکنیم
امکانپذیر هست؟
امم، امکان پذیر که هست ولی بذارید بررسی کنم
سلام سوالی برام پیش اومده که تو کامنت ها و دیتا شیت هم نتونستم پیدا کنم جوابش رو (البته ممکنه هم بی دقت خونده باشم). سوال این هست که برای ساعت این ماژول (نه پروتکول I2C) نیازی به کلاک خارجی (کریستال های 32 کیلو) وجود داره یا نه؟! اگه کریستال داخلی داره آیا به اندازه کافی دقیق هست و اگر نیست تا چه حد خطا ایجاد میکنه؟!
سلام دوست عزیزم
نه نیازی به گذاشتن کریستال ندارید چون خود این ماژول دارای یک کریستال داخلی است که به شدت دقیقه و از لحاظ دقت بسیار تایید شده است که توصیه میکنم برای درک بیشتر دقت این ماژول
در یوتیوب ds3231 vs ds1307 رو سرچ کنید تا قدرت این ایسی رو ببینید. لازم بذکره که بگم DS1307 مدل قدیمی تر همین ماژوله که دقت کمتری رو هم داره.
اما تا جایی که بنده اطلاع دارم و گفتن اینکه این ایسی در سال در حد چند ثانیه بیشتر تاخیر نداره که البته چون تست نکردم مطمن نیستم.
سلام! تشکر بسیار از پاسخگوییتون!
سلام
ماژول جالب و کاربردی ای معرفی کردید…
ممنون .
سلام دوست عزیزم
بسیار خوشحال شدم که مطلب برای شما مفید واقع شده بود.
موفق باشید.