Bramka 433Mhz odczyt parametrów

Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

Mam bramkę która odczytuje czujniki radiowe 433Mhz.
Temperaturę i wilgotność odczytuje prawidłowo lecz trzeci parametr którym jest wilgotność gleby nie udaje mi się odczytać. Co robie źle?
Poniżej program:

Kod: Zaznacz cały



#include <RFM69_ATC.h>                    //Pobierz z: https://github.com/lowpowerlab/rfm69
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>

#define OLED_RESET -1  // GPIO0
Adafruit_SSD1306 display(OLED_RESET);

#define NODEID 1                          //Unikalny numer bramki (1 - 254).
#define NETWORKID 100                     //Numer sieci (1 - 254) w której działą bramka SUPLA oraz inne transmitery. Bramka oraz max. 6 transmiterów musi działać w sieci o takim samym ID.
#define FREQUENCY RF69_433MHZ             //Jeśli posiadasz moduł radiowy pracujący z inną częstotliwością zamień parametr na RF69_433MHZ lub RF69_915MHZ.
//#define IS_RFM69HW_HCW                  //Usuń zacznik komentarza, jeśli posiadasz moduł radiowy w wersji RFM69HW/HCW.
#define ENCRYPTKEY "sampleEncryptKey"     //Klucz kodowania - 16 znaków (ani mniej, ani więcej) - identyczny w bramce SUPLA i we wszystkich transmiterach.
#define ENABLE_ATC                        //Wstaw znacznik komentarza jeśli chcesz wyłączyć automatyczną kontrolę transmisji (ATC).

#define SERIAL_BAUD 115200                //Prędkość transmisji portu szeregowego.

#define SUPLADEVICE_CPP
#include <SuplaDevice.h>

#define SUPLA_SERVER "svr4.supla.org"
#define LOCATION_ID 86
#define LOCATION_PASSWORD "8477"
// pobierz identyfikator urządzenia ze strony https://www.supla.org/arduino/get-guid i wprowadź go poniżej
#define GUID {0xE2,0x49,0x08,0x88,0x5D,0x77,0xB0,0x62,0x91,0x04,0xB2,0x1C,0x26,0x1D,0x20,0xD8}

RFM69_ATC radio(D3, D8, false);
bool promiscuousMode = false;

byte LED = 2;

const unsigned long period = 2400000;      //Czas (40 minut) po którym bramka uznaje brak odczytu z transmitera i ustawia wartości wysyłane do Supla Cloud na 0.
double temperature = 0.0;
double humidity = 0.0;
unsigned long startMillis = 0;
unsigned long currentMillis = 0;
unsigned long RFNodesCount = 0;
double wartosc;
typedef struct {
  int nodeid;
  int channelNumber;
  double temperature;
  double humidity;
  double batteryLevel;
  unsigned long lastContact;
} RF_TemperatureandHumidityNode;

RF_TemperatureandHumidityNode RFNodes[6];

void get_temperature_and_humidity(int channelNumber, double *temp, double *humidity) {

  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      *temp = RFNodes[i].temperature;
      *humidity = RFNodes[i].humidity;
    }
}
double get_temperature(int channelNumber, double last_val) {        //TA CZĘŚĆ PROGRMU NIE DZIAŁA PRAWIDŁOWO


  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
  return RFNodes[i].batteryLevel;
    }
  
}


#if (SSD1306_LCDHEIGHT != 48)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup() {
  Serial.begin(SERIAL_BAUD);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
  
  SuplaDevice.setTemperatureHumidityCallback(&get_temperature_and_humidity);
  SuplaDevice.setTemperatureCallback(&get_temperature);
  SuplaDevice.addDHT22();
  SuplaDevice.addDHT22();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
  
  char guid[SUPLA_GUID_SIZE] = GUID;
  uint8_t mac[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
  SuplaDevice.setName("BRAMKA SMMS-1");
  SuplaDevice.begin(guid, mac, SUPLA_SERVER, LOCATION_ID, LOCATION_PASSWORD); 
  
  radio.initialize(FREQUENCY,NODEID,NETWORKID);

#ifdef IS_RFM69HW_HCW
  radio.setHighPower();
#endif

  radio.encrypt(ENCRYPTKEY);
  //radio.promiscuous(promiscuousMode);

  char buff[65];
  sprintf(buff, "BRAMKA RB-10G. Start komunikacji radiowej na częstotliwości %d MHz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
}

byte ackCount = 0;
uint32_t packetCount = 0;

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length() - 1;

  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }

  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void readRadioData() {

  String value = "";
  if (radio.receiveDone())
  {
    int foundIdx = -1;

    for (int i = 0; i < RFNodesCount; i++)
      if (RFNodes[i].nodeid == radio.SENDERID)
      {
        foundIdx = i;
        break;
      }

    Serial.println("Odbieram dane...");
    if (foundIdx == -1)
    {
      if (RFNodesCount < 6)
      {
        Serial.println("Znalazłem nowy transmiter. Dodaję go do SUPLA Cloud");
        RFNodes[RFNodesCount].nodeid = radio.SENDERID;
        RFNodes[RFNodesCount].lastContact = millis();
        RFNodes[RFNodesCount].channelNumber = radio.SENDERID - 1;
        RFNodes[RFNodesCount].temperature = 0.0;
        RFNodes[RFNodesCount].humidity = 0.0;
        RFNodes[RFNodesCount].batteryLevel = 0;
        
        foundIdx = RFNodesCount;
        RFNodesCount++;
      } else {
        Serial.println("Maksymalna ilość transmiterów przekroczona!");
        foundIdx = 0;
      }
    } else
    {
      RFNodes[foundIdx].temperature = 0.0;
    }

    Serial.print("#[");
    Serial.print(++packetCount);
    Serial.print(']');
    Serial.print('['); Serial.print(radio.SENDERID, DEC); Serial.print("] ");

    value = "";
    for (byte i = 0; i < radio.DATALEN; i++)
      if (radio.DATA[i] != ' ')
        value += (char)radio.DATA[i];

    Serial.println(value);

    String tempStr = getValue(value, '|', 0);
    String humStr = getValue(value, '|', 1);
    String battLevelStr = getValue(value, '|', 2);
    wartosc = battLevelStr.toFloat();

    Serial.print("Temperatura: ");
    Serial.println(tempStr);
    Serial.print("Wilgotność: ");
    Serial.println(humStr);
    Serial.print("Poziom baterii: ");
    Serial.println(battLevelStr);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.display();
  display.setCursor(0,0);
  display.print("Temp:" + tempStr + "C");
  display.setCursor(0, 12);
  display.print("Hum: " + humStr + "%");
  display.setCursor(0, 24);
  display.print("Gleba:");
  display.setCursor(38, 24);
  display.print(battLevelStr + "%");
  display.setCursor(0, 36);
  display.print("RSSI:");
  display.setCursor(30, 36);
  display.print(radio.RSSI);
  display.setCursor(48, 36);
  display.print("dB");
  display.display();

    RFNodes[foundIdx].temperature = tempStr.toFloat();
    RFNodes[foundIdx].humidity = humStr.toFloat();
    RFNodes[foundIdx].batteryLevel = battLevelStr.toFloat();
    RFNodes[foundIdx].lastContact = millis();

    Serial.print("Poziom sygnału transmitera [RX_RSSI]:"); Serial.print(radio.RSSI); Serial.print(" dBm");

    if (radio.ACKRequested())
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      
      if (ackCount++ % 3 == 0)
      {
        Serial.print(" ACK TEST - Transmiter ");
        Serial.print(theNodeID);
        delay(5);
        radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0);
      }
    }

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  delay(60);
  digitalWrite(LED, HIGH);

  }

  for (int i = 0; i < RFNodesCount; i++)
  {
    if (millis() - RFNodes[i].lastContact >= period)
    {
      RFNodes[i].temperature = 0.0;
      RFNodes[i].humidity = 0.0;
      RFNodes[i].batteryLevel = 0;
      Serial.print("Brak odczytu z czujnika ");
      Serial.println (RFNodes[i].nodeid);
    };
  }
}



void loop() {
  readRadioData();
  SuplaDevice.iterate();
}
Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

Pomoże ktoś?

Jak zrobić aby do drugiego i trzeciego kanału Supli trafiły wartości "batteryLevel" z dwóch różnych czujników?
Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

Dałem radę:

Kod: Zaznacz cały

double get_temperature(int channelNumber, double last_val) {

for (int i = 0; i < RFNodesCount; i++)

  if (channelNumber == 3) {
  return RFNodes[1].batteryLevel;  
  }

  if (channelNumber == 2) {
    return RFNodes[0].batteryLevel;
  }

  
}
Awatar użytkownika
klew
Posty: 8283
Rejestracja: czw cze 27, 2019 12:16 pm
Lokalizacja: Wrocław

Pier pisze: czw lut 11, 2021 6:43 pm Dałem radę:
:)

W tym kodzie pętla "for" jest zbędna, wystarczy tak:

Kod: Zaznacz cały

double get_temperature(int channelNumber, double last_val) {
  if (channelNumber == 3) {
  return RFNodes[1].batteryLevel;  
  }
  if (channelNumber == 2) {
    return RFNodes[0].batteryLevel;
  }
}
Widzimy się na Supla Offline Party vol. 2 :!:
Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

Jak się okazało nie działa to dobrze, po pewnym czasie wartości potrafią się zamienić miejscami.
Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

Pomoże mi ktoś w ogarnięciu funkcji zapisu do kanału termometru do Supli?
Awatar użytkownika
klew
Posty: 8283
Rejestracja: czw cze 27, 2019 12:16 pm
Lokalizacja: Wrocław

Pier pisze: wt lut 23, 2021 1:37 pm Pomoże mi ktoś w ogarnięciu funkcji zapisu do kanału termometru do Supli?

Kod: Zaznacz cały

void get_temperature_and_humidity(int channelNumber, double *temp, double *humidity) {

  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      *temp = RFNodes[i].temperature;
      *humidity = RFNodes[i].humidity;
    }
}
double get_temperature(int channelNumber, double last_val) {        //TA CZĘŚĆ PROGRMU NIE DZIAŁA PRAWIDŁOWO


  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      return RFNodes[i].batteryLevel;
    }
  
}
....
  SuplaDevice.addDHT22();
  SuplaDevice.addDHT22();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
W kodzie masz 4 kanały - 2x DHT i 2xDS18B20. Ich numery (channelNumber) to kolejno 0, 1, 2, 3.
Do RFNodes masz przypisane 2 sensory na radiu. Ich "channelNumber" to 0 i 1. Dlatego wilgotność i temperatura działa poprawnie, bo channelNumber "DHT" pokrywa się z "RFNodes".
Natomiast program przy próbie odczytu get_temperature, pyta o wartości dla kanału 2 i 3. Niestety nie ma kanałów o takich numerach w RFNodes, więc ich nie znajduje.
Dla tej konkretnej sytuacji, z dwoma czujnikami, możesz to rozwiązać tak:

Kod: Zaznacz cały

double get_temperature(int channelNumber, double last_val) {
  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == (channelNumber - 2) )
    {
      return RFNodes[i].batteryLevel;
    }
}
Pamiętaj też, że używasz starej wersji biblioteki, która miała trochę błędów i przy kilku termometrach przestawały się poprawnie aktualizować wartości. Nie pamiętam tylko, czy przy 4 to było już widoczne, czy nie.
Widzimy się na Supla Offline Party vol. 2 :!:
Awatar użytkownika
QLQ
Posty: 2278
Rejestracja: ndz wrz 03, 2017 9:13 am
Lokalizacja: Koszalin

klew pisze: wt lut 23, 2021 9:51 pm
Pier pisze: wt lut 23, 2021 1:37 pm Pomoże mi ktoś w ogarnięciu funkcji zapisu do kanału termometru do Supli?

Kod: Zaznacz cały

void get_temperature_and_humidity(int channelNumber, double *temp, double *humidity) {

  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      *temp = RFNodes[i].temperature;
      *humidity = RFNodes[i].humidity;
    }
}
double get_temperature(int channelNumber, double last_val) {        //TA CZĘŚĆ PROGRMU NIE DZIAŁA PRAWIDŁOWO


  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      return RFNodes[i].batteryLevel;
    }
  
}
....
  SuplaDevice.addDHT22();
  SuplaDevice.addDHT22();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
W kodzie masz 4 kanały - 2x DHT i 2xDS18B20. Ich numery (channelNumber) to kolejno 0, 1, 2, 3.
Do RFNodes masz przypisane 2 sensory na radiu. Ich "channelNumber" to 0 i 1. Dlatego wilgotność i temperatura działa poprawnie, bo channelNumber "DHT" pokrywa się z "RFNodes".
Natomiast program przy próbie odczytu get_temperature, pyta o wartości dla kanału 2 i 3. Niestety nie ma kanałów o takich numerach w RFNodes, więc ich nie znajduje.
Dla tej konkretnej sytuacji, z dwoma czujnikami, możesz to rozwiązać tak:

Kod: Zaznacz cały

double get_temperature(int channelNumber, double last_val) {
  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == (channelNumber - 2) )
    {
      return RFNodes[i].batteryLevel;
    }
}
Pamiętaj też, że używasz starej wersji biblioteki, która miała trochę błędów i przy kilku termometrach przestawały się poprawnie aktualizować wartości. Nie pamiętam tylko, czy przy 4 to było już widoczne, czy nie.
Na starych SD 4 kanały działały poprawnie na bramce 868MHz przy ustawieniu na sztywno. Testowałem z V wiatru, Temp, Wilg, Cisnieniem.

edit: moja obecna stacja pogody chodzi na 4 kanałach bez problemu, nie zamienia miejsc wartosci: lux, P, H, Temp
jak coś nie działa to włącz zasilanie.....
Awatar użytkownika
QLQ
Posty: 2278
Rejestracja: ndz wrz 03, 2017 9:13 am
Lokalizacja: Koszalin

Pier pisze: czw lut 11, 2021 4:14 pm Pomoże ktoś?

Jak zrobić aby do drugiego i trzeciego kanału Supli trafiły wartości "batteryLevel" z dwóch różnych czujników?
Ax2rzuc jeszcze proszę kod nadajnika
jak coś nie działa to włącz zasilanie.....
Pier
Posty: 45
Rejestracja: śr lut 26, 2020 10:26 am

QLQ pisze: śr lut 24, 2021 8:16 pm
Pier pisze: czw lut 11, 2021 4:14 pm Pomoże ktoś?

Jak zrobić aby do drugiego i trzeciego kanału Supli trafiły wartości "batteryLevel" z dwóch różnych czujników?
Ax2rzuc jeszcze proszę kod nadajnika
Nadajnik ma kod Roberta Błaszczaka RB-10, zamiast wartości akumulatora dałem odczyt z pojemnościowego czujnika wilgotności.
klew pisze: wt lut 23, 2021 9:51 pm
Pier pisze: wt lut 23, 2021 1:37 pm Pomoże mi ktoś w ogarnięciu funkcji zapisu do kanału termometru do Supli?

Kod: Zaznacz cały

void get_temperature_and_humidity(int channelNumber, double *temp, double *humidity) {

  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      *temp = RFNodes[i].temperature;
      *humidity = RFNodes[i].humidity;
    }
}
double get_temperature(int channelNumber, double last_val) {        //TA CZĘŚĆ PROGRMU NIE DZIAŁA PRAWIDŁOWO


  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == channelNumber)
    {
      return RFNodes[i].batteryLevel;
    }
  
}
....
  SuplaDevice.addDHT22();
  SuplaDevice.addDHT22();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
W kodzie masz 4 kanały - 2x DHT i 2xDS18B20. Ich numery (channelNumber) to kolejno 0, 1, 2, 3.
Do RFNodes masz przypisane 2 sensory na radiu. Ich "channelNumber" to 0 i 1. Dlatego wilgotność i temperatura działa poprawnie, bo channelNumber "DHT" pokrywa się z "RFNodes".
Natomiast program przy próbie odczytu get_temperature, pyta o wartości dla kanału 2 i 3. Niestety nie ma kanałów o takich numerach w RFNodes, więc ich nie znajduje.
Dla tej konkretnej sytuacji, z dwoma czujnikami, możesz to rozwiązać tak:

Kod: Zaznacz cały

double get_temperature(int channelNumber, double last_val) {
  for (int i = 0; i < RFNodesCount; i++)
    if (RFNodes[i].channelNumber == (channelNumber - 2) )
    {
      return RFNodes[i].batteryLevel;
    }
}
Pamiętaj też, że używasz starej wersji biblioteki, która miała trochę błędów i przy kilku termometrach przestawały się poprawnie aktualizować wartości. Nie pamiętam tylko, czy przy 4 to było już widoczne, czy nie.
Próbowałem czegoś takiego, nie działa.
ODPOWIEDZ

Wróć do „Pomoc”