Untitled

 avatar
unknown
plain_text
5 months ago
10 kB
3
Indexable
#include <SoftwareSerial.h>
#include <avr/sleep.h>  // Biblioteka do zarządzania trybem uśpienia
#include <avr/wdt.h>

#define powerPIN     7//Arduino Digital pin used to power up / power down the modem
#define resetPIN     6//Arduino Digital pin used to reset the modem 
#define statusPIN    5//Arduino Digital pin used to monitor if modem is powered 

// Define the RX and TX pins for SoftwareSerial
SoftwareSerial gsmSerial(2, 3); // RX, TX
const int controlPin = 8;     // Pin do podtrzymywania stanu wysokiego

#define TF02_RX_PIN 10 // Pin for TF02 sensor RX
#define TF02_TX_PIN 11 // Pin for TF02 sensor TX

SoftwareSerial tf02Serial(TF02_RX_PIN, TF02_TX_PIN); // SoftwareSerial instance for TF02 sensor

#define powerKeyPin 7  // PWRKEY modułu GSM
#define converterControlPin 8 // Pin sterujący przetwornicą (stan niski = włącz)

// Czas uśpienia (4 godziny)
#define SLEEP_TIME 60 // W sekundach (4 * 3600)

const int NUM_READINGS = 5; // Number of readings to average
uint16_t distanceReadings[NUM_READINGS]; // Array to store distance readings
int currentIndex = 0; // Index for storing the current reading
uint16_t distance = 0;
const int analogPin = A0; // Wejście analogowe, np. A0

volatile bool wakeUp = false; // Flaga wybudzenia

// Liczba pomiarów
const int NUM_MEASUREMENTS = 16;
float data[NUM_MEASUREMENTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

// Parametry detekcji odstających wartości
const float THRESHOLD_MULTIPLIER = 0.2; // Próg w krotnościach odchylenia standardowego


// Funkcje pomocnicze
void powerOnGSM();
void powerOffGSM();
float readTF02Pro();
void sendSMS(String phoneNumber, String message);
void goToSleep(unsigned long seconds);
unsigned long sleepTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(powerKeyPin, OUTPUT);
  pinMode(converterControlPin, OUTPUT);
  digitalWrite(converterControlPin, HIGH); // Włącz zasilanie czujnika (jeśli sterowane)
  Serial.println("System uruchomiony.");

    // Initialize distance readings array
  for (int i = 0; i < NUM_READINGS; i++) {
    distanceReadings[i] = 0;
  }
}

void loop() {

  float voltage = readVoltage(analogPin); // Odczytaj napięcie z pinu analogowego
  Serial.print("Napiecie: ");
  Serial.print(voltage);
  Serial.println(" V");

  tf02Serial.begin(115200); // UART dla czujnika
  digitalWrite(converterControlPin, LOW);
  delay(3000); // Daj czujnikowi czas na stabilizację

  Serial.println("Wypełnanie tabelki:");

 for (int i = 0; i < 16; i++) {
  distance = readDistanceFromTF02();  
    if (distance != 0 && distance < 15000) {
    data[i] = distance;// Kod, który będzie wykonywany dopóki warunek jest prawdziwy
    Serial.print("zczytano pomiar, Odleglosc: ");
    Serial.print(distance);
    Serial.println(" cm");
  }
  else{
    Serial.print("Odrzucono pomiar, Odleglosc: ");
    Serial.print(distance);
    i--;
  }
 }

  float wynikDoWyslania = odrzucBledne(data, 16);

  digitalWrite(converterControlPin, HIGH);

  gsmSerial.begin(57600);  // UART dla modułu GSM
  powerOnGSM();
  delay(5000);
  sendSMS("+48602806856", "Odleglosc wynosi: " + String(distance) + " cm, napiecie baterii wynosi: " + String(voltage) + " V.");

  sleepTime = 60; // Czas w sekundach
  Serial.println("Przechodzę w stan uśpienia na 10 sekund...");
  delay(1000);
  preciseSleep(sleepTime);
}

float odrzucBledne(float pomiary[], int liczbapomiarow){
  // Próg w krotnościach odchylenia standardowego
  const float THRESHOLD_MULTIPLIER = 0.5;
  int licznikOdrzuconych = 0;

  Serial.println("Rozpoczynam analizę danych...");

  float mean = calculateMean(pomiary, liczbapomiarow);
  Serial.print("Średnia: ");
  Serial.println(mean);

  // Oblicz odchylenie standardowe
  float stdDev = calculateStandardDeviation(pomiary, liczbapomiarow, mean);
  Serial.print("Odchylenie standardowe: ");
  Serial.println(stdDev);

Serial.println("Pomiary odrzucone:");
  for (int i = 0; i < liczbapomiarow; i++) {
    if (abs(pomiary[i] - mean) > THRESHOLD_MULTIPLIER * stdDev) {
      Serial.print("Wartość odstająca: ");
      Serial.println(pomiary[i]);
      licznikOdrzuconych += 1;
    }
  } 
Serial.println("Nowa tabelka:");
  int roznicaPomiarow = (liczbapomiarow-licznikOdrzuconych);
  Serial.println(roznicaPomiarow);
  float poprawionaTabelka[roznicaPomiarow];
  int licznikDodanych = 0;
  for (int i = 0; i < liczbapomiarow; i++) {
    if (abs(pomiary[i] - mean) < THRESHOLD_MULTIPLIER * stdDev){
      Serial.print("Wartość dodana do tabelki: ");
      Serial.println(pomiary[i]);
      poprawionaTabelka[licznikDodanych] = pomiary[i];
      licznikDodanych += 1;
    }
  }
  float meanFinal = calculateMean(poprawionaTabelka, roznicaPomiarow);
  return meanFinal;
}

// Funkcja do obliczenia średniej
float calculateMean(float arr[], int size) {
  float sum = 0;
  for (int i = 0; i < size; i++) {
    sum += arr[i];
  }
  return sum / size;
}

// Funkcja do obliczenia odchylenia standardowego
float calculateStandardDeviation(float arr[], int size, float mean) {
  float sumSqDiff = 0;
  for (int i = 0; i < size; i++) {
    sumSqDiff += pow(arr[i] - mean, 2);
  }
  return sqrt(sumSqDiff / size);
}

float readVoltage(int pin) {
  int analogValue = analogRead(pin); // Odczytaj wartość analogową (0-1023)
  float voltage = analogValue * (5.0 / 1023.0) * 5.63; // Przeskaluj wartość na zakres napięcia (0-5V)
  return voltage;
}

// Function to send AT commands and print responses
void sendATCommand(String command) {
  gsmSerial.println(command);       // Send the command to the GSM module
  delay(100);                       // Wait for a response
  while (gsmSerial.available()) {
    Serial.write(gsmSerial.read()); // Display GSM response on Serial Monitor
  }
}

uint16_t readDistanceFromTF02() {
  // Send command to request distance data
  tf02Serial.write((uint8_t)0x5A); // Command to request distance data
  tf02Serial.write((uint8_t)0x05); // Data length
  tf02Serial.write((uint8_t)0x00); // Data byte 1
  tf02Serial.write((uint8_t)0x00); // Data byte 2
  tf02Serial.write((uint8_t)0x00); // Data byte 3
  tf02Serial.write((uint8_t)0x01); // Data byte 4

  // Read response
  uint8_t response[9];
  tf02Serial.readBytes(response, 9);

  // Check if response is valid
  if (response[0] == 0x59 && response[1] == 0x59) {
    // Extract distance data
    uint16_t distance = (response[3] << 8) | response[2]; // Combine high and low bytes
    return distance;
  } else {
    return 0; // Invalid response, return 0 distance
  }
}

// Function to send SMS
void sendSMS(String phoneNumber, String message) {
  // Send an AT command to check if GSM module is responding
  sendATCommand("AT");
  delay(2000);
  // Set the SMS text mode
  sendATCommand("AT+CMGF=1"); // Set SMS mode to text
  delay(2000);
  // Send the AT command to start the SMS process
  gsmSerial.print("AT+CMGS=\"");
  gsmSerial.print(phoneNumber);
  gsmSerial.println("\"");
  delay(2000); // Wait for prompt
  // Send the SMS message
  gsmSerial.print(message);
  delay(500);
  // Send the Ctrl+Z character to indicate end of message (ASCII code 26)
  gsmSerial.write(26);
  delay(5000); // Wait for the message to be sent
  // Print the result of the send operation
  Serial.println("SMS sent!");
  powerOffGSM();

}
void powerOnGSM() {
   Serial.println("Włączam moduł.");
  digitalWrite(powerKeyPin, LOW);   // Pull the power key pin low
  delay(2000);                      // Hold it low for 1 second (power on pulse)
  digitalWrite(powerKeyPin, HIGH);  // Release the power key pin
  delay(10000);                      // Wait for 2 seconds for module to boot up
}
void powerOffGSM() {
  digitalWrite(powerKeyPin, LOW);   // release the power key pin low
  delay(2000);                      // Hold it low for 1 second (power on pulse)
  digitalWrite(powerKeyPin, HIGH);  // pull the power key pin
  delay(10000);                      // Wait for 2 seconds for module to boot up
  Serial.println("Moduł wyłączony.");
}

// Funkcja wprowadzająca Arduino w tryb uśpienia na określony czas (w sekundach)
void preciseSleep(unsigned long seconds) {
  const unsigned long WDT_CYCLE = 8; // Maksymalny czas jednego cyklu Watchdog Timer (8 sekund)
  unsigned long elapsedSeconds = 0; // Licznik czasu, który upłynął

  while (elapsedSeconds < seconds) {
    unsigned long remainingSeconds = seconds - elapsedSeconds;
    unsigned long sleepDuration = (remainingSeconds >= WDT_CYCLE) ? WDT_CYCLE : remainingSeconds;

    // Uśpij na czas sleepDuration
    setSleepMode(sleepDuration);

    // Zaktualizuj upływający czas
    elapsedSeconds += sleepDuration;
  }
}

// Funkcja konfiguracji Watchdog Timer i przejścia w tryb uśpienia
void setSleepMode(unsigned long duration) {
  // Mapowanie czasu na preskaler Watchdog Timer
  uint8_t wdt_prescaler;
  if (duration <= 1) wdt_prescaler = WDP0;
  else if (duration <= 2) wdt_prescaler = WDP1;
  else if (duration <= 4) wdt_prescaler = WDP2;
  else if (duration <= 8) wdt_prescaler = WDP3;
  else return; // Jeśli czas > 8 sekund, użyj wielu cykli

  // Utrzymywanie stanu wysokiego na pinie 8
  digitalWrite(controlPin, HIGH);

  // Konfiguracja Watchdog Timer
  cli();                              // Wyłącz przerwania
  MCUSR = 0;                          // Reset flag Watchdog Timer
  WDTCSR = (1 << WDCE) | (1 << WDE);  // Włącz tryb zmiany ustawień WDT
  WDTCSR = (1 << WDIE) | wdt_prescaler; // Włącz przerwanie WDT
  sei();                              // Włącz przerwania globalne

  // Ustawienie trybu uśpienia
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Tryb minimalnego zużycia energii
  sleep_enable();                     // Włącz tryb uśpienia

  // Przejście w tryb uśpienia
  sleep_cpu();

  // Po wybudzeniu
  sleep_disable(); // Wyłączenie trybu uśpienia
  sei();           // Włącz przerwania globalne
}

// Procedura obsługi przerwania Watchdog Timer
ISR(WDT_vect) {
  Serial.println("Wybudzono z uśpienia!");
  wakeUp = true; // Flaga wybudzenia
}
Editor is loading...
Leave a Comment