[Из песочницы] Мобильная метеостанция на Arduino

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//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);
  }
}
//=====================================================================================


© Geektimes