Stasiun cuaca seluler di Arduino

Mungkin setiap orang yang mulai berkenalan dengan Arduino, mengedipkan LED dan menghubungkan sebuah tombol, mulai membuat stasiun cuaca sendiri. Saya tidak terkecuali.

Setelah meninjau berbagai proyek di Internet, persyaratan tertentu dibuat. Perangkat harus menampilkan waktu, suhu, tekanan dan jadwal perubahannya. Saya juga sangat ingin menghitung fase bulan dan waktu matahari terbit-terbenam. Dan persyaratan yang paling penting adalah mobilitas. Stasiun cuaca portabel yang dibuat seharusnya digunakan untuk membantu menangkap ikan, jadi stasiun itu harus berukuran kecil dan memiliki otonomi tertentu.

Menciptakan tubuh untuk produk buatan sendiri merupakan tantangan tersendiri. Di tempat sampah, ponsel Motorola T192 ditemukan.

gambar

Ternyata layar dari Nokia 3310 semakin bagus di dalamnya (tentu saja, menggunakan Nokia 3310 itu sendiri, mungkin akan lebih nyaman).
Mengelola semuanya dipercayakan kepada Arduino Pro Mini.

gambar

Untuk mencegah tombol gagal, papan tempat memotong roti dimasukkan. Saat menempel kembali keyboard, terlihat bahwa nada lubang tata letak hampir bersamaan dengan tombol. Di masa depan, ini memungkinkan penggunaan tombol.

gambar

Untuk mengukur tekanan, sensor bmp180 digunakan. Modul ds1302 diambil sebagai jam, tetapi untuk menghemat ruang, hanya rangkaian mikro yang diambil darinya. Kuarsa telah dihapus dari motherboard, dan baterai dihapus dari laptop (tentu saja, Anda juga dapat menggunakan cr2032 yang biasa dalam casing termal).

gambar

Karena ada output gratis, lampu latar layar tergantung pada salah satu yang gratis dan tombol pada yang kedua.

gambar

Untuk mengisi daya baterai lithium, modul muatan Li-ion pada TP4056 digunakan.

gambar

Bentuk akhir perangkat (kabel yang menempel di kanan adalah untuk firmware, sehingga mereka akan segera dihapus.)

gambar

Saat menulis program, cara biasa digunakan. Satu-satunya hal yang ingin saya perhatikan adalah perpustakaan TimeLord.h (https://github.com/probonopd/TimeLord). Dengan menggunakan fungsinya, menunjukkan tanggal, koordinat dan zona waktu, Anda dapat menentukan waktu matahari terbit dan terbenam matahari, fase bulan. Deskripsi dapat diunduh di sini: TimeLord.pdf .

Mengenai daya tahan baterai, tes singkat menunjukkan bahwa perangkat akan bekerja selama seminggu tepatnya. Hasil ini cukup memuaskan, jadi percobaan lebih lanjut tentang konservasi energi telah ditunda.

Sketsa saat ini menggunakan 81% dari memori perangkat, sehingga Anda dapat menambahkan sesuatu yang lain.

gambar

Antena (indikator kekuatan sinyal) ditampilkan di layar. Ini meninggalkan cadangan untuk menguji modul radio 433 MHz, untuk mendapatkan suhu dan kelembaban yang benar dari modul eksternal.

Kode sumber
#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/id392831/


All Articles