نحوه راه اندازی گوشی های هوشمند و رایانه های شخصی. پرتال اطلاعاتی
  • خانه
  • در تماس با
  • پروژه های ایستگاه هواشناسی مینی آردوینو پرو. ماژول سنسور فشار بارومتری BMP085 برای آردوینو (یا نحوه ساخت ایستگاه هواشناسی با دستان خود)

پروژه های ایستگاه هواشناسی مینی آردوینو پرو. ماژول سنسور فشار بارومتری BMP085 برای آردوینو (یا نحوه ساخت ایستگاه هواشناسی با دستان خود)

مانند بسیاری از افراد شاغل، پیگیری پروژه های خود تنها زمان آزاد باقیمانده شما را می گیرد. به همین دلیل است که من مدت زیادی است که چیزی خلق نکرده‌ام و دلم می‌خواهد کاری انجام دهم. این فرصتبه طرز عجیبی در دانشگاه ظاهر شد. سپتامبر خارج از پنجره، سال چهارم و یک دوره آموزشی آینده در زمینه طراحی مدار است. به ما گفته شد که کار درسی را می توان در دو نوع انجام داد: کاغذ و سخت افزار.

به مدت 5 سال، دروس کاغذی در دانشگاه ما بر اساس اصل "قدیمی ها را بگیرید و کنار هم بگذارید" انجام می شد. این رویکرد به دلیل روتین بودنش برای من مناسب نبود، بنابراین بلافاصله دروس سخت افزاری را انتخاب کردم. همانطور که قلب درس پیشنهاد شد میکروکنترلر آردوینوبه دلیل سهولت یادگیری آن پس از تعیین نوع دوره، یک سوال دیگر باقی ماند: دقیقاً چه کاری باید انجام شود. از آنجایی که من هیچ تجربه ای در برنامه نویسی میکروکنترلرها نداشتم، بلافاصله گوگل را باز کردم و شروع به مطالعه پروژه های موجود کردم. پروژه های زیادی وجود دارد، برخی از آنها بسیار ساده هستند، برخی مبتکرانه هستند (مثلاً اسکنر سه بعدی)، اما اکثریت قریب به اتفاق هیچ کاربرد عملی. و من فقط چیزی می خواستم که روی قفسه قرار نگیرد و گرد و غبار را جمع نکند. پس از نیم ساعت گشت و گذار در دنیای آردوینو، به موضوع ایستگاه های هواشناسی خانگی علاقه مند شدم و اجرای پروژه ها چندان دشوار به نظر نمی رسید (که عمدتاً تازه واردها را جذب می کرد).

به این ترتیب موضوع درس انتخاب شد و با گذشت زمان به نظر می رسید هیچ مشکلی وجود نداشته باشد.

انتخاب جزء

با نگاهی به پروژه های مختلف، متوجه شدم که نانو یا حتی Pro Mini، اما همچنان Arduino Uno را انتخاب کردم به این امید که برنامه نویسی برای آردوینو را دوست داشته باشم و در آینده پروژه های بیشتری را اجرا کنم. من قبلاً هرگز آهن لحیم کاری در دستانم نگرفته بودم، بنابراین برای توسعه آسان تر تصمیم گرفتم Sensor Shield v4 را نیز خریداری کنم.

جزئیات بیشتر

هزینه کمک می کند اتصال سریعسنسورها، ماژول‌ها، موتورهای سروو، رابط‌های سریال و I2C و همچنین تمام پورت‌های کنترل‌کننده فرم فاکتور Duemilanova/Uno را نمایش می‌دهد (همچنین می‌توان به سری مگا متصل شد، اما با محدودیت‌ها و پیامدهای متعاقب آن). از سپرهای دیگر در بالای خود پشتیبانی می کند.


من حسگرهای زیر را به عنوان منابع داده های هواشناسی انتخاب کردم:


من در مورد سنسورها تصمیم گرفته ام. اما با داده های دریافتی از سنسورها چه باید کرد؟ تصمیم گرفتم نمایشش بدم من یک عکس رنگی می خواستم، بنابراین بلافاصله راه حل های تک رنگ را دور انداختم. پس از چند دقیقه جستجو، صفحه نمایش TFT 1.8 اینچی ST7735 انتخاب شد.

جزئیات بیشتر

از آنجایی که نمایشگر از یک پروتکل 4 سیم SPI برای ارتباط استفاده می کند و دارای فریم بافر قابل آدرس دهی پیکسلی خاص خود است، می توان از آن با هر نوع میکروکنترلر استفاده کرد. صفحه نمایش 1.8 اینچی دارای پیکسل های رنگی 128x160 است. یک جای کارت نیز وجود دارد حافظه microSDبنابراین به راحتی می توانید تمام رنگی را دانلود کنید تصاویر شطرنجیاز FAT16/FAT32 سیستم فایلکارت های microSD

مشخصات:

  • صفحه نمایش مورب - 1.8 اینچ، وضوح 128x160 پیکسل، رنگ 18 بیتی (262144 رنگ)
  • کنترل‌کننده با آدرس‌دهی پیکسلی داخلی بافر حافظه ویدیویی
  • اسلات microSD داخلی - از بیش از 2 خط دیجیتال استفاده می کند
  • سازگار با ولتاژ 3.3 و 5 ولت
  • ابعاد: 34 میلی متر × 56 میلی متر × 6.5 متر


برنامه نویسی کنترلر آردوینو

بعد از اینکه در مورد اجزای ایستگاه هواشناسی تصمیم گرفتیم، برنامه نویسی کنترلر را شروع می کنیم. محیط مورد استفاده برای سیستم عامل آردوینو توسعه آردوینو IDE. همچنین از کتابخانه های Adafruit استفاده شده است.

قبل از رفتن به طرح، اجازه دهید به عملکرد نگاه کنیم:

  • هر 10 ثانیه از سنسورها قرائت می شود و فقط آن شاخص هایی که نسبت به اندازه گیری قبلی تغییر کرده اند روی صفحه نمایش به روز می شوند.
  • انتقال داده ها از طریق پورت COM انجام شده است

طرح

#عبارتند از // کتابخانه برای ارتباط با دستگاه های I2C #شامل // کتابخانه هسته برای همه حسگرها #شامل // کتابخانه برای BMP180 #include // کتابخانه هسته گرافیکی #شامل // کتابخانه مخصوص سخت افزار #include // کتابخانه برای ارتباط با دستگاه‌های SPI #شامل "dht.h" // کتابخانه برای DHT #تعریف DHT22_PIN 2 // پین داده DHT22 را به دو پایه دیجیتال متصل کنید #define TFT_CS 10 // وصل کنید پین CS TFT را به 10 پین دیجیتال #define TFT_RST 9 // اتصال پین RST TFT به 9 پین دیجیتال // می توانید این را به ریست آردوینو هم وصل کنید // در این صورت این پین #define را روی 0 قرار دهید! #define TFT_DC 8 // اتصال پین DC TFT به 8 پایه دیجیتال Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); //initialize TFT #define TFT_SCLK 13 // اتصال پین SCLK TFT به 13 پایه دیجیتال #define TFT_MOSI 11 // وصل کردن پین MOSI TFT به 11 پایه دیجیتال dht DHT. Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); //initialize BMP180 int bmpFlag = 0; struct ( uint32_t total; uint32_t ok; uint32_t crc_error; uint32_t time_out; uint32_t connect; uint32_t ack_l; uint32_t ack_h؛ uint32_t ناشناخته؛ ) stat = (0,0,0,0,0,0); // ساختار برای وضعیت dht void setup(void) (Serial.begin(9600); Serial.println("Meteo Test"); Serial.println(""); if(!bmp.begin()) // بررسی اتصال برای BMP180 ( Serial.print("اوه، هیچ BMP180 شناسایی نشد... سیم کشی یا I2C ADDR خود را بررسی کنید!"); bmpFlag = 1; ) tft.initR(INITR_BLACKTAB)؛ // TFT را راه اندازی کنید و با رنگ مشکی tft.fillScreen پر کنید (ST7735_BLACK)؛ tft.setRotation(tft.getRotation() + 1؛ tft.setTextSize(1.5)؛ delay(500)؛ // تاخیر به منظور اطمینان از اینکه TFT اولیه شده است) // آخرین شناور داده اندازه گیری شده دمای قدیمی = 0 ، ارتفاع قدیمی = 0، فشار قدیمی = 0، رطوبت قدیمی DHTH = 0، دمای قدیمیDHTT; bool wasUpdate = false; void loop(void) ( if(Serial.available() > 0) // داده داریم پورت سریال است ( Serial.read(); // خواندن بایت از پورت سریال و ارسال آخرین داده اندازه گیری شده printValue("Pressure", oldPressure , "hPa"، false); printValue("Temperature"، OldTemperature، "C"، false); printValue("Altitude"، oldAltitude، "m"، false); printValue("رطوبت"، oldDHTHhumidity، "%"، false); printValue("DHT_temperature"، oldDHTTtemperature، "C"، false); Serial.println("END_TRANSMISSION"); ) sensors_event_t رویداد؛ دمای شناور، ارتفاع؛ if(bmpFlag == 0) (bmp.getEvent(&event) ; // دریافت داده از BMP180 if (event.pressure) (bmp.getTemperature(&demperature); float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA; altitude = bmp.pressureToAltitude(seaLevelPressure, event.pressure, temperature.Serl)nl خطا"); ) ) uint32_t start = micros(); int chk = DHT.read22(DHT22_PIN); // دریافت داده از DHT22 uint32_t stop = micros(); stat.total++؛ سوئیچ (chk) // بررسی وضعیت DHT22 ( مورد DHTLIB_OK: stat.ok++; زنگ تفريح؛ مورد DHTLIB_ERROR_CHECKSUM: stat.crc_error++; Serial.print("خطای جمع بررسی،\t"); زنگ تفريح؛ مورد DHTLIB_ERROR_TIMEOUT: stat.time_out++; Serial.print("Time out error,\t"); زنگ تفريح؛ مورد DHTLIB_ERROR_CONNECT: stat.connect++; Serial.print("خطای اتصال،\t"); زنگ تفريح؛ مورد DHTLIB_ERROR_ACK_L: stat.ack_l++; Serial.print("Ack Low error,\t"); زنگ تفريح؛ مورد DHTLIB_ERROR_ACK_H: stat.ack_h++; Serial.print("Ack High error,\t"); زنگ تفريح؛ پیش فرض: stat.unknown++; Serial.print("خطای ناشناخته،\t"); زنگ تفريح؛ ) if(bmpFlag ! = 0 || !event.pressure) // به روز رسانی داده ها (tft.fillRect(0, 30, 160, 6, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED)؛ printValue("ERROR BMP INITIALIZATION"، 0 , "" true); ) else ( if(event.pressure != oldPressure) (tft.fillRect(0, 30, 160, 7, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED) ; printValue("Pressure", event.pressure, "hPa", true); oldPressure = event.pressure; wasUpdate = true; ) if(temperature != oldTemperature) (tft.fillRect(0, 38, 160, 7, ST7735_BLACK tft.setCursor(0, 38); tft.setTextColor(ST7735_WHITE)؛ printValue("دما"، دما، "C"، true)؛ oldTemperature = دما؛ wasUpdate = true؛ ) if(ارتفاع != oldAltitude) ( tft.fillRect(0, 46, 160, 7, ST7735_BLACK)؛ tft.setCursor(0, 46)؛ tft.setTextColor(ST7735_BLUE)؛ printValue("ارتفاع"، ارتفاع، "m"، true)؛ oldAltitude = ارتفاع. wasUpdate = true; ) ) if(DHT.humidity != oldDHTHhumidity) ( tft.fillRect(0, 54, 160, 7, ST7735_BLACK); tft.setCursor(0, 54); tft.setTextColor(ST7735_GREEN); printValue("رطوبت"، DHT.humidity، "%"، true); oldDHTHhumidity = DHT.humidity; wasUpdate = true; ) if(DHT.temperature != oldDHTTtemperature) (tft.fillRect(0, 80, 160, 7, ST7735_BLACK); tft.setCursor(0, 80); tft.setTextColor(ST7735_YELLOW); printValue("DHT_temperature",DHT_te دما، "C"، true)؛ oldDHTTtemperature = DHT.temperature؛ wasUpdate = true؛ ) if(wasUpdate) (Serial.println("END_TRANSMISSION"); ) wasUpdate = false; تاخیر (10000); ) void printValue(char* عنوان، مقدار دو برابر، char* اندازه گیری، bool tftPrint) ( if(tftPrint) // چاپ داده ها به TFT (tft.print(title); tft.print(": "); tft.print( مقدار؛ tft.println(measure); ) Serial.print (عنوان)؛ // ارسال داده به پورت سریال Serial.print(": "); Serial.print(value); Serial.println(measure); )

زمان مونتاژ بدنه است

شرط اصلی دوره یک نمونه اولیه کار به شکل قابل ارائه بود. بنابراین، مجبور شدم مسکن بخرم و با یک پرونده، ایستگاه هواشناسی را به هر طریقی وارد مسکن کنم.

کیس از یک فروشگاه لوازم الکترونیکی رادیویی محلی خریداری شده است.

قاب

(مورد در عکس کمی متفاوت است. من درب شفاف دارم)



سپس با استفاده از یک فایل، سوراخ هایی برای خروجی سنسورها و تامین برق ایجاد شد. تصمیم گرفتم سنسورها را به بیرون منتقل کنم، زیرا در حین تست سیستم بدون کیس، متوجه شدم که پشت صفحه بسیار داغ شده است که بر دمای داخل کیس تأثیر می گذارد.

مسکن با دهانه برای سنسور و قدرت



از آنجایی که مجبور شدم پاها را به 2 سنسور لحیم کنم و مسیر را روی یکی از آنها سوزاندم، تصمیم گرفتم سرنوشت را وسوسه نکنم و سیم ها را به سنسورها لحیم نکنم (روی چیز دیگری تمرین خواهم کرد) و برای اتصال برای اینکه کم و بیش قابل اعتماد باشم، تصمیم گرفتم نوار برق را به عقب برگردانم.

سیستم قبل از "پر کردن" در مسکن



از آنجایی که کیس بسیار بزرگتر از آردوینو است (کوچکتر از آن وجود نداشت)، مجبور شدم یک ساپورت بیاورم تا برد داخل کیس حرکت نکند. همچنین یک فیگور از فوم بریده شده بود و در آن یک مستطیل برای صفحه نمایش تعبیه شده بود تا قسمت های داخلی قاب پنهان شود. من سوپرچسب در دست نداشتم، بنابراین مجبور شدم از نوار دو طرفه استفاده کنم.

معجزه-یودا ماهی-نهنگ



درب را ببندید، برق را وصل کنید و منتظر بمانید.

ایستگاه هواشناسی تکمیل شده در ساختمان



پس از نمایش نتایج روی صفحه، یک خطای ناخوشایند را در اندازه گیری رطوبت شناسایی می کنیم: DHT22 با پشتکار رقم 99.90٪ را تولید می کند (1.00٪ بسیار نادر است). بیایید شروع کنیم تا بفهمیم مشکل چیست. اولین کاری که انجام می دهیم این است که به خروجی مقادیر پورت COM نگاه کنیم. حس خوبی داره پس از چندین بار پر کردن، جداسازی و مونتاژ مجدد کیس، این ایده به ذهن خطور می کند که به دنبال پاسخ در گوگل بگردید. همانطور که انتظار می رفت، گوگل روسی چیز مفیدی نگفته است. خوب. ما شروع به جستجو به زبان انگلیسی می کنیم و در یکی از انجمن ها با بچه هایی روبرو می شویم که مشکل مشابهی دارند. چهار صفحه اول بحث هیچ چیز مفیدی به دست نمی دهد، اما در صفحه پنجم پاسخ سوال خود را می یابیم:
سنسورهای رطوبت به راحتی می توانند تحت تأثیر گازهای اشتباه یا قرار گرفتن طولانی مدت در معرض رطوبت بالا IIRC قرار بگیرند. در برگه اطلاعات روشی وجود دارد که چگونه حسگر را "تنظیم مجدد" کنید، می توانید آن را امتحان کنید.

تنها سوالی که باقی ماند این بود که چه زمانی و چگونه توانستم به DHT22 آسیب بزنم. اما زمان گذراندن دوره نزدیک شده بود و بنابراین حل این مشکل را برای بعد گذاشتم.

پس گفتار

دوره گذرانده شد. ایستگاه هواشناسی به مدت نامعلومی به تعویق افتاد تا تمام باطله های دانشگاه بسته شود. با این حال، مجبور شدیم زودتر از آنچه فکر می کردم به ایستگاه هواشناسی برگردیم. این اتفاق افتاد که در اواسط نوامبر محل کارم را تغییر دادم و در تیم جدید با افرادی آشنا شدم که به پلتفرم آردوینو و مانند آن علاقه مند هستند. بنابراین، علاقه من به این پلت فرم، بدون اینکه فرصتی برای خنک شدن داشته باشم، دوباره شعله ور شد. ایستگاه هواشناسی خود را بیرون آوردم، آن را به کامپیوتر وصل کردم و به یاد آوردم که انتقال داده را از آردوینو از طریق پورت COM پیاده سازی کرده ام. و سپس این ایده به ذهنم رسید که برنامه ای بنویسم که داده ها را از طریق پورت COM از آردوینو دریافت می کند و این داده ها را به نظارت عمومی منتقل می کند.
  • آردوینو
  • افزودن برچسب

    ما به توسعه ایستگاه هواشناسی خود ادامه می دهیم.

    قبل از اینکه به بروزرسانی بپردازیم، می خواهم کمی توضیح بدهم.

    یکی از همکاران ما به من نامه نوشت که چرا تایمر نگهبان معرفی شد؟

    تایمر نگهبان در مواقع اضطراری در محل قرار دارد. همانطور که تمرین نشان می دهد، ENC28J60 بیشتر دوام نمی آورد (اگر حافظه خراب نشود) 4 اتصالات همزمان. با در نظر گرفتن تعداد اتصالات سرویس به طور مداوم برای حفظ عملکرد خود شبکه، و ترافیک ایجاد شده توسط انواع اسباب بازی های خانگی (به عنوان مثال، تلویزیون های مدرن، هاست های موجود در شبکه و پورت های باز آنها را اسکن کنید) طراحی به سادگی در حالت گیجی قرار می گیرد. ENC28J60 نمی تواند به طور مستقل با آن کار کند پروتکل های شبکهو همه چیز در کتابخانه ها اجرا می شود. شاید فقط آنها باشند.
    تمام کتابخانه های موجود را بررسی کرد و ماژول های مختلف(ازدواج ناگهانی)، اما برای رسیدن عملکرد پایدارخیلی وقت بود که نمی توانستم این کار را انجام دهم. حداکثر مدتحدود 3-4 هفته بود
    به همین دلیل است که "سگ" آنجا می چرخد ​​و اگر اتفاقی بیفتد، کنترلر را می کشد. بعد از این مشکل برطرف شد.
    من همچنین انکار نمی کنم که ممکن است تفاوت های ظریف یا مشکلات خاصی در شبکه خانگی من وجود داشته باشد. اما از آنجایی که من مشکلی داشتم، ممکن است شخص دیگری نیز آن را داشته باشد. تا الان فقط این راه حل را پیدا کردم.
    تا آنجا که من می دانم، تراشه های Wiznet (W5100 و بالاتر) این را ندارند یا به اندازه کافی خوب به نظر نمی رسند.

    بیایید به سمت به روز رسانی حرکت کنیم

    مهمتر از همه، ما در حال دور شدن از تراشه هستیم ENC28J60و برو به W5100. من سعی کردم همه چیز را روی تراشه قدیمی پیاده‌سازی کنم، اما به دلیل کتابخانه‌های بسیار بزرگ، حافظه میکروکنترلر کافی وجود ندارد ENC28J60. هنگام استفاده از یک تراشه جدید، استانداردکتابخانه ها از توسعه دهنده و تمام تغییرات ایجاد شده، حتی بیشتر باقی مانده است 20% حافظه خالیمیکروکنترلر ATMega328. و این ها نان های جدید هستند!

    در این نسخه (بیایید آن را دومی بنامیم) توانایی انتقال قرائت از حسگرها از طریق ارتباطات بی سیمبا استفاده از فرکانس 433 مگاهرتز. من خود ماژول ها را از چینی ها، علامت گذاری گرفتم XY-MK-5V. من می خواهم توجه داشته باشم که کیفیت انتقال بسیار عالی است. از دست دادن احتمالی سیگنال، نویز، عدم توانایی در انتقال همزمان و غیره و غیره. اما قیمت آنها (کمتر از 1 دلار در هر مجموعه) این کاستی ها را جبران می کند. من رازی را به شما می گویم که این (ارزان ترین) ماژول ها در بسیاری از ایستگاه های هواشناسی مارک دار یافت می شوند استفاده خانگی. وای، غیر منتظره؟

    بیایید با ایستگاه پایه شروع کنیم

    ما در حال حرکت به سمت آردوینو UNOو سپر اترنت(نسخه اول) بر اساس تراشه W5100. این یک ساندویچ است و هیچ فایده ای برای توصیف آن ندارد. من فقط مخاطبین اضافی مربوط به ماژول ها را شرح خواهم داد XY-MK-5V.

    ماژول فرستنده از برق استفاده می کند 5 ولت, GND(بدون مادر کجا بودیم) و D2سنجاق روی کنترلر ویرایش مخاطب D2 (DATA)می توانید از تابع استفاده کنید vw_set_tx_pinاز کتابخانه vw.

    برخلاف طرح قبلی، این طرح شامل دو طرح است کتابخانه های اضافی:

    #عبارتند از #عبارتند از

    خود طرح

    متن پنهان

    #عبارتند از #عبارتند از #عبارتند از #عبارتند از #عبارتند از #عبارتند از #عبارتند از #عبارتند از #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht(DHTPIN, DHTTYPE); بایت مک = (0x54، 0x34، 0x31، 0x31، 0x31، 0x31)؛ سرور char = "narodmon.ru"; پورت int = 8283; IPaddress ip(192,168,0,201); مشتری EthernetClient؛ BMP085 dps = BMP085(); درجه حرارت طولانی = 0، فشار = 0; شناور H، dP، dPt. فاصله bool = درست; EasyTransferVirtualWire ET. struct SEND_DATA_STRUCTURE( شناسه بایت؛ // شناسه دستگاه int دما؛ // فشار شناور دما؛ // رطوبت شناور فشار؛ // رطوبت شناور نقطه شبنم؛ // شبنم/نقطه یخ زدگی); پخش SEND_DATA_STRUCTURE. void setup() (// راه اندازی تایمر Watchdog wdt_disable(); delay(8000)؛ wdt_enable(WDTO_8S)؛ // راه اندازی کنسول Serial.begin(9600)؛ // راه اندازی سنسور DHT dht.begin();/ / راه اندازی ماژول 433 مگاهرتز ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_tx_pin(2); vw_setup(2000)؛ // شبکه را راه اندازی کنید، اگر منتظر داده های سرور DHCP نبوده ایم، سپس // به خودمان یک آدرس اختصاص دهیم اگر (Ethernet.begin(mac) == 0) Ethernet.begin(mac, ip); // Initializing 1-Wire Wire.begin(); delay(200)؛ // Initializing BMP180 با تنظیم ارتفاع // dps.init (MODE_STANDARD، 3200، درست)؛ // راه اندازی BMP180 dps.init(); Serial.println(Ethernet.localIP())؛ // ارسال اولین داده بلافاصله پس از روشن کردن دستگاه send_info (درست) ) // تابع نقطه شبنم NOAA / / مرجع (1): http://wahiduddin.net/calc/density_algorithms.htm // مرجع (2): http://www.colorado.edu/geography/weather_station /Geog_site/about.htm نقطه شبنم دو برابر (دوبرابر سانتیگراد، رطوبت دو برابر) ( // (1) فشار بخار اشباع = ESGG(T) دو برابر نسبت = 373.15 / (273.15 + سلسیوس); دو برابر RHS = -7.90298 * (نسبت - 1)؛ RHS += 5.02808 * log10 (نسبت)؛ RHS += -1.3816e-7 * (Pow(10, (11.344 * (1 - 1/RATIO))) - 1) ; RHS += 8.1328e-3 * (Pow(10, (-3.49149 * (نسبت - 1))) - 1) ; RHS += log10(1013.246); // فاکتور -3 برای تنظیم واحدها است - فشار بخار SVP * رطوبت دو برابر VP = pow (10، RHS - 3) * رطوبت. // (2) DEWPOINT = F(فشار بخار) دو برابر T = log(VP/0.61078); // بازگشت موقت var (241.88 * T) / (17.558 - T); ) void send_info(bool eth) ( bool fail = true; while(fail) ( // سعی می کنیم داده ها را از حسگر رطوبت DHT بخوانیم تا زمانی که // نتیجه را بگیریم. در 90٪ موارد همه چیز خوب کار می کند، اما ما نیاز داریم 100% if((H = dht.readHumidity()) >= 0) ( // دریافت رطوبت و دما از حسگر BMP180 dps.getPressure(&Pressure); dps.getTemperature(&Temperature); // نقطه شبنم را محاسبه کنید اگر دمای خارج از 0 درجه سانتیگراد است // و انتظار نتیجه بالاتر از 0 را دارید، در غیر این صورت خروجی 0 است. این ضروری است // تا در فصل زمستان گمراه کننده نباشد. // dP = دما> 0؟((dPt=نقطه شبنم(دما*0.1، H))<0?0:dPt):0; dP = dewPoint(Temperature*0.1, H); // Отправляем данные в эфир 433 мГц broadcast.ID = 1; broadcast.Temperature = floor(Temperature*0.1); broadcast.Pressure = floor(Pressure/133.3*10)/10; broadcast.Humidity = floor(H*10)/10; broadcast.dewPoint = floor(dP*10)/10; ET.sendData(); delay(250); if(eth) { // Подключаемся к серверу "Народный мониторинг" if(client.connect(server, port)) { // Начинаем передачу данных // адрес_устройства_в_проекте, имя_устройства, GPS широта, GPS долгота client.print(F("#fe-31-31-0e-5a-3b#Arduino Uno#71.344699#27.200014\n")); // Температура client.print(F("#T0#")); client.print(Temperature*0.1); client.print(F("#Температура\n")); // Давление client.print("#P1#"); client.print(Pressure/133.3); client.print(F("#Давление\n")); // Влажность client.print("#H1#"); client.print(H); client.print(F("#Влажность\n")); // Точка росы\инея client.print("#T1#"); client.print(dP); client.print((dP <= 0)? F("#Точка инея\n"):F("#Точка росы\n")); //client.print(F("#Точка росы\n")); // Отправляем конец телеграммы client.print("##"); // Даем время отработать Ethernet модулю и разрываем соединение delay(250); client.stop(); } } // Останавливаем цикл, если передача завершена fail = !fail; break; } delay(250); } } void loop() { // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера // Каждые 6 минут отправляем данные на "Народный мониторинг" // Каждые 30 секунд отсылаем данные в эфир 433 if(!(millis()%1000)) wdt_reset(); if(!(millis()%360000)) send_info(true); if(!(millis()%30000)) send_info(false); }

    یک آنتن باید به خود ماژول ها اضافه شود. برای 433 مگاهرتزیک سیم مسی بلند معمولی کافی است 17 سانتی متر. بدون آنتن، می توانید عملکرد عادی را فراموش کنید.

    بیایید به مهمترین بخش این به روز رسانی - ایستگاه بی سیم محلی - برویم

    برای اجرای آن (روی زانو) از آنالوگ استفاده کردم آردوینو نانو(روی پایه ATMega328) و TFTنمایش بر روی یک تراشه ST7735Sبا اجازه 128*160

    متن پنهان



    صفحه نمایش پینوت -> کنترلر

    ============================= LED | 3.3 ولت SCK | SCK (13) SDA | MOSI(11)A0 | DC (9) RESET | RST(8)CS | CS (10) GND | GND VCC | 5 ولت ============================

    ماژول گیرنده فقط به همان روش فرستنده متصل می شود داده هاسنجاق کردن D7.

    چند عکس از شکل ظاهری آن:

    متن پنهان

    طرح گیرنده

    متن پنهان

    #عبارتند از #عبارتند از #عبارتند از #عبارتند از int x, y; int w = 128, h = 160; اندازه int; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( شناسه بایت؛ // شناسه دستگاه int دما؛ // فشار شناور دما؛ // رطوبت شناور فشار؛ // رطوبت شناور نقطه شبنم؛ // شبنم/نقطه یخ زدگی); پخش SEND_DATA_STRUCTURE. int Log_Temperature = -1; float Log_Pressure = -1; float Log_Humidity = -1; float Log_dewPoint = -1; // TFT #define cs 10 #define dc 9 #define rst 8 char دما، فشار، رطوبت، نقطه شبنم. اطلاعات رشته؛ TFT TFTscreen = TFT (cs، dc، rst)؛ void setup())( Serial.begin(9600); // راه اندازی ماژول 433 مگاهرتز ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_rx_pin(7); vw_setup(2000); vw_rx_st); // راه‌اندازی و تنظیم اولیه نمایشگر TFTscreen.begin(); TFTscreen.setRotation(2)؛ TFTscreen.background(0, 0, 0)؛ // ترسیم عناصر استاتیک // 1. از ما دیدن کنید TFTscreen.stroke(255, 255) ، 255)؛ TFTscreen.setTextSize(1)؛ TFTscreen.text(" "، 10، 10)؛ // 2. شرح قرائت از حسگرهای TFTscreen.text("mmHg"، w/2+5، 80)؛ TFTscreen .text ("%"، w/2+5، 100)؛ TFTscreen.text("C"، w/2+5، 120)؛ پخش. دما = 0؛ پخش. فشار = 0؛ پخش. رطوبت = 0 پخش .dewPoint = 0؛ TFTPrint(); ) void loop())( if(ET.receiveData())( if(broadcast.ID == 1) TFTPrint(); /* Serial.println(broadcast.Temperature) ؛ سریال. println(پخش. فشار؛ سریال.println(پخش. رطوبت؛ سریال.println(broadcast.dewPoint)؛ سریال.println(); */) ) تغییرات خالی (int size, int x, int y, bool up, bool clear = false) ( if(clear) TFTscreen.stroke(0, 0, 0); else ( تغییرات(اندازه، x، y، !بالا، درست)؛ TFTscreen.stroke((بالا)?0:255، 0، (بالا)؟255:0؛ ) if((اندازه%2) == 0 ) اندازه ++; while(size > 0) ( TFTscreen.line(x, y, x+(size--), y); ++x, (up)?--y:++y, --size; ) /* while( اندازه > 0) ( TFTscreen.line(x, y, (بالا)?x+size-1:x, (بالا)?y:y+size-1); ++x, ++y, --size; ) */ ) int x_center(int w, int طول, int size) ( کف برگشتی ((w-length*(size*5)+size*2)/2); ) int x_alignment_right(int w, int length, int اندازه) (ceil return(w-length*(size*5)+size*2); ) void TFTPrint() (اندازه = 3; // ================ ================================================== === =============== // نمایش قرائت دما // ======================== ================================================================================ اگر (پخش. دما != Log_Temperature) ( TFTscreen.setTextSize(اندازه)؛ // بازنویسی داده های منسوخ شده String info = String(Log_Temperature); info.concat("C"); if(Log_Temperature > 0) info = "+"+info; info .toCharArray(Temperature, info.length()+1)؛ TFTscreen.stroke(0, 0, 0); TFTscreen.text(Temperature, x_center(w, info.length()+1 , size), 35); / / نمایش اطلاعات قرائت جدید = رشته (پخش شده. درجه حرارت)؛ info.concat ("C"); if(broadcast.Temperature > 0) info = "+"+info; info.toCharArray(دما، info.length()+1); // تغییر رنگ مقدار دما بسته به خود دما int r, g = 0, b; if(broadcast.temperature > 0) (r = map(broadcast.temperature, 0, 40, 255, 150); // قرمز b = map(broadcast.temperature, 0, 40, 30, 0); // تغییر رنگ برای انتقال بصری بیشتر از صفر ) else (r = نقشه (پخش. دما، -40، 0، 0، 30)؛ // تغییر رنگ برای انتقال بصری بیشتر از صفر b = نقشه (پخش. دما، - 40، 0، 150، 255)؛ // آبی ) TFTscreen.stroke(b، g، r); // توجه: موقعیت های رنگ در کتابخانه با هم مخلوط شده اند، مکان RGB توسط BGR استفاده می شود! TFTscreen.text(دما، x_center(w، info.length()+1، اندازه)، 35); ) اندازه = 1; // ================================================ ==== ====================================// قرائت فشار خروجی // === ================================================== ========= =============================== if(broadcast.Pressure != Log_Pressure) (TFTscreen.setTextSize(size); / / رونویسی اطلاعات منسوخ شده = String (Log_Pressure)؛ info.toCharArray (Pressure, info.length()؛ TFTscreen.stroke(0, 0, 0)؛ TFTscreen.text(Pressure, x_alignment_right(w/2-5, info .length()، اندازه)، 80)؛ // خروجی اطلاعات قرائت جدید = String(broadcast.Pressure); info.toCharArray(Pressure, info.length()); TFTscreen.stroke(255, 255, 255)؛ TFTscreen .text(Pressure, x_alignment_right (w/ 2-5, info.length(, size), 80); changes(10, 106, 85, (broadcast.Pressure > Log_Pressure)?true:false); ) else (تغییرات (10، 106، 85، درست، درست)؛ تغییرات (10، 106، 85، نادرست، درست)؛ ) // ====================== ================================================== =========== = // قرائت رطوبت خروجی // =============================== ================================================== ================== if(broadcast.Humidity != Log_Humidity) ( TFTscreen.setTextSize(size); // بازنویسی اطلاعات منسوخ شده = String(Log_Humidity); info.toCharArray(رطوبت، info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(رطوبت، x_alignment_right(w/2-5، info.length()، اندازه)، 100); // نمایش اطلاعات قرائت جدید = String(broadcast.Humidity); info.toCharArray(رطوبت، info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(رطوبت، x_alignment_right(w/2-5، info.length()، اندازه)، 100); تغییرات(10, 106, 105, (پخش. رطوبت > ورود_رطوبت)؟درست:نادرست); ) else ( تغییرات (10، 106، 105، درست، درست)؛ تغییرات (10، 106، 105، نادرست، درست)؛ ) // ================== ================================================== === ==============// خروجی خوانش نقطه شبنم/نقطه یخبندان // ===================== ================================================== if(broadcast.dewPoint ! = Log_dewPoint) ( TFTscreen.setTextSize(اندازه)؛ // بازنویسی اطلاعات منسوخ شده = String(Log_dewPoint)؛ info.toCharArray(dewPoint, info.length()؛ TFTscreen.stroke(0, 0, 0)؛ TFTscreen.text (dewPoint، x_alignment_right(w/2-5، info.length()، اندازه)، 120؛ // خروجی اطلاعات قرائت جدید = String(broadcast.dewPoint); info.toCharArray(dewPoint، info.length()); TFTscreen.stroke(255، 255، 255); TFTscreen.text(dewPoint، x_alignment_right(w/2-5، info.length()، اندازه)، 120); تغییرات(10، 106، 125، (broadcast.dewPoint > Log_dewPoint)?true:false);) else ( تغییرات(10، 106، 125، درست، درست)؛ تغییرات (10، 106، 125، نادرست، درست)؛ ) // مقادیر موجود در گزارش ها را برای موارد بعدی به روز کنید مقایسه خوانش Log_Temperature = پخش. دما; Log_Pressure = پخش. فشار; Log_Humidity = پخش.رطوبت; Log_dewPoint = broadcast.dewPoint; )

    قرائت ها کاملاً فشرده نمایش داده می شوند ، اما همانطور که تمرین نشان می دهد (و توصیه رفقای من) - "طعم و رنگ ، حتی همسر هم دوست نیست." به توصیه ها و پیشنهادات زیادی گوش دادم، اما با هم تناقض دارند. بنابراین، آن را به سلیقه خود انجام دهید.

    به نظر من طراحی بخشی از پروژه است که بیشتر زمان را به خود اختصاص می دهد!

    متن پنهان

    برخی از داده ها برای انعکاس برخی از عناصر طراحی ساخته شده اند.

    مصنوعات روی نمایشگر گرد و غبار و کثیفی های دیگری هستند که در طول مدت زمانی که نمایشگر در آن قرار داشت جمع شده اند ... یک جایی، ... خوب، آن جا، یادم نمی آید آن را از کجا آورده ام! بزار تو حال خودم باشم!

    طرح دارای عملکردهای موقعیت یابی است. آنها کاملاً ابتدایی هستند، اما به شما اجازه می دهند تا به اثرات خاصی برسید.

    1. x_center
    2. x_alignment_right

    اولی متن را در مرکز قرار می دهد و دومی آن را در سمت راست منطقه مشخص شده تراز می کند. تمام محاسبات نسبت به ابعاد انجام می شود متن داده شده، بر اساس بیان 1 سایز = 1PX x 1PXبخش فونت

    صفحه نمایش همچنین عناصر مربوط به افزایش یا کاهش در یک مقدار خواندن خاص را نشان می دهد. آنها به شکل مثلث نمایش داده می شوند. اما در کد تابع تغییر می کندیک صفحه نمایش جایگزین به شکل مثلث هایی وجود دارد که 45 درجه می چرخند. اگر خوانش ها افزایش یابد، عنصر قرمز و در غیر این صورت آبی است.

    به هر حال، رنگ و سایه دمای اصلی بسته به خود دما تغییر می کند. یک تصمیم کاملا بحث برانگیز، اما به نظر من، از نظر بصری راحت است. مدتی با آن مبارزه کردم و متوجه شدم که مقادیر در تابع وجود دارد سکته، هدف - شی صفحه نمایش TFT، به ترتیب اشتباه فهرست شده اند. BGRمحل RGB. این یک خطای توسعه دهنده است یا من چیزی را متوجه نمی شوم.

    PS: همه چیز بسیار جالب است، اما به نظر من شایسته است پیشرفتهای بعدی. این کاری است که ما بعد از مدتی انجام خواهیم داد.

    یک روز در حالی که در شهر قدم می زدم، یک فروشگاه الکترونیکی رادیویی جدید دیدم که باز شده بود. وقتی واردش شدم پیدا کردم تعداد زیادی ازشیلد برای آردوینو چون من یک آردوینو Uno و یک آردوینو نانو در خانه داشتم و بلافاصله ایده بازی با فرستنده های سیگنال از راه دور به ذهنم رسید. تصمیم گرفتم ارزان ترین فرستنده و گیرنده را با فرکانس 433 مگاهرتز بخرم:

    فرستنده سیگنال.


    گیرنده سیگنال

    پس از ثبت یک طرح انتقال داده ساده (نمونه ای از اینجا گرفته شده)، مشخص شد که دستگاه های انتقال ممکن است برای انتقال داده های ساده مانند دما، رطوبت کاملاً مناسب باشند.

    فرستنده دارای مشخصات زیر است:
    1. مدل: MX-FS - 03V
    2. برد (بسته به وجود اشیاء مسدود کننده): 20-200 متر
    3. ولتاژ کاری: 3.5 -12 ولت
    4. ابعاد ماژول: 19 * 19 میلی متر
    5. مدولاسیون سیگنال: AM
    6. قدرت فرستنده: 10mW
    7. فرکانس: 433 مگاهرتز
    8. طول آنتن خارجی مورد نیاز: 25 سانتی متر
    9. اتصال آسان (فقط سه سیم): DATA ; VCC ; زمین.

    ویژگی های ماژول دریافت:
    1. ولتاژ کاری: DC 5V
    2. جریان: 4 میلی آمپر
    3. فرکانس کاری: 433.92 مگاهرتز
    4. حساسیت: - 105dB
    5. ابعاد ماژول: 30 * 14 * 7 میلی متر
    6. ضروری آنتن خارجی: 32 سانتی متر

    اینترنت می گوید که محدوده انتقال اطلاعات با سرعت 2 کیلوبایت در ثانیه می تواند تا 150 متر برسد. من خودم آن را بررسی نکردم، اما در یک آپارتمان دو اتاقه همه جا پذیرفته می شود.

    سخت افزار ایستگاه هواشناسی خانگی

    پس از چندین آزمایش، تصمیم گرفتم یک سنسور دما، رطوبت و فرستنده را به آردوینو نانو وصل کنم.


    سنسور دمای DS18D20 به صورت زیر به آردوینو متصل می شود:

    1) GND به منهای میکروکنترلر.
    2) DQ از طریق یک مقاومت کششی به زمین و پین D2 آردوینو
    3) Vdd به +5V.

    ماژول فرستنده MX-FS - 03V با ولتاژ 5 ولت تغذیه می شود، خروجی داده (ADATA) به پایه D13 متصل می شود.

    به Arduino Uno متصل است صفحه نمایش ال سی دیو فشارسنج BMP085.


    نمودار اتصال به آردوینو Uno

    گیرنده سیگنال به پایه D10 متصل است.

    ماژول BMP085 - سنسور دیجیتال فشار جو. این سنسور به شما امکان می دهد دما، فشار و ارتفاع از سطح دریا را اندازه گیری کنید. رابط اتصال: I2C. ولتاژ تغذیه سنسور 1.8-3.6 V

    این ماژول به همان روشی که سایر دستگاه های I2C به آردوینو متصل می شود:

    • VCC - VCC (3.3 V);
    • GND - GND;
    • SCL - به پین ​​آنالوگ 5؛
    • SDA - به پین ​​آنالوگ 4.
    • خیلی کم هزینه
    • برق و I/O 3-5 ولت
    • تعیین رطوبت 20-80 درصد با دقت 5 درصد
    • تشخیص دما 0-50 درجه با دقت 2 درصد
    • فرکانس نظرسنجی بیش از 1 هرتز (نه بیشتر از یک بار در هر 1 ثانیه)
    • ابعاد 15.5mm x 12mm x 5.5mm
    • 4 پین با فاصله پین ​​0.1 اینچی

    DHT دارای 4 پین است:

    1. Vcc (منبع تغذیه 3-5 ولت)
    2. خروجی داده - خروجی داده
    3. استفاده نشده
    4. عمومی

    به D8 آردوینو متصل می شود.

    بخش نرم افزاری ایستگاه هواشناسی خانگی

    ماژول فرستنده هر 10 دقیقه دما را اندازه گیری و انتقال می دهد.

    در زیر برنامه آمده است:

    /* Sketch version 1.0 دما را هر 10 دقیقه ارسال کنید. */ #include #include #include #define ONE_WIRE_BUS 2 //Pin for connecting the Dallas OneWire sensor oneWire(ONE_WIRE_BUS); سنسورهای دمای دالاس (&oneWire)؛ آدرس دستگاه درون دماسنج. void setup(void) (//Serial.begin(9600); vw_set_ptt_inverted(true)؛ // لازم برای DR3100 vw_setup(2000)؛ // تنظیم نرخ باود (bit/s) sensors.begin(); if (! sensors.getAddress(insideThermometer, 0))؛ printAddress(insideThermometer); sensors.setResolution(insideThermometer, 9)؛ ) void printTemperature(DeviceAddress deviceAddress) (float tempC = sensors.getTempC(deviceAddress); C : ")؛ //Serial.println(tempC)؛ //تشکیل داده برای ارسال عدد int = tempC؛ نماد کاراکتر = "c"؛ //نماد سرویس برای تعیین اینکه این یک حسگر است String strMsg = "z" strMsg += نماد؛ strMsg += " "؛ strMsg += شماره؛ strMsg += " "؛ char msg; strMsg.toCharArray(msg, 255); vw_send((uint8_t *)msg, strlen(msg))؛ vx_wait_ (); / / صبر کنید تا انتقال کامل شود تاخیر(200)؛ ) void loop(void) ( for (int j=0; j<= 6; j++) { sensors.requestTemperatures(); printTemperature(insideThermometer); delay(600000); } } //Определение адреса void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress[i] < 16); //Serial.print("0"); //Serial.print(deviceAddress[i], HEX); } }

    دستگاه دریافت کننده داده ها را دریافت می کند، فشار و دمای اتاق را اندازه گیری می کند و آن را به نمایشگر ارسال می کند.

    #include #include LiquidCrystal lcd(12, 10, 5, 4, 3, 2); #شامل سنسور dht11؛ #define DHT11PIN 8 #include #include BMP085 dps = BMP085(); دما طولانی = 0، فشار = 0، ارتفاع = 0. void setup() (Serial.begin(9600); vw_set_ptt_inverted(true); // برای DR3100 ضروری است vw_setup(2000)؛ // تنظیم سرعت دریافت vw_rx_start(); // شروع نظارت بر پخش lcd.begin(16,2) ؛ Wire.begin(); delay(1000); dps.init(); //lcd.setCursor(14,0); //lcd.write(byte(0)); //lcd.home();) void loop() (uint8_t buf; // بافر برای پیام uint8_t buflen = VW_MAX_MESSAGE_LEN؛ // طول بافر if (vw_get_message(buf, &buflen)) // اگر پیام دریافت شد ( // شروع تجزیه int i; // اگر پیام خطاب به ما نیست، اگر (buf != "z") (return; ) char command = buf; // فرمان در شاخص 2 است خارج شوید // پارامتر عددی از شاخص 4 شروع می شود i = 4؛ عدد int = 0؛ // از آنجایی که انتقال کاراکتر به کاراکتر است، پس باید مجموعه کاراکتر را به عدد تبدیل کنید while (buf[i] != "") (شماره *= 10؛ عدد += buf[i] - "0"; i++; ) dps.getPressure(&Pressure)؛ dps.getAltitude (&Altitude); dps.getTemperature(&Temperature); //Serial.print(command); Serial.print(" ")؛ Serial.println( عدد)؛ lcd.print("T="); lcd.setCursor(2,0); lcd.print(شماره); lcd.setCursor(5,0); lcd.print("P="); lcd.print(Pressure/133.3); lcd.print("mmH"); lcd.setCursor(0,1); lcd.print("T="); lcd.print(دما*0.1); lcd.print("H="); lcd.print(sensor.humidity); lcd.home(); //تاخیر(2000); int chk = sensor.read(DHT11PIN); سوئیچ (chk) (مورد DHTLIB_OK: //Serial.println("OK")؛ شکست؛ مورد DHTLIB_ERROR_CHECKSUM: //Serial.println("خطای جمع بررسی")؛ شکست؛ مورد DHTLIB_ERROR_TIMEOUT: //Serial.println("Time out خطا")؛ شکست؛ پیش فرض: //Serial.println("خطای ناشناخته")؛ شکست؛ ) ))

    P.S. در آینده قصد دارم موارد زیر را اضافه کنم:
    - سنسور رطوبت به فرستنده، الگوریتم انتقال داده را دوباره کار کنید
    - سنسور برای اندازه گیری سرعت و جهت باد.
    - نمایشگر دیگری را به دستگاه گیرنده اضافه کنید.
    - گیرنده و فرستنده را به یک میکروکنترلر جداگانه منتقل کنید.

    در زیر عکسی از اتفاق افتاده است:

    فهرست عناصر رادیویی

    تعیین تایپ کنید فرقه تعداد توجه داشته باشیدخرید کنیددفترچه یادداشت من
    قسمت انتقال دهنده
    برد آردوینو

    آردوینو نانو 3.0

    1 به دفترچه یادداشت
    حسگر دما

    DS18B20

    1 به دفترچه یادداشت
    مقاومت

    220 اهم

    1 به دفترچه یادداشت
    ماژول فرستندهMX-FS-03V (433 مگاهرتز)1 به دفترچه یادداشت
    بخش دریافت رادیو
    برد آردوینو

    آردوینو اونو

    1 به دفترچه یادداشت
    مقاومت تریمر 1 به دفترچه یادداشت
    مقاومت

    پروژه ایستگاه هواشناسی از کتاب وی. از Arduino IDE 1.8.5 در ویندوز 10 استفاده شده است.
    هنگام اجرای طرح خطایی رخ داد

    در اینترنت می‌توانید کتابخانه‌هایی را برای آردوینو دانلود کنید که نام‌های مشابهی دارند اما محتوای متفاوتی دارند. اگر از کتابخانه اشتباهی استفاده می کنید، طرح ممکن است کار نکند. ظاهراً به کتابخانه های اشتباهی برخورد کردم. من یک سنسور BMP180 را برای اندازه گیری فشار اتمسفر به پروژه اضافه کردم و طرح را دوباره کار کردم.

    نمودار اتصال

    اسکن آدرس ها

    ابتدا سنسور BMP180 و نشانگر LCD1602 را به آردوینو وصل کنید. طرح اسکنر I2C را کامپایل کرده و آن را اجرا کنید تا آدرس دستگاه های موجود در گذرگاه I2C را مشخص کنید.

    هر 5 ثانیه برنامه دستگاه ها و آدرس های مربوط به پورت COM را اسکن می کند. من دو دستگاه با آدرس های 0x3F و 0x77 پیدا کردم. BMP180 به طور پیش فرض دارای آدرس 0x77 است، به این معنی که نشانگر LCD دارای آدرس 0x3F است.
    در برخی از مدارهای کتاب، مکان هایی که سیگنال های SDA و SCL به برد آردوینو متصل می شوند، با هم مخلوط شده اند. باید: SDA - به A4، SCL - به A5 باشد. اگر ماژول BMP180 دارای پنج پایه باشد، 5+ ولت به پایه VIN عرضه می شود.

    نمودار سیم کشی

    حالا مدار را به طور کامل جمع کنید. من از یک LED RGB کاتدی معمولی نصب شده روی برد همراه با مقاومت های 150 اهم استفاده کردم. کاتد مشترک به پایه GND متصل می شود، پایه های باقیمانده مطابق نمودار متصل می شوند. نیازی به تغییر در طرح نیست، زیرا روشنایی LED ها مطابق قانون چرخه ای تغییر می کند.
    نمودار اتصال یک LED RGB با یک آند مشترک را مانند کتاب نشان می دهد.
    اگر هیچ کاراکتری در صفحه LCD1602 قابل مشاهده نیست، کنترل روشنایی را بچرخانید. نور پس زمینه نشانگر جریان بسیار زیادی مصرف می کند، بنابراین از منبع تغذیه با جریان حداقل 2 آمپر استفاده کنید. من از هاب USB با منبع تغذیه خارجی 2 آمپر استفاده کردم.
    مدار از زنگ پیزو ZP-22 استفاده می کرد. مقاومت متصل به زنگ 100 اهم است. فرکانس صدا را می توان در برنامه تغییر داد. فرکانس 1000 هرتز را انتخاب کردم. اگر به یک زنگ با فرکانس صدای ثابت برخورد کردید، می توانید آن را به سادگی با اعمال و حذف ولتاژ روشن و خاموش کنید، مانند یک LED معمولی. وقتی طرح شروع می شود، یک بوق کوتاه به صدا در می آید. شما می توانید سیگنال دهی دوره ای را در حین اجرای برنامه با حذف نظر خط //bzz(100) فعال کنید. در طرح
    در پروژه من از یک سنسور DHT11 به شکل یک ماژول با یک مقاومت 4.7 کیلو اهم استفاده کردم. مقاومت می تواند از 4.7 تا 10 کیلو اهم باشد.
    پایه Vcc ماژول ساعت DS1302 را به باس +5 ولت وصل کنید. به این ترتیب تخلیه باتری را کاهش می دهید، اساساً فقط زمانی کار می کند که برق آردوینو خاموش باشد.

    برنامه (طرح)

    کتابخانه bmp085 برای سرویس دهی BMP180 استفاده می شود. مقدار فشار بستگی به ارتفاع منطقه دارد. برای مقدار صحیح فشار اتمسفر، باید ارتفاع را انتخاب کنید. برای انجام این کار، خط dps.init (MODE_STANDARD, 10000, true) را ویرایش کنید. قد من 100 متر (10000 سانتی متر) است. قطعه محاسبه فشار از مثال BMP085_test2.ino از کتابخانه bmp085 گرفته شده است.

    Sketch meteo_P

    #عبارتند از
    #عبارتند از
    #عبارتند از
    #شامل "DHT.h"
    #عبارتند از
    BMP085 dps = BMP085();
    فشار طولانی = 0، ارتفاع = 0;
    زمان طولانی بدون امضا1 = 0;

    #تعریف DHTPIN 10
    #define DHTTYPE 11 // 11 - DHT11, 22 - DHT22
    DHT dht (DHTPIN، DHTTYPE)؛

    int kCePin = 4; // RST DS1302
    int kIoPin = 3; // داده DS1302
    int kSclkPin = 2; //CLK DS1302
    DS1302 rtc (kCePin، kIoPin، kSclkPin)؛

    int REDpin = 9;
    int GREENpin = 6;
    int BLUEpin = 11;

    ال سی دی LiquidCrystal_I2C (0x3f, 16, 2); // آدرس خود را 0x20...0xff وارد کنید
    memTime طولانی بدون امضا.
    int bzzPin = 8;

    void HumTempRead() (
    float hum = dht.readHumidity();
    float temp = dht.readTemperature();
    اگر (اسنان(هوم) || ایسنان(دم)) (
    Serial.println("از حسگر DHT خوانده نشد!");
    lcd.setCursor(0, 1);
    lcd.print("H=--% T=---");
    lcd.setCursor(11, 1);
    lcd.print((char)223);
    lcd.setCursor(12, 1);
    lcd.print("C");
    ) دیگر (
    lcd.setCursor(0, 1);
    lcd.print("H=");
    lcd.setCursor(2, 1);
    lcd.print(hum);
    lcd.setCursor(4, 1);
    lcd.print("% T=+");
    lcd.setCursor(9, 1);
    lcd.print(temp);
    lcd.setCursor(11, 1);
    lcd.print((char)223);
    lcd.setCursor(12, 1);
    lcd.print("C");
    }
    }

    void setup_bzz() (
    pinMode (bzzPin، OUTPUT)؛
    }

    void bzz(int _bzzTime) (
    تن (bzzPin، 1000، _bzzTime)؛ // فرکانس 1000 هرتز
    }

    void setup() (
    Serial.begin(9600);
    Wire.begin();
    تاخیر (1000);

    dps.init(MODE_STANDARD، 10000، true); // 100 متر (ارتفاع از سطح دریا بر حسب سانتی متر)

    dht.begin();
    setup_bzz();
    bzz (100);

    LCD.init();
    lcd.backlight();
    lcd.home();
    // lcd.setCursor(0, 0);

    rtc.halt(false);
    rtc.writeProtect(false);

    //rtc.setDOW (جمعه)؛ // روز هفته را به FRIDAY تنظیم کنید روز هفته را تنظیم کنید
    //rtc.setTime(4, 58, 0); // زمان را روی 12:00:00 (قالب 24 ساعته) تنظیم کنید
    //rtc.setDate(6, 8, 2010); // تاریخ را روی 6 آگوست 2010 تنظیم کنید تاریخ را تنظیم کنید (روز، ماه، سال)
    }

    lcd.setCursor(8, 0);
    lcd.print(rtc.getTimeStr());

    if ((millis() - memTime > 2000) یا (millis()< memTime)) { // DHT11/22 1 time each 2 seconds
    HumTempRead();
    memTime = millis();
    }
    تاخیر (100);

    if (((millis() - time1) / 1000.0) >= 1.0) (
    dps.calcTrueTemperature();
    time1 = millis();
    }
    dps.getPressure(&Pressure);
    Serial.print("Presure(Pa):");
    Serial.println(Pressure);

    طولانی p2;
    int pi;
    p2 = (فشار / 133.3224)؛ // Pa بر حسب mmHg.
    pi = trunc(p2); // حذف جزء کسری یک عدد

    lcd.setCursor(0, 0);
    lcd.print("P=");
    lcd.setCursor(2, 0);
    lcd.print(pi); // خروجی اتمسفر. فشار روی LCD
    lcd.setCursor(5, 0);
    lcd.print("mm");
    // تاخیر(3000);
    //bzz(100); // اگر می‌خواهید به سیگنال‌ها گوش دهید، نظر را لغو کنید
    {
    برای (int value = 0 ; value<= 255; value += 1) {
    analogWrite (REDpin، مقدار)؛
    analogWrite (GREENpin، 255 - مقدار)؛
    analogWrite(BLUEpin, 255);
    تاخیر (5);
    }

    برای (int value = 0; value<= 255; value += 1) {
    analogWrite(REDpin, 255);
    analogWrite (GREENpin، مقدار)؛
    analogWrite(BLUEpin، 255 - مقدار)؛
    تاخیر (5);
    }

    برای (int value = 0; value<= 255; value += 1) {
    analogWrite (REDpin، 255 - مقدار)؛
    analogWrite(GREENpin, 255);
    analogWrite (BLUEpin، مقدار)؛
    تاخیر (5);
    }
    }
    }

    در کاتالوگ فایل می توانید طرح و کتابخانه های مورد استفاده در پروژه را دانلود کنید.

    کتابخانه های LiquidCrystal_I2C.zip، bmp085.zip، DS1302.zip و DHT.zip را از بایگانی دانلود شده به Arduino IDE وارد کنید. به منو بروید طرح اتصال کتابخانه افزودن کتابخانه .ZIP...و در پنجره آرشیو فشرده کتابخانه را انتخاب کنید.
    طرح meteo_P را آپلود کنید. آدرس LCD1602 را در طرح با مقدار بدست آمده با اسکن گذرگاه I2C جایگزین کنید. اسکچ را کامپایل و اجرا کنید.
    اگر طرح کار کرد، مانیتور پورت را باز کنید و پیام های نمایش داده شده را مشاهده کنید. ارتفاع را در عبارت dps.init (MODE_STANDARD, 10000 , true) تنظیم کنید. برای بدست آوردن مقادیر واقعی فشار
    ساعت خود را تنظیم کنید لغو نظر خط //rtc.setTime(4, 58, 0); و در پرانتز زمان فعلی را نشان دهید (ساعت، دقیقه و ثانیه با کاما از هم جدا شده اند) و طرح را دوباره در کنترلر بارگذاری کنید. پس از تعیین زمان، دوباره این خط را نظر دهید و دوباره طرح را اجرا کنید.
    اگر نور نور شب شما را آزار می دهد، می توانید با تغییر طول تاخیر در حلقه های for در انتهای طرح، آن را تنظیم کنید. با تاخیر(2); چرخه 2-3 ثانیه طول می کشد، با تاخیر (5). - از 4 تا 5 ثانیه، با تاخیر (30)؛ - حداکثر 15-16 ثانیه. اطلاعات مربوط به نشانگر در همان بازه زمانی به روز می شود.
    هنگام استفاده از ایستگاه هواشناسی به طور مستقل، به عنوان مثال. بدون اتصال به پورت USB کامپیوتر، خطوط موجود در طرح را با عبارت Serial ... کامنت کنید تا خروجی اطلاعات به مانیتور پورت COM غیرفعال شود.

    PS. در طرح کتاب و در مثال‌های مربوط به کتابخانه DHT، خط تعریف مشخص شده است #تعریف DHTTYPE DHT 11. طرح شروع می شود، اما پس از چند ساعت خراب می شود. ساعت متوقف می شود، صفحه نمایش تغییر نمی کند. یک پیام مبهم در مانیتور پورت ظاهر می شود که حاوی پیوندی به dht است.
    در این خط من حروف DHT را حذف کردم، یعنی. انجام داد #define DHTTYPE 11. پس از این، طرح به طور پایدار شروع به کار کرد.

    مقاله به روز شده در 25 ژوئن 2018

    منابع مورد استفاده
    1. پتین وی. پروژه ها با استفاده از کنترلر آردوینو (Electronics) ویرایش دوم، سنت پترزبورگ. BHV-Petersburg, 2015 464 p.
    2. Petin V. A., Binyakovsky A. A. دایره المعارف عملی آردوینو. - M., DMK Press, 2017. - 152 ص.
    3. http://arduinolearning.com/code/i2c-scanner.php
    4. http://arduino.ru/forum/programmirovanie/ds1302lcd1602
    5. http://robotehnika18.rf/how-to-connect-lcd-1602-to-arduino-via-i2c/
    6. مثال BMP085_test2.ino از کتابخانه bmp085.zip
    7. http://proginfo.ru/round/
    8. http://homes-smart.ru/index.php?id=14&Itemid=149&option=com_content&view=article
    9. http://iarduino.ru/lib/datasheet%20bmp180.pdf
    10. http://it-donnet.ru/hd44780_dht11_arduino/

    ایستگاه هواشناسی DIY

    عصر بود، بعد از سال نو کاری برای انجام دادن وجود نداشت. طبق معمول، در تعطیلات سال نو زمستانی می خواهم سر و دستانم را با چیزی مفید و خلاقانه مشغول کنم. در این تعطیلات سال نو تصمیم گرفتم با دستان خود یک ایستگاه هواشناسی بسازم. از قبل شروع به آماده سازی کردم، تمام اجزا را قبل از سال نو خریداری و مونتاژ کردم و در تعطیلات برنامه نویسی اصلی را انجام دادم.

    (زیر برش عکس های زیادی وجود دارد!)

    ابتدا، من به اجزای آن می پردازم؛ چون محصولات موجود در eBay (در حساب شخصی من) بایگانی شده اند، پیوندی نمی دهم. من بسیاری از قطعات را به آرامی در eBay خریدم. من برای اولین بار حراجی را امتحان کردم، قبل از اینکه همیشه «اکنون بخر» می خریدم. چه می توانم بگویم، اگر در خرید عجله نکنید، می توانید برخی از قطعات را ارزان تر خریداری کنید (تفاوت گاهی اوقات دو برابر آن است).

    سنسور فشار VMR085
    این سنسور اصلی است. وقتی آن را در eBay دیدم، می دانستم که می خواهم یک ایستگاه هواشناسی خانگی بسازم.
    سنسور در یک پاکت معمولی، پوشیده شده با پوشش حباب دار وارد شد.

    داخل پاکت کارت ویزیت فروشنده و یک حسگر بود که در یک کیسه ضد الکتریسیته ساکن بسته بندی شده بود و در لایه دیگری از پوشش حباب دار پیچیده شده بود.

    کیسه آنتی استاتیک مهر و موم شده بود تا رطوبت در طول پرواز سنسور را تهدید نکند

    سنسور را بیرون می آوریم. در یک طرف یک خط تماس لحیم کاری وجود دارد که برای جلوگیری از خم شدن آنها در فوم قرار داده شده است. در طرف دیگر خود سنسور و علامت های تماس وجود دارد.




    همه چیز خوب خواهد بود، اما علائم تماس در یک تصویر آینه اعمال می شود.
    سنسور از طریق گذرگاه I2C متصل می شود و با ولتاژ 3.3 ولت تغذیه می شود. یعنی برای عملکرد عادی به 4 سیم (+، -، SDA، SCL) نیاز دارید.
    شما می توانید حسگر را به دو روش بازجویی کنید: یا از طریق کتابخانه، یا با استفاده از توابع مستقیماً در طرح.
    نمونه برنامه:

    #عبارتند از

    #define BMP085_ADDRESS 0x77 // آدرس I2C BMP085

    کاراکتر بدون علامت OSS = 0; // تنظیمات نمونه برداری بیش از حد

    // مقادیر کالیبراسیون
    int ac1;
    int ac2;
    int ac3;
    بدون امضا int ac4;
    بدون علامت int ac5;
    بدون امضا int ac6;
    int b1;
    int b2;
    int mb;
    int mc;
    int md;

    دمای کوتاه؛
    فشار طولانی؛

    تنظیم خالی ()
    {
    Serial.begin(9600);
    Wire.begin();
    bmp085Calibration();
    }

    حلقه خالی()
    {
    دما = bmp085GetTemperature(bmp085ReadUT());
    فشار = bmp085GetPressure(bmp085ReadUP());
    Serial.print("دما: ");
    چاپ سریال (دما/10.0، DEC)؛
    Serial.println("C");
    Serial.print("Pressure:");
    Serial.print(pressure/133.322, DEC);
    Serial.println("mm Hg");
    Serial.println();
    تاخیر (1000);
    }

    Void bmp085calibration()
    {
    ac1 = bmp085ReadInt(0xAA);
    ac2 = bmp085ReadInt(0xAC);
    ac3 = bmp085ReadInt(0xAE);
    ac4 = bmp085ReadInt(0xB0);
    ac5 = bmp085ReadInt(0xB2);
    ac6 = bmp085ReadInt(0xB4);
    b1 = bmp085ReadInt(0xB6);
    b2 = bmp085ReadInt(0xB8);
    mb = bmp085ReadInt(0xBA);
    mc = bmp085ReadInt(0xBC);
    md = bmp085ReadInt(0xBE);
    }

    کوتاه bmp085GetTemperature (unsigned int ut)
    {
    طولانی x1، x2;
    x1 = (((طولانی)ut - (طولانی)ac6)*(طولانی)ac5) >> 15;
    x2 = ((طول) mc<< 11)/(x1 + md);
    b5 = x1 + x2;

    بازگشت ((b5 + 8)>>4);
    }

    طولانی bmp085GetPressure (بدون امضا)
    {
    طولانی x1، x2، x3، b3، b6، p;
    بلند بدون امضا b4, b7;
    b6 = b5 - 4000;
    // B3 را محاسبه کنید
    x1 = (b2 * (b6 * b6)>> 12)>> 11;
    x2 = (ac2 * b6)>> 11;
    x3 = x1 + x2;
    b3 = (((((بلند)ac1)*4 + x3)<>2;
    // B4 را محاسبه کنید
    x1 = (ac3 * b6)>> 13;
    x2 = (b1 * ((b6 * b6)>> 12))>> 16;
    x3 = ((x1 + x2) + 2)>> 2;
    b4 = (ac4 * (طولانی بدون علامت) (x3 + 32768))>> 15;
    b7 = ((طولانی بدون علامت)(بالا - b3) * (50000>>OSS));
    اگر (b7< 0x80000000)
    p = (b7<<1)/b4;
    دیگر
    p = (b7/b4)<<1;
    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>> 16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>> 4;
    بازگشت p;
    }

    // خواندن 1 بایت از BMP085 در "آدرس"
    char bmp085Read (آدرس char بدون امضا)
    {
    داده های کاراکتر بدون امضا؛

    Wire.write(آدرس);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 1);
    while(!Wire.available())
    ;
    بازگشت Wire.read();
    }

    Int bmp085ReadInt (آدرس char بدون امضا)
    {
    char بدون امضا msb, lsb;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(آدرس);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 2);
    while(Wire.available()<2)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    بازگشت (int) msb<<8 | lsb;
    }

    // مقدار دمای جبران نشده را بخوانید
    int بدون امضا bmp085ReadUT()
    {
    بدون امضا int ut;
    // 0x2E را در Register 0xF4 بنویسید
    // این یک خواندن دما را درخواست می کند
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();
    // حداقل 4.5 میلی‌ثانیه صبر کنید
    تاخیر (5);
    // خواندن دو بایت از ثبات های 0xF6 و 0xF7
    ut = bmp085ReadInt(0xF6);
    بازگشت ut;
    }

    // مقدار فشار جبران نشده را بخوانید
    طولانی bmp085ReadUP() بدون امضا
    {
    char unsigned msb, lsb, xlsb;
    بدون علامت طولانی = 0;
    // نوشتن 0x34+(OSS<<6) into register 0xF4
    // درخواست خواندن فشار با تنظیم نمونه برداری بیش از حد
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();
    // منتظر تبدیل باشید، زمان تاخیر بستگی به OSS دارد
    تاخیر(2 + (3<// خواندن ثبات 0xF6 (MSB)، 0xF7 (LSB) و 0xF8 (XLSB)
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);
    // منتظر بمانید تا داده ها در دسترس قرار گیرند
    while(Wire.available()< 3)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    xlsb = Wire.read();
    بالا = (((بلند بدون علامت) msb<< 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
    بازگشت به بالا
    }


    علاوه بر این، سنسور دارای سنسور حرارتی خود برای جبران فشار و ارتفاع سنج است

    آردوینو نانو نسخه 3.0
    این قلب کل ایستگاه هواشناسی است. به عبارت ساده، اندازه کنترلر مینیاتوری است.
    خریدم
    من در مورد کنترلر با جزئیات صحبت نمی کنم، زیرا این قبلاً قبل از من انجام شده است:


    بسته lightake پیش ساخته بود، کنترلر در یک بسته حاوی یک کابل USB و یک آردوینو در یک کیسه ضد الکتریسیته ساکن عرضه شد.

    برای تخمین اندازه، یک سکه 1 روبلی در کنار آردوینو گذاشتم.

    برد کنترلر از نزدیک



    کابل USB خوب است، با یک حلقه فریت. آردوینو از طریق کابل USB تغذیه می شود. محیط توسعه قابل دانلود است (صفحه دانلود). زبان "C" است، هیچ مشکلی با تسلط بر آن وجود نداشت، زیرا من در محل کار برنامه نویسی زیادی با آن انجام می دهم.

    صفحه نمایش ال سی دی
    در محل کار من یک صفحه نمایش LCD 1602 سازگار در سطل ها پیدا کردم. من مجبور شدم اتصال را سرهم کنم، زیرا نتوانستم دیتاشیتی برای آن پیدا کنم. در نتیجه LCD شروع به کار کرد.

    اما بعد از مدت کوتاهی استفاده متوجه شدم که این صفحه برای من کافی نیست و امکان نمایش داده های بیشتری وجود نخواهد داشت، زیرا فقط 2 خط هر کدام 16 کاراکتر دارد. در ابتدا به نظر می رسد که این پارامترها کافی هستند، اما وقتی برنامه نویسی را شروع می کنید، متوجه می شوید که حداکثر مقداری که می توانید در آن فشار دهید 3-4 پارامتر است. و اگر یک منو بسازید (من به ایجاد یک منو روی این صفحه فکر می کردم)، پس فقط 1-2 پارامتر فضای خالی باقی می ماند.
    در نتیجه شروع به جستجوی صفحه نمایش دیگری کردم. ابتدا از نزدیک به صفحه گرافیکی نوکیا 3310 نگاه کردم و حتی برای خرید آن در حراج eBay شرکت کردم، اما نتیجه ای نداشت (که بسیار خوشحالم)، بنابراین مجبور شدم این صفحه را رها کنم. اکنون می دانم که برای اهداف من بسیار کوچک است، زیرا چیزی برای مقایسه با آن وجود دارد.
    در حالی که به طور تصادفی سپرهای آردوینو را جستجو می کردم، با یک صفحه گرافیکی 12864 روی یک کنترلر ST7920 روبرو شدم. این صفحه نمایش اندازه مناسب و وضوح خوبی برای نیازهای من دارد (128x64). یعنی به راحتی می توانید 6-7 خط 20 کاراکتری را در یک فونت معمولی خوانا قرار دهید. از آنجایی که صفحه نمایش گرافیکی است، علاوه بر متن، می توان گرافیک را با فونت های مختلف نیز قرار داد. به طور خلاصه، این دقیقاً همان چیزی است که من نیاز داشتم، همه چیز در این صفحه وجود داشت، بنابراین نتوانستم مقاومت کنم و آن را سفارش دادم.
    بسته به سرعت رسید و به صورت استاندارد بسته بندی شد: یک پاکت بسته بندی حباب دار، داخل یک لایه دیگر از بسته بندی حباب دار و یک صفحه در یک کیسه ضد الکتریسیته ساکن وجود داشت:






    برای تخمین اندازه، یک سکه 1 روبلی در کنار LCD قرار دادم.




    برای اتصال سریع صفحه نمایش به آردوینو، من یک خط تماس را به پین ​​های LCD لحیم کردم. LCD را می توان از طریق گذرگاه سریال یا موازی متصل کرد. من گزینه اول را انتخاب کردم، زیرا در حال حاضر تعداد کمی از مخاطبین رایگان آردوینو وجود دارد.
    اتصال (برگرفته از وب):

    - پایه 1 (GND) به باس مشترک متصل است
    - پایه 2 (VCC) به گذرگاه برق +5 ولت متصل است و مصرف جریان نسبتاً کم است و نمایشگر می تواند از تثبیت کننده داخلی آردوینو تغذیه شود.
    - پین های 4، 5 و 6 به خروجی های دیجیتال آردوینو متصل می شوند و رابط سریال SPI را تشکیل می دهند:
    پین 4 - (RS) - مربوط به خط CS است (مثلا 7)
    پین 5 - (RW) - مربوط به خط MOSI است (مثلا 8)
    پین 6 - (E) - مربوط به خط SCK است (مثلا 3)
    شماره تماس آردوینو می تواند هر چیزی باشد، نکته اصلی این است که هنگام تنظیم اولیه نمایشگر فراموش نکنید که آنها را به درستی در متن برنامه نشان دهید.
    - پایه 15 (PSB) به باس مشترک متصل است.
    - کنتاکت های 19 (A) و 20 (K) منبع تغذیه نور پس زمینه (به ترتیب +5V و GND) هستند. برای تنظیم روشنایی نور پس زمینه، می توانید از یک مقاومت متغیر 10 کیلو اهم متصل شده بین گذرگاه برق و GND استفاده کنید. ولتاژ موتور آن به پایه 19 نمایشگر می رسد.
    طبق این دستورالعمل، من همه چیز را به جز نور پس زمینه وصل کردم. من از آردوینو PWM برای روشن کردن نور پس زمینه استفاده کردم.
    برای اتصال برنامه نویسی LCD به آردوینو، از کتابخانه u8glib استفاده می شود. می توانید آن را دانلود کنید. اگر مشکلی در بارگیری وجود دارد، می توانم کتابخانه را در narod.ru آپلود کنم.
    خود کتابخانه پیچیده نیست و به شما امکان می دهد متن را با فونت های مختلف نمایش دهید، یک خط بکشید، اشکال هندسی ساده (مستطیل، دایره) بکشید و تصاویر خود را که به روشی خاص تهیه شده اند نمایش دهید. در اصل، این ابزار برای اکثر کارها کافی است.
    در اینجا نتیجه یک برنامه ساده است:

    خود برنامه:

    #include "U8glib.h"

    U8GLIB_ST7920_128X64 u8g(3، 9، 8، U8G_PIN_NONE)؛ // SPI E = 3، RW = 9، RS = 8

    // زیر برنامه برای تعیین حافظه آزاد
    int freeRam() (
    extern int __heap_start, *__brkval;
    در تلویزیون؛
    بازگشت (int) &v - (__brkval == 0? (int) &__heap_start: (int) __brkval);
    }

    تنظیم خالی (باطل) (
    u8g.setFont(u8g_font_6x10); // فونت
    u8g.setRot180(); //صفحه را برگردانید
    analogWrite(6, 115); // روشنایی صفحه را تنظیم کنید (آند نور پس زمینه روی 6 پین)
    }

    حلقه خالی (باطل) (
    u8g.firstPage();
    انجام دادن(

    u8g.setPrintPos(1, 12); // موقعیت
    u8g.print("سلام!!!"); // خروجی متن
    u8g.drawBox(0,22,128,9); // مستطیل را سفید رنگ کنید
    u8g.setColorIndex(0); // جوهر سفید، پس زمینه سیاه
    u8g.setPrintPos(1, 30); // موقعیت
    u8g.print("Word..."); // خروجی متن

    U8g.setColorIndex(1); // جوهر سفید، پس زمینه سیاه
    u8g.setPrintPos(1, 50); // موقعیت
    u8g.print("پس از شروع ="); // خروجی متن
    u8g.setPrintPos(85, 50); // موقعیت
    u8g.print(millis() / 1000); // خروجی تعداد ثانیه پس از شروع
    u8g.setPrintPos(1, 64); // موقعیت
    u8g.print(freeRam()); // مقدار حافظه اشغال شده را خروجی می دهد
    ) while(u8g.nextPage());

    تاخیر(200);
    }

    ساعت واقعی DS1307
    یکی دیگر از اجزای ایستگاه هواشناسی من. این شیلد یک ساعت بیدرنگ اجرا می کند. من آنها را در eBay سفارش دادم. فروشنده روسری ساعت را در یک جعبه بزرگ غیر واقعی فرستاد


    داخل جعبه دو برگه تبلیغاتی A4 و یک دستمال ساعت بود که در سلفون پیچیده شده بود


    من می خواهم توجه داشته باشم که هزینه از 2 روبل تجاوز نمی کند. سکه و اندازه جعبه 13x15x5 سانتی متر است.
    تخته در یک کیسه ضد الکتریسیته ساکن بسته بندی شده بود

    شال از نزدیک



    مجبور شدم با این ماژول کار کنم. اولاً، مشکلات اتصال وجود داشت. و دوم اینکه هیچ کوارتزی روی این تخته وجود ندارد. اگر می دانستم که زمان زیادی را روی ماژول صرف می کنم، به احتمال زیاد خودم آن را مونتاژ می کردم، زیرا اینترنت پر از نمودار است. ساده ترین مدار شامل 4-5 جزء است.
    در مورد اتصال. کتابخانه‌ای پیدا کردم که می‌گفت رابط I2C را می‌توان نه به ورودی‌های آنالوگ معمول آردوینو (A4 و A5)، بلکه به هر ورودی مجزا متصل کرد. همانطور که نوشته بود انجام دادم. در ابتدا هیچ چیز درست نشد، اما پس از یک رقص طولانی با تنبور، ساعت شروع به کار کرد. خوب، فکر کردم، همین است، مشکلات تمام شده است، اما بعد از اینکه سعی کردم همان ماژول را به آردوینو دیگری وصل کنم، رقص با تنبور ادامه یافت. من زمان زیادی را صرف یافتن راه حلی برای این مشکل کردم و تقریباً در همه جا به اتصال نادرست یا عدم وجود مقاومت های کششی در مخاطبین SCL و SDA اشاره شد. من قبلاً می خواستم با یک آهن لحیم کاری وارد برد شوم، اما در یکی از انجمن ها به طور تصادفی با کدی برخورد کردم که در آن گفته شده بود SCL و SDA را به پورت های استاندارد I2C در آردوینو متصل می کند. پس از اتصال استاندارد، همه چیز بلافاصله کار کرد.
    حالا در مورد کوارتز. من نمی‌دانم چینی‌ها چه نوع کوارتزی را در آنجا قرار می‌دهند، اما ساعت‌هایی با چنین کوارتزی 10-11 ثانیه در روز فرار می‌کنند. این خطا 5 دقیقه در ماه و 1 ساعت در سال است. نیازی به چنین ساعتی نیست مجبور شدم دوباره آنلاین شوم و به دنبال چگونگی رفع این اشکال باشم. اولین راه حلی که می آید می گوید که باید کوارتز را زمین کنید. من آن را انجام دادم - نتیجه صفر بود. من همچنین جایی پیدا کردم که باید یک مادربرد قدیمی پیدا کنم و کوارتز ساعت را از آنجا حذف کنم. من آن را انجام دادم - نتیجه ای وجود دارد. اکنون ساعت نه 10-11 ثانیه، بلکه 1.5 ثانیه در روز دور می شود. بیایید بگوییم که بهتر شده است، اما از ایده آل فاصله زیادی دارد. از آنجایی که دیگر حوصله لحیم کاری را ندارم، تصمیم گرفته شد ساعت را به صورت برنامه ای تنظیم کنم، یعنی یک بار در روز ساعت را به مقدار مورد نیاز تنظیم کنم. بعد از 10 روز، ساعت بیش از یک ثانیه خاموش شد. روش خوب است، اما فقط زمانی که دستگاه همگام سازی آردوینو به برق وصل باشد، در غیر این صورت ساعت با باتری کار می کند و همچنان از بین می رود.
    یک برنامه تست کوچک:

    #شامل "Wire.h"
    #define DS1307_I2C_ADDRESS 0x68 // SDA A4، SCL A5

    بایت decToBcd (بایت val)
    {
    بازگشت ((val/10*16) + (val%10));
    }

    بایت bcdToDec (بایت val)
    {
    بازگشت ((val/16*10) + (val%16));
    }

    setDateDs1307 باطل (بایت ثانیه، // 0-59
    دقیقه بایت، // 0-59
    بایت ساعت) // 0-99
    {

    Wire.write(0);
    Wire.write(decToBcd(ثانیه));
    Wire.write(decToBcd(دقیقه));
    Wire.write(decToBcd(ساعت));
    Wire.endTransmission();
    }

    لغو getDateDs1307 (بایت *ثانیه،
    بایت * دقیقه،
    بایت *ساعت)
    {

    Wire.beginTransmission(DS1307_I2C_ADDRESS);
    Wire.write(0);
    Wire.endTransmission();

    Wire.requestFrom(DS1307_I2C_ADDRESS, 3);

    *second = bcdToDec(Wire.read());
    *minute = bcdToDec(Wire.read());
    *hour = bcdToDec(Wire.read());
    }

    تنظیم خالی ()
    {
    بایت ثانیه، دقیقه، ساعت؛
    Wire.begin();
    Serial.begin(9600);

    دوم = 45;
    دقیقه = 5;
    ساعت = 16;

    SetDateDs1307 (ثانیه، دقیقه، ساعت)؛
    }

    حلقه خالی()
    {
    بایت ثانیه، دقیقه، ساعت؛

    GetDateDs1307(&ثانیه، &دقیقه، &ساعت)؛
    Serial.print (ساعت، دسامبر);
    Serial.print(":");
    Serial.print (دقیقه، دسامبر)؛
    Serial.print(":");
    Serial.println (دوم، DEC);

    تاخیر(1000);
    }


    در اینجا از کتابخانه استفاده نمی شود و عملکردهای زمان خواندن و نوشتن کوتاه شده است.

    سنسور دما و رطوبت DHT11
    در مورد این سنسور چیزی برای گفتن وجود ندارد. من حتی اگر رطوبت لازم نبود از آن استفاده نمی کردم. متأسفانه هنگام دریافت عکسی از آن نگرفتم بنابراین هیچ عکسی وجود نخواهد داشت. عکس های این سنسور را می توانید در زیر مشاهده کنید، جایی که آن را به آردوینو وصل کردم. اتصال سنسور ساده است (+، خروجی دیجیتال، -). به طور معمول سنسورها با چهار پین ساخته می شوند. با این فرم فاکتور، پایه سوم به چیزی وصل نمی شود.
    برای اتصال به آردوینو می توانید از کتابخانه استفاده کنید. می توانید آن را دانلود کنید.
    یک برنامه آزمایشی کوچک با خروجی اطلاعات روی صفحه نمایش LCD 1602:

    // شامل کد کتابخانه:
    #عبارتند از
    #عبارتند از

    // اعلان اشیا
    dht11 DHT11;
    ال سی دی LiquidCrystal (12، 11، 6، 5، 4، 3);

    #define DHT11PIN 7
    int i;

    تنظیم خالی ()
    {
    lcd.begin(16, 2);
    lcd.print("وضعیت:");
    i=0;
    }

    حلقه خالی()
    {
    int chk = DHT11.read(DHT11PIN);
    lcd.setCursor(8, 0);
    سوئیچ (chk)
    {
    case 0: lcd.print("OK"); break;// lcd.setCursor(11, 0); lcd.print(millis()/2000); زنگ تفريح؛
    case -1: lcd.print ("خطای جمع بررسی"); mErr(); زنگ تفريح؛
    case -2: lcd.print("Time out error"); mErr(); زنگ تفريح؛
    پیش فرض: lcd.print ("خطای ناشناخته"); mErr(); زنگ تفريح؛
    }
    تاخیر (500);
    lcd.setCursor(15, 0);
    سوئیچ (i)
    {
    case 0: lcd.print("^"); lcd.setCursor(15, 1); lcd.print(" "); break;
    مورد 1: lcd.print("v"); lcd.setCursor(15, 1); lcd.print(" "); break;
    پیش فرض: lcd.setCursor(15, 1); lcd.print("E"); زنگ تفريح؛
    }
    i=i+1;
    اگر (i>1) i=0;
    lcd.setCursor(0, 1);
    lcd.print("H=");
    lcd.setCursor(2, 1);
    lcd.print((float)DHT11.humidity, 0);
    lcd.setCursor(4, 1);
    lcd.print("%");
    lcd.setCursor(8, 1);
    lcd.print("T=");
    lcd.setCursor(10, 1);
    lcd.print((float)DHT11.temperature, 0);
    lcd.setCursor(12, 1);
    lcd.print("C");

    Void mErr()
    {
    lcd.setCursor(2, 1);
    lcd.print("**");
    lcd.setCursor(10, 1);
    lcd.print("**");
    i=5;
    }


    سنسور دارای معایبی است - داده های سنسور فقط به اعداد کامل است و محدوده ضعیف است.

    به نظر می رسد که من در مورد تمام اجزای آن نوشتم. تنها چیزی که باقی می ماند جمع آوری همه چیز در یک کل واحد است.
    اوه، تقریباً فراموش کردم! برای مونتاژ دستگاه به یک کیس نیاز دارید. من کیس را هم در Ebay سفارش دادم. معلوم شد که فروشنده اهل انگلستان است. بسته سریع رسید، اما من از آن عکس نگرفتم. تمامی عکس های پرونده در زیر آمده است.

    ابتدا همه چیز روی میز را با استفاده از سیم کشی مخصوص مونتاژ کردم. یک برنامه آزمایشی نوشتم و در کنترلر آپلود کردم.



    در واقع، رنگ آبی نور پس زمینه بسیار روشن تر است. حتی در حداقل روشنایی (روشن = 5)، قاب روشن می شود.

    برای مونتاژ همه چیز به صورت بی سیم، تصمیم گرفته شد که یک مادربرد مینی بسازیم و بردها و شیلدهای آردوینو روی کانکتورها قرار گرفتند. اگر اتفاقی بیفتد، می توان آنها را به سرعت و به راحتی حذف کرد. من همچنین تصمیم گرفتم صفحه نمایش LCD و دکمه های کنترل را به کانکتورها وصل کنم و فقط سنسور دما را روی سیم ها لحیم کنم.
    اینطوری روسری بیرون آمد



    در عکس آخر، من کاملاً شار را پاک نکرده ام. من لاستیک متخلخل را زیر سپرهای کنار کانکتورها چسباندم تا حداقل تکیه گاهی وجود داشته باشد. اگرچه در واقع سپرهای اتصالات روی کنتاکت ها به خوبی حفظ می شوند.

    مادربرد با شیلدهای نصب شده و برد آردوینو.

    اتصال کامل به مادربرد به این شکل است


    به جای دکمه، از یک سپر خانگی که روی تخته نان لحیم شده استفاده کردم. من از دکمه های موش های قدیمی به عنوان دکمه استفاده کردم.
    همانطور که می بینید تعداد سیم ها کاهش یافته است.

    مشکل اصلی قرارگیری در کیس، بریدن یک شیار صاف برای صفحه LCD است. هرچقدر هم که تلاش کردم، باز هم کاملاً درست نشد. شکاف ها در برخی نقاط کمی بیشتر از 1 میلی متر بود. برای اینکه همه چیز مرتب به نظر برسد، درزگیر آکواریوم مشکی را گرفتم و تمام شکاف ها را پر کردم، در همان زمان صفحه را به این درزگیر وصل کردم. بعد از خشک شدن درزگیر، اضافه آن را از بیرون جدا کردم. در نور شدید، درزگیر قابل مشاهده است، اما در نور معمولی، همه چیز با بدنه ادغام می شود.
    این همان چیزی است که کیس از داخل با یک صفحه نمایش LCD و مادربرد نصب شده به نظر می رسد.

    این همان چیزی است که از بیرون در نور شدید به نظر می رسد (با عرض پوزش بابت اثر انگشت، وقتی داشتم عکس ها را مرتب می کردم آنها را دیدم).

    خیلی وقته فکر میکردم که چطور دکمه ها رو داخل قاب قرار بدم و مهمتر از همه اینکه از چه دکمه هایی استفاده کنم...
    در فروشگاه‌های رادیو الکترونیک، دکمه‌ای با سنجاق بلند و نوک‌هایی که روی این پین قرار می‌گیرد را دوست داشتند. از این دکمه ها برای لحیم کاری به برد استفاده می شود. همه چیز خوب خواهد بود، اما آنها یک منهای دارند - ضربه فشار دادن بسیار کوچک و بلند است.
    ما باید دکمه ها را در دو مرحله قرار می دادیم: مرحله اول قرار دادن دکمه ها روی تخته، مرحله دوم این بود که این تخته را روی تخته دیگری نصب کنیم. و سپس همه اینها را در بدنه روی راهنماها قرار دهید.

    روسری با دکمه به این شکل است:



    صفحه نگهدارنده به این صورت است:


    در اینجا می توانید راهنماهایی را مشاهده کنید که تخته دکمه ای در آن قرار داده شده است. برخی از عناصر به منظور استحکام دادن به برد لحیم شدند.

    حالا همه چیز را داخل بدن قرار می دهیم
    بدون دکمه های اتصال:


    با اتصال دکمه:

    کیس را ببندید و روشن کنید. همه چیز عالی کار می کند، دکمه ها همانطور که باید کار می کنند.

    در پایان یک ویدیوی کوتاه از عملکرد دستگاه در حالت های مختلف ارسال می کنم:
    http://www.youtube.com/watch?v=KsiVaUWkXNA&feature=youtu.be
    برای کسانی که ویدیوی اینجا را نمی بینند، این لینک است

    وقت آن است که بررسی را به پایان برسانیم.
    من کمی در مورد برنامه می نویسم، و سپس چند نتیجه گیری کوتاه. وقتی برنامه را نوشتم، فکر نمی کردم خیلی سریع به محدودیت 30720 بایت برسم.


    مجبور شدم کد را بهینه کنم. بسیاری از کدها را به زیر روال ها منتقل کردم. من هرگز فکر نمی کردم که یک دستور switch...case به شکل کامپایل شده فضای بیشتری را نسبت به چندین دستور if...else اشغال کند. اعلان صحیح متغیرها نیز باعث صرفه جویی در فضا می شود. اگر یک آرایه طولانی را اعلام کنید، اگرچه امکان دریافت بر اساس بایت وجود دارد، بسته به اندازه آرایه، بیش از حد حافظه به 500 بایت می رسد. وقتی برنامه ای می نویسید، به آن فکر نمی کنید و فقط بعداً، وقتی برنامه را آنالیز می کنید، متوجه می شوید که برخی کارها را اشتباه انجام داده اید و شروع به بهینه سازی کد می کنید. بعد از رفع مشکلات اندازه برنامه، با محدودیت RAM مواجه شدم. این در این واقعیت بیان شد که برنامه پس از بارگیری شروع به یخ زدن کرد. مجبور شدم زیر برنامه ای برای محاسبه رم رایگان معرفی کنم. در نتیجه، من مجبور شدم یک الگوریتم پیش بینی آب و هوا را کنار بگذارم، زیرا باید آیکون ها را روی صفحه نمایش دهد. خود الگوریتم کار می کند، اما خروجی آیکون ها باید ثبت می شد. من هنوز ایده هایی در مورد نحوه بهینه سازی کد دارم، اما در آینده نزدیک دستگاه را همانطور که هست می گذارم تا عملکرد آن را ارزیابی کنم و تمام اشکالات را شناسایی کنم.

    حالا چند نتیجه گیری
    موارد منفی
    1) قیمت. توجیه این ضرر این است که یک سرگرمی هرگز ارزان نیست.

    طرفداران
    1) عملکرد عالی دستگاه
    2) افزایش توابع فقط توسط کنترلر مورد استفاده و تمایل خود شما محدود می شود
    3) لذت زیبایی شناختی از تفکر و رضایت اخلاقی از این که در نهایت این دستگاه را مونتاژ و تکمیل کردم.

    من قصد خرید +85 را دارم اضافه کردن به علاقه مندی ها من نقد را دوست داشتم +137 +304

    بهترین مقالات در این زمینه