[Arduino] Pomiar przewodności wody

Nie wiesz jak przetłumaczyć kod z innego języka? Napisz. Postaram/postaramy się pomóc.
C-->Bascom, Arduino-->Bascom. Nie bój żaby zapytać :D
ODPOWIEDZ
Awatar użytkownika
pimowo
Posty: 392
Rejestracja: 28 maja 2016, 10:07

[Arduino] Pomiar przewodności wody

Post autor: pimowo » 09 mar 2021, 8:32

Hej,
Potrzebuję przetłumaczyć kod Arduino do Bascom, a konkretnie chodzi mi o to, że posiadam moduł: DFRobot Gravity - analogowy czujnik TDS, czystości wody dla Arduino znalazłem kod dla Arduino, a dla Bascom niestety nic nie ma :(

Jak dobrze rozumiem to pierwszy kod jest kodem podstawowym, gdzie po prostu odczytuję moduł:
  1. /***************************************************
  2.  DFRobot Gravity: Analog TDS Sensor / Meter For Arduino
  3.  <https://www.dfrobot.com/wiki/index.php/Gravity:_Analog_TDS_Sensor_/_Meter_For_Arduino_SKU:_SEN0244>
  4.  
  5.  Created 2017-8-22
  6.  By Jason <jason.ling@dfrobot.com@dfrobot.com>
  7.  
  8.  GNU Lesser General Public License.
  9.  See <http://www.gnu.org/licenses/> for details.
  10.  All above must be included in any redistribution
  11.  
  12.  /***********Notice and Trouble shooting***************
  13.  1. This code is tested on Arduino Uno and Leonardo with Arduino IDE 1.0.5 r2 and 1.8.2.
  14.  2. More details, please click this link: <https://www.dfrobot.com/wiki/index.php/Gravity:_Analog_TDS_Sensor_/_Meter_For_Arduino_SKU:_SEN0244>
  15.  ****************************************************/
  16.  
  17. #define TdsSensorPin A1
  18. #define VREF 5.0      // analog reference voltage(Volt) of the ADC
  19. #define SCOUNT  30           // sum of sample point
  20. int analogBuffer[SCOUNT];    // store the analog value in the array, read from ADC
  21. int analogBufferTemp[SCOUNT];
  22. int analogBufferIndex = 0,copyIndex = 0;
  23. float averageVoltage = 0,tdsValue = 0,temperature = 25;
  24.  
  25. void setup()
  26. {
  27.     Serial.begin(115200);
  28.     pinMode(TdsSensorPin,INPUT);
  29. }
  30.  
  31. void loop()
  32. {
  33.    static unsigned long analogSampleTimepoint = millis();
  34.    if(millis()-analogSampleTimepoint > 40U)     //every 40 milliseconds,read the analog value from the ADC
  35.    {
  36.      analogSampleTimepoint = millis();
  37.      analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin);    //read the analog value and store into the buffer
  38.      analogBufferIndex++;
  39.      if(analogBufferIndex == SCOUNT)
  40.          analogBufferIndex = 0;
  41.    }  
  42.    static unsigned long printTimepoint = millis();
  43.    if(millis()-printTimepoint > 800U)
  44.    {
  45.       printTimepoint = millis();
  46.       for(copyIndex=0;copyIndex<SCOUNT;copyIndex++)
  47.         analogBufferTemp[copyIndex]= analogBuffer[copyIndex];
  48.       averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
  49.       float compensationCoefficient=1.0+0.02*(temperature-25.0);    //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
  50.       float compensationVolatge=averageVoltage/compensationCoefficient;  //temperature compensation
  51.       tdsValue=(133.42*compensationVolatge*compensationVolatge*compensationVolatge - 255.86*compensationVolatge*compensationVolatge + 857.39*compensationVolatge)*0.5; //convert voltage value to tds value
  52.       //Serial.print("voltage:");
  53.       //Serial.print(averageVoltage,2);
  54.       //Serial.print("V   ");
  55.       Serial.print("TDS Value:");
  56.       Serial.print(tdsValue,0);
  57.       Serial.println("ppm");
  58.    }
  59. }
  60. int getMedianNum(int bArray[], int iFilterLen)
  61. {
  62.       int bTab[iFilterLen];
  63.       for (byte i = 0; i<iFilterLen; i++)
  64.       bTab[i] = bArray[i];
  65.       int i, j, bTemp;
  66.       for (j = 0; j < iFilterLen - 1; j++)
  67.       {
  68.       for (i = 0; i < iFilterLen - j - 1; i++)
  69.           {
  70.         if (bTab[i] > bTab[i + 1])
  71.             {
  72.         bTemp = bTab[i];
  73.             bTab[i] = bTab[i + 1];
  74.         bTab[i + 1] = bTemp;
  75.          }
  76.       }
  77.       }
  78.       if ((iFilterLen & 1) > 0)
  79.     bTemp = bTab[(iFilterLen - 1) / 2];
  80.       else
  81.     bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
  82.       return bTemp;
  83. }
a drugi kod dodatkowo ma możliwość kalibracji:
  1. /***************************************************
  2.  DFRobot Gravity: Analog TDS Sensor/Meter
  3.  <https://www.dfrobot.com/wiki/index.php/Gravity:_Analog_TDS_Sensor_/_Meter_For_Arduino_SKU:_SEN0244>
  4.  
  5.  ***************************************************
  6.  This sample code shows how to read the tds value and calibrate it with the standard buffer solution.
  7.  707ppm(1413us/cm)@25^c standard buffer solution is recommended.
  8.  
  9.  Created 2018-1-3
  10.  By Jason <jason.ling@dfrobot.com@dfrobot.com>
  11.  
  12.  GNU Lesser General Public License.
  13.  See <http://www.gnu.org/licenses/> for details.
  14.  All above must be included in any redistribution.
  15.  ****************************************************/
  16.  
  17.  /***********Notice and Trouble shooting***************
  18.  1. This code is tested on Arduino Uno with Arduino IDE 1.0.5 r2 and 1.8.2.
  19.  2. Calibration CMD:
  20.      enter -> enter the calibration mode
  21.      cal:tds value -> calibrate with the known tds value(25^c). e.g.cal:707
  22.      exit -> save the parameters and exit the calibration mode
  23.  ****************************************************/
  24.  
  25. #include <EEPROM.h>
  26. #include "GravityTDS.h"
  27.  
  28. #define TdsSensorPin A1
  29. GravityTDS gravityTds;
  30.  
  31. float temperature = 25,tdsValue = 0;
  32.  
  33. void setup()
  34. {
  35.     Serial.begin(115200);
  36.     gravityTds.setPin(TdsSensorPin);
  37.     gravityTds.setAref(5.0);  //reference voltage on ADC, default 5.0V on Arduino UNO
  38.     gravityTds.setAdcRange(1024);  //1024 for 10bit ADC;4096 for 12bit ADC
  39.     gravityTds.begin();  //initialization
  40. }
  41.  
  42. void loop()
  43. {
  44.     //temperature = readTemperature();  //add your temperature sensor and read it
  45.     gravityTds.setTemperature(temperature);  // set the temperature and execute temperature compensation
  46.     gravityTds.update();  //sample and calculate
  47.     tdsValue = gravityTds.getTdsValue();  // then get the value
  48.     Serial.print(tdsValue,0);
  49.     Serial.println("ppm");
  50.     delay(1000);
  51. }
Oczywiście bardziej mnie interesuje ten drugi ponieważ jest tam (niby) możliwość kalibracji ;)

*Wszytko robię na ATmega328P z wewnętrznym napięciem odniesienia 1.1V i do tego rezystorowy dzielnik napięcia 12k do VCC i 11k do GND (moduł daje sygnał analogowy 0-2.3V) Dodatkowo będzie czujnik temperatury DS18B20

PS
A może jeszcze inaczej zapytam... O co tu w ogóle chodzi, jak ja mam odczytany sygnał ADC przeliczyć (uwzględniając temperaturę) na EC/TDS?
W sumie jak będę znał jakimi wzorami się posłużyć to już reszta z górki ;)
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: [Arduino] Pomiar przewodności wody

Post autor: niveasoft » 09 mar 2021, 9:03

Mogę to przepisać do Bascom, ale to musiałoby chwilę poczekać.
Szybciej będzie jak napiszę o co tam chodzi.

Jest tablica 30 Word`ów na odczyty ADC i do niej w kółko (Word(idx) = ADC, a kiedy Idx ma 30 to jest ustawiane na 1 ) zbierane są odczyty ADC co 40ms

Kiedy mija 800ms to ta tablica jest kopiowana do drugiej takiej samej tablicy tymczasowej(mozna uzyć Memcopy) bo ta jest sortowana i wyciagana jest mediana. Z tego wybranego oblicza się napiecie przeliczajac względem AREF i to jest AverageVoltage.
Potem obliczany jest przelicznik JakasSingle = 1.02 * (temperatura - 25)
Obliczasz sobie conpensationVoltage mnożąc AverageVoltage przez przelicznik.

Ostatnie działanie to taka funkcja MAP - zamianatego odczytu na wartości TDS. Normalne działanie które w Bascom trzeba rozbić na osobne linie.

Co do tego drugiego kodu to to jest tylko kod który wykorzystuje gotową bibliotekę której tu nie widać. GravityTDS.h wskazuje na funkcje które są prawdopodobnie napisane w GravityTDS.cpp. Tak na przykład funkcja gravityTds.begin(); odwoła sie po kolei do odczytu danych po czym może to skalibruje.

To jest wszystko podobne do tego czujnika PH od DFrobot.
Awatar użytkownika
pimowo
Posty: 392
Rejestracja: 28 maja 2016, 10:07

Re: [Arduino] Pomiar przewodności wody

Post autor: pimowo » 09 mar 2021, 9:52

Dziękuję za tłumaczenie na nasze ;)
Zastanawiam się po co tyle kombinacji z tym odczytem ADC? Czy to nie wystarczy po prostu odczytać ADC i przeliczyć?

Znalazłem brakujące pliki - nie zauważyłem wcześniej, a na stronie którą podałem wszytko jest.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: [Arduino] Pomiar przewodności wody

Post autor: niveasoft » 09 mar 2021, 12:59

Okay zajrzę później. Na razie łap pierwszy kod.
Wiem że musisz teraz zmienić z AVCC na 1.1V ;)
Funkcja jest dopisana względem oryginalnego kodu bo w funkcjach można deklarować lokalne które potem nie są potrzebne w programie.
Jako że temperatura jest wpisana na sztywno 25 to 25-25 da zero i mnozenie 0.2x0 da 0 więc coefficient i tak masz równy 1.0 :D

  1. $regfile = "m2560def.dat"                                   '8K SRAM | 4K EEPROM
  2. $crystal = 16000000
  3. $hwstack = 256
  4. $swstack = 128
  5. $framesize = 256
  6. $baud = 115200
  7.  
  8. Config Submode = New
  9.  
  10. Const Scount = 30
  11. Const Mediana =(scount + 1) / 2
  12.  
  13. Dim Analogbuffer(scount) As Word                            ' / / Store The Analog Value In The Array , Read From Adc
  14. Dim Analogbuffertemp(scount) As Word
  15. Dim Analogbufferindex , Copyindex As Byte
  16. Dim Averagevoltage , Tdsvalue , Temperature As Single
  17. Dim 800ms As Byte , M As Byte
  18. Temperature = 25
  19.  
  20. Function Getmediannum(byref Buffer() As Word) As Single
  21.  Sort Buffer(1)
  22.   Getmediannum = Buffer(mediana)
  23. End Function
  24.  
  25. Function Get_tds()as Single
  26.  Local Temps1 As Single , Temps2 As Single
  27.  Local Compensationcoefficient As Single
  28.  Local Compensationvolatge As Single
  29.  
  30.  Temps1 = Temperature - 25.0
  31.  Compensationcoefficient = Temps1 * 0.2
  32.  Compensationcoefficient = Compensationcoefficient + 1.0
  33.  Compensationvolatge = Averagevoltage / Compensationcoefficient
  34.  
  35.  Temps1 = Compensationvolatge ^ 3
  36.  Temps1 = Temps1 * 133.42
  37.  
  38.  Temps2 = Compensationvolatge ^ 2
  39.  Temps2 = Temps2 * 255.86
  40.  
  41.  Temps1 = Temps1 - Temps2
  42.  
  43.  Temps2 = Compensationvolatge * 857.39
  44.  
  45.  Get_tds = Temps1 + Temps2
  46.  
  47. End Function
  48.  
  49. Do
  50.  Incr Analogbufferindex : If Analogbufferindex > Scount Then Analogbufferindex = 1
  51.  
  52.   Analogbuffer(analogbufferindex) = Getadc(0)
  53.  
  54.  If 800ms < 19 Then
  55.   Incr 800ms
  56.  Else
  57.   800ms = 0
  58.    M = Memcopy(analogbuffer(1) , Analogbuffertemp(1) , 60)  'scount * 2
  59.  
  60.    Averagevoltage = Getmediannum(analogbuffertemp(1))
  61.    Averagevoltage = Averagevoltage * 0.0049                 'dla VREF=AVCC
  62.    Tdsvalue = Get_tds()
  63.  
  64.    Print "TDS Value:" ; Tdsvalue ; "ppm"
  65.  End If
  66.  
  67.  
  68.  Waitms 40
  69. Loop
  70.  
  71.  
Awatar użytkownika
pimowo
Posty: 392
Rejestracja: 28 maja 2016, 10:07

Re: [Arduino] Pomiar przewodności wody

Post autor: pimowo » 09 mar 2021, 14:33

Przeogromnie dziękuje.
Późnym wieczorkiem, jak wrócę z pracy to od razu będę testował ;)
Awatar użytkownika
pimowo
Posty: 392
Rejestracja: 28 maja 2016, 10:07

Re: [Arduino] Pomiar przewodności wody

Post autor: pimowo » 10 mar 2021, 12:44

Po małych testach wyszło mi tak:
1. sprzęt testowy:
- płytka Arduino UNO
- moduł TDS Meter v1.0
- brak dzielnika rezystorowego
- napięcie odniesienia dla ADC to VCC
- tani miernik TDS-3
- szklanka wody
2. program się blokuje, ale jak usunąłem linię: Sort Buffer(1) to program działa
3. odczyty
- miernik TDS 20st 310ppm
- Arduino 25st 216ppm
- Bascom 25st 435ppm
*po zmianie temperatury w kodzie na 20st
- Arduino pokazuje: 245ppm
- Bascom pokazuje: 0ppm

Będę musiał się zaopatrzyć w jakiś płyn/bufor na przewodność, aby być pewnym, które urządzenie jest najbliżej prawdy.
ODPOWIEDZ