Категории

Метеостанция на esp32 - медицинский режим

23.12.2025 | коды из категории: Простотак

про Метеостанция на esp32 с возможностью предсказывать головные боли по погоде

Эта пример кодов для метеостанции, которая анализирует текущие погодные параметры и сравнивает их с известными триггерами обострения симптомов при височно-нижнечелюстном суставе (TMJ), бруксизме и хроническом мышечном напряжении. Ну вы можете добавить под свои болячки ) Если обнаружено совпадение — вы получаете персонализированное предупреждение.

🔔 Система срабатывает при:

На основе данных от датчиков (давление, влажность, температура) и алгоритма, учитывающего медицинские исследования (например, из Journal of Oral Rehabilitation), система выдаёт рекомендации: «Сегодня — день для TENS-терапии», «Избегайте твёрдой пищи», «Сделайте расслабляющую гимнастику для челюсти» и т.п.

Не погода болит — болит реакция на неё. Эта станция помогает быть на шаг впереди.

📡 Входные данные (сенсоры)

float pressure_hPa;     // атмосферное давление (гПа)
float temp_C;           // температура (°C)
float humidity_percent; // влажность (%)
float solar_flux;       // упрощённо: яркость/UV или геомагнитная активность (Kp-индекс)
// (если нет солнечного датчика — можно брать из интернета или заменить на "резкость изменения давления за час")

🧠 Логика рекомендаций (с приоритетами)

String getMedicalAdvice() {
  String advice = "";

  // 1. Падение давления → TMJ/голова/спазмы
  if (pressure_trend < -3.0) { // если за последний час давление упало >3 гПа
    advice += "⚠️ Чувствительность повышена!\n";
    if (temp_C < 10 || temp_C > 30) {
      advice += "❄️🔥 + экстремальная температура → мышечные спазмы!\n";
    }
    advice += "Сегодня — день покоя для челюсти и шеи.\n";
    return advice;
  }

  // 2. Высокая влажность + тепло → отёчность
  if (humidity_percent > 75 && temp_C > 25) {
    advice += "💧 Жарко и сыро → возможны отёки в суставах!\n";
    advice += "Пей воду, избегай соли и твёрдой пищи.\n";
    return advice;
  }

  // 3. Резкие перепады температуры (день/ночь или час/час)
  if (abs(temp_trend_last_hour) > 5.0) {
    advice += "🌡️ Резкая смена температуры → риск головной боли!\n";
    advice += "Одевайся по погоде, избегай сквозняков.\n";
    return advice;
  }

  // 4. Высокая геомагнитная активность (если есть данные)
  if (geo_magnetic_index > 5) { // Kp ≥ 5 = возмущение
    advice += "🧲 Магнитная буря! У многих — усталость, мигрень.\n";
    advice += "Отдыхай, избегай стресса и кофеина.\n";
    return advice;
  }

  // 5. Солнечная активность + высокое давление → "ясно, но напряжённо"
  if (solar_flux > 80 && pressure_hPa > 1020) {
    advice += "☀️ Антициклон + солнце → перевозбуждение!\n";
    advice += "Мозг может «перегреться» — снижай нагрузку.\n";
    return advice;
  }

  // 6. Всё нормально
  advice = "🙂 Погода стабильна. Отличный день для работы!\n";
  return advice;
}

🔧 Как получить pressure_trend и temp_trend?
Храни предыдущие значения в памяти ESP32 и обновляй каждые 15–60 минут:

// Глобальные переменные
float prev_pressure = 0;
float prev_temp = 0;
unsigned long last_update = 0;

// В loop():
if (millis() - last_update > 3600000) { // раз в час
  pressure_trend = pressure_hPa - prev_pressure;
  temp_trend_last_hour = temp_C - prev_temp;
  prev_pressure = pressure_hPa;
  prev_temp = temp_C;
  last_update = millis();
}


Если с Wi-Fi подключением — можно раз в час дергать API вроде:
https://services.swpc.noaa.gov/products/noaa-planetary-k-index.json (Kp-индекс)
Или простой UV-датчик (VEML6075) → косвенно = «солнечная энергия»


💡 Идеи для UI на экране (например, 240x320 TFT)
Крупный шрифт: "СЕГОДНЯ ОПАСНО ДЛЯ..." → "ЧЕЛЮСТИ", "ГОЛОВЫ", "МЫШЦ"
Иконки: 🌪️ 💧 🧲 ☀️ ❄️
Цвет фона: красный — при угрозе, зелёный — всё ок

Пример вывода на экран:

[ 24 ДЕК 2025 | 14:00 ]
АТМ. ДАВЛ.: 998 гПа ↓
ТЕМП.: 6°C | ВЛАЖН.: 82%

⚠️ Чувствительность повышена!
❄️ + экстремальная температура → мышечные спазмы!
Сегодня — день покоя для челюсти и шеи.

готовый .ino

#include <Wire.h>
#include <Adafruit_BME280.h>
#include <TFT_eSPI.h>

// Инициализация BME280
Adafruit_BME280 bme;

// Инициализация TFT
TFT_eSPI tft = TFT_eSPI();

// Переменные для трендов
float prev_pressure = 0.0;
float prev_temp = 0.0;
unsigned long last_measurement = 0;
const unsigned long MEASURE_INTERVAL = 15 * 60 * 1000; // 15 минут

// Текущие значения
float pressure_hPa = 0;
float temp_C = 0;
float humidity_percent = 0;
float pressure_trend = 0;
float temp_trend = 0;

// Флаг первого запуска
bool first_run = true;

void setup() {
  Serial.begin(115200);

  // Инициализация BME280
  if (!bme.begin(0x76)) {
    Serial.println("BME280 не найден!");
    while (1);
  }

  // Инициализация TFT
  tft.init();
  tft.setRotation(1); // подстрой под ориентацию
  tft.fillScreen(TFT_BLACK);
  
  // Первое чтение
  readSensors();
  prev_pressure = pressure_hPa;
  prev_temp = temp_C;
  last_measurement = millis();
  
  drawScreen();
}

void loop() {
  unsigned long now = millis();
  
  if (now - last_measurement >= MEASURE_INTERVAL) {
    readSensors();
    pressure_trend = pressure_hPa - prev_pressure;
    temp_trend = temp_C - prev_temp;
    prev_pressure = pressure_hPa;
    prev_temp = temp_C;
    last_measurement = now;
    
    drawScreen();
    first_run = false;
  }

  delay(1000);
}

void readSensors() {
  pressure_hPa = bme.readPressure() / 100.0F;    // в гПа
  temp_C = bme.readTemperature();
  humidity_percent = bme.readHumidity();
}

String getMedicalAdvice() {
  if (first_run) {
    return "Ожидание данных...\nСкоро будет прогноз!";
  }

  // Условия по трендам и значениям
  if (pressure_trend < -3.0) {
    String msg = "⚠️ Давление падает!\n";
    if (temp_C < 8 || temp_C > 30) {
      msg += "❄️🔥 + экстр. темп →\nспазмы!\n";
    }
    msg += "Отдых для челюсти и шеи!";
    return msg;
  }

  if (humidity_percent > 75 && temp_C > 25) {
    return "💧 Жарко + сыро →\nотёки в суставах!\nПей воду, избегай соли.";
  }

  if (abs(temp_trend) > 5.0) {
    return "🌡️ Резкий скачок темп →\nриск головной боли!\nИзбегай сквозняков.";
  }

  // Упрощённая "магнитная буря" — отключена без интернета
  // Можно позже добавить Kp через Wi-Fi

  return "🙂 Погода стабильна.\nХороший день для\nработы и отдыха!";
}

void drawScreen() {
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_GREEN);
  tft.setTextSize(2);
  tft.setCursor(10, 10);
  tft.println("МИКРОПРОГНОЗ");

  tft.setTextSize(1);
  tft.setCursor(10, 40);
  tft.printf("ДАВЛ: %.0f hPa", pressure_hPa);
  if (!first_run) {
    if (pressure_trend < -0.5) tft.print(" ↓");
    else if (pressure_trend > 0.5) tft.print(" ↑");
  }
  tft.setCursor(10, 60);
  tft.printf("ТЕМП: %.1f C", temp_C);
  tft.setCursor(10, 80);
  tft.printf("ВЛАЖ: %.0f%%", humidity_percent);

  // Отображение совета
  String advice = getMedicalAdvice();
  tft.setTextSize(1);
  tft.setCursor(10, 110);

  if (advice.indexOf("⚠️") != -1 || advice.indexOf("💧") != -1 || advice.indexOf("🌡️") != -1) {
    tft.setTextColor(TFT_YELLOW);
  } else {
    tft.setTextColor(TFT_GREEN);
  }

  // Вывод многострочного текста (наивно, но работает)
  int16_t x = 10, y = 110;
  int16_t lineHeight = 16;
  int start = 0;
  for (int i = 0; i <= advice.length(); i++) {
    if (advice[i] == '\n' || i == advice.length()) {
      tft.setCursor(x, y);
      tft.print(advice.substring(start, i));
      y += lineHeight;
      start = i + 1;
    }
  }
}

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку

Посетителей сегодня: 0


кто я | о блоге

© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA