Kamis, 17 Januari 2019

Interfacing PN532 dengan NodeMCU

PN532 adalah salah satu chip NFC, dan tertanam pada kebanyakan smartphone maupun peralatan NFC dengan kemampuan pembacaan dan penulisan tags maupun cards.

PN532 adalah cukup fleksible dengan kemampuan komunikasi melalui modus HSU, I2C maupun SPI.

Pada penulisan ini kita akan meggunakan modus I2C yang hanya membutuhkan 4 kabel yang menghubungkan antara PN532 dengan NodeMCU, yaitu pin VCC, GND, SDA, dan SCL

Untuk menggunakan modus I2C, perlu dipastikan terlebih dahulu setting pada
broad adalah:
- SEL0 adalah High (On)
- Sel1 adalah low (Off)


Perkabelan yang dilakukan:
1. Pin GND ke GND di NodeMCU
2. Pin VCC ke VCC di NodeMCU
3. Pin SDA ke D2 di NodeMCU
4. Pin SCL ke D1 di NodeMCU



Persiapan IDE Sketch

Kemudian lakukan persiapan pada IDE Sketch, dengan mendownload library tambahan yang perlu ditambahkan ke IDE Sketch sehingga proses kompilasi dapat berjalan dengan baik:
- Download Library Tambahan PN532

Setelah download, maka lakukan proses unzip, sehingga akan muncul beberapa folder sebagai berikut:
- NDEF
- PN532
- PN532_I2C






Tambahkan masing-masing folder ke library IDE Skecth anda dengan menggunakan pilihan Sketch, Include Library, add .ZIP library, kemudian import folder diatas satu-per-satu, dan juga  memperhatikan status keberhasilan dari proses import, pastikan tidak ada kegagalan.





Pembuatan Koding

Untuk menguji keberhasilan dari proses perkabelan dan persiapan IDE Sketch, maka dilakukan koding sebagai berikut:

#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);

void setup(void) {
    Serial.begin(9600);
    Serial.println("NDEF Reader");
    nfc.begin();
}

void loop(void) {
    Serial.println("\nScan a NFC tag\n");
    if (nfc.tagPresent())
    {
        NfcTag tag = nfc.read();
        tag.print();
    }
    delay(5000);
}

Klik pada verifikasi pada Skecth, pastikan semua berjalan lancar
Klik pada upload pada sketch, pastikan semua berjalan lancar

Aktifkan Serial Monitor dan pastikan setting ke 9600baud


Dan jika di scan NFC Tag


NFC Tag - NFC Forum Type 2
UID 53 34 5E 54 00 A1 80

NDEF Message 1 record, 3 bytes
  NDEF Record
    TNF 0x0 Empty
    Type Length 0x0 0
    Payload Length 0x0 0
    Type  
    Payload  
    Record is 3 bytes

Dan jika di scan RFID Tag


Tag is not NDEF formatted.
NFC Tag - Mifare Classic
UID D0 51 3A 1B

No NDEF Message

Selamat Mencoba.

Minggu, 14 Mei 2017

Absensi Berbasis RFID-RC522 dan NodeMCU

Tulisan ini adalah menbahas pemanfaatan RFID-RC522 dan NodeMCU untuk proses scan absensi berbasis RFID yang mana data akan dicatat di cloud dengan server berbasis PHP.

Gambar 1. Sensor RFID-RC522 dan RFID Card

Pin pada RFID-RC522


Pin pada NodeMCU


Sehingga interfacing antara sensor RFID-RCC522 dan NodeMCU dapat dilakukan sebagai berikut:

pin SDA ke D2
pin SCK ke D5
pin MOSI ke D7
pin MISO ke D6
pin IRQ diabaikan
pin GND ke GND
pin RST ke D4
pin VCC ke 3V3

Script Sketch:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include "MFRC522.h"

const char* ssid     = "ssid wifi anda";
const char* password = "password wifi anda";
String url = "http://172.21.12.105/absensi.php?uid=";

#define RST_PIN D4
#define SS_PIN  D2
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

boolean reconnect() {
  digitalWrite(D0, HIGH);
  WiFi.begin(ssid, password);

  int retry = 51;
  while (WiFi.status() != WL_CONNECTED) {
    if (retry > 50) {
      Serial.println("");
      Serial.printf("Trying connect to %s", ssid);
      retry = 0;
    }
    delay(500);
    Serial.print(".");
    retry++;
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  digitalWrite(D0, LOW);
}

String logToServer(unsigned long cardUID) {

  Serial.printf("Send Request to %s%u\n", url.c_str(), cardUID);
  HTTPClient http;

  http.begin(url + cardUID); //HTTP
  int httpCode = http.GET();
  if (httpCode > 0) {
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();

      Serial.println(payload);

      if (payload == "Ok!") {

        for (int i = 0; i < 3; i++) {
          digitalWrite(D0, HIGH);
          digitalWrite(D1, HIGH);
          delay(100);
          digitalWrite(D0, LOW);
          digitalWrite(D1, LOW);
          delay(100);
        }

      }
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }

  http.end();

}

void setup() {
  pinMode(D0, OUTPUT);
  pinMode(D1, OUTPUT);
  Serial.begin(9600);
  Serial.println("");
  delay(1000);

  reconnect();

  SPI.begin();        // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card

  //If you set Antenna Gain to Max it will increase reading distance
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
}

unsigned long getCardUID() {
  if ( !mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
    return -1;
  }
  unsigned long hex_num;
  hex_num =  mfrc522.uid.uidByte[0] << 24;
  hex_num += mfrc522.uid.uidByte[1] << 16;
  hex_num += mfrc522.uid.uidByte[2] <<  8;
  hex_num += mfrc522.uid.uidByte[3];
  mfrc522.PICC_HaltA(); // Stop reading
  return hex_num;
}

int wait = 51;

void loop() {
  if (WiFi.status() != WL_CONNECTED)
    reconnect();

  if (wait > 50) {
    Serial.println("");
    Serial.print("Wait for new Card");
    wait = 0;
  }

  Serial.print(".");

  wait++;

  if (wait % 2 == 0)
    digitalWrite(D0, HIGH);
  else
    digitalWrite(D0, LOW);

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    delay(100);
    return;
  }

  unsigned long cardUID = getCardUID();

  for (int i = 0; i < 3; i++) {
    digitalWrite(D0, HIGH);
    delay(100);
    digitalWrite(D0, LOW);
    delay(100);
  }

  if (cardUID == -1) {
    Serial.println("Failed to get UID");
    return;
  }

  Serial.printf("\nCard UID is %u\n", cardUID);

  for (int i = 0; i < 3; i++) {
    digitalWrite(D1, HIGH);
    delay(250);
    digitalWrite(D1, LOW);
    delay(250);
  }

  logToServer(cardUID);

  wait = 51;
}

Script PHP:

<?php
//Save string to log, use FILE_APPEND to append.
$info = date('Y-m-d H:i:s') . ';' . $_SERVER['REMOTE_ADDR'] . ';' . $_GET['uid'] . ';';
file_put_contents("./log/log_" . date('Ymd') . ".txt", $info . md5($info) . PHP_EOL, FILE_APPEND | LOCK_EX);

echo "Ok!";
?>

Rabu, 10 Mei 2017

Interfacing RFID-RC522 Sensor dengan Wemos D1 mini pro

FRID-RC522 Sensor adalah contacless reader/writer yang mendukung semua varian dari MIFARE Mini, baik protokol identifikasi MIFARE 1K maupun MIFARE 4K, MIFRARE Ultralight, MIFARE DESFire EV1 dan MIFARE Plus RF. Berikut ini adalah gambar sensor yang dimaksud.


Adapun Pin Dengan Pin sebagai berikut:


Adapun Pin pada Wemos D1 mini pro adalah sebagai berikut:


Sehingga Interfacing antara RFID-RC522 dengan Wemos D1 mini pro adalah:

pin SDA ke D2
pin SCK ke D5
pin MOSI ke D7
pin MISO ke D6
pin IRQ diabaikan
pin GND ke GND
pin RST ke D4
pin VCC ke 3V3

Setelah melakukan interfacing, maka kini saatnya untuk mempersiapkan lingkungan pengembangan dengan mendownload Arduino RFID Library for MFRC522 yang dapat didownload pada link, setelah download, maka pada sketch pilih menu :

Browse dan Add file rfid-master.zip

Copy dan Paste koding berikut ini yang saya peroleh dari internet, dan telah saya modifikasi (saya tandai warna merah)

#include "MFRC522.h"
#define RST_PIN D4  // RST-PIN ke D4
#define SS_PIN  D2  // SDA-PIN ke D2


MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance
MFRC522::MIFARE_Key key;

void setup() {
  Serial.begin(9600); // Initialize serial communications
  while (!Serial);    // Do nothing until serial port is opened
  SPI.begin();        // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card

  // Prepare the key (used both as key A and as key B)
  // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
  Serial.print(F("Using key (for A and B):"));
 
  dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
 
  Serial.println();
  Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
}

/**
   Main loop.
*/
void loop() {
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
    return;

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
    return;

  // Show some details of the PICC (that is: the tag/card)
  Serial.print(F("Card UID:"));
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println();
  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));

  // Check for compatibility
  if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
          &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
          &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("This sample only works with MIFARE Classic cards."));
    return;
  }

  // In this sample we use the second sector,
  // that is: sector #1, covering block #4 up to and including block #7
  byte sector         = 1;
  byte blockAddr      = 4;
  byte dataBlock[]    = {
    0x01, 0x02, 0x03, 0x04, //  1,  2,   3,  4,
    0x05, 0x06, 0x07, 0x08, //  5,  6,   7,  8,
    0x08, 0x09, 0xff, 0x0b, //  9, 10, 255, 12,
    0x0c, 0x0d, 0x0e, 0x0f  // 13, 14,  15, 16
  };
  byte trailerBlock   = 7;
  MFRC522::StatusCode status;
  byte buffer[18];
  byte size = sizeof(buffer);

  // Authenticate using key A
  Serial.println(F("Authenticating using key A..."));
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Show the whole sector as it currently is
  Serial.println(F("Current data in sector:"));
  mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
  Serial.println();

  // Read data from the block
  Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
  dump_byte_array(buffer, 16); Serial.println();
  Serial.println();

  // Authenticate using key B
  Serial.println(F("Authenticating again using key B..."));
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Write data to the block
  Serial.print(F("Writing data into block ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  dump_byte_array(dataBlock, 16); Serial.println();
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.println();

  // Read data from the block (again, should now be what we have written)
  Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
  dump_byte_array(buffer, 16); Serial.println();

  // Check that data in block is what we have written
  // by counting the number of bytes that are equal
  Serial.println(F("Checking result..."));
  byte count = 0;
  for (byte i = 0; i < 16; i++) {
    // Compare buffer (= what we've read) with dataBlock (= what we've written)
    if (buffer[i] == dataBlock[i])
      count++;
  }
  Serial.print(F("Number of bytes that match = ")); Serial.println(count);
  if (count == 16) {
    Serial.println(F("Success :-)"));
  } else {
    Serial.println(F("Failure, no match :-("));
    Serial.println(F("  perhaps the write didn't work properly..."));
  }
  Serial.println();

  // Dump the sector data
  Serial.println(F("Current data in sector:"));

  for (int sectorcount=0; sectorcount < 16; sectorcount++) {
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sectorcount);
    Serial.println();
  }


  // Halt PICC
  mfrc522.PICC_HaltA();
  // Stop encryption on PCD
  mfrc522.PCD_StopCrypto1();
}

/**
   Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

Hasil pengujian:

Aktifkan serial monitor:

 

Scan a MIFARE Classic PICC to demonstrate read and write.
Using key (for A and B): FF FF FF FF FF FF
BEWARE: Data will be written to the PICC, in sector #1
Card UID: 46 74 1E 2B
PICC type: MIFARE 1KB
Authenticating using key A...
Current data in sector:
   1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
          6   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          5   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          4   01 02 03 04  05 06 07 08  08 09 FF 0B  0C 0D 0E 0F  [ 0 0 0 ]

Reading data from block 4 ...
Data in block 4:
 01 02 03 04 05 06 07 08 08 09 FF 0B 0C 0D 0E 0F

Authenticating again using key B...
Writing data into block 4 ...
 01 02 03 04 05 06 07 08 08 09 FF 0B 0C 0D 0E 0F

Reading data from block 4 ...
Data in block 4:
 01 02 03 04 05 06 07 08 08 09 FF 0B 0C 0D 0E 0F
Checking result...
Number of bytes that match = 16
Success :-)

Current data in sector:
   0      3   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
          2   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          1   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          0   46 74 1E 2B  07 08 04 00  62 63 64 65  66 67 68 69  [ 0 0 0 ]

   1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
          6   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          5   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          4   01 02 03 04  05 06 07 08  08 09 FF 0B  0C 0D 0E 0F  [ 0 0 0 ]

   2     11   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         10   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          9   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          8   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   3     15   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         14   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         13   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         12   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   4     19   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         18   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         17   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         16   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   5     23   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         22   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         21   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         20   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   6     27   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         26   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         25   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         24   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   7     31   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         30   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         29   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         28   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   8     35   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         34   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         33   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         32   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   9     39   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         38   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         37   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         36   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  10     43   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         42   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         41   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         40   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  11     47   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         46   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         45   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         44   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  12     51   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         50   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         49   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         48   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  13     55   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         54   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         53   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         52   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  14     59   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         58   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         57   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         56   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         62   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         61   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         60   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

Trouble Shooting, jika anda mendapatkan pesan kesalahan seperti MIFARE_Read() failed: Timeout in communication atau PCD_Authenticate() failed: Timeout in communication.

Card UID: 46 74 1E 2B
PICC type: MIFARE 1KB
Authenticating using key A...
Current data in sector:
   1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
          6   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          5   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          4   01 02 03 04  05 06 07 08  08 09 FF 0B  0C 0D 0E 0F  [ 0 0 0 ]

Reading data from block 4 ...
MIFARE_Read() failed: Timeout in communication.
Data in block 4:
 30 04 26 EE 05 06 07 08 08 09 FF 0B 0C 0D 0E 0F

Authenticating again using key B...
PCD_Authenticate() failed: Timeout in communication.

Jangan kuatir, error tersebut diatas terjadi karena anda mengerakan kartu, atau tag RFID selama dibaca oleh sensor.

Selamat Memcoba.

Sabtu, 24 Desember 2016

Om Telolet Om: WeMos D1 OLED Shield (ESP-8266EX, NodeMCU, Lua)

Pada tulisan ini akan dibuat script untuk menampilkan pesan "Selamat Hari Natal" pada WeMos D1 OLED Shield.

Gambar 1. WeMos D1 mini OLED Shield

Untuk dapat menggunakan OLED Shield, anda perlu melakukan kustomisasi firmware NodeMCU dengan memasukan module i2c dan u8g, dan memilih ukuran OLED yang digunakan.

Gambar 8. Menentukan ukuran layar OLED

Sehingga ketika boot akan tampil module yang ditandai warna merah.
NodeMCU custom build by frightanic.com
    branch: master
    commit: 81ec3665cb5fe68eb8596612485cc206b65659c9
    SSL: true
    modules: bit,cjson,crypto,dht,file,gpio,http,i2c,net,node,rtctime,sntp,tmr,u8g,uart,websocket,wifi
 build     built on: 2016-12-23 16:47
 powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
Adapun script yang digunakan untuk menampikan pesan adalah sebagai berikut:

sda = 2 -- SDA Pin
scl = 1 -- SCL Pin

function init_OLED(sda,scl) --Set up the u8glib lib
     sla = 0x3C
     i2c.setup(0, sda, scl, i2c.SLOW)
     disp = u8g.ssd1306_64x48_i2c(sla)
     disp:setFont(u8g.font_6x10)
     disp:setFontRefHeightExtendedText()
     disp:setDefaultForegroundColor()
     --disp:setRot90()           -- Rotate Display if needed
     --disp:setRot180()           -- Rotate Display if needed
     --disp:setRot270()           -- Rotate Display if needed
end

function print_OLED()
   disp:firstPage()
   --disp:setScale2x2()
   repeat
     --disp:drawFrame(0,0,64,47)
     disp:drawStr(0, 10, str1)
     disp:drawStr(0, 30, str2)
   until disp:nextPage() == false
   --disp:undoScale()
end

-- Main Program
str1="  Selamat   "
str2=" Hari Natal "
init_OLED(sda,scl)
print_OLED()

Jumat, 23 Desember 2016

Om Telolet Om: WeMos D1 mini pro as APSTATION (ESP-8266EX, NodeMCU, Lua)

Pada tulisan ini akan memberi contoh script untuk mengaktifkan WeMos D1 mini pro sebagai APSTATION yang terdiri dari tiga script utama yaitu init.lua yang bertujuan untuk menghindari terjebak reboot ulang tak terhingga akibat adanya kesalahan script pada init.lua, konfigurasi untuk APSTATION adalah disimpan pada apconfig.lua, dan konfigurasi untuk sebagai STATION adalah disimpan pada credentilas.lua. Script utama anda adalah disimpan pada file app.lua, yang secara otomatis akan diaktifkan dalam waktu tiga detik. Jika ada kesalahan pada script app.lua, maka anda dapat menjalankan perintah file.remove("app.lua") dalam waktu tiga detik sehingga terhindar dari jebakan reboot ulang tak terhingga.

Gambar 1. WeMos D1 mini pro

apconfig.lua
cfg={}
cfg.ssid="myssid"
cfg.pwd="password"
cfg.auth=wifi.WPA_WPA2_PSK

dhcp_config ={}
dhcp_config.start = "192.168.4.100"

credentials.lua
-- Credentials
SSID = "rapsberrypi"
PASSWORD = "password"

init.lua
-- aplikasi ini berfungsi menghindarkan module anda terjebak
-- pada kondisi restart tak terhingga jika terjadi bugs pada
-- init.lua.

-- aplikasi ini dapat mengaktifkan board anda sebagai access
-- point, jika anda menginginkan hal ini, maka anda perlu
-- menyediakan file apconfig.lua.

-- aplikasi dapat berjalan pada dua modus, yaitu standalone
-- atau terkoneksi ke wifi.

-- agar dapat terkoneksi ke wifi, maka username dan password
-- didefinisikan pada file credentials.lua

-- aplikasi akan menunggu selama 3 detik sebelum file app.lua
-- dieksekusi, jika terjadi bugs pada app.lua, maka anda
-- dapat menjalankan file.remove("app.lua") sehingga tidak
-- terjebak pada kondisi restart tak terhingga.

function startup()
    print("Running")
    -- aplikasi autoexec anda  sekarang adalah 'app.lua'
    if file.open("app.lua") == nil then
        print("app.lua tidak ditemukan, silakan buat app.lua sebagai auto executable.")
    else 
        file.close("app.lua")
        dofile("app.lua")
    end
end

if file.open("apconfig.lua") ~= nil then
    print("activate as access point")
    dofile("apconfig.lua")
    -- set mode as stationAP  
    wifi.setmode(wifi.STATIONAP)
    wifi.setphymode(wifi.PHYMODE_G)
    wifi.ap.config(cfg)
    print("AP IP Address:" .. wifi.ap.getip())   
    pool_ipstart, pool_ipend = wifi.ap.dhcp.config(dhcp_config)
    if wifi.ap.dhcp.start() then
        print("DHCP server started, pool addr from " .. pool_ipstart .. " to " .. pool_ipend .. "!")
    else
        print("DHCP server failed!")
    end
else
    -- default mode as station
    wifi.setmode(wifi.STATION)
    wifi.setphymode(wifi.PHYMODE_N)
end

-- periksa keberadaan file credentials.lua yang mendefinisikan
-- 'SSID' and 'PASSWORD' wifi
if file.open("credentials.lua") == nil then
    -- bagian module standalone
    print("Boot sebagai module standalone")
    print("You have 3 seconds to abort")
    print("Waiting...")
    -- jalankan fungsi startup setelah 3 detik      
    tmr.alarm(0, 3000, 0, startup)
else   
    -- bagian module koneksi wifi
    file.close("credentials.lua")
    -- muat variable SSID dan PASSWORD
    dofile("credentials.lua")
    print("Koneksi ke " .. SSID)
    station_cfg={}
    station_cfg.ssid=SSID
    station_cfg.pwd=PASSWORD
    wifi.sta.config(station_cfg, false)
   
    --wifi.sta.config(SSID, PASSWORD)
    -- wifi.sta.connect() not necessary because config() uses auto-connect=true by default

    -- mencoba koneksi setiap detik sampai tmr.stop(1)
    trycount = 1
    tmr.alarm(1, 1000, 1, function()
        if wifi.sta.getip() == nil then
            print("trying " .. trycount .. " second(s)")
            trycount = trycount + 1
        else
            -- berhasil koneksi dan mendapatkan IP Address
            tmr.stop(1)
            print("WiFi connected")
            print("Client IP Address:" .. wifi.sta.getip())
            print("You have 3 seconds to abort")
            print("Waiting...")
            -- issue file.remove("app.lua") here
            -- jalankan fungsi startup setelah 3 detik      
            tmr.alarm(0, 3000, 0, startup)
        end       
    end)
end

Om Telolet Om: WeMos DH11 Shield (ESP8266EX, NodeMCU, Lua)

Pada tulisan ini akan membahas pembuatan Lua script untuk mengukur temperatur dan humidity dengan menggunakan perangkat WeMos DH11, pemakai perangkat IoT dapat membantu para peneliti untuk merekam kondisi dilapangan dari waktu ke waktu sehingga cukup berkonsentrasi pada variabel lainnya, sedangkan variabel terkait dengan temperatur dan kelembaban dapat secara otomatis direkam oleh perangkat IoT.

Gambar 1. WeMos DHT11 Shield

Interface antara DH11 shield dengan WeMos board adalah melalui pin D1, keuntungan dari pemakaian shield adalah anda tidak membutuhkan bread-board maupun menggunakan jumper untuk menghubungkan antara WeMos board dengan sensor DH11, tetapi cukup shield DH11 ditumpukan diatas WeMos board.

pinDHT11 = 4 -- pin D4 pada board WeMos D1 mini

function readFromDHT11()
    status, temp, humi, temp_dec, humi_dec = dht.read11(pinDHT11)

    if status == dht.OK then
        wib = rtctime.epoch2cal(rtctime.get()+7*60*60) -- tambah 7 WEST INDONESIA TIME
        timeStr = string.format("%04d/%02d/%02d %02d:%02d:%02d", wib["year"], wib["mon"], wib["day"], wib["hour"], wib["min"], wib["sec"])
        print(timeStr ..";" .. temp .. ";" .. humi)
      
    elseif status == dht.ERROR_CHECKSUM then
        print( "DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print( "DHT timed out." )
    end
end

sntp.sync("1.id.pool.ntp.org",
 function(sec,usec,server)
   print('setting time to:', sec, usec, "from: " .. server)
   rtctime.set(sec, usec)
 end,

 function()
   print('failed!')
 end
)

tmr.alarm(0,1000,1,readFromDHT11) -- setiap detik baca dari sensir DHT11

Pada script berikut ini adalah melakukan log ke file harian setiap 5 detik untuk keperluaan penelitian.

pinDHT11 = 4 -- pin D4 pada board WeMos D1 mini

function readFromDHT11()
    status, temp, humi, temp_dec, humi_dec = dht.read11(pinDHT11)

    if status == dht.OK then
        wib = rtctime.epoch2cal(rtctime.get()+7*60*60) -- tambah 7 WEST INDONESIA TIME
        timeStr = string.format("%04d/%02d/%02d %02d:%02d:%02d", wib["year"], wib["mon"], wib["day"], wib["hour"], wib["min"], wib["sec"])
        --print(timeStr ..";" .. temp .. ";" .. humi)
        payload = timeStr ..";" .. temp .. ";" .. humi
        return payload
      
    elseif status == dht.ERROR_CHECKSUM then
        print( "DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print( "DHT timed out." )
    end
end

function logToFile()
    wib = rtctime.epoch2cal(rtctime.get()+7*60*60) -- tambah 7 WEST INDONESIA TIME
    fname = string.format("%04d%02d%02d", wib["year"], wib["mon"], wib["day"])
    -- open file in 'a+' mode   
    if file.open(fname, "a+") then
        -- write 'foo bar' to the end of the file
        file.writeline(readFromDHT11())
        print("log to " .. fname)
        file.close()
    end
end

sntp.sync("1.id.pool.ntp.org",
 function(sec,usec,server)
   print('setting time to:', sec, usec, "from: " .. server)
   rtctime.set(sec, usec)
 end,

 function()
   print('failed!')
 end
)

tmr.alarm(0,5000,1,logToFile) -- setiap detik baca dari sensir DHT11