Avaleht
uus teema   vasta Tarkvara »  Programmeerimine »  Arduino'ga temp/niiskuse andur RS485 suhtlus märgi kõik teemad loetuks
märgi mitteloetuks
vaata eelmist teemat :: vaata järgmist teemat
Hinnavaatlus :: Foorum :: Uudised :: Ärifoorumid :: HV F1 ennustusvõistlus :: Pangalink :: Telekavad :: HV toote otsing
autor
sõnum Saada viide sõbrale. Teata moderaatorile
otsing:  
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 28.10.2022 19:02:31 Arduino'ga temp/niiskuse andur RS485 suhtlus vasta tsitaadiga

Plaanis kasvuhoonet automatiseerida ning soetasin Sellise RS485'ga töötava anduri mis mõõdab niiskust ja tempi: https://www.aliexpress.com/item/1005001524845572.html?spm=a2g0o.order_list.0.0.21ef1802ta3pnb

Füüsiliselt on asi ühendatud, kuid koodiga olen veits hädas.
Manualist väljavõte:


Mingi netist leitud kellegi sarnase asja kood, kus paar korrektuuri tegin


#include <SoftwareSerial.h>
     
const byte nitro [] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];
SoftwareSerial mod(26, 27); // RX=26 , TX =27

void setup() {
  Serial.begin(115200);
  mod.begin(4800);// modbus configuration
}




void loop() {
  byte val1;
  val1 = nitrogen();
  delay(4000);
  Serial.print("Nitrogen: ");
  Serial.print(val1, DEC);
  Serial.println();

}

byte nitrogen() {

  delay(10);
  if (mod.write(nitro, sizeof(nitro)) == 8) {

    for (byte i = 0; i < 7; i++) {
      values[i] = mod.read();
    }
   
  }
  return values[4];
}

Tahaks esijalgu temperatuuri väärtust andurist lugeda. Serial ühendusest andmeid tuleb (suht lambi nr'd), kuid ma ei saa koodist aru.

byte values[11]; - Miks just 11?
sizeof(nitro)) == 8) - miks just 8?
return values[4] - mis see 4 on?

Ehk keegi viitsib paari sõnaga seletada juhendada?

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
andre85
HV vaatleja

liitunud: 10.09.2006




sõnum 28.10.2022 20:18:24 Re: Arduino'ga temp/niiskuse andur RS485 suhtlus vasta tsitaadiga

Terror kirjutas:
Plaanis kasvuhoonet automatiseerida ning soetasin Sellise RS485'ga töötava anduri mis mõõdab niiskust ja tempi: https://www.aliexpress.com/item/1005001524845572.html?spm=a2g0o.order_list.0.0.21ef1802ta3pnb

Füüsiliselt on asi ühendatud, kuid koodiga olen veits hädas.
Manualist väljavõte:


Mingi netist leitud kellegi sarnase asja kood, kus paar korrektuuri tegin


#include <SoftwareSerial.h>
     
const byte nitro [] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];
SoftwareSerial mod(26, 27); // RX=26 , TX =27

void setup() {
  Serial.begin(115200);
  mod.begin(4800);// modbus configuration
}




void loop() {
  byte val1;
  val1 = nitrogen();
  delay(4000);
  Serial.print("Nitrogen: ");
  Serial.print(val1, DEC);
  Serial.println();

}

byte nitrogen() {

  delay(10);
  if (mod.write(nitro, sizeof(nitro)) == 8) {

    for (byte i = 0; i < 7; i++) {
      values[i] = mod.read();
    }
   
  }
  return values[4];
}

Tahaks esijalgu temperatuuri väärtust andurist lugeda. Serial ühendusest andmeid tuleb (suht lambi nr'd), kuid ma ei saa koodist aru.

byte values[11]; - Miks just 11?
sizeof(nitro)) == 8) - miks just 8?
return values[4] - mis see 4 on?

Ehk keegi viitsib paari sõnaga seletada juhendada?


1) 11 - puhvri suurus 11 baiti, see on sensori vastuse pikkus
2) 8 - kontrollib, et saadetud oleks kogu päringu puhverpikkusega 8 baiti
3) values[4] on arusaamatu, sest see tagastab 5nda vastuse baidi, mis on osa niiskuse väärtusest; ma ütleks, et see on vigane koht

_________________
andres
Kommentaarid: 8 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 7
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 28.10.2022 23:32:58 vasta tsitaadiga

Ei suutnud oma mõistusega seda eelnevat koodi tööle saada nii, et sealt tulev tulemus vastaks reaalsusele.

Leidsin netist ühe teise koodi kust üritasin kõik mittevajaliku välja visata millest mõistus üle käis. Jäi järgi selline kood:


HardwareSerial mySerial1(1); // Soft serial port, used to communicate with the sensor
unsigned char item[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};

// The following defines a function to communicate with the sensor and send temperature and humidity to the database.


void setup()
{

  Serial.begin(115200);
  mySerial1.begin(4800,SERIAL_8N1,26,27);


}

void loop()
{
  String Niiskus="";
  String Temperatuur ="";
  char tem1[5];
  char hem[4];
  String data = "";
  char buff[128];// Define an array of storage sensor data
  String info[11];
 
  for (int i = 0 ; i < 8; i++) {  // Send a temperature measurement command
    mySerial1.write(item[i]);   // WRITE output
    }
 
  delay(100);  // Waiting for the temperature measurement data to return
  data = "";
  while (mySerial1.available()) {// Read data from the serial port
    unsigned char in = (unsigned char)mySerial1.read();  // read
    Serial.print(in, HEX);
    Serial.print(',');
    data += in;
    data += ',';
  }
 
  if (data.length() > 0) { // Output the received data
    Serial.print(data.length());
    Serial.println();
    Serial.println(data);
    int commaPosition = -1;
    // Store with a string array
    for (int i = 0; i < 11; i++) {
      commaPosition = data.indexOf(',');
      if (commaPosition != -1){
        info[i] = data.substring(0, commaPosition);
        data = data.substring(commaPosition + 1, data.length());
      }
    else {
      if (data.length() > 0) { 
        info[i] = data.substring(0, commaPosition);
        }
      }
    }
  }
  Niiskus = dtostrf((info[3].toInt() * 256 + info[4].toInt())/10.0,2,1,tem1);
  Serial.print("Niiskus:");
  Serial.println(Niiskus);
  Temperatuur = dtostrf((info[5].toInt() * 256 + info[6].toInt())/10.0,2,1,hem);
  dtostrf((info[5].toInt() * 256 + info[6].toInt())/10.0,2,1,hem);
  Serial.print("Temperatuur:");
  Serial.println(Temperatuur);
  Serial.println(buff);
  delay(4000);
 
}

Niiskus ja temperatuur väärtused paistavad siit korrektsed tulevat. Ausaltöeldes ei oska ma seda asja ise enam lühemaks teha (ei saa aru, kuidas väärtus üldse tuleb, näiteks dtostrf((info[5].toInt() * 256 + info[6].toInt())/10.0,2,1,hem); Boldiga on eriti segane.
Oskab keegi aidata?

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
mikk36
HV Guru
mikk36

liitunud: 21.02.2004




sõnum 29.10.2022 01:28:46 vasta tsitaadiga

dtostrf(
   (info[5].toInt() * 256 + info[6].toInt())/10.0,
   2,
   1,
   hem
);


Esimene argument loob selle temperatuuri väärtuse. Kümnega jagatakse, sest väärtus on komakohtadeta ja kümme korda suurem täisarv (eelnevalt antud teisel pildil vastuse osa -101 -> -10,1).
Ülejäänud argumentide väärtused leiad dtostrf funktsiooni dokumentatsioonist.
Kommentaarid: 85 loe/lisa Kasutajad arvavad:  :: 0 :: 2 :: 78
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 29.10.2022 08:35:22 vasta tsitaadiga

Andmete liigutamine "data" stringi, pärast sealt otsimine komade järgi ja lõpuks "info"-sse tundub täiesti mõttetu. Info sisaldab lõpuks sama infot mis esialgne massiiv, kui andmed oleks kohe sinna loetud?
Lisaks, kui mõni bait on sama koodiga mis koma, ei tööta see õigesti.

Esimene näide tegi seda lugemist mõistlikult. Küll aga peaks ka seal kogu seriali puhvri tühjaks lugema, mitte ainult esimesed 8 baiti. Võib-olla oli too näide mõne teise sedame jaoks?

Ma pole mälu järgi päris kindel, aga negatiivsete arvude teisendamisel byte->int ei pruugi 256-ga korrutamine õigesti töötada. Kuigi antud juhul vist negatiivsete temperatuuridega tegemist ei tule. Kindlam oleks kasutada märgiga arvude nihutamist.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 29.10.2022 11:05:23 vasta tsitaadiga

Tegin esimese näite veits ümber:

HardwareSerial mySerial1(1);
     
const byte sensor [] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];

void setup() {
  Serial.begin(115200);
  mySerial1.begin(4800,SERIAL_8N1,26,27);

}


void loop() {
  float val1;
  val1 = temperatuur();
  delay(4000);
  Serial.println();
  Serial.print("temperatuur: ");
  Serial.print(val1);
  Serial.println();

}

byte temperatuur() {

  delay(10);
  if (mySerial1.write(sensor, sizeof(sensor)) == 8) {

    for (byte i = 0; i < 11; i++) {
      values[i] = mySerial1.read();
    }
    Serial.print(values[0], HEX);
    Serial.print(":");
    Serial.print(values[1], HEX);
    Serial.print(":");
    Serial.print(values[2], HEX);
    Serial.print(":");
    Serial.print(values[3], HEX);
    Serial.print(":");
    Serial.print(values[4], HEX);
    Serial.print(":");
    Serial.print(values[5], HEX);
    Serial.print(":");
    Serial.print(values[6], HEX);
    Serial.print(":");
    Serial.print(values[7], HEX);
    Serial.print(":");
    Serial.print(values[8], HEX);
    Serial.print(":");
    Serial.print(values[9], HEX);
    Serial.print(":");
    Serial.print(values[10], HEX);
   
     Serial.println();
   
    Serial.print(values[0], DEC);
    Serial.print(":");
    Serial.print(values[1], DEC);
    Serial.print(":");
    Serial.print(values[2], DEC);
    Serial.print(":");
    Serial.print(values[3], DEC);
    Serial.print(":");
    Serial.print(values[4], DEC);
    Serial.print(":");
    Serial.print(values[5], DEC);
    Serial.print(":");
    Serial.print(values[6], DEC);
    Serial.print(":");
    Serial.print(values[7], DEC);
    Serial.print(":");
    Serial.print(values[8], DEC);
    Serial.print(":");
    Serial.print(values[9], DEC);
    Serial.print(":");
    Serial.print(values[10], DEC);

  }
 
  return (values[5]*256+values[6])/10;
}



Serial output on selline:


Küsimused:

1) Miks kuvatakse temperatuuri 21.00, kuigi peaks olema 20,9?
2) Kas temperatuuri väärtuse saab alati nii korrektse: (values[5]*256+values[6])/10 ? Tahaks, et ka neg temperatuurid õieti kuvataks jne (ei ole võimalik hetkel praktikas kontrollida). Miks üldse value 5*256 ning mitte value 6 puhul ? Mis situatsioonis see value 5 ei ole null? Kui seriali vaatan, siis value 6 on nagu see kus on temp väärtus...
3) KAs eal seriali sensori vastuses on mingi veakontrolli võimalus ka olemas? St mingi osa vastusest on alati üks ja sama, näiteks algus 1:3:6:3? Et saaks vajadusel mingi veakontrolli teha.

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 29.10.2022 11:25:04 vasta tsitaadiga

1) praegu tehaks väärtus täisarvuks koodis. Kui tahta reaalarve, peaks teisendamisel ja väljanäitamisel float andmetüüpi kasutama. Aga see ei ole väga oluline, kuna tegelikult läheb ju seda väätust tarvis edaspidi kusagil programmis. Väljanäitamine on praegu ainult siulimiseks, ma arvan.
2) [5] ei ole null, kui temp on suurem kui 25.5 kraadi või siis negatiivne. Näiteks 30 kraadi oleks [5]=1 ja [6]=44 (kümnendsüsteemis)
3) esimesed 3 baiti peaks olema konstantsed, kui kasutatakse sama seadme numbrit.
Põhimõtteliselt on veakontrolliks mõeldud kahes viimases baidis olevat kontrollsumma, aga see kisub antud juhul juba kõrgemaks matemaatikaks sinu jaoks icon_wink.gif

edit:
1) ma soovitaksin funktsiooni väärtusena jätta temperatuuri läbi jagamata 10-ga ning kasutada int andmetüüpi selle jaoks siis. Las ta olla väljanäitamisel 10x suurem, aa nii on kõige lihtsam seda pärast kasutada.

Negatiivsete väärtuste testimiseks (kui see on vajalik) võid ju programmis käsitsi kirjutada [5]=0xff ja [6]=0x9B, nagu ülal seadme kirjelduses näiteks toodud. Vastus peaks siis olema -10.1 (või -101 läbi jagamata)
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 30.10.2022 09:44:06 vasta tsitaadiga

Anduriga on vähemalt esmapilgul OK.
Nüüd on vaja releedele juhtloogika teha mis vee voolu sisse välja lülitavad.

Idee on järgmine: kastmine saab toimuda ainult 7-8 vahel hommikul. Mulla niiskus peab olema alla 30%, et relee saaks rakenduda. Korraga saab relee sees olla 300sek. Seejärel on 300sek paus (niiskus maas ühtlustub veidi) ning seejärel vaadatakse uuesti niiskust ning kellaega.

Eile tegin niipalju, kuid see 300+300sek timer ajab kuidagi juhtme kokku :S Ei oska seda implementeerida.
if (Soilhumidity1 <= 30 && currentHour == 7) {
// turn RELEE on
digitalWrite(relee_1, HIGH);
relee_1_state = 1;
} else {
// turn RELEE off
digitalWrite(relee_1, LOW);
relee_1_state = 0;
}

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
kalvis
Kreisi kasutaja

liitunud: 20.10.2009




sõnum 30.10.2022 10:16:59 vasta tsitaadiga

Käivitaks kellaaeg 7.00.00 (minutid, sekundid) mis lülitab kastmise sisse
if (timer==7.00.00 && niikusandur<30%) pump=ON; //pumba sisselülimine kell 7 hommikul
ja kui soovid enneaegset väljaklülitumist niiskusandurist siis
if (pump==ON && niiskusandur>niiskusäte) pump OFF; //niiskusandurist väljalülimine tegelikult pump==ON ei peagi olema tingimuses. Siin võib kasutada mistahes muud erisätet väljalülimiseks
if (timer==7.05.00) pump=OFF;//timeri järgi väljalülimine) (ei pea pabistama kui eelnev on juba OFF lükanud.
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 30.10.2022 17:27:32 vasta tsitaadiga

Kui midagi muud selle protsessoriga samal ajal tarvis teha ei ole, siis oli Arduinol miski delay vist ka, millega 300 sek oodata.
See on üsna jõuga lahendus. Kui tarvis protsessorit samal ajal ka muu jaoks kasutada, siis ei sobi kindlasti.

Momendil tuleb pähe näiteks protsessori timeri interrupti kasutamine, mis oleks muidugi ilus lahendus.
Või siis pumba käivitamisel välja arvutada ja kuhugi kirja panna vajalik lõpuaeg ning kontrollida, kas ollakse sinnani jõutud.
Miski olekumasin loogika tuleks enda jaoks ehitada: mis olekus aparaat momendil on ning siis vastavalt käituda.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 30.10.2022 21:11:16 vasta tsitaadiga

Lahendasin nii (loop's):


  currentHour = timeClient.getHours();
  currentMinute = timeClient.getMinutes();


  if (currentHour != previuosHour){
    previuosHour = currentHour;
    Timer_OFF_Time_1 = 10;
    Timer_ON_Time_1 = 5;

  }
 
  if (Soilhumidity1 <= 30 && currentHour == 20 && currentMinute <= Timer_ON_Time_1) {
      // turn RELEE on
      digitalWrite(relee_1, HIGH);
      relee_1_state = 1;

    }

  else if (currentMinute > Timer_ON_Time_1 && currentMinute > Timer_OFF_Time_1){
    Timer_OFF_Time_1 = currentMinute + 10;
    Timer_ON_Time_1 = currentMinute + 5;

  }   

  else {
     
      // turn RELEE off
      digitalWrite(relee_1, LOW);
      relee_1_state = 0;
    }


Tundub lollikindel ning suht kompaktne koodi mõistes. 5min ON, 5min OFF ning kordub pidevalt.

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
kalvis
Kreisi kasutaja

liitunud: 20.10.2009




sõnum 31.10.2022 11:17:43 vasta tsitaadiga

timer interrupt on vaid siis mõistlik kui prose peab ka muud tööd tegema. Kui muuks tööks on samuti temperatuuri mõõtmine siis pannakse need käsud ikkagi igavesse loopi. Pole mõtet koodi ilmaasjata keerulisemaks teha kui lihtsamini saab.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 19.11.2022 15:27:41 vasta tsitaadiga

Väike tõrge millega oleks abi vaja.
Esmasel käivitusel kood takerdub kuskile (ESP32 ennast wifi võrku ei ühenda). Kui ma korraks serial1 juhtmed tagant ära tõmban ning tagasi panen ESP32'l, siis ärkab asi ellu.
ESP32 software serial Serial1 (pin26, 27) ühendub serial - RS485 konverterisse ning sealt edasituleb RS485 andur. https://www.aliexpress.com/item/32889414931.html?spm=a2g0o.order_list.0.0.21ef1802DQ9YDb

Ma ei tea ise kuidas RS485 ning kasvõi seriali puhul suhtlus protokollid on.
Näiteks minu kood saadab üle seriali (ühe korra?) oma baidijada ning jääb vastust ootama? Mingit timeouti siin vist ei ole ning nüüd ongi eetris lõputult vaikus ning oodatakse?

Või eelneva näite puhul võiks ikkagi asi ennast Wifisse ära ühendada? St, kui saadab päringu ning ootab oma vastust ei tekista ju miski wifi'sse ühendamist. Kuid asi ärkab ellu just siis, kui selle seriali korra lahti võtan ning tagasi panen.

Hetkel on üks RS485 andur taga kuna teist ei ole veel tulnud. Ühele aadressile tehakse hetkel 2 järjestikst päringut koodis. Sensor1 ja Sensor2.
Kuna asi on nüüd kasvuhones paigas, siis ei saa üle seriali arvutist täpsemat debugi teha :/ Maha võtta ning tuppa tuua oleks suht tülikas - loodaks vea kuidagi muud mood iavastada.

-EDIT-

Probleem tundub olevat tegelikult palju müstilisem. Esmakäivitusel on lihtsalt wifi levi ülimalt kehva. -88-90dB. St lihtsalt ei suuda ühendada. Kui seriali juhtme välja võtan ja tagasi panen on kõik järsku OK -58dB.

Kogu kood järgnev:


// ESPmDNS for esp32 - Version: Latest
#include <ESPmDNS.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <Update.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include "ThingSpeak.h"
#include <NTPClient.h>


const char* hostname = "esp32_Kasvuhoone";
const char* ssid = "000";
const char* password = "000";

WebServer server(80);
WiFiClient  client;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 600000);


const char* loginIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
   "<input type='file' name='update'>"
        "<input type='submit' value='Update'>"
    "</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
  "$('form').submit(function(e){"
  "e.preventDefault();"
  "var form = $('#upload_form')[0];"
  "var data = new FormData(form);"
  " $.ajax({"
  "url: '/update',"
  "type: 'POST',"
  "data: data,"
  "contentType: false,"
  "processData:false,"
  "xhr: function() {"
  "var xhr = new window.XMLHttpRequest();"
  "xhr.upload.addEventListener('progress', function(evt) {"
  "if (evt.lengthComputable) {"
  "var per = evt.loaded / evt.total;"
  "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  "}"
  "}, false);"
  "return xhr;"
  "},"
  "success:function(d, s) {"
  "console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";

unsigned long myChannelNumber = 000;
const char * myWriteAPIKey = "000";

HardwareSerial mySerial1(1);
     
const byte sensor1 [] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];
int Soiltemp1;
int Soilhumidity1;


const byte sensor2 [] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB}; //0x02 esimene bait, kui aadress muuta?
byte values2[11];
int Soiltemp2;
int Soilhumidity2;


const int relee_1 = 16;
const int relee_2 = 17;
int relee_1_state = 0;
int relee_2_state = 0;

int Niiskus_1_Treshold = 30;
int Niiskus_2_Treshold = 30;
unsigned long Timer_ON_Time_1;
unsigned long Timer_ON_Time_2;
unsigned long Timer_OFF_Time_1;
unsigned long Timer_OFF_Time_2;
int currentHour;
int currentMinute;
int previuosHour;
int previuosMinute;


float temperatureC; //onewire andurist tulev temp

const int oneWireBus = 4;     //temp anduri pin

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);


void setup() {
 
  Serial.begin(115200);
  mySerial1.begin(4800,SERIAL_8N1,26,27);

  WiFi.mode(WIFI_STA);
  WiFi.hostname(hostname);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (!MDNS.begin(hostname)) { //http://esp32.local
    Serial.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");
  /*return index page which is stored in serverIndex */
  server.on("/", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", loginIndex);
  });

  /*handling uploading firmware file */
  server.on("/update", HTTP_POST, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
    ESP.restart();
  }, []() {
    HTTPUpload& upload = server.upload();
    if (upload.status == UPLOAD_FILE_START) {
      Serial.printf("Update: %s\n", upload.filename.c_str());
      if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_WRITE) {
        /* flashing firmware to ESP*/
        if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_END) {
        if (Update.end(true)) { //true to set the size to the current progress
        Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
      } else {
        Update.printError(Serial);
      }
    }
  });
  server.begin();


  sensors.begin();
  ThingSpeak.begin(client);  // Initialize ThingSpeak
 
  timeClient.begin();

  pinMode(relee_1, OUTPUT);
  pinMode(relee_2, OUTPUT);
}

void loop() {
 
  server.handleClient();
  timeClient.update();
  currentHour = timeClient.getHours();
  currentMinute = timeClient.getMinutes();
 
  if (currentHour != previuosHour){
    previuosHour = currentHour;
    Timer_OFF_Time_1 = 10;
    Timer_ON_Time_1 = 5;
    Timer_OFF_Time_2 = 5;
    Timer_ON_Time_2 = 0;
  }

  if (currentMinute != previuosMinute){
    sensors.requestTemperatures();
    temperatureC = sensors.getTempCByIndex(0);
    RS485sensor();
    relee1();
    relee2();
    relee1();
    relee2();
    thingspeak();
    previuosMinute=currentMinute;
  }
 

}



void RS485sensor() {

 
  if (mySerial1.write(sensor1, sizeof(sensor1)) == 8) {

    for (byte i = 0; i < 11; i++) {
      values[i] = mySerial1.read();
    }
    if (values[0]==1 && values[1]==3 && values[2]==6){ // 3 esimese baidi kontroll sensori vastusest, need on alati samad
        Soilhumidity1 = (values[3]*256+values[4])/10;
        Soiltemp1 = (values[5]*256+values[6])/10;
    }
  }

  delay(10);

  if (mySerial1.write(sensor2, sizeof(sensor2)) == 8) {
 
    for (byte i = 0; i < 11; i++) {
      values[i] = mySerial1.read();
    }
    if (values[0]==2 && values[1]==3 && values[2]==6){ // 3 esimese baidi kontroll sensori vastusest, need on alati samad
        Soilhumidity2 = (values[3]*256+values[4])/10;
        Soiltemp2 = (values[5]*256+values[6])/10;
    }
  }

 
}

void relee1(){
 
    if (currentHour == 7 && Soilhumidity1 <= Niiskus_1_Treshold && currentMinute <= Timer_ON_Time_1 && relee_2_state == 0) {
      // turn RELEE on
      digitalWrite(relee_1, HIGH);
      relee_1_state = 1;
      Serial.println();
      Serial.print("IF");
    }

  else if (currentMinute > Timer_ON_Time_1 && currentMinute > Timer_OFF_Time_1){
    Timer_OFF_Time_1 = currentMinute + 10;
    Timer_ON_Time_1 = currentMinute + 5;
      Serial.println();
      Serial.print("else IF");
  }   

  else {
     
      // turn RELEE off
      digitalWrite(relee_1, LOW);
      relee_1_state = 0;
      Serial.println();
      Serial.print("else");
    }
}


void relee2(){
 
    if (currentHour == 7 && Soilhumidity2 <= Niiskus_2_Treshold && currentMinute <= Timer_ON_Time_2 && relee_1_state == 0) {
      // turn RELEE on
      digitalWrite(relee_2, HIGH);
      relee_2_state = 1;
      Serial.println();
      Serial.print("IF");
    }

  else if (currentMinute > Timer_ON_Time_2 && currentMinute > Timer_OFF_Time_2){
    Timer_OFF_Time_2 = currentMinute + 10;
    Timer_ON_Time_2 = currentMinute + 5;
      Serial.println();
      Serial.print("else IF");
  }   

  else {
     
      // turn RELEE off
      digitalWrite(relee_2, LOW);
      relee_2_state = 0;
      Serial.println();
      Serial.print("else");
    }
}


void thingspeak(){
       
    // Connect or reconnect to WiFi
    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Attempting to connect");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password);
        delay(5000);     
      }
      Serial.println("\nConnected.");
    }

    ThingSpeak.setField(1,temperatureC);
    ThingSpeak.setField(2,Soiltemp1);
    ThingSpeak.setField(3,Soilhumidity1);
    ThingSpeak.setField(4,Soilhumidity2);
    ThingSpeak.setField(5,relee_1_state);
    ThingSpeak.setField(6,relee_2_state);
    // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
    // pieces of information in a channel.  Here, we write to field 1.
    int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
 
    if(x == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(x));
    }
}

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
Supiplex
HV veteran
Supiplex

liitunud: 11.12.2002




sõnum 19.11.2022 22:29:38 vasta tsitaadiga

Julgen ennustada, et ilma terminali väljundit nägemata sa jäädki seda probleemi uurima. Vii läpakas kasvuhoonesse või ESP32 tuppa või mõtle mingi kolmas lahendus et näeks mis juttu logitakse.

Muide: selline kood teeb vea otsimise keeruliseks sest ta teeb lihtsalt restarti kui WiFi ühenduse loomine esimesel katsel ebaõnnestub. Veakood aga läheb sealjuures kaotsi (WiFi draiver küll logib ise üsna asjalikult, kui sa tal suud kinni pole pannud, aga hea oleks lõpliku veakoodi oma silmaga näha).

  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }


Kasulikum oleks logida, mis õieti juhtus:

  WiFi.begin(ssid, password);
  int rc = WiFi.waitForConnectResult();
  if (rc != WL_CONNECTED) {
    Serial.println("WiFi conn failed: %d", rc);
    delay(5000);
    ESP.restart();
  }


Puhtalt kõhutunde pealt pakun, et võib-olla on kohe restardi tegemine pisut karm. Ehk tasub näiteks kolm korda "viisakalt" katsuda ühendust taasluua.

#define MAX_WIFI_RETRIES 3
int rc, retries = 0;
do {
  WiFi.begin(ssid, password);
  rc = WiFi.waitForConnectResult();
  if (rc != WL_CONNECTED) {
    Serial.println("WiFi conn failed: %d (retry %d/%d)", rc, retries, MAX_WIFI_RETRIES);
    delay(1000);
  }
} while (rc != WL_CONNECTED && retries++ < MAX_WIFI_RETRIES);
if (rc != WL_CONNECTED) {
  Serial.println("Failed all WiFi conn retries, rebooting");
  delay(5000);
  ESP.restart();
}

_________________
The young lady had an unusual list,
Linked in part to a structural weakness.
She set no preconditions.
Kommentaarid: 38 loe/lisa Kasutajad arvavad:  :: 0 :: 1 :: 34
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 20.11.2022 14:54:27 vasta tsitaadiga

Seda wifi osa võiks muuta küll, see reboot peale 5 sek on kuksilt netist copytud koodi osa.

Sellele probleemile sain aga jälile. Oli teine riistvaraline. See TTL-RS485 adapter töötab 5V pealt ning kuigi ESP32 manualis on kirjas, et pinid on 5V tolerant, siis algul initsialiseerides ei tohi seal 5V peal olla. Vastasel juhul tekib mingi anomaalia, kus wifi levi on äärmiselt nõrk.

Tegin takistitega pingejaguri signaali osale ning nüüd toimetab ilusti.

Kuna temp andureid tuleb 2tk, ning plaanis nad mõlemad paralleelselt sama RS485-TTL külge toppida, siis peab ühel aadressi ära muutma.
Muutsin, siis aadressi USB-RS485 klotsi ning vastava tarkvaraga ära, kuid ESP32 nüd anduriga enam suhelda ei suutnud. Adaperi lede vaadates päringu teeb, kuid vastust ei tule.

Vist isegi tean milles probleem on...

Muutsin aadressi 0x02 peale ning päring andurisse järgmine: const byte sensor2 [] = {0x02,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};

Aga 2 viimast byte on error check lo ja hi (mida iganes see tähendab täpselt). Ning kui ma muutsin aadressi ära, siis muutub ka see error checki koodi osa ju?
Kuidas seda üldse arvutada mis need viimsed 2 baiti peaksid olema nüüd?

-EDIT-
Leidsin programmi "Simply Modbus Master" millega saab selle CRC osa koodist kui eelnev kood sama panna mis mu pärin on. Päring tuleks {0x02,0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xF8};
Proovin hiljem ära, kui hetkel leidsin vist ühe teise probleemi veel.
Temperatuur on paar kraadi miinuses, kuid andur ütleb, et temp on nullis.
Ei saa ise aru ka koodis sellest miks temperatuuri komakohaga ei edastata vaid täisarvuna?

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
mikk36
HV Guru
mikk36

liitunud: 21.02.2004




sõnum 20.11.2022 18:27:01 vasta tsitaadiga

Terror, floating point väärtused ei ole täpsed ja vajavad ka rohkem ruumi edastamisel, lihtsam on edastada kümnekordne väärtus ja siis ise jagad kümnega uuesti tulemuse.
Kommentaarid: 85 loe/lisa Kasutajad arvavad:  :: 0 :: 2 :: 78
tagasi üles
vaata kasutaja infot saada privaatsõnum
Supiplex
HV veteran
Supiplex

liitunud: 11.12.2002




sõnum 20.11.2022 22:02:11 vasta tsitaadiga

Hiinlaste dokumentatsioon pole algajatele icon_smile.gif. Vihjetest saab aru, et sensor kasutab standardset Modbus RTU protokolli. Seal kasutatakse CRC arvutamiseks Wikipedia andmetel polünoomi CRC-16-ANSI algväärtusega 0xFFFF. Pannes õige algväärtuse suvalisse internetist leitud näidisesse on sinu CRC arvutamise kood selline:

#define TBLSIZE         256
#define CRC16_INIT      0xFFFF

uint16_t CRC16Table[TBLSIZE] = {
   0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
   0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
   0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
   0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
   0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
   0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
   0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
   0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
   0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
   0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
   0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
   0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
   0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
   0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
   0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
   0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
   0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
   0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
   0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
   0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
   0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
   0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
   0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
   0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
   0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
   0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
   0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
   0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
   0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
   0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
   0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
   0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};

uint16_t BlockCRC16(uint8_t *block, int16_t len) {
   uint16_t crc = CRC16_INIT;
   for (unsigned i = 0; i < len; i++) {
      crc=(int16_t) ((crc>>8)^(uint16_t)CRC16Table[(crc^(uint16_t)block[i])&0x00ff]);
   }
   return (crc);
}


Kontrollisin üle, tulevad õiged CRC-d välja küll.

Selle algoritmi ässitad oma andmevälja kallale, v.a. kaks viimast baiti (Error Check Lo/Hi). Välja tuleb kahebaidine arv mille noorem bait läheb "Error Check (Lo)" ja vanem bait "Error Check (Hi)" väljale. Midagi sellist:

byte sensor1[] = {0x01,0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}; // Last 2 bytes reserved for CRC
uint16_t crc = BlockCRC16(sensor1, sizeof(sensor1 - 2));
sensor1[sizeof(sensor1) - 2] = (byte) (crc | 0x00FF); // "Error Check (Lo)"
sensor1[sizeof(sensor1) - 1] = (byte) ((crc | 0xFF00) >> 8); // "Error Check (Hi)"

_________________
The young lady had an unusual list,
Linked in part to a structural weakness.
She set no preconditions.
Kommentaarid: 38 loe/lisa Kasutajad arvavad:  :: 0 :: 1 :: 34
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 21.11.2022 10:19:59 vasta tsitaadiga

mikk36 kirjutas:
Terror, floating point väärtused ei ole täpsed ja vajavad ka rohkem ruumi edastamisel, lihtsam on edastada kümnekordne väärtus ja siis ise jagad kümnega uuesti tulemuse.

Sellest saan aru, ning koodis on:

int Soiltemp1;
...
Soiltemp1 = (values[5]*256+values[6])/10;

Aga kui ma Soiltemp1 välja prindin on see täisarv mitte komakohaga. Ei saa sellest aru miks ta printides ei ole komakohaga.

Negatiivsete temperatuuride kohta kirjutab siin manualis justkui nii, et negatiivsete temperatuuride puhul lisatakse "H" temperatuuriväärtusele? FF9B H = -101 =>-10,1

Kas ma saan õieti aru, et saadetud vastuse pikkus muutub pikemaks? Et ei ole 10 baiti vaid muutub 11 peale?

Tahtsin üritada vastuses CRC kontrolli teha, kuid minu piiratud oskuste juures, kui vastuse pikkus muutub läheks see vist väga keeruliseks.

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 21.11.2022 10:36:04 vasta tsitaadiga

Kui solitemp1 on int siis lõigataksegi täisarvuliseks. Kasuta float kui tarvis, või nagu ülalpool soovitati, kasutagi 10 korda suuremat väärtust.

Ei lähe vastus pikemaks. FF9B on ikka kogu vastus. H võib siin viidata 16-süsteemile. Negatiivsed arvud siis täiendkoodis muidugi.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 21.11.2022 17:12:03 vasta tsitaadiga

Mis siin muidu valesti on? void RS485sensor() kutsutakse loopis. Justkui jääb sinna do while loopi kinni kus crc'd kontrollitakse.


void RS485sensor() {



  word checksum;
  word crc;
  do
    {
      mySerial1.write(sensor1, sizeof(sensor1));

      for (byte i = 0; i < 11; i++) {
        values[i] = mySerial1.read();
        checksum = CRC16 (values, 8);                               // calculate CRC-16/MODBUS checksum
        crc = values[10] * 256 + values[9];               // get checksum from buffer
      }
    }
    while (checksum != crc);                                                   // test if checksum is ok

 
  Soilhumidity1 = (values[3]*256+values[4])/10;
  Soiltemp1 = (values[5]*256+values[6])/10;
}

// CRC-16/MODBUS calc function

uint16_t CRC16 (const byte *nData, uint16_t wLength)
    {
    static const uint16_t wCRCTable[] = {
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };

    byte nTemp;
    uint16_t wCRCWord = 0xFFFF;

    while (wLength--)
        {
        nTemp = *nData++ ^ wCRCWord;
        wCRCWord >>= 8;
        wCRCWord  ^= wCRCTable[(nTemp & 0xFF)];
        }
    return wCRCWord;
    } // End: CRC16

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 21.11.2022 18:33:41 vasta tsitaadiga

Kas crc ei peaks arvutama 9 baidi järgi? Ja seda ei maksaks teha sisemises tsüklis.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 21.11.2022 20:42:57 vasta tsitaadiga

Sul on õigus. Tegin korrektuuri:


void RS485sensor() {


 
  word checksum;
  word crc;
  do
    {
      x=x++;
      mySerial1.write(sensor1, sizeof(sensor1));
      for (byte i = 0; i < 11; i++) {
        values[i] = mySerial1.read();
      }

      Serial.println();
      Serial.print(values[0], DEC);
      Serial.print(":");
      Serial.print(values[1], DEC);
      Serial.print(":");
      Serial.print(values[2], DEC);
      Serial.print(":");
      Serial.print(values[3], DEC);
      Serial.print(":");
      Serial.print(values[4], DEC);
      Serial.print(":");
      Serial.print(values[5], DEC);
      Serial.print(":");
      Serial.print(values[6], DEC);
      Serial.print(":");
      Serial.print(values[7], DEC);
      Serial.print(":");
      Serial.print(values[8], DEC);
      Serial.print(":");
      Serial.print(values[9], DEC);
      Serial.print(":");
      Serial.print(values[10], DEC);   
      Serial.println();
     
      checksum = CRC16 (values, 9); // calculate CRC-16/MODBUS checksum
     
      Serial.print("checksum: ");
      Serial.print(checksum);   
      Serial.println();
     
      crc = values[10] * 256 + values[9]; // get checksum from buffer
     
      Serial.print("CRC: ");
      Serial.print(crc);   
      Serial.println();
      Serial.print("retries: ");
      Serial.print(x);   
      Serial.println();

      delay(200);
    }
    while (checksum != crc || x<10); // test if checksum is ok. Tahaks, et max 10 korda oleks, et kood kinni ei jookseks, kui mingi jama on.

  x=0;
 
  Soilhumidity1 = (values[3]*256+values[4])/10;
  Soiltemp1 = (values[5]*256+values[6])/10;


CRC töötab, kuid tahaks teha nii, et kui seal mingi kala on, siis ei jookseks asi omadega umbe (ala igavene do while loop ning ei saa OTA tarkvara uuendust ega midagi teha). Panin sinna omaarust 10 korra proovimise piirangu, kuid asi ei toimi.
Serial out selline:

1:3:6:0:0:0:160:0:0:33:87
checksum: 22305
CRC: 22305
retries: 0

1:3:6:0:0:0:160:0:0:33:87
checksum: 22305
CRC: 22305
retries: 0

1:3:6:0:0:0:160:0:0:33:87
checksum: 22305
CRC: 22305
retries: 0

1:3:6:0:0:0:160:0:0:33:87
checksum: 22305
CRC: 22305
retries: 0

....


Soiltemp1 võin float'ks muuta, kuid see ei mõjuta tulemust. Endiselt on täisarv...
Näiteks 1:3:6:0:0:0:159:0:0:33:87 puhul anna 16 kraadi, kuigi peaks olema 15,9.

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 21.11.2022 20:57:07 vasta tsitaadiga

x = x++;
see on natuke kahtlane kirjapilt. Postfix operaatori korral on avaldise väärtuseks x väärtus *enne* suurendamist
Kasuta lihtsalt x++ või siis x = x + 1 Aga ma praegu ei testinud, mälu järgi võib see probleem olla.

Kui Soiltemp on float ja see sobib, siis pane seal jagamise avaldises 10 asemele 10.0. Muidu on mõlemal pool täisarvud ja tulemsu samuti.
tagasi üles
vaata kasutaja infot saada privaatsõnum
Terror
HV veteran
Terror

liitunud: 08.11.2001




sõnum 21.11.2022 21:54:41 vasta tsitaadiga

Selle sai kõik toimima thumbs_up.gif

Nüüd on negatiivse temp kuvamine vaja korda saada. Decimal from signed 2's complement - midagi sellist...
Leidsin mingi koodijupi googlist aga ma ei tea kas toimib, toas vähemalt pos tempi näitab õieti.

Soiltemp1 =((int)((word)values[5] << 8 | (word)values[6])/ 10.0);

_________________
Väiksemagabariidilised trei, frees ning keevitustööd. PS.
Kommentaarid: 100 loe/lisa Kasutajad arvavad:  :: 1 :: 2 :: 91
tagasi üles
vaata kasutaja infot saada privaatsõnum
jh_
HV vaatleja

liitunud: 04.09.2021




sõnum 21.11.2022 22:00:35 vasta tsitaadiga

Eeldusel, et int on 2 baidine, võiks silma järgi töötad. Kirjuta testimiseks vastavatess baitidesse teadaolevad väärtused.
tagasi üles
vaata kasutaja infot saada privaatsõnum
näita postitusi alates eelmisest:   
uus teema   vasta Tarkvara »  Programmeerimine »  Arduino'ga temp/niiskuse andur RS485 suhtlus
[vaata eelmist teemat] [vaata järgmist teemat]
 lisa lemmikuks
näita foorumit:  
 ignoreeri teemat 
sa ei või postitada uusi teemasid siia foorumisse
sa ei või vastata selle foorumi teemadele
sa ei või muuta oma postitusi selles foorumis
sa ei või kustutada oma postitusi selles foorumis
sa ei või vastata küsitlustele selles foorumis
sa ei saa lisada manuseid selles foorumis
sa võid manuseid alla laadida selles foorumis



Hinnavaatlus ei vastuta foorumis tehtud postituste eest.