محطة الطقس المتنقلة في اردوينو

ربما كل من يبدأ في التعرف على Arduino ، ويومض LED ويصل زرًا ، يواصل إنشاء محطة الطقس الخاصة به. لم أكن استثناء.

بعد مراجعة المشاريع المختلفة على الإنترنت ، تم وضع متطلبات معينة. يجب أن يعرض الجهاز الوقت ودرجة الحرارة والضغط وجدول تغييره. كما أردت حقًا حساب مراحل القمر ووقت شروق الشمس وغروبها. وكان أهم شرط التنقل. كان من المفترض استخدام محطة الطقس المحمولة التي تم إنشاؤها للمساعدة في صيد الأسماك ، لذلك يجب أن يكون لها حجم مضغوط وأن يكون لها استقلالية معينة.

يعد إنشاء جسم لأي منتج محلي الصنع تحديًا كبيرًا. في الصناديق ، تم العثور على هاتف محمول Motorola T192.

الصورة

اتضح أن الشاشة من Nokia 3310 تزداد جمالًا (بالطبع ، باستخدام Nokia 3310 نفسه ، ربما سيكون أكثر ملاءمة).
تم تكليف إدارة كل شيء بـ Arduino Pro Mini.

الصورة

لمنع الأزرار من الفشل ، تم إدخال لوحة توصيل. عند إعادة لصق لوحة المفاتيح ، لوحظ أن خطوة ثقوب التخطيط تزامنت تقريبًا مع الأزرار. في المستقبل ، سمح هذا باستخدام الأزرار.

الصورة

لقياس الضغط ، يتم استخدام مستشعر bmp180. تم أخذ وحدة ds1302 كساعة ، ولكن لتوفير المساحة ، تم أخذ دائرة صغيرة فقط منها. تمت إزالة الكوارتز من اللوحة الأم ، وتمت إزالة البطارية من الكمبيوتر المحمول (بالطبع ، يمكنك أيضًا استخدام cr2032 المعتاد في الغلاف الحراري).

الصورة

نظرًا لوجود مخرجات مجانية ، تم تعليق الإضاءة الخلفية للشاشة على أحد الخطوط المجانية والزر في الثانية.

الصورة

لشحن بطارية الليثيوم ، تم استخدام وحدة شحن Li-ion في TP4056.

الصورة

الشكل النهائي للجهاز (الأسلاك الملتصقة إلى اليمين مخصصة للبرامج الثابتة ، لذلك ستتم إزالتها قريبًا.)

الصورة

عند كتابة البرنامج ، تم استخدام الوسائل المعتادة. الشيء الوحيد الذي أود أن ألفت الانتباه إليه هو مكتبة TimeLord.h (https://github.com/probonopd/TimeLord). باستخدام وظائفها ، تشير إلى التاريخ والإحداثيات والمنطقة الزمنية ، يمكنك تحديد وقت شروق الشمس وغروبها ، مرحلة القمر. يمكن تنزيل الوصف هنا: TimeLord.pdf .

فيما يتعلق بعمر البطارية ، أظهر اختبار قصير أن الجهاز سيعمل لمدة أسبوع بالضبط. هذه النتيجة مرضية للغاية ، لذلك تم تأجيل المزيد من التجارب على الحفاظ على الطاقة.

يستخدم Sketch حاليًا 81٪ من ذاكرة الجهاز ، لذا يمكنك إضافة شيء آخر.

الصورة

يتم عرض الهوائي (مؤشر قوة الإشارة) على الشاشة. وقد ترك هذا احتياطيًا لاختبار وحدة الراديو 433 ميجاهرتز ، من أجل الحصول على درجة حرارة ورطوبة حقيقية من الوحدة الخارجية.

كود المصدر
#include <BMP085.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <DS1302.h>
#include <TimeLord.h>
#include <Wire.h>

//84x48
Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 6, 7);
// Create a DS1302 object.
DS1302 rtc(12, 11, 10);// Chip Enable, Input/Output, Serial Clock
Time t = rtc.time();
String dayAsString(const Time::Day day) {
  switch (day) {
    case Time::kSunday: return "Sunday";
    case Time::kMonday: return "Monday";
    case Time::kTuesday: return "Tuesday";
    case Time::kWednesday: return "Wednesday";
    case Time::kThursday: return "Thursday";
    case Time::kFriday: return "Friday";
    case Time::kSaturday: return "Saturday";
  }
  return "(unknown day)";
}
//-------------
TimeLord tardis;
float const LATITUDE = 52.70;
float const LONGITUDE = 25.40;
//byte today[] = {0,0,12,22,03,16};
byte today[6];
//-------------
//long previousMillis = 0, previousMillis2 = 0;      //    
//long interval = 1800000;           //   
//long interval = 3600000;           //   
//long interval2 = 1000;           //   
byte prevSecond = 99, prevHour = 99;
//-------------
BMP085 dps = BMP085();
long Temperature = 0, Pressure = 0;
float t_f = 0;

//-------------buttons--------------------
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;

//-------------moon----------------------
//0.0 New Moon 0.99 - Almost new
const unsigned char PROGMEM moon0[] =
{ B00000111, B11100000,
  B00001000, B00010000,
  B00010000, B00001000,
  B00100000, B00000100,
  B01000000, B00000010,
  B10000000, B00000001,
  B10000000, B00000001,
  B10000000, B00000001,
  B10000000, B00000001,
  B10000000, B00000001,
  B01000000, B00000010,
  B00100000, B00000100,
  B00010000, B00001000,
  B00001000, B00010000,
  B00000111, B11100000
};

//Waxing Crescent
const unsigned char PROGMEM moon1[] =
{ B00000111, B11100000,
  B00001000, B01110000,
  B00010000, B00111000,
  B00100000, B00011100,
  B01000000, B00001110,
  B10000000, B00001111,
  B10000000, B00001111,
  B10000000, B00001111,
  B10000000, B00001111,
  B10000000, B00001111,
  B01000000, B00001110,
  B00100000, B00011100,
  B00010000, B00111000,
  B00001000, B01110000,
  B00000111, B11100000
};

//0.25 First Quarter
const unsigned char PROGMEM moon2[] =
{ B00000111, B11100000,
  B00001000, B11110000,
  B00010000, B11111000,
  B00100000, B11111100,
  B01000000, B11111110,
  B10000000, B11111111,
  B10000000, B11111111,
  B10000000, B11111111,
  B10000000, B11111111,
  B10000000, B11111111,
  B01000000, B11111110,
  B00100000, B11111100,
  B00010000, B11111000,
  B00001000, B11110000,
  B00000111, B11100000
};

//Waxing Gibbous
const unsigned char PROGMEM moon3[] =
{ B00000111, B11100000,
  B00001011, B11110000,
  B00010111, B11111000,
  B00101111, B11111100,
  B01001111, B11111110,
  B10001111, B11111111,
  B10001111, B11111111,
  B10001111, B11111111,
  B10001111, B11111111,
  B10001111, B11111111,
  B01001111, B11111110,
  B00101111, B11111100,
  B00010111, B11111000,
  B00001011, B11110000,
  B00000111, B11100000
};

//0.5 Full Moon
const unsigned char PROGMEM moon4[] =
{ B00000111, B11100000,
  B00001111, B11110000,
  B00011111, B11111000,
  B00111111, B11111100,
  B01111111, B11111110,
  B11111111, B11111111,
  B11111111, B11111111,
  B11111111, B11111111,
  B11111111, B11111111,
  B11111111, B11111111,
  B01111111, B11111110,
  B00111111, B11111100,
  B00011111, B11111000,
  B00001111, B11110000,
  B00000111, B11100000
};

//Waning Gibbous
const unsigned char PROGMEM moon5[] =
{ B00000111, B11100000,
  B00001111, B11010000,
  B00011111, B11101000,
  B00111111, B11110100,
  B01111111, B11110010,
  B11111111, B11110001,
  B11111111, B11110001,
  B11111111, B11110001,
  B11111111, B11110001,
  B11111111, B11110001,
  B01111111, B11110010,
  B00111111, B11110100,
  B00011111, B11101000,
  B00001111, B11010000,
  B00000111, B11100000
};

//0.75 Third Quarter  (Last Quarter)
const unsigned char PROGMEM moon6[] =
{ B00000111, B11100000,
  B00001111, B00010000,
  B00011111, B00001000,
  B00111111, B00000100,
  B01111111, B00000010,
  B11111111, B00000001,
  B11111111, B00000001,
  B11111111, B00000001,
  B11111111, B00000001,
  B11111111, B00000001,
  B01111111, B00000010,
  B00111111, B00000100,
  B00011111, B00001000,
  B00001111, B00010000,
  B00000111, B11100000
};


//Waning Crescent
const unsigned char PROGMEM moon7[] =
{ B00000111, B11100000,
  B00001110, B00010000,
  B00011100, B00001000,
  B00111000, B00000100,
  B01110000, B00000010,
  B11110000, B00000001,
  B11110000, B00000001,
  B11110000, B00000001,
  B11110000, B00000001,
  B11110000, B00000001,
  B01110000, B00000010,
  B00111000, B00000100,
  B00011100, B00001000,
  B00001110, B00010000,
  B00000111, B11100000
};
//=====================================================================================
void drawMoon(int moon_x, int moon_y, int phase) {
  display.fillRect(moon_x, moon_y, 16, 15, WHITE);
  display.drawBitmap(moon_x, moon_y, moon4,  16, 15, WHITE);
  switch (phase) {
    case 0:
      display.drawBitmap(moon_x, moon_y, moon0,  16, 15, BLACK);
      break;
    case 1:
      display.drawBitmap(moon_x, moon_y, moon1,  16, 15, BLACK);
      break;
    case 2:
      display.drawBitmap(moon_x, moon_y, moon2,  16, 15, BLACK);
      break;
    case 3:
      display.drawBitmap(moon_x, moon_y, moon3,  16, 15, BLACK);
      break;
    case 4:
      display.drawBitmap(moon_x, moon_y, moon4,  16, 15, BLACK);
      break;
    case 5:
      display.drawBitmap(moon_x, moon_y, moon5,  16, 15, BLACK);
      break;
    case 6:
      display.drawBitmap(moon_x, moon_y, moon6,  16, 15, BLACK);
      break;
    case 7:
      display.drawBitmap(moon_x, moon_y, moon7,  16, 15, BLACK);
      break;
    default:
      display.drawBitmap(moon_x, moon_y, moon4,  16, 15, WHITE);
  }
}
//===========================================================================================
void drawMoonDate(int moon_x, int moon_y, uint8_t * datetoday) {
  float phase;
  phase = tardis.MoonPhase(datetoday);
  if (phase >= 0.0   && phase <= 0.0625)  {
    drawMoon(moon_x, moon_y, 0);
  }; //0.000  New moon
  if (phase > 0.0625 && phase <= 0.1875)  {
    drawMoon(moon_x, moon_y, 1);
  }; //0,125
  if (phase > 0.1875 && phase <= 0.3125 ) {
    drawMoon(moon_x, moon_y, 2);
  }; //0.250  First Quarter
  if (phase > 0.3125 && phase <= 0.4375)  {
    drawMoon(moon_x, moon_y, 3);
  }; //0,375
  if (phase > 0.4375 && phase <= 0.5625)  {
    drawMoon(moon_x, moon_y, 4);
  }; //0.500  Full
  if (phase > 0.5625 && phase <= 0.6875)  {
    drawMoon(moon_x, moon_y, 5);
  }; //0,625
  if (phase > 0.6875 && phase <= 0.8125)  {
    drawMoon(moon_x, moon_y, 6);
  }; //0.750  Last Quarter
  if (phase > 0.8125 && phase <= 0.9375)  {
    drawMoon(moon_x, moon_y, 7);
  }; //0.875
  if (phase > 0.9375 && phase <= 1)       {
    drawMoon(moon_x, moon_y, 0);
  }; //0.990  Almost new
}
//=====================================================================================
void drawSignal(float streng) {
  display.fillRect(0, 0, 12, 6, WHITE);
  display.drawTriangle(0, 0, 8, 0, 4, 4, BLACK);
  display.drawLine(4, 0, 4, 6, BLACK);

  display.drawLine(6, 5, 6, 6, BLACK);
  display.drawLine(8, 4, 8, 6, BLACK);
  display.drawLine(10, 2, 10, 6, BLACK);
  display.drawLine(12, 0, 12, 6, BLACK);

}
//=====================================================================================
void drawBatteryState(float v_bat) {
  display.fillRect(68, 0, 16, 7, WHITE);
  display.drawRect(83, 2, 1, 3, BLACK);
  display.drawRoundRect(68, 0, 15, 7, 2, BLACK);
  // 3, 44  4, 2 0, 76  0, 152
  //4,200 full  4
  //4,048       3
  //3,896       2
  //3,744       1
  //3,592       0
  //3,440 zero  -

  if (v_bat > 4500)   {
    display.fillRect(70, 2, 10, 3, BLACK);
  }
  if (v_bat > 4048)   {
    display.drawRect(79, 2, 2, 3, BLACK);
  }
  if (v_bat > 3896)   {
    display.drawRect(76, 2, 2, 3, BLACK);
  }
  if (v_bat > 3744)    {
    display.drawRect(73, 2, 2, 3, BLACK);
  }
  if (v_bat > 3592)    {
    display.drawRect(70, 2, 2, 3, BLACK);
  }
}
//=====================================================================================
void drawTime(byte x, byte y) {
  display.fillRect(0 + x, 0 + y, 48, 7, WHITE);
  //display.fillRect(0+x, 0+y, 30, 7, WHITE);
  Time t = rtc.time();
  display.setTextColor(BLACK);
  display.setTextSize(1);
  display.setCursor(x, y);
  display.print(t.hr);
  display.print(":");
  display.print(t.min);
  display.print(":");
  display.print(t.sec);
}
//===========================================================================================
void updateMoonSunDate()
{
  Time t = rtc.time();
  today[0] = 0;
  today[1] = 0;
  today[2] = 12;
  today[3] = t.date;
  today[4] = t.mon;
  today[5] = t.yr - 2000;
}
//=====================================================================================
void drawSunRiseSet(byte x, byte y) {
  updateMoonSunDate();
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.fillRect(x, y, 33, y + 8, WHITE);

  if (tardis.SunRise(today)) // if the sun will rise today (it might not, in the [ant]arctic)
  {
    display.setCursor(x, y);
    display.print((int) today[tl_hour]);
    display.print(":");
    display.println((int) today[tl_minute]);
  }
  if (tardis.SunSet(today)) // if the sun will set today (it might not, in the [ant]arctic)
  {
    display.setCursor(x, y + 8);
    display.print((int) today[tl_hour]);
    display.print(":");
    display.println((int) today[tl_minute]);
  }

}
//=====================================================================================
void drawPressure(byte x, byte y) {
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.fillRect(x, y, 33, y + 8, WHITE);
  display.setCursor(x, y);
  t_f = Temperature;
  display.println( t_f / 10, 1);
  display.setCursor(x, y + 8);
  //display.println(ceil(Pressure / 133.3), 0);
  display.println(Pressure / 133.3, 1);
}
//=====================================================================================
long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

  delay(75); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both

  long result = (high << 8) | low;

  //scale_constant = internal1.1Ref * 1023 * 1000
  //
  //internal1.1Ref = 1.1 * Vcc1 (_) / Vcc2 (__readVcc())
  //4.967/4600-------1215079.369565217
  // result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*100000
  result = 1132060 / result;

  return result; // Vcc in millivolts
  //http://blog.unlimite.net/?p=25
}
//===========================================================================================
void drawVcc(byte x, byte y, word vcc) {
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.fillRect(x, y, 33, y + 8, WHITE);
  display.setCursor(x, y);
  display.println(vcc);
}
//=====================================================================================
void pressure_drawLine(byte x, byte h)
{
  display.drawLine(x, 47 - h, x, 47, BLACK);
}
void pressure_drawGraph()
{
  display.fillRect(0, 25, 83, 47, WHITE);
  for (int i = 0; i <= 83; i++) {
    pressure_drawLine(i, EEPROM.read(i));
  }
}

//===========================================================================================
void setup()
{
  Serial.begin(9600);
 
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(2, OUTPUT);
  //-----------------------------------------------------------------------------
  //rtc.writeProtect(false);
  //rtc.halt(false);
  String day = dayAsString(t.day);
  //-----------------------------------------------------------------------------
  tardis.TimeZone(3 * 55);
  tardis.Position(LATITUDE, LONGITUDE);
  //-----------------------------------------------------------------------------
  Wire.begin();
  display.begin();
  display.setContrast(55);
  display.clearDisplay();

  display.drawLine(0, display.height() / 2, display.width(), display.height() / 2, BLACK);
  dps.init();

  updateMoonSunDate();
  drawMoonDate(34, 8, today);
  pressure_drawGraph();
  display.display();

  prevHour = rtc.time().hr;
  //EEPROM.write(0, 9);
  // for (int i=0; i <= 83; i++){
  // EEPROM.write(i, random(1, 23));
  //   pressure_drawLine(i,EEPROM.read(i));
  //     Serial.println(EEPROM.read(i));
  // }

}
//=====================================================================================
void loop()
{
  unsigned long currentMillis = millis();
  unsigned long currentMillis2 = millis();
  byte temp;

  //timer---------------------- 1 hour
  //  if (currentMillis - previousMillis > interval) {
  //  previousMillis = currentMillis;
  if (rtc.time().hr != prevHour) {
    prevHour = rtc.time().hr;

    dps.getPressure(&Pressure);
    dps.getTemperature(&Temperature);

    for (int i = 0; i <= 82; i++) {
      temp = EEPROM.read(i + 1);
      EEPROM.write(i, temp);
    }
    EEPROM.write(83, ceil(Pressure / 133.3) - 740);
    pressure_drawGraph();
    display.display();


  }
  //timer---------------------- 1 sec
  // if (currentMillis2 - previousMillis2 > interval2) {
  //   previousMillis2 = currentMillis2;

  if (rtc.time().sec != prevSecond) {
    prevSecond = rtc.time().sec;

    dps.getPressure(&Pressure);
    dps.getTemperature(&Temperature);
    updateMoonSunDate();

    drawPressure(0, 8);
    drawTime(17, 0);
    drawSunRiseSet(53, 8);
    drawMoonDate(34, 8, today);
    drawBatteryState(readVcc());
    drawSignal(5);
    //    drawVcc(0, 16, readVcc());
    display.display();
  }
  //timer----------------------

  buttonState = digitalRead(8);
  // Serial.println(buttonState);
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
    }
  }
  lastButtonState = buttonState;
  if (buttonPushCounter % 2 == 0) {
    digitalWrite(2, HIGH);
  } else {
    digitalWrite(2, LOW);
  }
}
//=====================================================================================

Source: https://habr.com/ru/post/ar392831/


All Articles