Semua Tentang Belajar Teknologi Digital Dalam Kehidupan Sehari - Hari

  • IC Timer 555 yang Multifungsi

    IC timer 555 adalah sirkuit terpadu (chip) yang digunakan dalam berbagai pembangkit timer, pulsa dan aplikasi osilator. Komponen ini digunakan secara luas, berkat kemudahan dalam penggunaan, harga rendah dan stabilitas yang baik

  • Ayo Migrasi TV Digital

    Kami bantu anda untuk memahami lebih jelas mengenai migrasi tv digital, apa sebabnya dan bagaimana efek terhadap kehidupan. Jasa teknisi juga tersedia dan siap membantu instalasi - setting perangkat - pengaturan antena dan distribusi televisi digital ke kamar kos / hotel

  • Bermain DOT Matrix - LOVEHURT

    Project Sederhana dengan Dot Matrix dan Attiny2313. Bisa menjadi hadiah buat teman atau pacarmu yang ulang tahun dengan tulisan dan animasi yang dapat dibuat sendiri.

  • JAM DIGITAL 6 DIGIT TANPA MICRO FULL CMOS

    Jika anda pencinta IC TTL datau CMOS maka project jam digital ini akan menunjukkan bahwa tidak ada salahnya balik kembali ke dasar elektronika digital , sebab semuanya BISA dibuat dengan teknologi jadul

  • Node Red - Kontrol Industri 4.0

    Teknologi kontrol sudah melampaui ekspektasi semua orang dan dengan kemajuan dunia elektronika, kini semakin leluasa berkreasi melalui Node Red

Tampilkan postingan dengan label esp8266. Tampilkan semua postingan
Tampilkan postingan dengan label esp8266. Tampilkan semua postingan

Kamis, 01 Juli 2021

[ ESP8266 ] Kunci Motor Menggunakan wifi + password lewat SD card - (Part3 : Gabungin yuk...)

Kita sampai pada bagian ujung dari praktek pembuatan kunci motor berbasis wifi + sdcard , dimana kita akan menggabungkan pembahasan sebelumnya yaitu esp8266 sebagai async webserver dan bahasan kedua mengenai SD Card. Jadi pembahasan awal ini perlu dipahami terlebih dulu agar tidak terlalu membingungkan bagi pembaca setia blog ini.




Secara garis besar tujuan yg ingin dicapai dari seri praktek kali ini adalah :


  • Menggunakan ESP8266 sebagai akses poin dan webserver  untuk diakses smartphone dan selanjutnya mengontol relay yg terhubung dengan sistem elektrik kunci motor
  • SD card digunakan sebagai media penyimpanan parameter wifi dan kunci jawaban / challenge kode yg akan dipecahkan pengguna lewat smartphone


Rangkaian yg saya rancang diagramnya seperti ini :




Nah kali ini akan saya bahas bagian  yg penting saja dan belum pernah dibahas pada 2 seri tulisan sebelumnya, yaitu bagian file seting wifi dan pertanyaan untuk password, dimana pengguna dapat menulis sendiri di SD card melalui PC/Laptop dan  membuat alat ini bisa diubah sesuai keinginan. Disini saya menggunakan file seting bernama kunci.txt yg berisikan data:


wifi,motorku,kerensekali
1,merek motor,suzuki
2,tahun beli,2012
3,kota,surabaya
4,nama kucing,pussy
5,hobby,mancing

Baris paling atas wifi,motorku,kerensekali merupakan setting untuk nama wifi dan password (minimal 8 karakter). Sedangkan selanjutnya merupakan 5 buah urutan pertanyaan yg bisa dipecahkan untuk menghidupkan relay kontak motor.

Untuk script pembacaan isi file perbaris kemudian di parsing sebagai berikut:

dataFile = SD.open("kunci.txt");

  if (dataFile) {

    while (dataFile.available()) {

    buffer = dataFile.readStringUntil('\r\n');
   //Buka seting wifi password
    if(getStringPartByNr(buffer,',',0) == "wifi")
    {
    Serial.println(buffer);
    ssid =  getStringPartByNr(buffer,',',1);
    password = getStringPartByNr(buffer,',',2);
      
    }
    //buka pertanyaan dan jawaban sesuai urutan sequence
    else if(getStringPartByNr(buffer,',',0) == String(sequ))
    {
    Serial.print("pertanyaan : ");
    key = getStringPartByNr(buffer,',',1);
    Serial.print(key);
    Serial.print(" - jawaban : ");
    chal =getStringPartByNr(buffer,',',2); 
    Serial.println(chal);
    }
   }
   
    dataFile.close();


Sedangkan untuk melakukan perubahan pertanyaan agar tidak sama terus yg ditanyakan, perlu diadakan proses penambahan sequence yg disimpan pada file seq.txt , ya mirip seperti proses random / memilih pertanyaan secara acak.


SD.remove("seq.txt");  //hapus dulu lalu bikin lagi
  File myFile = SD.open("seq.txt", FILE_WRITE);
  if (myFile) // it opened OK
    {
    Serial.println("Writing to seq.txt");
    sequ++; //nambah posisi pertanyaan
    if(sequ > maxsequ) sequ= 1; //muter ke awal
    //nulis ke SD sequence baru
    myFile.print(String(sequ));
    myFile.close(); 
    Serial.print("sequence sekarang :");
    Serial.println(String(sequ));
    }
  else 
    Serial.println("Error opening seq.txt");


Untuk membandingkan apakah jawaban benar atau tidak maka dilakukan pembandingan di inputan yg diresponse oleh form submit secara asynchronous.


server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    
    // GET input1 value on <ESP_IP>/get?input=<inputMessage>
    if (request->hasParam(PARAM_INPUT) ) {
      inputMessage = request->getParam(PARAM_INPUT)->value();
      inputParam = PARAM_INPUT;

    }
   
    else {
      inputMessage = "No challenge ";
      inputParam = "none";
    }
    Serial.print("jawaban : ");
    Serial.println(inputMessage); 

    //jika jawaban sesuai
    if(inputMessage == chal)
    {

    
    request->send(200, "text/html", SendBenar());
    
    
    }

    else{
     olkey = key ; 
     request->send(200, "text/html", SendSalah(olkey,inputMessage));
      }

    writeToFile();  //nambah sequence pertanyaan
   

                                     
  }); 


Hasilnya cukup memuaskan dan pertanyaannya dapat diubah sesuai keinginan.





Karena masih berupa web dan formatnya berupa GET biasa, maka untuk pengembangan bisa diwrap kedalam APK android yg cukup simple, hanya butuh merubah web HTML ke aplikasi android. Juga jika mau keren bisa disertai Relay kedua untuk melakukan starter melalui tombol di layar smartphone.






Berminat mengembangkan ke produk jadi ? Hubungi : 08155737755
Share:

Rabu, 30 Juni 2021

[ ESP8266 ] Kunci Motor Menggunakan wifi + password lewat SD card - (Part2 : Parsing File SD Card)

Mungkin ini adalah bagian yg paling sering dan mudah dicari pembahasannya di berbagai blog dan tulisan, karena fasilitas SD card dan modul siap pakainya untuk arduino yg berbasis SPI sangat murah dipasaran. Jadi saya akan membahas yg lebih lanjut yaitu melakukan parsing perbaris dari sebuah file didalam SD Card.

Untuk melengkapi praktek pada rulisan ini, bisa membaca part 1 disini : https://www.aisi555.com/2021/06/esp8266-kunci-motor-pintu-menggunakan.html


Padahal kalau diingat bagaimana dulu saya sudah berhasil membaca file SD Card secara RAW pada praktek yg saya lakukan bertahun-tahun yg lalu menggunakan ATTINY 2313 yg bisa dibaca disini :  https://www.aisi555.com/2012/12/belajar-access-sd-card-cara-simple_3994.html




Karena siap pakai inilah maka anda akan dimanjakan dengan koneksi langsung ke modul node MCU atau Wemoz D1, langsung saja cari PIN SPI ( MOSI, MISO, SCK ) dan CS yg sesuai lalu gunakan library yg tersedia langsung pada sketch Arduino yaitu SD.h dan SPI.h .




Dan yg paling gampang adalah script mengetest apakah koneksi nya sudah benar apa belum yg sederhana seperti berikut :


#include <SPI.h>
#include <SD.h>

const int chipSelect = D8; // use D0 for Wemos D1 Mini
File root; 


void setup() {
 Serial.begin(9600);
  Serial.print("\r\nWaiting for SD card to initialise...");
  if (!SD.begin(chipSelect)) { // CS is D8 in this example
    Serial.println("SD Card Initialising failed!");
    return;
  }
  Serial.println("SD Card Initialisation completed");

 File dataFile = SD.open("key.csv");
 

  if (dataFile) {

    while (dataFile.available()) {

       Serial.write(dataFile.read());
    }

    dataFile.close();

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening seq.txt");

  }
  

}

void loop() {
  

}




Hasilnya adalah seperti ini :






Data yg saya punya berupa data CSV yg saya buat menggunakan excel seperti format berikut :





Jadi perbaris terdapat 3 buah data yg di pisahkan dengan "koma" dan diakhiri dengan ascii CR LF atau kalau dalam bahasa coding bahasa C merupakan karakter '\r\n'. Sehingga yg sangat ampuh ketika ingin mencari baris dengan index tertentu dan selanjutnya melakukan parsing adalah script function yg saya temukan di internet seperti ini :


String getStringPartByNr(String data, char separator, int index)
{
    // spliting a string and return the part nr index
    // split by separator
    
    int stringData = 0;        //variable to count data part nr 
    String dataPart = "";      //variable to hole the return text
    
    for(int i = 0; i<data.length()-1; i++) {    //Walk through the text one letter at a time
      
      if(data[i]==separator) {
        //Count the number of times separator character appears in the text
        stringData++;
        
      }else if(stringData==index) {
        //get the text when separator is the rignt one
        dataPart.concat(data[i]);
        
      }else if(stringData>index) {
        //return text and stop if the next separator appears - to save CPU-time
        return dataPart;
        break;
        
      }

    }
    //return text if this is the last part
    return dataPart;
}




Selanjutnya saya gabungkan untuk mendapatkan data pada baris yg di tentukan dengan index pada "no", saya gunakan console untuk menunggu input keyboard dari data baris yg diinginkan .


#include <SPI.h>
#include <SD.h>

const int chipSelect = D8; // use D0 for Wemos D1 Mini
File root; 

String buffer;
String rx_str = ""; //variabel string untuk menunggu input
char rx_byte = 0;

String getStringPartByNr(String data, char separator, int index)
{
    // spliting a string and return the part nr index
    // split by separator
    
    int stringData = 0;        //variable to count data part nr 
    String dataPart = "";      //variable to hole the return text
    
    for(int i = 0; i<data.length()-1; i++) {    //Walk through the text one letter at a time
      
      if(data[i]==separator) {
        //Count the number of times separator character appears in the text
        stringData++;
        
      }else if(stringData==index) {
        //get the text when separator is the rignt one
        dataPart.concat(data[i]);
        
      }else if(stringData>index) {
        //return text and stop if the next separator appears - to save CPU-time
        return dataPart;
        break;
        
      }

    }
    //return text if this is the last part
    return dataPart;
}


void bacaSD( String index) //baca line dari index
{
 
  File dataFile = SD.open("key.csv");
 
  if (dataFile) {

    while (dataFile.available()) {

    buffer = dataFile.readStringUntil('\r\n');
    
    //parsing 
    if(getStringPartByNr(buffer,',',0) == index)
    {
    Serial.print("no : "); 
    Serial.print(index); 
    Serial.print(" - key : ");
    Serial.print(getStringPartByNr(buffer,',',1));
    Serial.print(" - challenge : ");
    Serial.println(getStringPartByNr(buffer,',',2));
     
    }
    
    }
    dataFile.close();

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening KEY.CSV");

  }


}

void setup() {
 Serial.begin(9600);
  Serial.print("\r\nWaiting for SD card to initialise...");
  if (!SD.begin(chipSelect)) { // CS is D8 in this example
    Serial.println("SD Card Initialising failed!");
    return;
  }
  Serial.println("SD Card Initialisation completed");
  Serial.println("Masukkan index baris: ");
 
  

}

void loop() {
 
if (Serial.available() > 0) {    // is a character available?
    rx_byte = Serial.read();       // get the character
    
    if (rx_byte != '\n') {
      // a character of the string was received
      rx_str += rx_byte;
    }
    else {
      // end of string
      Serial.print("Data baris ke: ");
      Serial.println(rx_str);
      bacaSD(rx_str);
      
      rx_str = "";                // clear the string for reuse
      Serial.println("");
      Serial.println("Masukkan index baris: ");
    }
  } // end
}


Hasilnya bisa dilihat pada animasi berikut, dan jika anda mencobanya bisa gunakan mode "newline" pada console monitor arduino sketch .





Share:

[ ESP8266 ] Kunci Motor Menggunakan wifi + password lewat SD card - (Part1 : AsyncWebServer)

Keamanan yg canggih merupakan sebuah keniscayaan di jaman serba digital, didukung oleh semakin terjangkaunya modul-modul kontrol digital siap pakai. Pada seri tulisan kali ini akan dibahas secara mendalam mengenai perancangan sistem kunci digital berbasis ESP8266 - yg merupakan modul favorit kesukaan para pencipta mikrokontroler AVR 8 bit dengan keunggulan modul wifi siap pakai.






Praktek kali ini merupakan penggabungan dari berbagai library dari hardware esp8266 yg bisa anda pakai langsung atau dalam modul kit development yg bisa nda pilih seperti node mcu, wemoz, esp32 dan sebagainya. Untuk versi yang saya kembangkan meliputi bahasan seperti berikut :


-  EspAsyncWebserver  ( dari Me-No-Dev


Merupakan librari popular dan sangat ampuh untuk membuat Async HTTP dan WebSocket Server pada  ESP8266 Arduino. Dengan library ini memudahkan pekerjaan server yg bekerja diluar loop utama sehingga handal dalam melayani akses dari beberapa user secara bersama.




Untuk ESP8266 memerlukan ESPAsyncTCP untuk menggunakan library ini, Anda mungkin perlu memiliki versi git terbaru dari ESP8266 Arduino Core


Contoh yg saya gunakan seperti pembuatan form sederhana dibawah ini, dimana wemos d1 saya berfungsi sebagai SoftAP 


#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WiFiClient.h> 


AsyncWebServer server(80);

const char* PARAM_INPUT = "input";
const char *ssid = "coba";
const char* password = "sayamencoba";

String SendHTML()
{

String ptr = " <!DOCTYPE HTML><html><head> ";
  ptr +="<title>CONTOH INPUTAN</title> ";
  ptr +="<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> ";
  ptr +=" </head><body> ";
  ptr +=" Masukkan Sesuatu disini ";
  ptr +=" <br> ";
  ptr +="<form action=\"/get\"> ";
  ptr +=" Challenge: <input type=\"text\" name=\"input\"> ";
  ptr +="  <input type=\"submit\" value=\"Submit\"> ";
  ptr +="</form><br><br>";
  ptr +="</body> ";
  ptr +="</html> ";
  return ptr;
}

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void setup(){
 
 Serial.begin(9600);
 WiFi.softAP(ssid, password );//AP
 
 IPAddress apip = WiFi.softAPIP(); //alamat IP
    Serial.print("Hubungkan wifi dan buka : \n");  //menuliskan alamat IP yang bisa dikunjungi
    Serial.println(apip);
 
  // Send web page dengan inputan berupa text 
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", SendHTML() ); 
  });

  // Send a GET request to <ESP_IP>/get?input=<inputMessage>
  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    
    // GET input1 value on <ESP_IP>/get?input=<inputMessage>
    if (request->hasParam(PARAM_INPUT) ) {
      inputMessage = request->getParam(PARAM_INPUT)->value();
      inputParam = PARAM_INPUT;

    }
   
    else {
      inputMessage = "No challenge ";
      inputParam = "none";
    }

    Serial.print("param : ");
    Serial.println(inputParam );
    Serial.print("pesan : ");
    Serial.println(inputMessage); 
    
     request->send(200, "text/html", "Dikirm dengan Param (" 
                                     + inputParam + ") dengan pesan : " + inputMessage +
                                     "<br><a href=\"/\">Return to Home Page</a>");
                                     
  });
  server.onNotFound(notFound);
  server.begin();
}

void loop() {
  // kosong

}


Hasil nya ketika saya masuk ke wifinya yg dipancarkan oleh Wemos / ESP8266 dan masuk ke alamat http://192.168.4.1 seperti berikut :






- Membaca SD card
Share:

Rabu, 22 Juli 2020

Cara Mudah Belajar MODBUS - Komunikasi Industri Jaman dulu [part 5 -End] Modbus vs Antares.id



Belum lengkap rasanya kalau saya belum mencoba praktek modbus yang telah lengkap piramida IOT nya kedalam platform IOT lokal yaitu ANTARES by telkomiot. Tentunya pembaca yang ingin mengikuti pembahasan kali ini diharapkan membaca penelusuran saya dengan Antares vs ESP 8266 disini dan disini. Masih dengan rangkaian yang sama kita akan mencoba mengirim data pembacaan sensor modbus dan juga menunggu perintah dikirimkan dari antares ke sensor modbus yang saya buat menggunakan arduino.


Dari standar OneM2M yang digunakan antares maka ada ketentuan data MQTT yang di publish dan subscribe hanya terbatas pada 2 topik berikut :


PUBLISH  TOPIC :
/oneM2M/req/access:key/antares-cse/json

SUBSCRIBE TOPIC :
/oneM2M/resp/antares-cse/access:key/json



Data yang dikirim / PUBLISH berupa JSON dimana polanya harus sesuai dimana data apapun yang akan dikirim ke Antares merupakan isi dari dalam "con" :

{
  "m2m:rqp": {
    "fr": "access:key",
    "to": "/antares-cse/antares-id/project-name/device-name",
    "op": 1,
    "rqi": 123456,
    "pc": {
      "m2m:cin": {
        "cnf": "message",
        "con": "{\"data\":\"value\"}"
      }
    },
    "ty": 4
  }
}

Jadi script publish mqtt menggunakan function atau routine sebagai berikut :


   void kirim(String tombol, String suhu, String humi) // kirim 3 item sekaligus
{
    Serial.println("publish to antares topik: " );
    Serial.print(TOPIKPUB);
    Serial.print(" : ");
    Serial.println(tombol + " - " + suhu + " - " + humi );
    
    String pubString ;  //isi json pub message yg super panjang
    pubString += F("{");
    pubString += F("\"m2m:rqp\": {");
    pubString += F("\"fr\": \"");
    pubString += String(accessKey) ;
    pubString += F("\",");
    pubString += F("\"to\": \"/antares-cse/antares-id/");
    pubString += String(projDev);
    pubString += F("\",");
    pubString += F("\"op\": 1,");
    pubString += F("\"rqi\": 123456,");
    pubString += F("\"pc\": {");
    pubString += F("\"m2m:cin\": {");
    pubString += F("\"cnf\": \"message\",");
    pubString += F("\"con\": \"{\\\"tombol\\\":");
    pubString += tombol;
    pubString += F(",\\\"suhu\\\":");
    pubString += suhu;
    pubString += F(",\\\"humidity\\\":");
    pubString += humi;
    pubString += F("}\"");
    pubString += F("}");
    pubString += F("},");
    pubString += F("\"ty\": 4");
    pubString += F("}");
    pubString += F("}");

   // kirim ke topik TOPIKPUB
   char message_buff[pubString.length() + 1];
   pubString.toCharArray(message_buff, pubString.length() + 1);
   client.publish(TOPIKPUB,message_buff);
  
}

    




Untuk menunggu request dari antares harus diperhatikan yang diterima melalui callback merupakan JSON juga lhooo...jadi kalau mumet sebaiknya dihentikan segera melanjutkan membaca blog ini!

 {
   "m2m:rsp" : {
      "rsc" : 2001,
      "rqi" : "123456",
      "pc" : {
         "m2m:cin" : {
            "rn" : "cin_63068886",
            "ty" : 4,
            "ri" : "/antares-cse/cin-63068886",
            "pi" : "/antares-cse/cnt-682859183",
            "ct" : "20200707T152502",
            "lt" : "20200707T152502",
            "st" : 0,
            "cnf" : "message",
            "cs" : 35,
            "con" : "{\"led\":\"on\"}"
         }
      },
      "to" : "access:key",
      "fr" : "/antares-cse"
   }
}


Untuk mengolah data request dari antares maka ESP8266 akan melakukan parsing JSON dari payload MQTT dengan menggunakan library ARDUINO JSON


    DynamicJsonDocument doc(512);
    deserializeJson(doc, message);
    String parsedString = doc["m2m:rsp"]["pc"]["m2m:cin"]["con"]; //pertama cari isi con
    deserializeJson(doc, parsedString);
    String lednya = doc["led"]; //kedua cari isi led on apa off
    Serial.println("lednya : " + lednya);
    

Jadi untuk mendapatkan isi dari message led "on" atau "off" maka diperlukan 2 kali parsing json karena isi dalam "con" juga di syaratkan sebagai JSON. Kenapa begitu? Ya karena itulah standar onem2m yang digunakan jadi harus diikuti saja.




Selengkapnya bisa dilihat pada video berikut ini 



Script lengkap :


// by www.aisi55.com please attach our credential if you using our script
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

SoftwareSerial mod(4, 5); // RX, TX

const char *ssid =  "nama wifi";  
const char *pass =  "password";

const char *mqtt_server = "mqtt.antares.id";
const int mqtt_port = 1883;
const char *mqtt_user = "";
const char *mqtt_pass = "";
const char *mqtt_client_name = "ahocool1265352";  
//sesuaikan dengan parameter akun antares kamu
#define TOPIKPUB "/oneM2M/req/access:key/antares-cse/json"
#define TOPIKSUB "/oneM2M/resp/antares-cse/access:key/json"
#define accessKey "access:key"
#define projDev "Project_name/Device_name" WiFiClient wclient; PubSubClient client(wclient); byte ledOn[] = {0x05, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8D, 0xBE};
//ngidupin Led byte ledOff[] = {0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x4E};//matikan Led byte tombol[] = {0x05, 0x02, 0x00, 0x00, 0x00, 0x01, 0xB8, 0x4E};//tombol byte tombolL[] = {0x05, 0x02, 0x01, 0x00, 0xa0, 0xB8}; // tombol Low byte tombolH[] = {0x05, 0x02, 0x01, 0x01, 0x61, 0x78}; // tombol High byte humitemp[] = {0x05, 0x04, 0x00, 0x00, 0x00, 0x03, 0xB1, 0x8F};//baca dht11 byte dhtOK[] = {0x05, 0x04, 0x06} ; byte bufferDataModbus[50]; byte *ptr; bool urut= false; bool led= false; unsigned long previousMillis = 0; String suhunya ="0"; String huminya ="0"; String tomb ="0"; void setup() { Serial.begin(9600); Serial.println(F("ESP8266 Modbus Bridge to ANTARES")); Serial.println(F("http://www.aisi555.com")); Serial.println(); if (WiFi.status() != WL_CONNECTED) { Serial.print("Connecting to Wifi: "); Serial.print(ssid); Serial.println("..."); WiFi.begin(ssid, pass); if (WiFi.waitForConnectResult() != WL_CONNECTED) return; Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } mod.begin(9600); ptr = bufferDataModbus; client.setServer(mqtt_server, mqtt_port); client.setCallback(mqtt_callback); } void reconnectmqtt() { Serial.println("Connecting to MQTT server.."); if (client.connect(mqtt_client_name,mqtt_user, mqtt_pass)) { Serial.println("Connected to MQTT server"); } else { Serial.println("Could not connect to MQTT server"); } if (client.connected()){ Serial.println("subscribe to topic: "); Serial.println(TOPIKSUB); client.subscribe(TOPIKSUB); } } void kirim(String tombol, String suhu, String humi) { Serial.println("publish to antares topik: " ); Serial.print(TOPIKPUB); Serial.print(" : "); Serial.println(tombol + " - " + suhu + " - " + humi ); String pubString ; pubString += F("{"); pubString += F("\"m2m:rqp\": {"); pubString += F("\"fr\": \""); pubString += String(accessKey) ; pubString += F("\","); pubString += F("\"to\": \"/antares-cse/antares-id/"); pubString += String(projDev); pubString += F("\","); pubString += F("\"op\": 1,"); pubString += F("\"rqi\": 123456,"); pubString += F("\"pc\": {"); pubString += F("\"m2m:cin\": {"); pubString += F("\"cnf\": \"message\","); pubString += F("\"con\": \"{\\\"tombol\\\":"); pubString += tombol; pubString += F(",\\\"suhu\\\":"); pubString += suhu; pubString += F(",\\\"humidity\\\":"); pubString += humi; pubString += F("}\""); pubString += F("}"); pubString += F("},"); pubString += F("\"ty\": 4"); pubString += F("}"); pubString += F("}"); char message_buff[pubString.length() + 1]; pubString.toCharArray(message_buff, pubString.length() + 1); client.publish(TOPIKPUB,message_buff); } void loop() { if (!client.connected()) { reconnectmqtt(); } else client.loop(); //cek terus kalau ada data masuk unsigned long currentMillis = millis(); if(currentMillis - previousMillis >= 5000) { // save the last time you read the sensor previousMillis = currentMillis; if(!urut )mod.write(tombol, sizeof(tombol)); else mod.write(humitemp, sizeof(humitemp)); urut =!urut; } long millisResponModbus = millis() + 1000; while (!mod.available()) { if (millisResponModbus < millis()) { break;//timeout } } while (mod.available()) { byte b = mod.read(); *ptr++ = b; Serial.print("0x"); Serial.print(String(b, HEX)); Serial.print(" "); delay(2); } if (memcmp(bufferDataModbus, ledOn, sizeof(ledOn)) == 0) { ptr = bufferDataModbus; memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } else if (memcmp(bufferDataModbus, ledOff, sizeof(ledOff)) == 0) { ptr = bufferDataModbus; memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } else if (memcmp(bufferDataModbus, tombolL, sizeof(tombolL)) == 0) { ptr = bufferDataModbus; tomb="0"; kirim(tomb,suhunya,huminya); memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } else if (memcmp(bufferDataModbus, tombolH, sizeof(tombolH)) == 0) { ptr = bufferDataModbus; tomb="1"; kirim(tomb,suhunya,huminya); memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } else if (memcmp(bufferDataModbus, dhtOK, sizeof(dhtOK)) == 0) { ptr = bufferDataModbus; suhunya = String(ptr[4]) + '.' +String(ptr[6]) ; huminya = String(ptr[8]); kirim(tomb,suhunya,huminya) ; memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } else { ptr = bufferDataModbus; //Serial.println(""); memset(bufferDataModbus, 0x00, sizeof(bufferDataModbus)); } } void mqtt_callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived in topic: "); Serial.println(topic); //Serial.print("Message:"); String message; for (int i = 0; i < length; i++) { message = message + (char)payload[i]; //Conver *byte to String } // Serial.print(message); //kepanjangan makanya di tutup DynamicJsonDocument doc(512); deserializeJson(doc, message); String parsedString = doc["m2m:rsp"]["pc"]["m2m:cin"]["con"]; deserializeJson(doc, parsedString); String lednya = doc["led"]; Serial.println("lednya : " + lednya); if(lednya == "on") { mod.write(ledOn, sizeof(ledOn)); Serial.println("lednya hidup"); } if(lednya == "off") { mod.write(ledOff, sizeof(ledOff)); Serial.println("lednya mati "); } Serial.println(); Serial.println("-----------------------"); }

Share:

Selasa, 09 Juni 2020

[Praktek Gampang] Jam di TV dengan Arduino - Part 3 - Esp8266-01 Kirim NTP via I2C



Kegemaran saya mengoprek jam kalender dan TV dimulai sejak  membaca tulisan mengenai steve wozniak dan steve jobs tentang bagaimana mereka bekerjasama membuat hardware video game "breakout" di Atari, hingga akhirnya menciptakan komputer apple yang legendaris itu. Dulu saat penulis kuliah sempat mendapat praktikum interfacing monitor VGA tapi hanya selintas aja dan menyesal juga kenapa gak sedari dulu bisa mengerti walau nilai praktikum dapat A (nyontek teman yg pinter sihhh). Dari dua latar belakang tersebut dan ketika microcontroller semakin murah dan mudah didapatkan menjadi tantangan tersendiri bermain micro di TV dan terlihat seperti main-main dan menghabiskan waktu, memang itu benar tapi asyik lhoo!  Tapi jangan berkecil hati karena penulis juga dapat banyak ilmu terutama mengenai pemrograman script yang lebih efisien. Salah satunya adalah ketika tantangan komunikasi arduino ke ESP agar tidak mengganggu timer Atmega328 untuk scanning TV. Jika menggunakan Serial baik Hardware atau emulasi software tetap aja akan menimbulkan interfrensi timer. Untuk itu digunakan komunikasi dengan timer  yg independen yaitu I2C. Dari hasil googling didapat bahwa ESP8266 bisa juga dimanfaatkan sebagai I2C master dan Arduino sebagai Slave nya. 




Komunikasi I2C sudah tersedia librarinya dalam instalasi default sketch,  yaitu dengan library " wire.h ". Untuk arduino uno / mini / micro yg berbasis ATmega328 pin SDA = A4 pin SCL =A5 . Dengan menggunakan I2C maka master dapat mengirim data atau meminta data ke slave. Tiap komponen yg diakses memiliki address masing-masing. Untuk ESP8266-01 memiliki 2 output GPIO yang bukan berfungsi sebagai I2C secara spesifik, sehingga perlu dilakukan inisialisasi port sendiri mana yg berfungsi sebagai SDA atau SCL. 

Menyambung tulisan mengenai jam di TV dan esp8266 , maka sebelum melanjutkan ke bahasan dibawah ada baiknya paca dulu PART1 dan PART2


- Praktek Testing I2C

Kita akan mencoba menghubungkan ESP sebagai master, terhubung secara I2C ke Arduino sebagai Slave dan tujuannya adalah mengirimkan data kalender secara periodik. Slave kemudian akan menuliskan hasil data yg diperoleh ke Serial port.

Script Master ( ESP8266-01)

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "TimeLib.h"
//library I2c
#include <Wire.h>
//library NTP , unduh jika blom ada
#include <NTPClient.h>

const char *ssid     = "Nama Wifi";
const char *password = "Password";
//Offset WIB +7 , sesuaikan
const long utcOffsetInSeconds = 25200;

long previousMillis = 0;   
long interval = 10000; //tiap 10 detik
//Array kalender
char tanggalan[] ="20,1,1,23,59,0" ;

// NTP lokal, ubah jika perlu
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp.bmkg.go.id", utcOffsetInSeconds);

void setup(){
  Serial.begin(9600); //monitor
  Wire.begin(0, 2); 
/* Koneksi i2c  SDA=0 and SCL=2  pada ESP-01 */

  WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }

  timeClient.begin();
}

void loop() {

  unsigned long currentMillis = millis(); 

  if(currentMillis - previousMillis > interval) {

  previousMillis = currentMillis;
  timeClient.update();
  unsigned long epoch ;
  epoch = timeClient.getEpochTime();
  
//output ke array
  sprintf(tanggalan,"%2d,%02d,%02d,%02d,%02d,%02d", year(epoch)-2000, month(epoch), day(epoch), hour(epoch), minute(epoch), second(epoch));

  Wire.beginTransmission(8); /* address 8 */
  Wire.write(tanggalan);  /* kirim Kalender */
  Wire.endTransmission();    /* stop */
  Serial.print("tanggal : ");
  Serial.println(tanggalan);

  }
}



Script Slave (Arduino)

#include <Wire.h>


void setup()
{
Serial.begin(9600);
Wire.begin(8);
//rutin event receive i2c
Wire.onReceive(espWifiReceiveEvent);

}

void loop()
{
delay(1);
}

//Kirim ke serial saat ada data i2c masuk

void espWifiReceiveEvent(int count)
{
Serial.print("Received[");
while (Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
Serial.println("]");

}


Nah jika dilihat output pada serial monitor / putty disisi arduino/slave seperti berikut:




- SCRIPT JAM LENGKAP

Terdapat beberapa hal yg menjadi perhatian saat data diterima arduino pada port I2C, dimana timer tetap akan kacau kalau data i2c nya panjang. I2C akan hang itulah yg terjadi saat 17 byte char diterima ,  jadi diakali dengan melakukan penonaktifan I2C setelah data kalender lengkap. Peng-update-an tanggalan dilakukan setiap jam atau sesuai keinginan misalnya tiap jam 3 pagi jika TV mau nyala terus dan gak dipake emak nonton sinetron..hehehehe...ayuk kita kupas satu persatu.


#include <TVout.h>
#include <Wire.h>
#include "fontALL.h"
#include <String.h>

TVout TV;

long previousMillis = 0;    
byte second, minute, hour, dayOfMonth, month, year;
long interval = 200;
int tvx,tvy,tvradius,x2,y2,x3,y3;
char buff[20]="20,08,06,23,58,58";
int buffindex=0;
char incomingByte ;

//status flag
bool ntpkomplit = false;
bool ntpupdate = false;

//function nulis kalender dan jam
void printTime()
{

second++;

if(second >=60){
  minute++;
  second=0;

}

if(minute >=60){
  hour++;
  minute=0;

  //reset flag
  ntpkomplit=false;
  ntpupdate=false;
  
  //restart i2C
   TWCR = 0;
   Wire.begin(8); //address 8
   Wire.onReceive(espWifiReceiveEvent);

}

if(hour >=24){
  hour=0;  
  dayOfMonth++;
}

//jika flag ntp komplit maka update kalender
if( ntpkomplit == true && ntpupdate == false ){
//parsing koma ke kalender
  char* ptr = strtok(buff, ",");
  byte i = 0;
  while (ptr) {
    if( i ==0 )year=atoi(ptr);
    else if( i == 1)month=atoi(ptr);
    else if( i == 2)dayOfMonth=atoi(ptr);
    else if( i == 3)hour=atoi(ptr);
    else if( i == 4)minute=atoi(ptr);
    else if( i == 5)second=atoi(ptr);
    
    ptr = strtok(NULL, ",");
    i++;
  }
  //flag ntp telah terupdate
  ntpupdate = true;
}

//tulis kalender

TV.set_cursor(0,0);
TV.print( char( hour/10 + 0x30) );
TV.print( char( hour%10 + 0x30) );
TV.print(":");
TV.print( char(minute/10 + 0x30));
TV.print( char(minute%10 + 0x30));
TV.print(":");
TV.print(char (second/10+0x30));
TV.print(char (second%10+0x30));


TV.set_cursor(8,9);
TV.print(char(dayOfMonth/10+0x30));
TV.print(char(dayOfMonth%10+0x30));
TV.print("/");
TV.print(char(month/10+0x30));
TV.print(char(month%10+0x30));
TV.set_cursor(10,18);
TV.print("20");
TV.print(char(year/10+0x30));
TV.print(char(year%10+0x30));
  
//status NTP connecting atau OK 

if( ntpupdate == false)
{
  TV.set_cursor(10,38);
  TV.print("con");
}

else{

  TV.set_cursor(10,38);
  TV.print("OK!");
}

//gambar Jam
//courtesy of Giant Metal Robot Blog 
  
TV.draw_circle(tvx,tvy,tvradius-5,BLACK,BLACK);

float angle = second*6 ;
angle=(angle/57.29577951) ; //Convert degrees to radians  
x3=(tvx+(sin(angle)*(tvradius-6)));
y3=(tvy-(cos(angle)*(tvradius-6)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);
angle = minute * 6 ;
angle=(angle/57.29577951) ; //Convert degrees to radians  
x3=(tvx+(sin(angle)*(tvradius-11)));
y3=(tvy-(cos(angle)*(tvradius-11)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);
angle = hour * 30 + int((minute / 12) * 6 )   ;
angle=(angle/57.29577951) ; //Convert degrees to radians  
x3=(tvx+(sin(angle)*(tvradius-15)));
y3=(tvy-(cos(angle)*(tvradius-15)));
TV.draw_line(tvx,tvy,x3,y3,WHITE);

}


void setup()  {
//TV di mode NTSC

TV.begin(_NTSC,150,71);
TV.select_font(font6x8);
TV.clear_screen();

tvx= TV.hres()/2;
tvy=TV.vres()/2;
tvradius=TV.vres()/2 ;
//clock face lingkaran
 TV.draw_circle(tvx,tvy,tvradius,WHITE);
//hour ticks
for( int z=0; z < 360;z= z + 30 ){
  //Begin at 0° and stop at 360°
  float angle = z ;
  angle=(angle/57.29577951) ; //Convert degrees to radians
  x2=(tvx+(sin(angle)*tvradius));
  y2=(tvy-(cos(angle)*tvradius));
  x3=(tvx+(sin(angle)*(tvradius-5)));
  y3=(tvy-(cos(angle)*(tvradius-5)));

  TV.draw_line(x2,y2,x3,y3,WHITE);
}
  
  
  TV.set_cursor(10,30);
  TV.print("NTP");
  TV.set_cursor(0,55);
  TV.print("aisi555");
  TV.set_cursor(3,63);
  TV.print(".com");



//buka serial kalau mau debug
//Serial.begin(9600);
Wire.begin(8); // I2C
Wire.onReceive(espWifiReceiveEvent);

}

void loop() {
  
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval) {

  previousMillis = currentMillis;
  TV.delay(980); // Sesuaikan antara 950-1000
  printTime();

  }

}


void espWifiReceiveEvent(int count)
{

 //buka blok serial kalau mau debug
//Serial.print("Received[");

//jika i2c terima data dan blum komplit kalendernya
while (Wire.available() && ntpkomplit == false)
{
 char c = Wire.read();
 //Serial.print(c);
 buff[buffindex]=c;
 buffindex++;
}
//Serial.println("]");


//Ntpkomplit = true Jika buffer kalender sampe menit terpenuhi 
if(buffindex >=14) {
  ntpkomplit = true;
  TWCR = 0; //bunuh i2c
  
}

buffindex = 0;

}




HASIL :



Proses update yg saya gunakan adalah tiap JAM atau menit ke 0, jadi memang tidak akan langsung terupdate akibat proses BITBANG tabrak menabrak antar timer vs i2c. Jadi seperti video berikut ini dapat dilihat UPDATE ke waktu NTP terjadi hampir  2 menit kemudian.



Bagaimana ? Sudah Mumet ? Sebaiknya baca dari awal ya PART1 dan PART2 dan juga bagian sebelumnya mengenai TV menggunakan microcontroller yang sudah saya tulis sejak 2012. 

SELAMAT MENCOBA

Share:

Kontak Penulis



12179018.png (60×60)
+628155737755

Mail : ahocool@gmail.com

Site View

Categories

555 (8) 7 segmen (3) adc (4) amplifier (2) analog (19) android (12) antares (8) arduino (26) artikel (11) attiny (3) attiny2313 (19) audio (5) baterai (5) blog (1) bluetooth (1) chatgpt (2) cmos (2) crypto (2) dasar (46) digital (11) dimmer (5) display (3) esp8266 (26) euro2020 (13) gcc (1) iklan (1) infrared (2) Input Output (3) iot (59) jam (7) jualan (12) kereta api (1) keyboard (1) keypad (3) kios pulsa (2) kit (6) komponen (17) komputer (3) komunikasi (1) kontrol (8) lain-lain (8) lcd (2) led (14) led matrix (6) line tracer (1) lm35 (1) lora (7) MATV (1) memory (1) metal detector (4) microcontroller (70) micropython (6) mikrokontroler (1) mikrokontroller (14) mikrotik (5) modbus (9) mqtt (3) ninmedia (5) ntp (1) paket belajar (19) palang pintu otomatis (1) parabola (88) pcb (2) power (1) praktek (2) project (33) proyek (1) python (7) radio (28) raspberry pi (4) remote (1) revisi (1) rfid (1) robot (1) rpm (2) rs232 (1) script break down (3) sdcard (3) sensor (2) sharing (3) signage (1) sinyal (1) sms (6) software (18) solar (1) solusi (1) tachometer (2) technology (1) teknologi (2) telegram (2) telepon (9) televisi (167) television (28) transistor (2) troubleshoot (3) tulisan (93) tutorial (108) tv digital (6) tvri (2) vu meter (2) vumeter (2) wav player (3) wayang (1) wifi (3)

Arsip Blog

Diskusi


kaskus
Forum Hobby Elektronika