Penelitian ini bertujuan bagaimana merancang alat ukur (instrument) suhu dan kelembaban tanah berbasis Internet Of Thing’s (IoT) dengan memanfaatkan platform ThingSpeak. Singkat kata kedepanya peneliti mengusung topik smart farmer dengan konsep baru yang mengacu pada pengelolaan peternakan dengan memanfaatkan Teknologi Informasi dan Komunikasi Modern untuk meningkatkan kuantitas dan kualitas produk sekaligus mengoptimalkan tenaga kerja yang dibutuhkan. Dengan konsep diatas diharapkan pertanian lebih terkontrol dan lebih akurat dalam hal pemeliharaan tanaman maupun ternak. Komponen yang menjadi kuncinya adalah penggunaan TI dan berbagai item seperti sensor, sistem kontrol, robotika, kendaraan otonom, perangkat keras otomatis, dlsbg. Penggunaan internet berkecepatan tinggi, perangkat seluler dan sistem komunikasi tanpa kabel yang handal dan biaya relatif lebih murah merupakan teknologi utama yang mengindikasikan atau ciri dari trend pertanian presisi. Produk dan layanan VRI (Variable Optimalisasi Rate Irrigation) menggunakan probe kelembaban tanah untuk memaksimalkan profitabilitas pada lahan tanaman beririgasi dengan topografi atau variabilitas tanah, meningkatkan hasil dan efisiensi penggunaan air.

1. Alat / Bahan
  • Arduino IDE
  • Wemos D1 Mini
  • OLED 0.66″ (64×48) I2C SCL SDA
  • Capasitive Sensor v2.0
  • Temperature Sensor DS18B20
  • RTC DS1307 Data Logger
  • Cable Jumper
  • Mini Rocker Switch
  • Baseboard Wemos D1 Mini
  • Acrylic Laser Cutting & Engraving
  • Battery 9V Alkaline
  • LED 3mm
  • Resistor 330ohm

2. Skematik Rangkaian

3. Code

#include <SPI.h>              //Library 
#include <SD.h>               //Library SD CARD
#include <Ethernet.h>         //Library
#include <ESP8266WiFi.h>      

#include <OneWire.h>          //Library Temperature sensor DS18B20

#include <Wire.h>             //Library OLED
#include <Adafruit_GFX.h>     //Library OLED
#include <Adafruit_SSD1306.h> //Library OLED

byte mac[]= { 0xA1, 0x37, 0xA5, 0x11, 0xB1, 0xC3 }; //mac address

//------------------------------------------------------------------------------------------
//START Inisialisasi OLED
//------------------------------------------------------------------------------------------

#define OLED_RESET 0 //GPIO 0
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16
//END Inisialisasi OLED
//------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------
//START Setting API ThingSpeak
//------------------------------------------------------------------------------------------

String apiKey = "OA0WDKFW6QNGA5Z3";  
const char* ssid = "LAB_TE";
const char* password = "innovation";
const char* server = "api.thingspeak.com";
WiFiClient client;
//END ThingSpeak
//------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------
//Inisialisasi PORT I/O dan Default Nilai Sensor
int SensorTerendam = D0;    // Sensor dicelupkan di air
int LEDKering = D5;         // Hijau
int LEDBasah = D6;          // Kuning
int LEDBanjir = D7;         // Merah
int Buzzer = D8;            // Buzzer Alarm
int RH = 0;                 // inisial tipe integer (bilangan bulat) relative humidity
int AirValue = 520;         // nilai udara
int WaterValue = 260;       // nilai air
int OverValue = 720;        // nilai ketika sensor tidak tertanam
const int sleepSeconds = 5; 
const int chipSelect = A0;  // constanta integer u/ analog port yg terhubung ke sensor kelembaban

//------------------------------------------------------------------------------------------
//START Temperature Sensor DS18B20
//------------------------------------------------------------------------------------------

OneWire  ds(D3);  // on pin D3 (a 4.7K resistor pull up is necessary)
//END DS18B20

void setup() 
{
  Serial.begin(9600); //open serial port, set the baud rate as 9600 atau 115200 bps
  
  //Inisialisasi WIFI START
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay (500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected");
  //END WIFI
  
  //START OLED
  //by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 64x48)  
  
  display.clearDisplay();       //bersihkan oled
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setTextColor(WHITE);  //pilih warna putih
  display.setCursor(35,10);     //set lokasi hurup "setCursor(x,y)"
  display.print("Moisture");    //tampilkan "Moisture" di koordinat 35,10
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("Module IoT");  //tampilkan "Module IoT" di koordinat 35,20
  display.display();            //tampilkan
  display.clearDisplay();       //bersihkan oled
  delay(1000);                  //delay 1 detik
  //END OLED

  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(90,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("K");           //kering 
  display.display();            //tampilkan
  
  //START OLED C1520201010 | Arienda NA
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setTextColor(WHITE);  //pilih warna putih
  display.setCursor(35,10);     //set lokasi hurup "setCursor(x,y)"
  display.print("1520201010");  //tampilkan "1520201010" di koordinat 35,10
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("Arienda NA");  //tampilkan "Arienda NA" di koordinat 35,20
  display.display();            //tampilkan
  display.clearDisplay();       //bersihkan oled
  delay(1000);                  //delay 1 detik
  //END OLED

  //START OLED UMTAS 2019 | Tasikmalaya
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setTextColor(WHITE);  //pilih warna putih
  display.setCursor(35,10);     //set lokasi hurup "setCursor(x,y)"
  display.print("UMTAS 2019");  //tampilkan "UMTAS 2019" di koordinat 35,10
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("Tasikmalaya"); //tampilkan "Tasikmalaya" di koordinat 35,20
  display.display();            //tampilkan
  display.clearDisplay();       //bersihkan oled
  delay(1000);                  //delay 1 detik
  //END OLED

  //START OLED Budhi | Prayoga
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setTextColor(WHITE);  //pilih warna putih
  display.setCursor(35,10);     //set lokasi hurup "setCursor(x,y)"
  display.print("Budhi Pra-");  //tampilkan "UMTAS 2019" di koordinat 35,10  
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("yoga,M.Eng");  //tampilkan "UMTAS 2019" di koordinat 35,20  
  display.display();            //tampilkan
  display.clearDisplay();       //bersihkan oled
  delay(1000);                  //delay 1 detik
  //END OLED
  
  
  pinMode(BUILTIN_LED, OUTPUT);   // make led on wemos D1 Mini Pro as Output
  pinMode(LEDKering, OUTPUT);     // make led pin d5 as output pin
  pinMode(LEDBasah, OUTPUT);      // make led pin d6 as output pin
  pinMode(LEDBanjir, OUTPUT);     // make led pin d7 as output pin
  pinMode(Buzzer, OUTPUT);        // make led pin d8 as output pin

  //Data Logger Start
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println("Inisialisasi SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
  {
    //tampilkan diserial monitor 
    Serial.println("+-----------------------+");
    Serial.println("|kartu tidak terdeteksi.|");
    Serial.println("|masukan sd card........|");
    Serial.println("+-----------------------+");
    
    for (int i = 0; i < 200; i++) //built-in led biru flash blink sebanyak 50x
      {
        digitalWrite(BUILTIN_LED, LOW);   // BUILT-IN LED LOW = ON
        digitalWrite(Buzzer, HIGH);       // BUZZER ON
        delay(25);                        // Delay 1/2 detik
        digitalWrite(BUILTIN_LED, HIGH);  // BUILT-IN LED HIGH = OFF
        digitalWrite(Buzzer, LOW);        // BUZZER OFF
        delay(25);                        // Delay 1/2 detik
        
        //START OLED
        display.clearDisplay();       //bersihkan oled
        display.setTextSize(0);       //pilih ukuran text 0 default
        display.setTextColor(WHITE);  //pilih warna putih
        display.setCursor(45,10);     //set lokasi hurup "setCursor(x,y)"
        display.print("MASUKAN");     //tampilkan "MASUKAN" di koordinat 35,10  
        display.setTextSize(0);       //pilih ukuran text 0 default
        display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
        display.print("SD CARD...");  //tampilkan "MASUKAN" di koordinat 35,20
        display.display();            //tampilkan
        display.clearDisplay();       //bersihkan oled
        //END OLED
      }
      
    // convert to microseconds
    // ESP.deepSleep(sleepSeconds * 1000000);
    // don't do anything more:
    return;
  }
  Serial.print("data akan disimpan dengan nama Humidity_Data.txt");
  delay(500);
  //Data Logger End
}

void run()
{  
  // put your main code here, to run repeatedly:
  // nilai interval = (520 - 260)/3 = 86,66
  int intervals = (AirValue - WaterValue)/3;
  int val;
  val = analogRead(A0);  //connect sensor to Analog 0
  String dataString = "";
  dataString += String(val);
  RH = (convertToPercent(val)) - 32;
  float voltage = val * (3.2 / 1023.0);

  //START OLED
  display.clearDisplay();       //bersihkan oled
  display.setTextColor(WHITE);  //pilih warna putih
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,10);     //set lokasi hurup "setCursor(x,y)"
  display.print("Moist: ");     //tampilkan "Moist: " di koordinat 35,10
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(72,10);     //set lokasi hurup "setCursor(x,y)"
  display.print(val);           //tampilkan nilai A0 dari hasil pembacaan sensor
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(35,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("RH: ");        //tampilkan "RH: " di koordinat 35,20
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(53,20);     //set lokasi hurup "setCursor(x,y)"
  display.print(RH);            //tampilkan nilai algoritma RH dari hasil perhitungan
  display.setTextSize(0);       //pilih ukuran text 0 default
  display.setCursor(75,20);     //set lokasi hurup "setCursor(x,y)"
  display.print("%");           //tampilkan "%" di koordinat 75,20
  display.display();            //tampilkan
  //END OLED
  
  //START Temperature Sensor DS18B20
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) 
  {
    ds.reset_search();
    delay(250);
    return;
  }
  
  if (OneWire::crc8(addr, 7) != addr[7]) 
  {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) 
  {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 
  ds.reset();           // reset
  ds.select(addr);      // pilih address
  ds.write(0x44, 1);    // start conversion, with parasite power on at the end  
  delay(500);          // delay 1 detik
  present = ds.reset(); // reset
  ds.select(addr);      // pilih address 
  ds.write(0xBE);       // Read Scratchpad
  //END DS18B20

  //START Temperature Sensor DS18B20
    for ( i = 0; i < 9; i++) 
    {           
      data[i] = ds.read();
    }
    // Convert the data to actual temperature
    int16_t raw = (data[1] << 8) | data[0]; // Register Format 8 Bit 
    // S = 0 (Positif) dan S = 1 (Negatif)
    if (type_s) // S for "Sign Bit" : mengindikasikan temperature positif atau negatif 
    {
      raw = raw << 3; // 9 bit resolution default, artinya R0 = 0 dan R1 = 0
      // maka maximum conversion time nya dalah 93.75ms (refers to DS18B20 datasheet page 9)
      if (data[7] == 0x10) {
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else 
    {
      byte cfg = (data[4] & 0x60);
      if (cfg == 0x00) raw = raw & ~7;      // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
   
    }
    //Algoritma konversi suhu dari celcius ke fahrenheit
    celsius = (float)raw / 16.0;
    fahrenheit = celsius * 1.8 + 32.0;
    //END Temperature Sensor
        
    //START OLED
    display.clearDisplay();
    display.setTextColor(WHITE); display.setTextSize(0); display.setCursor(35,10); display.print("T= ");
    display.setTextSize(0); display.setCursor(50,10); display.print(celsius); 
    display.setTextSize(0); display.setCursor(85,10); display.print("C");
    display.setTextSize(0); display.setCursor(35,20); display.print("F= ");
    display.setTextSize(0); display.setCursor(50,20); display.print(fahrenheit);
    display.display();
    display.clearDisplay();
    delay(500);
    //END OLED

  //Terendam Air
  //jika nilai sensor (val) lebih dari 260 dan kurang dari (260 + 86,66)
  //berarti nilai val diantara 260 - 346,66 maka dikatakan sensor terendam air
  //toleransi error plus minus 3 (hanya kondisi ketika terendam air)
  if(val > WaterValue && val < (WaterValue + intervals))
  {
    //display.setTextSize(0);         //pilih ukuran text 0 default
    //display.setCursor(90,20);       //set lokasi hurup "setCursor(x,y)"
    //display.print("A");             //terendam air dan tidak memungkinkan u/ berubah kering dalam waktu singkat
    //display.display();              //tampilkan
    digitalWrite(BUILTIN_LED, HIGH);  //off
    digitalWrite(LEDKering, HIGH);    //off
    digitalWrite(LEDBasah, HIGH);     //off
    digitalWrite(LEDBanjir, LOW);     //on
    //tampilkan di serial monitor
    Serial.println("");
    Serial.print("Nilai Sensor : ");
    Serial.println(val);            //nilai yang terbaca oleh sensor
    Serial.print("Kelembaban : ");  //tampilkan text "Kelembaban"
    Serial.print(RH);               //nilai relative humidity
    Serial.println("%");            //tampilkan text "percent / %"
    //delay(500);                     //delay 0.5 detik
    Serial.print("T = ");           // tampilkan text "T" u/ Temperature
    Serial.print(celsius);          // Tampilkan nilai suhu dalam celcius
    Serial.print(" ⁰C | ");         // tampilkan text "derajat dalam celcius"
    Serial.print(fahrenheit);       // tampilkan nilai suhu dalam fahrenheit
    Serial.println(" ⁰F ");         // tampilkan text "derajat dalam satuan fahrenheit"
    Serial.println("Banjir, Merah");
    Serial.print("Tegangan Sensor Humidity: ");
    Serial.println(voltage);
    
    //START OLED
    display.clearDisplay();
    display.setTextColor(WHITE);
    display.setTextSize(0); display.setCursor(35,10); display.print("Sensor ter");
    display.setTextSize(0); display.setCursor(35,20); display.print("rendam air");
    display.display();
    display.clearDisplay();
    delay(500);
    //END OLED 
  }
  
  //BASAH
  //jika nilai sensor (val) lebih dari (260 + 86,66) dan kurang dari (520 - 86,66)
  //berarti nilai val diantara 347 - 433 maka dikatakan sawah basah 
  //toleransi error plus minus 3 (hanya kondisi ketika basah)
  else if(val > (WaterValue + intervals) && val < (AirValue - intervals))
  {
    digitalWrite(BUILTIN_LED, HIGH);    //off
    digitalWrite(LEDKering, HIGH);      //off
    digitalWrite(LEDBasah, LOW);        //on
    digitalWrite(LEDBanjir, HIGH);      //off
    digitalWrite(Buzzer, LOW);          //on
    //tampilkan di serial monitor
    Serial.println("");
    Serial.print("Nilai Sensor : ");
    Serial.println(val);            //nilai yang terbaca oleh sensor
    Serial.print("Kelembaban : ");  //tampilkan text "Kelembaban"
    Serial.print(RH);               //nilai relative humidity
    Serial.println("%");            //tampilkan text "percent / %"
    //delay(500);                   //delay 0.5 detik
    Serial.print("T = ");           // tampilkan text "T" u/ Temperature
    Serial.print(celsius);          // Tampilkan nilai suhu dalam celcius
    Serial.print(" ⁰C | ");         // tampilkan text "derajat dalam celcius"
    Serial.print(fahrenheit);       // tampilkan nilai suhu dalam fahrenheit
    Serial.println(" ⁰F ");         // tampilkan text "derajat dalam satuan fahrenheit"
    Serial.print("Basah, Kuning");
    Serial.print("Tegangan Sensor Humidity: ");
    Serial.println(voltage);
    
    //START OLED
    display.clearDisplay();
    display.setTextColor(WHITE);
    display.setTextSize(0); display.setCursor(51,10); display.print("Tanah");
    display.setTextSize(0); display.setCursor(51,20); display.print("Basah");
    display.display();
    display.clearDisplay();
    delay(500);
    //END OLED
  }

  //KERING
  //jika nilai sensor (val) kurang dari 520 dan dan lebih dari (520 - 86,66)
  //berarti nilai val 433 - 520 maka dikatakan sawah kering 
  else if(val < AirValue && val > (AirValue - intervals)) 
  {
    //digitalWrite(BUILTIN_LED, HIGH);   //off
    digitalWrite(LEDKering, HIGH);       //on
    //digitalWrite(LEDBasah, HIGH);      //off
    //digitalWrite(LEDBanjir, HIGH);     //off       
    digitalWrite(Buzzer, LOW);           //on
    //tampilkan di serial monitor
    Serial.println("");
    Serial.print("Nilai Sensor : ");
    Serial.println(val);            //nilai yang terbaca oleh sensor
    Serial.print("Kelembaban : ");  //tampilkan text "Kelembaban"
    Serial.print(RH);               //nilai relative humidity
    Serial.println("%");            //tampilkan text "percent / %"
    //delay(500);                     //delay 0.5 detik
    Serial.print("T = ");           // tampilkan text "T" u/ Temperature
    Serial.print(celsius);          // Tampilkan nilai suhu dalam celcius
    Serial.print(" ⁰C | ");         // tampilkan text "derajat dalam celcius"
    Serial.print(fahrenheit);       // tampilkan nilai suhu dalam fahrenheit
    Serial.println(" ⁰F ");         // tampilkan text "derajat dalam satuan fahrenheit"
    Serial.println("Kering, Hijau");
    Serial.print("Tegangan Sensor Humidity: ");
    Serial.print(voltage);
    //START OLED
    display.clearDisplay();
    display.setTextSize(0);
    display.setTextColor(WHITE);
    display.setCursor(51,10);
    display.print("Tanah");
    display.setTextSize(0);
    display.setCursor(48,20);
    display.print("Kering");
    display.display();
    display.clearDisplay();
    delay(500);
    //END OLED
  }

  //Sensor Tidak Tertanam pada media sawah atau tanah
  //jika nilai sensor (val) lebih dari 520
  else if(val > AirValue)       
  {
    digitalWrite(Buzzer, HIGH);       //off
    // LED: LOW = on, HIGH = off
      for (int i = 0; i < 5; i++)
      {
        digitalWrite(BUILTIN_LED, LOW);   //on
        //digitalWrite(LEDKering, HIGH);    //off
        //digitalWrite(LEDBasah, HIGH);     //off
        //digitalWrite(LEDBanjir, HIGH);    //off
        digitalWrite(Buzzer, HIGH);       //off
        delay(100);
        digitalWrite(BUILTIN_LED, HIGH);  //off
        //digitalWrite(LEDKering, HIGH);    //off
        //digitalWrite(LEDBasah, HIGH);     //off
        //digitalWrite(LEDBanjir, HIGH);    //off
        digitalWrite(Buzzer, LOW);        //on
        delay(100);
      }
    Serial.println("");
    //tampilkan di serial monitor
    Serial.print("Nilai Sensor : ");
    Serial.println(val);            //nilai yang terbaca oleh sensor
    Serial.print("Kelembaban : ");  //tampilkan text "Kelembaban"
    Serial.print(RH);               //nilai relative humidity
    Serial.println("%");            //tampilkan text "percent / %"
    //delay(500);                     //delay 0.5 detik
    Serial.print("T = ");           // tampilkan text "T" u/ Temperature
    Serial.print(celsius);          // Tampilkan nilai suhu dalam celcius
    Serial.print(" ⁰C | ");         // tampilkan text "derajat dalam celcius"
    Serial.print(fahrenheit);       // tampilkan nilai suhu dalam fahrenheit
    Serial.println(" ⁰F ");         // tampilkan text "derajat dalam satuan fahrenheit"
    Serial.print("Tegangan Sensor Humidity: ");
    Serial.println(voltage);
    Serial.println("sensor_tidak_tertanam");  // nilai sensor lebih dari 520
    //START OLED
    display.clearDisplay();
    display.setTextSize(0);
    display.setTextColor(WHITE);
    display.setCursor(35,10);
    display.print("Sensor tdk");
    display.setTextSize(0);
    display.setCursor(35,20);
    display.print("tertanam !!");
    display.display();
    display.clearDisplay();
    delay(500);
    //END OLED
  }
  else if(val < 50)
    {
      //START OLED
      //display.setFontType(0);
      display.clearDisplay();
      display.setTextSize(0);
      display.setTextColor(WHITE);
      display.setCursor(35,10);
      display.print("SENSOR tdk");
      display.setTextSize(0);
      display.setCursor(35,20);
      display.print("Terhubung");
      display.display();
      display.clearDisplay();
      Serial.println("Sensor tidak terhubung");
      //END OLED
      for (int i = 0; i < 100; i++)
      {
        digitalWrite(BUILTIN_LED, LOW);   //on
        digitalWrite(Buzzer, HIGH);       //off
        delay(300);
        digitalWrite(BUILTIN_LED, HIGH);  //off
        digitalWrite(Buzzer, LOW);        //on
        delay(300);
      }
    }

  //START THINGSPEAK
  if (client.connect(server,80))
    {
      String postStr = apiKey;
           postStr +="&field1=";
           postStr += String(val);        // Nilai Sensor setelah di calibrasi
           postStr +="&field2=";
           postStr += String(RH);         // Nilai Relative Humidity
           postStr +="&field3=";
           postStr += String(voltage);    // Nilai Tegangan yang terbaca di Port A0
           postStr +="&field4=";
           postStr += String(celsius);    // Nilai Suhu (Celcius)
           postStr +="&field5=";
           postStr += String(fahrenheit); // Nilai Suhu (Fahrenheit)
           postStr += "\r\n\r\n"; 
      
      client.print("POST /update HTTP/1.1\n"); 
      client.print("Host: api.thingspeak.com\n"); 
      client.print("Connection: close\n"); 
      client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); 
      client.print("Content-Type: application/x-www-form-urlencoded\n"); 
      client.print("Content-Length: "); 
      client.print(postStr.length()); 
      client.print("\n\n"); 
      client.print(postStr);
    }
    client.stop();
    //thingspeak membutuhkan minimal 15 detik jeda waktu untuk update data ke server
    //selang waktu update realnya di thingspeak = 24 detik
    //sedangkan jeda waktu serial print atau beep atau update 10 detik
    //kenapa 10 detik karena 3 digit NIM 010
    Serial.print("Waiting...");    
  for(unsigned int i = 0; i < 15; i++)
  {
    Serial.print(i);
    delay(500);                         
  }                 
  //END THINGSPEAK
  //DateTime Now = rtc.now();
  
  File dataFile = SD.open("Humidity_Data.txt", FILE_WRITE);
  if (dataFile)
  {    
    //Simpan di SD CARD
    dataFile.println("Nilai Sensor : ");
    dataFile.println(dataString);   // Nilai kelembaban yang terbaca oleh sensor
    dataFile.println("Kelembaban : ");
    dataFile.println(RH);           // Relative Humidity dalam percent (%)
    dataFile.println("Temperature : ");
    dataFile.println(celsius);      // Nilai suhu dalam celcius
    dataFile.println(fahrenheit);   // Nilai suhu dalam fahrenheit
    dataFile.println(voltage);  
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
  else 
  {
    Serial.println("error opening datalog.txt");
  }
}

void loop() 
{
  run();
  delay(100);
}

int convertToPercent(int value)
{
  int percentValue = 0;
  percentValue = map(value, 1023, 465, 0, 100);
  return percentValue;
}

Untuk lebih lengkap nya silahkan kunjungi link ini.