Skocz do zawartości

Problem z zaprogramowaniem czujnika poziomu cieczy Grove Seeedstudio 101020635


Pomocna odpowiedź

Napisano (edytowany)

Witam,

zakupiłem czujnik poziomu cieczy wymieniony w tytule, jednak pomimo zrealizowania kursu nie potrafię go zaprogramować. Producent podał przykładowy kod lecz jest on dla mnie nieczytelny. 

#include <Wire.h>

#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif

unsigned char low_data[8] = {0};
unsigned char high_data[12] = {0};


#define NO_TOUCH       0xFE
#define THRESHOLD      100
#define ATTINY1_HIGH_ADDR   0x78
#define ATTINY2_LOW_ADDR   0x77

void getHigh12SectionValue(void)
{
  memset(high_data, 0, sizeof(high_data));
  Wire.requestFrom(ATTINY1_HIGH_ADDR, 12);
  while (12 != Wire.available());

  for (int i = 0; i < 12; i++) {
    high_data[i] = Wire.read();
  }
  delay(10);
}

void getLow8SectionValue(void)
{
  memset(low_data, 0, sizeof(low_data));
  Wire.requestFrom(ATTINY2_LOW_ADDR, 8);
  while (8 != Wire.available());

  for (int i = 0; i < 8 ; i++) {
    low_data[i] = Wire.read(); // receive a byte as character
  }
  delay(10);
}

void check()
{
  int sensorvalue_min = 250;
  int sensorvalue_max = 255;
  int low_count = 0;
  int high_count = 0;
  while (1)
  {
    uint32_t touch_val = 0;
    uint8_t trig_section = 0;
    low_count = 0;
    high_count = 0;
    getLow8SectionValue();
    getHigh12SectionValue();

    Serial.println("low 8 sections value = ");
    for (int i = 0; i < 8; i++)
    {
      Serial.print(low_data[i]);
      Serial.print(".");
      if (low_data[i] >= sensorvalue_min && low_data[i] <= sensorvalue_max)
      {
        low_count++;
      }
      if (low_count == 8)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }
    Serial.println("  ");
    Serial.println("  ");
    Serial.println("high 12 sections value = ");
    for (int i = 0; i < 12; i++)
    {
      Serial.print(high_data[i]);
      Serial.print(".");

      if (high_data[i] >= sensorvalue_min && high_data[i] <= sensorvalue_max)
      {
        high_count++;
      }
      if (high_count == 12)
      {
        Serial.print("      ");
        Serial.print("PASS");
      }
    }

    Serial.println("  ");
    Serial.println("  ");

    for (int i = 0 ; i < 8; i++) {
      if (low_data[i] > THRESHOLD) {
        touch_val |= 1 << i;

      }
    }
    for (int i = 0 ; i < 12; i++) {
      if (high_data[i] > THRESHOLD) {
        touch_val |= (uint32_t)1 << (8 + i);
      }
    }

    while (touch_val & 0x01)
    {
      trig_section++;
      touch_val >>= 1;
    }
    SERIAL.print("water level = ");
    SERIAL.print(trig_section * 5);
    SERIAL.println("% ");
    SERIAL.println(" ");
    SERIAL.println("*********************************************************");
    delay(1000);
  }
}

void setup() {
  SERIAL.begin(115200);
  Wire.begin();
}

void loop()
{
  check();
}


 

Zależy mi na pobraniu informacji o poziomie cieczy oraz przypisaniu jej do zmiennej. Czy jest ktoś w stanie wytłumaczyć poszczególne elementy powyższego kodu lub napisać własny ale mniej skomplikowany. Największą wartość ma dla mnie zrozumienie kodu a nie tylko przekopiowanie.

Z góry dziękuje za odpowiedź.

Edytowano przez piet
źle wstawiony kod
Dnia 21.09.2024 o 20:33, piet napisał:

Producent podał przykładowy kod lecz jest on dla mnie nieczytelny. 

Wrzuć w AI, niech ci opisze kod, może coś rozjaśni. Tak komentuje gpt4o.
 

#include <Wire.h> // Importuje bibliotekę Wire do komunikacji I2C

// Ustawia odpowiedni interfejs szeregowy w zależności od platformy
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif

// Deklaracja tablic na dane z odczytów I2C
unsigned char low_data[8] = {0};  // Tablica na 8 bajtów danych z niskiego adresu
unsigned char high_data[12] = {0}; // Tablica na 12 bajtów danych z wysokiego adresu

// Stałe definiujące pewne progi i adresy I2C
#define NO_TOUCH       0xFE    // Wartość oznaczająca brak dotyku (niewykorzystana w kodzie)
#define THRESHOLD      100     // Próg dla wykrywania
#define ATTINY1_HIGH_ADDR   0x78  // Adres I2C pierwszego urządzenia
#define ATTINY2_LOW_ADDR    0x77  // Adres I2C drugiego urządzenia

// Funkcja odczytująca 12 bajtów z urządzenia pod adresem ATTINY1_HIGH_ADDR
void getHigh12SectionValue(void)
{
  memset(high_data, 0, sizeof(high_data)); // Czyści tablicę high_data
  Wire.requestFrom(ATTINY1_HIGH_ADDR, 12); // Żąda 12 bajtów z urządzenia
  while (12 != Wire.available()); // Czeka aż wszystkie bajty będą dostępne
  for (int i = 0; i < 12; i++) {
    high_data[i] = Wire.read(); // Odczytuje dane i zapisuje do tablicy
  }
  delay(10); // Krótka przerwa, na stabilizację
}

// Funkcja odczytująca 8 bajtów z urządzenia pod adresem ATTINY2_LOW_ADDR
void getLow8SectionValue(void)
{
  memset(low_data, 0, sizeof(low_data)); // Czyści tablicę low_data
  Wire.requestFrom(ATTINY2_LOW_ADDR, 8); // Żąda 8 bajtów z urządzenia
  while (8 != Wire.available()); // Czeka aż wszystkie bajty będą dostępne
  for (int i = 0; i < 8; i++) {
    low_data[i] = Wire.read(); // Odczytuje dane i zapisuje do tablicy
  }
  delay(10); // Krótka przerwa, na stabilizację
}

// Funkcja analizująca odczytane dane i obliczająca poziom wody
void check()
{
  int sensorvalue_min = 250; // Minimalna wartość dla czujników do zaliczenia
  int sensorvalue_max = 255; // Maksymalna wartość dla czujników do zaliczenia
  int low_count = 0;         // Licznik dla sekcji niskich
  int high_count = 0;        // Licznik dla sekcji wysokich

  while (1)
  {
    uint32_t touch_val = 0;   // Przechowuje wartości sekcji po przekroczeniu progu
    uint8_t trig_section = 0; // Liczy, ile sekcji przekroczyło próg
    low_count = 0;
    high_count = 0;

    getLow8SectionValue();     // Pobiera wartości niskich sekcji
    getHigh12SectionValue();   // Pobiera wartości wysokich sekcji

    SERIAL.println("low 8 sections value = ");
    for (int i = 0; i < 8; i++)
    {
      SERIAL.print(low_data[i]); // Drukuje każdą wartość z niskich sekcji
      SERIAL.print(".");
      if (low_data[i] >= sensorvalue_min && low_data[i] <= sensorvalue_max)
      {
        low_count++; // Zlicza ilość wartości mieszczących się w przedziale
      }
      if (low_count == 8)
      {
        SERIAL.print("      ");
        SERIAL.print("PASS"); // Drukuje "PASS", jeśli wszystkie wartości spełniają warunek
      }
    }

    SERIAL.println("  ");
    SERIAL.println("  ");

    SERIAL.println("high 12 sections value = ");
    for (int i = 0; i < 12; i++)
    {
      SERIAL.print(high_data[i]); // Drukuje każdą wartość z wysokich sekcji
      SERIAL.print(".");
      if (high_data[i] >= sensorvalue_min && high_data[i] <= sensorvalue_max)
      {
        high_count++; // Zlicza ilość wartości mieszczących się w przedziale
      }
      if (high_count == 12)
      {
        SERIAL.print("      ");
        SERIAL.print("PASS"); // Drukuje "PASS", jeśli wszystkie wartości spełniają warunek
      }
    }

    SERIAL.println("  ");
    SERIAL.println("  ");

    // Przetwarza dane i przekształca je na wartość binarną touch_val
    for (int i = 0; i < 8; i++) {
      if (low_data[i] > THRESHOLD) {
        touch_val |= 1 << i; // Ustawia odpowiednie bity dla sekcji niskich
      }
    }
    for (int i = 0; i < 12; i++) {
      if (high_data[i] > THRESHOLD) {
        touch_val |= (uint32_t)1 << (8 + i); // Ustawia odpowiednie bity dla sekcji wysokich
      }
    }

    // Liczy ilu-sekcyjne detekcje zostały uruchomione
    while (touch_val & 0x01)
    {
      trig_section++;
      touch_val >>= 1;
    }

    // Oblicza poziom wody w procentach i drukuje wynik
    SERIAL.print("water level = ");
    SERIAL.print(trig_section * 5);
    SERIAL.println("% ");
    SERIAL.println(" ");
    SERIAL.println("*********************************************************");

    delay(1000); // Opóźnienie przed kolejnym pomiarem
  }
}

void setup() {
  SERIAL.begin(115200); // Inicjalizuje komunikację szeregową z prędkością 115200 bps
  Wire.begin();         // Inicjalizuje interfejs I2C
}

void loop()
{
  check(); // Nieskończona pętla wykonywująca funkcję check()
}

 

Ten program wiele się nie da uprościć.

Z czujnika trzeba pobrać sporo danych - 8 bajtów z jednego adresu i 12 bajtów z drugiego. Problem tylko jak te dane interpretować; przydałby się jakiś podręcznik użytkownika, ale tak na szybko nie udało mi się go znaleźć.

 

Widziałem tę stronę z kodem.

Jest tam nawet animowany obraz ekranu, przedstawiający wynik działania programu, ale niewiele on pomaga w zrozumieniu struktury danych.

Trzeba by pobawić się czujnikiem, zanurzając go stopniowo i obserwując dane, przy jednoczesnej analizie kodu.

(edytowany)

Biorąc pod uwagę brak dokumentacji w desperacji można z tego kodu wywnioskować, że końcowy wynik (liczbę zanurzonych sekcji czujnika) ustala się się jako liczbę kolejnych następujących po sobie odczytanych bajtów (z 8 + 12 = 20 bajtów reprezentujących kolejnych 20 sekcji czujnika), które mają wartość powyżej wartości THRESHOLD (w kodzie zdefiniowana na 100). Jeżeli odczytany bajt ma wartość mniejszą niż THRESHOLD to ten bajt i wszystkie następne są pomijane przy obliczaniu wyniku (nawet gdybyś jeszcze któreś miały wartość powyżej THRESHOLD). Każdy zliczony bajt dodaje 5% (1 z 20) do wyniku głębokości zanurzenia.

Zliczanie liczby odczytów powyżej progu (wynik trafia do trig_section) odbywa się w tym fragmencie:

    for (int i = 0 ; i < 8; i++) {
      if (low_data[i] > THRESHOLD) {
        touch_val |= 1 << i;

      }
    }
    for (int i = 0 ; i < 12; i++) {
      if (high_data[i] > THRESHOLD) {
        touch_val |= (uint32_t)1 << (8 + i);
      }
    }

    while (touch_val & 0x01)
    {
      trig_section++;
      touch_val >>= 1;
    }

Ponadto ten fragment przykładowego programu - dwie pętle - zawiera jakąś dodatkową weryfikację danych z sygnalizacją na konsoli, ale bez wpływu na dalszy przebieg programu - nie ma nic wspólnego z obliczaniem wyniku:

    Serial.println("low 8 sections value = ");
    for (int i = 0; i < 8; i++)
    {
     	// (...) zobacz wyzej
    }
    Serial.println("  ");
    Serial.println("  ");
    Serial.println("high 12 sections value = ");
    for (int i = 0; i < 12; i++)
    {
      // (...) zobacz wyzej
    }

 

 

 

Edytowano przez ReniferRudolf

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...