Mały, bezprzewodowy czujnik temperatury na radiu

Post Reply
User avatar
fracz
Posts: 1589
Joined: Fri Oct 28, 2016 10:56 pm
Location: Rybna

Sun Jul 14, 2019 8:59 am

Chciałbym zrobić coś podobnego jak dłubał @maffiu, ale mniejsze, bez paneli słonecznych tylko na baterię, idealnie na guzikową. Oczywiście wtedy wifi odpada, więc komunikacja byłaby na radiu.

Marzy mi się takie coś: https://inode.pl/iNode-Care-Sensor-T,p,24 i w sumie nawet pomimo ceny bym spróbował to wsuplić, ale nie znalazłem nigdzie protokołu komunikacji więc trzeba by to rozgryzać... No i to nie radio tylko BT.
iNode_Care_Sensor_T_[120]_1200.jpg
iNode_Care_Sensor_T_[120]_1200.jpg (14.36 KiB) Viewed 1234 times
Pomysł na komunikację radiową z supli mam mało odkrywczy, tj. moduły będą się komunikować w 433MHz z bramką postawioną na np NodeMCU (podpiętą w domu do stałego zasilania) i ona będzie dalej wysyłać wartości do supli. Czujniki będą wysyłać temperaturę tylko cyklicznie (np. 5 minut), dlatego w pozostałych momentach NodeMCU będzie udawać, wysyłając do SUPLI ostatnio przekazaną od czujnika temperaturę.

Poszukałem i takie pomysły znalazłem:
  1. Tutaj gość rozdłubuje Arduino PRO Mini 3.3V uzyskując w trybie uśpienia 4.5 μA. Pomysł ciekawy, ale...
  2. tutaj wykorzystano po prostu ATMegę bez "obudowy" arduino żeby ominąć diody i stabilizatory więc byłoby bez rozdłubywania. tutaj też
  3. Jako ciekawostka (bo nie chcę panelu solarnego), tutaj gość buduje czujnik w oparciu o panel + duży kondensator zamiast akumulatora.
Czujnik chyba powinien się składać z:
  • Atmegi - zasilanie od 1.8V do 5.5V
  • RFM69HW 2.4V - 3.6
  • DS18B20 3.0V - 5.5V (choć gdzieś sugerowali że 750ms wykonywania pomiaru przez niego to zbyt duża strata energii i lepiej użyć inny, ale nie wiem jaki)
Jeśli chodzi o zasilanie - myślałem rzeczywiście o "guziku" np. CR2032 choć wszyscy piszą że to podziała kilka sekund :( Pomysłałem więc o oginwie 18650, ale bez stabilizatora taka konstukcja bedzie ją drenować do zera więc będą jednorazowe. W ostateczności koszyk z 2xAA, ale to wtedy się już robi duże.

Chciałbym usłyszeć Wasze pomysły i uwagi, bo ja dopiero zaczynam zabawę z suploelektroniką i mogę zakładać coś co jest niemożliwe ;)
Simono
Posts: 313
Joined: Mon Sep 17, 2018 5:26 pm

Sun Jul 14, 2019 10:13 am

Też szukam czegoś małego do pomiaru temperatury co mógłbym porozmieszczać w domu. Najlepiej chyba z jakimś akumulatorem.
piomar2
Posts: 110
Joined: Fri Apr 26, 2019 5:32 pm
Location: Bukowice

Sun Jul 14, 2019 1:16 pm

Witam !
Jakiś czas temu chcąc zabezpieczyć dom przed pożarem (oprócz czujek dymu) wykonałem 8 szt nadajników 433 z DS18B20 rozmieszczonych w różnych punktach (4 na strychu i 4 w domu) oraz odbiornik, który alarmuje, kiedy przekroczone są ustawione temperatury (tem9 - strych, tem10 - dom). W związku z tym, że w domu mam drugą instalację na 12V to nadajniki zasilam z tego napięcia. Odbiornik powiadamia mnie również poprzez dodatkowy moduł na telefon (Pushover). Program w nadajnikach działa tak, że po wysłaniu wartości temperatury "zasypia" (czas można ustawić). Można się pobawić i spróbować zasilania z aku lub baterii. Nadajniki i odbiornik jest na arduino nano. Nadajniki zamknąłem w małych obudowach (fotka) a odbiornik mam w "szafie sterowniczej". Dołączam kody : nadajnika-1 oraz odbiornika.

Code: Select all

//NADAJNIK
//DS18B20 - pin 2
//TX433 - pin 12

#include <VirtualWire.h>
float temp;

char dataString [7];
const int led_pin = 13;

// Sleep
#include <avr/sleep.h>
#include <avr/power.h>

// Watchdog timer
#include <avr/wdt.h>

// Thermometer
#include <OneWire.h>
#include <DallasTemperature.h>

// -- Global variables --

volatile int f_wdt = 1;
int counter = 0;
int packetCounter = 0;

OneWire oneWire(2);
DallasTemperature sensors(&oneWire);

// -- Functions --

void counterHandler()
{
  // Increment the sleep counter
  counter++;

  // Should be 75 for 10 minutes (75 * 8 = 600 seconds = 10 minutes)
  // Use 1 for debugging purposes
  
  if(counter == 1) {    
    // Reset the counter to 0
    counter = 0;
    
    // Power up components
    power_all_enable();
    
  } else {
    // Sleep time isn't over yet, sleep some more
    enterSleep();
  } 
}

void enterSleep()
{
  // Start the watchdog timer
  f_wdt = 0;
 
  // Enter sleep
  sleep_enable();
  sleep_mode();
  
  // Wake from sleep
  sleep_disable();
  
  // Increment the interrupt counter
  counterHandler();
}

ISR(WDT_vect)
{
  // Stop the watchdog timer
  f_wdt = 1;
}

void setupWDT()
{
  // Setup the Watchdog timer for an interruption every 8 seconds
  
  MCUSR &= ~(1<<WDRF);
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  WDTCSR = 1<<WDP0 | 1<<WDP3;
  WDTCSR |= _BV(WDIE);
}


void setupThermometer()
{
  // Initiate the sensor interface
  sensors.begin();
  
  // Set the bit resolution to 10 for fast conversion times (9 - 12)
  sensors.setResolution(9);
}

void setup()
{ 
  // Disable Brown out detection (uses power)
  sleep_bod_disable();
  
  // Sleep mode setup
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  
  // Watchdog timer setup
  setupWDT();
  
  // Thermometer setup
  setupThermometer();

  vw_set_tx_pin(12);          // Ustawia pin D12 jako pin TX
vw_setup(2000);         // Ustawia ile ma być bitów na sekundę
pinMode(led_pin, OUTPUT);
Serial.begin(9600);
}

void loop()
{
  // Request the sensors temperatures
  sensors.requestTemperatures();
  
  float temp = sensors.getTempCByIndex(0);
  int temp1 = (temp-(int)temp)*100;
  
  sprintf(dataString, "1%2d.%1d",int(temp),temp1); 
  //kolejne nadajniki - zmienic pierwszy znak ciagu na 2...3 itd

 digitalWrite(led_pin, HIGH); 

vw_send((uint8_t *)dataString, strlen(dataString));
vw_wait_tx(); 
vw_send((uint8_t *)dataString, strlen(dataString));
vw_wait_tx();                                                                            
delay(200);
digitalWrite(led_pin, LOW); 
  // Sleep time
  enterSleep();
}
I odbiornik

Code: Select all

//odbiornik - 8 x nadajnik
//RX433 - D 2
//buzzer - D 12
//powiadomienie Pushover D 10


#include <VirtualWire.h>
//#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
const int led_pin = 13;
LiquidCrystal_I2C	lcd(0x27,2,1,0,4,5,6,7);
byte newChar[8] = {B11100, B10100, B11100, B00000, B00000, B00000, B00000, B00000};
        // definiujemy znak stopnia w celu wyświetlenia na lcd
int i;
       String tem0;
       float tem1;
       float tem2;
       float tem3;
       float tem4;
       float tem5;
       float tem6;
       float tem7;
       float tem8;
       float tem9 = 53;
       float tem10 = 40;
 int a=0;     
 
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);//Pushover
  digitalWrite(10, LOW);
pinMode(12, OUTPUT);//sygnal dzwiekowy
  digitalWrite(12, LOW);
  
lcd.begin (20,4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.createChar(1, newChar);  // przypisanie wcześniej zdefiniowanego znaku do 0
lcd.home ();
 pinMode(led_pin, OUTPUT);

    vw_setup(2000);
    vw_set_rx_pin(2);	 
    vw_rx_start();       
}

void loop()
{

    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;

    if (vw_get_message(buf, &buflen)) 
       {

  
//---------------- nadajnik 1 --------------------------  
     if ((char) buf[0]=='1'){   
     tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem1=0;
  tem1 = (tem0.toFloat());
  lcd.setCursor(1, 0);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH);
  delay(500); 
 lcd.setCursor(0, 0);
 lcd.print("1:");
 lcd.setCursor(2, 0);
 lcd.print (tem1);
 lcd.write(1); //znak stopnia
 digitalWrite(led_pin, LOW);
   }
 //---------------- nadajnik 2 --------------------------  
    if ((char) buf[0]=='2'){  
    tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem2=0;
  tem2 = (tem0.toFloat());    
  lcd.setCursor(1, 1);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH); 
  delay(500);
 lcd.setCursor(0, 1);
 lcd.print("2:");
 lcd.setCursor(2, 1);
 lcd.print (tem2);
 lcd.write(1); //znak stopnia
  digitalWrite(led_pin, LOW);

   }

 //---------------- nadajnik 3 --------------------------  
 
        if ((char) buf[0]=='3'){  
    tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem3=0;
  tem3 = (tem0.toFloat());    
  lcd.setCursor(1, 2);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH); 
  delay(500);
 lcd.setCursor(0, 2);
 lcd.print("3:");
 lcd.setCursor(2, 2);
 lcd.print (tem3);
 lcd.write(1); //znak stopnia
  digitalWrite(led_pin, LOW);
      
   }
    
//---------------- nadajnik 4 --------------------------  
 
        if ((char) buf[0]=='4'){  
    tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem4=0;
  tem4 = (tem0.toFloat());    
  lcd.setCursor(1, 3);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH); 
  delay(500);
 lcd.setCursor(0, 3);
 lcd.print("4:");
 lcd.setCursor(2, 3);
 lcd.print (tem4);
 lcd.write(1); //znak stopnia
  digitalWrite(led_pin, LOW);    
    
   }
//---------------- nadajnik 5 --------------------------  
   if ((char) buf[0]=='5'){   
     tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem5=0;
  tem5 = (tem0.toFloat());
  lcd.setCursor(10, 0);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH);
  delay(500); 
 lcd.setCursor(9, 0);
 lcd.print("5:");
 lcd.setCursor(11, 0);
 lcd.print (tem5);
 lcd.write(1); //znak stopnia
 digitalWrite(led_pin, LOW);
   }
     
 
 //---------------- nadajnik 6 --------------------------  
 
   if ((char) buf[0]=='6'){   
     tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem6=0;
  tem6 = (tem0.toFloat());
  lcd.setCursor(10, 1);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH);
  delay(500); 
 lcd.setCursor(9, 1);
 lcd.print("6:");
 lcd.setCursor(11, 1);
 lcd.print (tem6);
 lcd.write(1); //znak stopnia
 digitalWrite(led_pin, LOW);
   }    
 
//---------------- nadajnik 7 --------------------------  
  if ((char) buf[0]=='7'){   
     tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem7=0;
  tem7 = (tem0.toFloat());
  lcd.setCursor(10, 2);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH);
  delay(500); 
 lcd.setCursor(9, 2);
 lcd.print("7:");
 lcd.setCursor(11, 2);
 lcd.print (tem7);
 lcd.write(1); //znak stopnia
 digitalWrite(led_pin, LOW);
   }    
  
//---------------- nadajnik 8 --------------------------  

 if ((char) buf[0]=='8'){   
     tem0 = "";
    for (i = 1; i < 5; i++)
  {   tem0 +=char(buf[i]);  }
  tem8=0;
  tem8 = (tem0.toFloat());
  lcd.setCursor(10, 3);
  lcd.print (" ");   
  digitalWrite(led_pin, HIGH);
  delay(500); 
 lcd.setCursor(9, 3);
 lcd.print("8:");
 lcd.setCursor(11, 3);
 lcd.print (tem8);
 lcd.write(1); //znak stopnia
 digitalWrite(led_pin, LOW);
   }    
    
//---------------------------------------------   


 if (tem1  > tem9 | tem2  > tem9 | tem3  > tem9 | tem4  > tem9)
 {
  digitalWrite(10, HIGH);
  
  for(byte i=0; i<10; i++){
  digitalWrite(12, HIGH);
  delay (100);
   digitalWrite(12, LOW);
   delay (100);
  }
   digitalWrite(10, LOW);
  }

  if (tem5  > tem10 | tem6  > tem10 | tem7  > tem10 | tem8  > tem10)
 {
  digitalWrite(10, HIGH);
  
  for(byte i=0; i<10; i++){
  digitalWrite(12, HIGH);
  delay (100);
   digitalWrite(12, LOW);
   delay (100);
  }
   digitalWrite(10, LOW);
  }
  
  a=a+1;
  if (a==40){
    a=0;
    lcd.clear();
  }
       }
 }
      
Może się komuś przyda...
Pozdrawiam
Attachments
IMG_odbiornik.jpg
IMG_odbiornik.jpg (310.26 KiB) Viewed 1194 times
IMG_nadajnik.jpg
IMG_nadajnik.jpg (763.13 KiB) Viewed 1194 times
piomar2
User avatar
wojtas567
Posts: 1787
Joined: Sun Apr 03, 2016 7:16 pm
Location: Olsztyn

Sun Jul 14, 2019 2:29 pm

No i to nie radio tylko BT.
Ale na dzień dzisiejszy nie mamy tego mostu łączącego wifi z radiem.
ESP32 ma w sobie wifi i BT może tu dałby ktoś radę napisać kod połączenia tych dwóch sieci i wtedy ta mała pluskwa by zadziałała w supli :)
Jakiś czas temu zakupiłem ten czujnik https://pl.aliexpress.com/item/32855738 ... 5c0fKKNbHd i jest w nim ESP ale on odzywa się tylko jak czujka dostanie wody, nadal działa a bateria jest full. Na razie nie próbowałem tego rozkładać na czynniki pierwsze :) może trzeba pokombinować w tym kierunku?
Pozdrawiam
Wojtek
User avatar
fracz
Posts: 1589
Joined: Fri Oct 28, 2016 10:56 pm
Location: Rybna

Sun Jul 14, 2019 2:43 pm

wojtas567 wrote:
Sun Jul 14, 2019 2:29 pm
Ale na dzień dzisiejszy nie mamy tego mostu łączącego wifi z radiem.
To nie będzie trudne. Wystarczy do np. Nodemcu albo wemosa dodać odbiornik 433 i przekazywać dane do supli.
Beku
Posts: 91
Joined: Tue Nov 06, 2018 1:49 pm

Sun Jul 14, 2019 3:00 pm

W zeszłym roku złożyłem taki zestaw o którym piszesz, tyle ze dołożyłem do niego akumulatorki 18650. Całość oparłem o rfm69 i atmege pro mini 3.3v . Do supli wysyłałem nawet poziom baterii ale nie chciało mi się grzebać w sofcie serwera wiec wykorzystałem do tego wilgotność 🙂. Trochę projekt leży z braku czasu ale całość dopóki nie wyłączyłem bramki z prądu działała sprawnie pół roku. Zamierzam do tego wrócić teraz, chętnie podzielę się spostrzeżeniami 🙂
piomar2
Posts: 110
Joined: Fri Apr 26, 2019 5:32 pm
Location: Bukowice

Sun Jul 14, 2019 3:20 pm

Ja swoje rozwiązanie oparłem na najtańszych nadajnikach i odbiorniku. Działa już jakiś czas. Był moment, kiedy "spotkałem się z suplą" i próbowałem to ze sobą zintegrować (treningowo) ale była jakaś kolizja z bibliotekami supli i VirtualWire.h (w odbiorniku 433) i dałem sobie spokój. Powiadomienie mam po pushover i jest to dla mnie układ skończony ale... :roll: będę obserwował temat, bo ciekawy.
piomar2
User avatar
maffiu
Posts: 487
Joined: Wed Nov 30, 2016 9:30 pm
Location: Kraków/Skawina

Sun Jul 14, 2019 5:12 pm

No właśnie znowu ten nieszczęsny most jak by był to wiele rzeczy można by dołączyć...
Fajne sensory temp i całkiem ładne ma xiaomi do swojego systemu

mój temat umarł ze względu na same panele bo ich wydajność jest żenująca a większy panel nie wchodził w grę
User avatar
fracz
Posts: 1589
Joined: Fri Oct 28, 2016 10:56 pm
Location: Rybna

Sun Jul 14, 2019 5:19 pm

Oto most :D Działa pod NodeMCU v3. Póki tylko udaję, że jest odczyt z RF (podpiąłem potencjometr w roli termometru pod A0) - ale proof of concept powinien być czytelny. Jest tu jeden termometr który daje temp co 5 minut, drugi co minutę i trzeci - natychmiast - "fizycznie" podłączony do nodemcu. Działa pięknie. Zamiana analogReadów na odczyt z RFM69 i mamy bramkę.

Code: Select all

#define SUPLADEVICE_CPP
#include <SuplaDevice.h>

#define SUPLA_SERVER "svr3.supla.org"
#define LOCATION_ID 999
#define LOCATION_PASSWORD "xxxx"
// pobierz identyfikator urządzenia ze strony https://www.supla.org/arduino/get-guid i wprowadź go poniżej
#define GUID {0x6B,0x4D,0xF1,0xBE,0x5F,0x36,0x6D,0xCA,0x37,0x22,0x05,0x52,0xAE,0x20,0x3B,0xC3}

unsigned long currentTime = 0;

// zmienne sumulujace przesylanie danych z czujnikow
unsigned long lastSensor1SendTime = 0;
unsigned long lastSensor2SendTime = 0;
double temperaturesFromRadio[] = {10 ,10, 10};

double get_temperature(int channelNumber, double last_val) {
    return temperaturesFromRadio[channelNumber];  
}

void setup() {
  Serial.begin(115200);
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.addDS18B20Thermometer();
  SuplaDevice.setTemperatureCallback(&get_temperature);
  char guid[SUPLA_GUID_SIZE] = GUID;
  uint8_t mac[6] = {0x00, 0x05, 0x04, 0x03, 0x02, 0x01};
  SuplaDevice.begin(guid, mac, SUPLA_SERVER, LOCATION_ID, LOCATION_PASSWORD);
}

void loop() {
  SuplaDevice.iterate();
  currentTime = millis();
  if (lastSensor1SendTime + 300000L < currentTime) { // symulacja czujnika wysylajacego dane co 300s (5 min)
    temperaturesFromRadio[0] = analogRead(A0) * 100 / 1024;
    lastSensor1SendTime = currentTime;
  }
  if (lastSensor2SendTime + 60000L < currentTime) { // co 60 s
    temperaturesFromRadio[1] = analogRead(A0) * 100 / 1024;
    lastSensor2SendTime = currentTime;
  }
  temperaturesFromRadio[2] = analogRead(A0) * 100 / 1024; // fizyczny czujnik
  delay(10);
}
Dla czytelności, przeniosłem cały kod z komunikacją po WiFi do pliku SuplaTcp.cpp, który musi być obok pliku .ino żeby ArduinoIDE go pociągnęło z automatu.
Beku
Posts: 91
Joined: Tue Nov 06, 2018 1:49 pm

Sun Jul 14, 2019 6:35 pm

bramka:

Code: Select all

#define SUPLADEVICE_CPP
#include <SuplaDevice.h>
#include <ESP8266WiFi.h>
#include <RFM69_ATC.h>
#include <RFM69.h>         //get it here: https://www.github.com/lowpowerlab/rfm69
#define NODEID        0    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define FREQUENCY     RF69_433MHZ
#define ENCRYPTKEY    "RETFDEDEXXXWsdeW" //exactly the same 16 characters/bytes on all nodes!
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI -75

WiFiClient client;
#ifdef ENABLE_ATC
RFM69_ATC radio(D8, D2, false);
#else
RFM69 radio;
#endif

// Setup Supla connection
const char* ssid     = "XXX";
const char* password = "XXX";
const unsigned long period = 60000;  //the value is a number of milliseconds

double temperature = 0.0;
unsigned long startMillis = 0;
unsigned long currentMillis = 0;
unsigned long RFTempNodesCount = 0;
typedef struct {
  int nodeid;
  int channelNumber;
  double temperature;
  double humidity;
  double batteryVoltage;
  double batteryPercentage;
  unsigned long lastContact;
} RF_TemperatureNode;

RF_TemperatureNode RFTempNodes[SUPLA_CHANNELMAXCOUNT]; // 32

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

  for (int i = 0; i < RFTempNodesCount; i++)
    if (RFTempNodes[i].channelNumber == channelNumber)
    {
      Serial.print("Temperature C: ");
      Serial.println(RFTempNodes[i].temperature);
      Serial.print("Humidity: " );
      Serial.println(RFTempNodes[i].batteryVoltage);
      *temp = RFTempNodes[i].temperature;
      *humidity = RFTempNodes[i].batteryVoltage;
    }
}

void setup() {
  Serial.begin(9600);
  Serial.println("Starting SuplaGateway v 1.0");
  char GUID[SUPLA_GUID_SIZE] = {0x20, 0x09, 0xFA, 0xF8, 0x1D, 0x00, 0x58, 0x3C, 0x76, 0x2D, 0x0B, 0x86, 0x7D, 0x63, 0xB0, 0xF9};

  uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  radio.initialize(FREQUENCY, NODEID, NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(false);

  radio.setPowerLevel(29);
#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif
  radio.sleep();

  SuplaDevice.setTemperatureHumidityCallback(&get_temperature);
  for (int i = 0; i < 12; i++)
    SuplaDevice.addDHT11();

  SuplaDevice.begin(GUID,              // Global Unique Identifier
                    mac,               // Ethernet MAC address
                    "",  // SUPLA server address
                    1,                 // Location ID
                    "xxxx");               // Location Password
  startMillis = millis();
}

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 temp = "";
  if (radio.receiveDone())
  {
    int foundIdx = -1;

    for (int i = 0; i < RFTempNodesCount; i++)
      if (RFTempNodes[i].nodeid == radio.SENDERID)
      {
        Serial.print("Node found at index ");
        Serial.println(i);
        foundIdx = i;
        break;
      }

    Serial.println("received data");
    if (foundIdx == -1)
    {
      if (RFTempNodesCount < SUPLA_CHANNELMAXCOUNT)
      {
        Serial.println("Adding new node");
        RFTempNodes[RFTempNodesCount].nodeid = radio.SENDERID;
        RFTempNodes[RFTempNodesCount].lastContact = millis();
        RFTempNodes[RFTempNodesCount].channelNumber = radio.SENDERID - 1;
        RFTempNodes[RFTempNodesCount].temperature = 0.0;
        RFTempNodes[RFTempNodesCount].humidity = 0.0;
        RFTempNodes[RFTempNodesCount].batteryVoltage = 0.0;
        RFTempNodes[RFTempNodesCount].batteryPercentage = 0.0;

        foundIdx = RFTempNodesCount;
        RFTempNodesCount++;
      } else {
        Serial.println("Max node count exceded!");
        foundIdx = 0;
      }
    } else
    {
      RFTempNodes[foundIdx].temperature = 0.0;
    }

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

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

    Serial.println(temp);

    String tempStr = getValue(temp, '|', 0);
    String battVoltStr = getValue(temp, '|', 1);
    String battLevlStr = getValue(temp, '|', 2);

    Serial.print("Battery voltage: ");
    Serial.println(battVoltStr);
    Serial.print("Battery percentage: ");
    Serial.println(battLevlStr);

    RFTempNodes[foundIdx].batteryVoltage = battVoltStr.toFloat();
    RFTempNodes[foundIdx].batteryPercentage = battLevlStr.toFloat();
    RFTempNodes[foundIdx].temperature = tempStr.toFloat();
    RFTempNodes[foundIdx].lastContact = millis();

    Serial.print(RFTempNodes[foundIdx].temperature);
    Serial.print("   [RX_RSSI:"); Serial.print(radio.RSSI); Serial.print("]");

    if (radio.ACKRequested())
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      Serial.print(" - ACK sent.");

      if (ackCount++ % 3 == 0)
      {
        Serial.print(" Pinging node ");
        Serial.print(theNodeID);
        Serial.print(" - ACK...");
        delay(3); //need this when sending right after reception .. ?
        if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
          Serial.print("ok!");
        else Serial.print("nothing");
      }
    }
    Serial.println();
  }

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

void loop() {

  if (WiFi.status() != WL_CONNECTED) // Jeżeli sieć WiFi nie jest podłączona, wywołaj procedurę łączenia
  {
    WiFi_up();
  }

  readRadioData();

  SuplaDevice.iterate();
}

// Supla.org ethernet layer
int supla_arduino_tcp_read(void *buf, int count) {
  _supla_int_t size = client.available();

  if ( size > 0 ) {
    if ( size > count ) size = count;
    return client.read((uint8_t *)buf, size);
  };

  return -1;
};

int supla_arduino_tcp_write(void *buf, int count) {
  return client.write((const uint8_t *)buf, count);
};

bool supla_arduino_svr_connect(const char *server, int port) {
  return client.connect(server, 2015);
}

bool supla_arduino_svr_connected(void) {
  return client.connected();

}

void supla_arduino_svr_disconnect(void) {
  client.stop();
}

void supla_arduino_eth_setup(uint8_t mac[6], IPAddress *ip) {
  WiFi_up();
}

SuplaDeviceCallbacks supla_arduino_get_callbacks(void) {
  SuplaDeviceCallbacks cb;

  cb.tcp_read = &supla_arduino_tcp_read;
  cb.tcp_write = &supla_arduino_tcp_write;
  cb.eth_setup = &supla_arduino_eth_setup;
  cb.svr_connected = &supla_arduino_svr_connected;
  cb.svr_connect = &supla_arduino_svr_connect;
  cb.svr_disconnect = &supla_arduino_svr_disconnect;
  cb.get_temperature = NULL;
  cb.get_temperature_and_humidity = NULL;
  cb.get_rgbw_value = NULL;
  cb.set_rgbw_value = NULL;

  return cb;
}

void WiFi_up() // Procedura podłączenia do sieci WiFi
{
  Serial.print("Proba podlaczenia do sieci ");
  Serial.println(ssid);

  WiFi.begin(ssid, password); // Próba podłączenia do sieci


  for (int x = 60; x > 0; x--) // Powtarzaj pętlę maksymanie maksymalnie 30 sekund (ponieważ przy każdym elsie jest 0,5 sekundy zwłoki)
  {
    if (WiFi.status() == WL_CONNECTED) // Jezeli WiFi jest podłączone
    {
      break;                           // to zatrzymaj pętlę
    }
    else                                 // w przeciwnym wypadku
    {
      Serial.print(".");               // wystaw na serial .
      delay(500);                      // i czekaj 0,5 sekundy
    }

  }

  if (WiFi.status() == WL_CONNECTED) // Jeżeli połączenie z siecią zostało nawiązane, wyślij na serial jego parametry
  {
    Serial.println("");
    Serial.println("Polaczenie nawiazane");
    Serial.println("Adres IP: ");
    Serial.print(WiFi.localIP());
    Serial.print(" / ");
    Serial.println(WiFi.subnetMask());
    Serial.print("Brama: ");
    Serial.println(WiFi.gatewayIP());
    long rssi = WiFi.RSSI();
    Serial.print("Sila sygnalu (RSSI): ");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
  else    // w przeciwnym wypadku poinformuj przez serial o nieudanej próbie
  {
    Serial.println("");
    Serial.println("Polaczenia nie udalo sie nawiazac");
  }
}
node:

Code: Select all

#include <LowPower.h>
#include <RFM69_ATC.h>
#include <DallasTemperature.h>
#include "Battery.h"
#define ONEWIRE_PIN A2
#define NODEID        2    //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
#define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
#define GATEWAYID     0
#define FREQUENCY   RF69_433MHZ
#define ENCRYPTKEY  "RETFDEDEXXXWsdeW" //exactly the same 16 characters/bytes on all nodes!
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI -75

RFM69_ATC radio;
OneWire onewire(ONEWIRE_PIN);
DallasTemperature sensors(&onewire);
Battery battery(2000, 4100, A0);
char payload[] = "               ";
byte sendSize = 15;
float temperature = 0;
int iteration = 7;
double curvolt = 0.0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000;
float R2 = 10000;

void setup() {
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  radio.setPowerLevel(29);
  radio.enableAutoPower(ATC_RSSI);
  radio.sleep();
  sensors.setResolution(10);
  sensors.begin();
  battery.begin(3300, 1.26);
  Serial.begin(9600);
  Serial.println("Starting SuplaNode v 1.0...");
}

void loop() {
  iteration += 1;
  if (iteration > 1)
  {
    sensors.requestTemperatures();
    temperature = sensors.getTempCByIndex(0);
    String tempStr = String(temperature, 2);
    String battVoltStr = String(battery.voltage()/1000.00, 2);
    String battLevelStr = String(battery.level());
    
    String all = tempStr + '|' + battVoltStr + '|' + battLevelStr;
    all.toCharArray(payload, sendSize);
   // Serial.println(payload);

    radio.send(GATEWAYID, payload, sendSize);
    radio.sleep();
    iteration = 0;
    //Serial.flush();
  }
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);  
}
póki co podpiąłem DS'y ale docelowo chcę w to zapiąć HTU21D - dosyć dokładne i mało żrące prądowo czujniki temp + wilgotność.
Czyli docelowo nod'y temp+wilgotność+bateria. Bramka obsługuje 12 kanałów niejako z automatu. Dodanie kolenych polega jedynie na zwiększeniu Id node'a tak aby radio się poprawnie komunikowało.

Polecam jeszcze lekturę:

https://wisen.com.au/blog/running-a-wir ... -a-cr2032/
Post Reply