Tampilkan postingan dengan label Arduino. Tampilkan semua postingan
Tampilkan postingan dengan label Arduino. Tampilkan semua postingan

Minggu, 09 September 2018

Revisi Library Modul ADC MCP3424 pada Arduino

Late post, seharusnya sekitar bulan September 2017. 


Pada postingan kali ini Saya akan membahas mengenai library untuk modul ADC MCP3424. Library untuk Arduino ini awalnya Saya download dari https://github.com/battosai30/MCP3424. (Kalau tidak salah Saya download sekitar bulan Juli atau Agustus 2017)

Oiya sebelumnya perlu Saya infokan bahwa modul ADC MCP3424 ini merupakan IC untuk mengkonversi sinyal analog menjadi sinyal digital. IC ini memiliki resolusi 18 bits. Untuk berkomunikasi dengan mikrokontroler, IC ini menggunakan protokol I2C. IC ini juga sudah memiliki PGA (Programmable Gain Amplifier - sebesar 1x, 2x, 4x dan 8x) didalamnya, sehingga sinyal yang kecil bisa langsung dikuatkan dengan cara memprogram IC ini. Range kerja IC ini adalah -2,048 V sampai +2,048 V (setelah dikuatkan melalui PGA). Untuk lebih detil silahkan cek di datasheet MCP3424.

Cara mudah menggunakan IC ini adalah dengan mencari dan menggunakan library yang sudah tersedia (jika ada hehehe). Dan Alhamdulillah sudah ada yang membuat dan membagikan library tersebut. Library untuk Arduino ini awalnya Saya download dari https://github.com/battosai30/MCP3424. Saya download sekitar bulan juli 2017 kalo tidak salah.

Yang akan Saya share disini adalah adanya sedikit kesalahan pada saat pembacaan. Perbaikan ini juga sudah Saya sampaikan ke pembuat library awal (batto@hotmail.fr). Kira-kira begini ceritanya.hehe Mohon maaf jika bahasa inggrisnya kacau.


##the first problem dealed with negative number
in the previous version, the conversion (for example from 18 to 32 bits format)
is just by using adding ('or' logic) the magnitute value 0x xxxxxxxx xxxxxxxx with 10000000 00000000 00000000 00000000
this will give result 10000000 0000000x xxxxxxxx xxxxxxxx
the problem is 10000000 0000000x xxxxxxxx xxxxxxxx (32 bits format) is not the same number with 1x xxxxxxxx xxxxxxxx (18 bits format)
lets take an example if we have 11 11111111 11111110 (18 bits format) = -2 (decimal)
conversion --> 01 11111111 11111110 (magnitute only) + 10000000 00000000 00000000 00000000 = 10000000 00000001 11111111 11111110 (32 bits format) = -2147352578 (decimal)
and it is big different number (that the problem)

considering two's complement concept for negative number (it was mention in datasheet that negative number format deal with two's complement concept).
so the conversion should be done by using:
adding ('or' logic) the magnitute value 00000000 0000000x xxxxxxxx xxxxxxxx with 11111111 11111110 00000000 00000000
with the same example if we have 11 11111111 11111110 (18 bits format) = -2
conversion --> 01 11111111 11111110 (magnitute only) + 11111111 11111110 00000000 00000000 = 11111111 11111111 11111111 11111110 (32 bits format) = -2 (decimal)
and the problem solved.

considering datasheet again for 18 bits format, the data will take 3 bytes or 24 bits. and for negative number the data format is
1111111x xxxxxxxx xxxxxxxx (without extract the magnitute value) and we just need to add ('or' logic) with 11111111 00000000 00000000 00000000 (0xFF000000 in hex)
so the conversion will result 11111111 1111111x xxxxxxxx xxxxxxxx

considering datasheet again for 16, 14, 12 bits format, the data will take 2 bytes or 16 bits, so for negative conversion
we just need to add ('or' logic) with 11111111 11111111 00000000 00000000 (0xFFFF0000 in hex)


##the second problem dealed with positive magnitute extraction on 14 and 12 bits format
in previous version, for 14 bits:
_resultat = (((long)_buffer[0] & 0xBF) << 8) | ((long)_buffer[1] & 0xFF);
it should be:
_resultat = (((long)_buffer[0] & 0x1F) << 8) | ((long)_buffer[1] & 0xFF);    
//0x1F (0b00011111) because in 14 bits, the magnitute started from 13rd bit (or from 5th bit in first byte)


in previous version, for 12 bits:
_resultat = (((long)_buffer[0] & 0x0F) << 8) | ((long)_buffer[1] & 0xFF);
it should be:
_resultat = (((long)_buffer[0] & 0x07) << 8) | ((long)_buffer[1] & 0xFF);    
//0x07 (0b00000111) because in 12 bits, the magnitute started from 11st bit (or from 3rd bit in first byte)

Berikut adalah link untuk download Library MCP3424 Revisi


Sebagai catatan, pada saat Saya mencoba dengan simulasi proteus ISIS terdapat masalah pada range nilai negatif. Oiya ini hanya saat simulasi di proteus ISIS (mudah-mudahan saat ini sudah diperbaiki oleh Proteus ISIS)

##the third problem dealed with the range for negative number
after trial updated library in Proteus ISIS simulation, i found the problem again.
now is about the negative range, in datasheet i found the range should be -1 LSB to -VRef
but in simulation the range is inverted (from -VRef to -1 LSB)
so i use this formula (for 18 bits):
_resultat = (-1) - _resultat + (-131071) ;
the negative range should be -1 to -131072 for 18 bit
because there is bit for 0 (zero) number in bitween negative and positive number, i choose -131071 instead

for 16 bits:
_resultat = (-1) - _resultat + (-32767) ;
for 14 bits:
_resultat = (-1) - _resultat + (-8191) ;
for 12 bits:
_resultat = (-1) - _resultat + (-2047) ;

Berikut adalah link untuk download Library MCP3424 Revisi (untuk simulasi Proteus ISIS)


Screenshoot saat simulasi Proteus ISIS

Revised by: 
Muhammad Nurul Puji
to support Project-G

Senin, 13 April 2015

Cara mengakses Serial Port menggunakan Matlab pada Linux Ubuntu 14.04 (Kasus komunikasi dgn Arduino)

Pada postingan sebelumnya Sy mencoba komunikasi dgn Arduino melalui Serial Port melalui Visual Basic. Kali ini Sy mencoba share tentang cara komunikasi Serial Port melalui Matlab di Linux Ubuntu 14.04.

Berikut adalah perintah yang umum digunakan pada Matlab untuk komunikasi melalui Serial Port.

%untuk inisialisasi Serial Port.
s = serial(portname,'BaudRate',baudrate,'terminator', 'LF');
%untuk membuka koneksi Serial Port
fopen(s);

%untuk kirim perintah ke mikro melalui Serial Port
perintah=char(strcat(frekuensi, {' '}, num2str(i) , {' '} , num2str(j)));   %Hanya contoh perintah
fprintf(s,perintah);   %untuk menulis perintah melalui Serial Port

%untuk membaca data melalui Serial Port
readbuffer=fscanf(s);

%untuk menutup koneksi apabila sudah selesai
fclose(s);
delete(s);
clear s;

Baris perintah (command) di atas akan bisa langsung digunakan pada OS berbasis windows dgn memasukkan portname='COM1' atau port yang lain.

Namun ternyata pada saat Sy coba dgn OS Ubuntu 14.04 dgn portname yang aktif adalah '/dev/ttyACM0' ternyata pada saat fopen(s) komunikasi tidak berhasil dan tampil kesalahan pada console Matlab. Bikin panik aja, apalagi saat saat genting.haha.. 



Setelah searching kesana kemari ternyata pada Matlab under Ubuntu, nama Portname harus diberi alias. Caranya dengan menambahkan kode berikut (termasuk tanda '-')

-Dgnu.io.rxtx.SerialPorts=/dev/ttyS0:/dev/ttyS1:/dev/ttyS2:/dev/ttyS3:/dev/ttyS4:/dev/ttyS5:/dev/USB0:/dev/USB1:/dev/USB2:/dev/USB3:/dev/USB4:/dev/USB5:/dev/ttyACM0:/dev/ttyACM1:/dev/ttyACM2:/dev/ttyACM3:/dev/ttyACM4:/dev/ttyACM5

kemudian disimpan dalam file bernama java.opts dan disimpan kedalam direktori aktif Matlab. Biasanya alamat direktori aktifnya adalah

/usr/local/MATLAB/R2012b/bin/glnxa64/

dengan catatan gnlxa64 adalah untuk 64 bit. Silahkan dicek lagi jika berbeda. Jangan lupa merestart aplikasi Matlab supaya bisa berfungsi. Alhamdulillah Serial Port sdh bisa terkoneksi.



















Jumat, 06 Maret 2015

Programmable Gain Amplifier (PGA) MCP6S21 menggunakan Arduino

PGA atau Programmable Gain Amplifier adalah OpAmp yang memiliki gain pada range tertentu dan dapat diprogram. Jika pada OpAmp biasa pensettingan gain dilakukan menggunakan konfigurasi resistor, maka pada PGA setting gain dilakukan dengan menggunakan software. Hal ini sangat berguna untuk pengukuran besaran analog atau pengaturan tegangan analog yang bersifat dinamis. Yang mana dibutuhkan besaran gain yang fleksibel sesuai kebutuhan.



Pada posting kali ini, PGA yang digunakan adalah MCP6S21 dari Microchip. MCP6S21 memiliki besaran gain +1, +2, +4, +5, +8, +10, +16 dan +32 dengan bandwith 2-12 MHz (typ). MCP6S21 hanya memiliki 1 (satu) channel input. MCP6S21 menggunakan komunikasi SPI untuk pengaturan gain maupun mode shutdown. Model PGA MCP6S21 tidak memiliki pin SO (MISO).





Berbeda dengan tipe MCP6S26 yang memiliki 6 channel input dan MCP6S28 dengan 8 channel input sehingga dapat sekaligus berfungsi sebagai multiplexer. MCP6S26 dan MCP6S28 memiliki pin SO (MISO) sehingga memungkinkan konfigurasi daisy chain (cascade atau bersambung dengan menggunakan SPI yang sama)


Berikut adalah source code untuk mengatur gain dan mode shutdown pada PGA MCP6S21. Code ini dibuat berdasarkan datasheet dan referensi lain. Source code berikut memungkinkan merubah gain maupun mode shutdown melalui serial terminal. Sehingga bisa dikembangkan untuk komunikasi dengan program desktop lain (seperti VB, Delphi, C atau yang lain).

/*
Author: Muhammad Nurul Puji
muhammadpuji.its@gmail.com
6 Mar 2015
*/

#include <SPI.h>
/*
CS- to pin 10 (SS Pin)
SI- to pin 11 (MOSI Pin)
CLK - to pin 13 (SCK Pin)
*/
const int CS_PGA = 10;  //#define CS_PGA 10

char buff_char;
String buff_string = "";
int gain;

void setup()
{
  //setting SPI-PGA MCP6S2x
  pinMode(CS_PGA,OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);  //MSB first bit order
  SPI.setDataMode(SPI_MODE0);  //SPI Mode 0
  SPI.setClockDivider(SPI_CLOCK_DIV4);  //16MHZ/4=4MHZ
  
  //setting Serial
  Serial.begin(57600);
  delay(1);
  Serial.println("");
  Serial.println("Welcome Muhammad Nurul Puji");
  Serial.println("Silahkan masukkan nilai gain yang diinginkan");
  Serial.println("0--> +1; 1--> +2; 2--> +4; 3--> +5; 4--> +8; 5--> +10; 6--> +16; 7--> +32; Other--> Shutdown");
  Serial.println("");
  delay(1);
}

void loop()
{
  while(Serial.available()) {
    buff_char = Serial.read();
    buff_string.concat(buff_char);
    delay(1);  //delay ini sangat penting
  }  

  if(buff_string != ""){
    gain=buff_string.toInt();  
    if(gain<=7){
    PGA_set_gain(gain); 
    Serial.println("Gain is Changed");
    }
    else{
    PGA_shutdown();
    Serial.println("PGA is Shutdown");
    }
    buff_string="";
  }
}

//pengaturan set nilai gain pada PGA MCP6S21
void PGA_set_gain(int gain){
  int instruction = 0b01000000;  //untuk instruksi merubah gain
  digitalWrite(CS_PGA,LOW);
  SPI.transfer(instruction);   
  SPI.transfer(gain);    //set gain
  digitalWrite(CS_PGA,HIGH);
}

//untuk shutdown pada PGA MCP6s21
void PGA_shutdown(){
  int instruction = 0b00100000;  //untuk instruksi shutdown
  digitalWrite(CS_PGA,LOW);
  SPI.transfer(instruction);
  SPI.transfer(0);    //hanya untuk memenuhi aturan 16bit
  digitalWrite(CS_PGA,HIGH);
}



Prosedur PGA_set_gain() dan PGA_shutdown() dapat dikembangkan untuk PGA MCP6S26 maupun MCP6S26 baik mode single maupun mode daisy chain serta untuk pemilihan channel. Hal ini harus disesuaikan dengan datasheet.

Thanks to Mas Rohmadi (http://rohmadi.my.id) atas pinjaman Oscilloscopnya :)
--
Referensi:
http://ww1.microchip.com/downloads/en/DeviceDoc/21117B.pdf (Datasheet)
http://forum.arduino.cc/index.php?topic=19775.0

Kamis, 26 Februari 2015

Arduino Komunikasi serial dan pemisahan terhadap separator perintah

Berikut adalah penggunaan Arduino dengan komunikasi serial. Yang mana perintah dikirim dari pc melalui komunikasi serial. Perintah yang dikirim oleh pc memiliki format "data_1""separator""data_2". Disini separator yang digunakan adalah tanda "+". Misalnya pc mengirimkan perintah "12+3" maka Arduino harus memisahkan perintah tersebut menjadi data_1 dan data_2. Pada percobaan kali ini data_1 dan data_2 kemudian dijumlahkan.

Berikut adalah sourcecode yang digunakan: 


/*
Author: Muhammad Nurul Puji
muhammadpuji.its@gmail.com
16 Feb 2015
*/

char buff_char;
String buff_string = "";
float data_1, data_2, total;
String buff_data_1, buff_data_2;

void setup()
{
  Serial.begin(57600);
  delay(100);
  Serial.println("Welcome Muhammad Nurul Puji");
  Serial.println("");
  delay(1000);
}

void loop()
{
 

while(Serial.available()) {  //blok untuk menerima perintah serial    
    buff_char = Serial.read();
    buff_string.concat(buff_char);
    delay(1);  //delay ini sangat penting
  } 
 
 
  if(buff_string != ""){
    buff_data_1=(splitValue(buff_string, '+', 0));  //memisahkan string data dengan string separator "+"
    buff_data_2=(splitValue(buff_string, '+', 1));
   
    //char buff[buff_data_1.length()];               //mengubah string ke float
    //buff_data_1.toCharArray(buff,buff_data_1.length()+1);
    //data_1=atof(buff);

    data_1=buff_data_1.toInt();   //cara singkat mengubah string ke number
   
    //buff[buff_data_2.length()];                    //mengubah string ke float
    //buff_data_2.toCharArray(buff,buff_data_2.length()+1);
    //data_2=atof(buff); 

    data_2=buff_data_2.toInt();   //cara singkat mengubah string ke number   
    

    total = data_1 + data_2;
   
    Serial.print("Perintah awal adalah ");
    Serial.print(buff_string);  //bukan println karena perintah dikirim setelah ditekan enter
    Serial.print("Data 1 = ");
    Serial.println(data_1);
    Serial.print("Data 2 = ");
    Serial.println(data_2);
    Serial.print("Total data adalah ");
    Serial.println(total);
    Serial.println("");
   
    buff_string="";
  }
}

//Function untuk memisahkan data dengan separator

String splitValue(String data, char separator, int index){
  int found = 0;
  int strIndex[]={0, -1};
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i) == separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}



Referensi: dari postingan - postingan sebelumnya...........
--
Semoga bermanfaat

Selasa, 24 Februari 2015

Source code untuk mengenali pola data string dan memisahkannya dalam masing-masing variabel

Berikut adalah beberapa code untuk mengenali pattern ato pola string kemudian data string tersebut dapat dipisah sesuai "separator" yg digunakan. Source code berikut sangat powerfull dan terpilih dari beberapa sumber.

Pemisahan pattern string sangat penting dalam pemberian perintah (command), misal dalam aplikasi mikrokontroler yg diperintah oleh PC (atau mikrokontroller lain) untuk kontrol pengambilan data. Sehingga dalam sekali kirim perintah bisa dimasukkan beberapa parameter yg diinginkan. Kemudian mikrokontroller bisa memisahkan parameter-parameter tsb dgn sourcecode berikut ini.

Excellent code....

Stackexchange.com







Stackoverflow.com



Github.com



--
Sumber referensi (dicopy tgl 15 Februari 2015)
http://arduino.stackexchange.com/questions/1013/how-do-i-split-an-incoming-string
http://stackoverflow.com/questions/9072320/split-string-into-string-array
https://github.com/ka1/sousVide/blob/master/arduino/TempYun/functions.ino#

Rabu, 17 September 2014

Signal Generator (DDS AD9850) dan Frekuensi Meter dan Kontrol Frekuensi dari Serial Monitor

Ini adalah posting lanjutan dari Signal Signal Generator DDS A9850 dan Frekuensi Meter . Dengan Saya tambahkan bagian untuk dapat merubah frekuensi secara serial melalui serial monitor pada Arduino sehingga frekuensi dapat diatur lebih fleksibel tanpa bolak balik upload program. 

Berikut definisi variable yang perlu ditambahkan pada source code sebelumnya:

float buff_data;
String buff_string = "";
char buff_char;
 

Berikut modifikasi souce code (pengganti) yang berada pada bagian void loop(). Sedangkan yang lain masih tetap sama dengan source code sebelumnya.

void loop()
{
       
        //lcd.clear();
       
        //cek perintah serial
        while(Serial.available()) {
        buff_char = Serial.read();
        buff_string.concat(buff_char);    //menggabungkan variabel buff_char ke variable buff_string
        }
       
        //merubah tipe data string ke float (tipe data float = double)
        char buf[buff_string.length()];
        buff_string.toCharArray(buf,buff_string.length()+1);
        float buff_data=atof(buf);  //buff_data akan nol pada loop berikutnya jika tidak ada perintah

                                    //(karena buff_string dikosongkan "" diakhir loop)
       
        //cek jika ada permintaan perubahan frekuensi 
        if (buff_data>0) sendFrequency(buff_data);
      
        Serial.print(freq_cek);
        Serial.print(" ");
        Serial.println(freq_satuan);
        lcd.setCursor(0,0);   
        lcd.print("Freq DDS AD9850");
        lcd.setCursor(0,1);   
        lcd.print("Freq= ");
        lcd.print(freq_cek);
        lcd.print(" ");
        lcd.print(freq_satuan);
        //delay(500);
       
        buff_string="";
}



Berikut adalah screenshot hasil modifikasi dengan source code di atas:

Contoh Hasil pada Serial Monitor


Beberapa referensi utama:
http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
http://www.ad7c.com/projects/ad9850-dds-vfo/

http://letsmakerobots.com/content/how-convert-strings-double
http://stackoverflow.com/questions/5697047/convert-serial-read-into-a-useable-string-using-arduino 

Merubah tipe data String ke Float (atau Double)

Berikut adalah source code untuk merubah tipe data String ke tipe data float (atau double). Ini sangat berguna saat komunikasi serial yang biasanya perintah dikirimkan melalui tipe data string

float buff_data;
String buff_string = "123.22";

//merubah tipe data string ke float (tipe data float = double)
        char buf[buff_string.length()];
        buff_string.toCharArray(buf,buff_string.length()+1);
        float buff_data=atof(buf);


double buff_data;
String buff_string = "123.22";

//merubah tipe data string ke float (tipe data float = double)
        char buf[buff_string.length()];
        buff_string.toCharArray(buf,buff_string.length()+1);
        double buff_data=atof(buf);


Referensi:
http://letsmakerobots.com/content/how-convert-strings-double

Membaca tipe String pada komunikasi serial (Arduino - PC)

Berikut adalah source code untuk membaca string pada komunikasi serial. Hasil yang terbaca adalah semua string yang dikirim secara serial setelah ditekan enter.

String buff_string = "";
char buff_char;

while(Serial.available()) {
  buff_char = Serial.read();
  buff_string.concat(buff_char);    //menggabungkan variabel buff_char ke variable buff_string

}

Referensi:
http://stackoverflow.com/questions/5697047/convert-serial-read-into-a-useable-string-using-arduino

Signal Generator (DDS AD9850) dan Frekuensi Meter

Posting kali ini bertujuan untuk membangkitkan signal DDS menggunakan IC AD 9850. IC ini sudah tersedia dalam bentuk modul. Keluaran IC ini berupa gelombang sinus dan kotak. Karena IC ini bersifat programmable maka frekuensi akan disetting menggunakan Arduino Uno.

Kemudian dibuat pula program untuk mengecek frekuensi yang dikeluarkan oleh IC tersebut setelah diprogram sebelumnya. Aplikasi penghitung frekuensi ini juga dapat digunakan untuk menghitung frekuensi yang lain dengan cara menghubungkan sumber frekuensi ke pin T1 (timer1 sebagai counter.

Untuk menghitung frekuensi yang dikeluarkan oleh DDS AD9850 maka output signal kotak dihubungkan ke pin T1 dari Arduino Uno.

Hasil penghitungan frekuensi kemudian ditampilkan dalam LCD 16x2 dan dikirim ke PC secara serial.

Konfigurasi Pin Arduino Uno

Konfigurasi Pin Modul DDS AD9850
Konfigurasi LCD:
LiquidCrystal lcd(12,13,3,4,6,7); //Konfigurasi schematic LCD Keypad

Konfigurasi DDS AD9850:
///////////////AD9850
#define W_CLK 8   // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 9   // Pin 9 - connect to freq update pin (FQ)
#define DATA 10   // Pin 10 - connect to serial data load pin (DATA)
#define RESET 11  // Pin 11 - connect to reset pin (RST)
///////////////AD9850
Konfigurasi Counter1:
Pin output gelombang kotak dari DDS AD9850 dihubungkan ke pin T1 pada Arduino Uno.

Berikut Source Code Lengkapnya:
/*
Author: Muhammad Nurul Puji
muhammadpuji.its@gmail.com
This program have been tested on Arduino Uno R3, DDS AD9850 and LCD Keypad
2013
*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,13,3,4,6,7); //Konfigurasi schematic LCD Keypad

///////////////AD9850
#define W_CLK 8   // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 9   // Pin 9 - connect to freq update pin (FQ)
#define DATA 10   // Pin 10 - connect to serial data load pin (DATA)
#define RESET 11  // Pin 11 - connect to reset pin (RST)
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
String freq; // string to hold the frequency
///////////////AD9850

/////////Freq Cek
float freq_cek;
int kilo,mega, timer0;
String freq_satuan;
/////////Freq Cek

void setup()
{
       
        ///////////setting counter atau timer
        timer0;
        kilo=0;
        mega=0;
        freq_cek=0;
        freq_satuan="Hz";
       
        cli();//stop interrupts
     
        //set timer0 interrupt
        TCCR0A = 0;// set entire TCCR0A register to 0
        TCCR0B = 0;// same for TCCR0B
        TCNT0  = 0;//initialize counter value to 0
        // set compare match register for 2khz increments
        OCR0A = 249;// 250 (dimulai dari 0) - karena prescaler 64 (250KHz) maka diperlukan 1000 kali interrupt untuk 1 detik
        // turn on CTC mode
        TCCR0A |= (1 << WGM01);
        // Set CS01 and CS00 bits for 64 prescaler (250KHz)
        TCCR0B |= (1 << CS01) | (1 << CS00);  
        // enable timer compare interrupt
        TIMSK0 |= (1 << OCIE0A);
     
        //set timer1 interrupt sebagai counter sinyal frekuensi yang masuk
        TCCR1A = 0;// set entire TCCR1A register to 0
        TCCR1B = 0;// same for TCCR1B
        TCNT1  = 0;//initialize counter value to 0
        // set compare match register for 1hz increments
        OCR1A = 999;//seribu kali - mulai dari 0
        // turn on CTC mode
        TCCR1B |= (1 << WGM12);
        // Set CS10 and CS11 bits for external clock T1 falling edge
        TCCR1B |= (1 << CS12) | (1 << CS11); 
        // enable timer compare interrupt
        TIMSK1 |= (1 << OCIE1A);
     
        sei();//allow interrupts       
        //////////////setting counter atau timer
     
   
        ///////////////AD9850
        pinMode(FQ_UD, OUTPUT);
        pinMode(W_CLK, OUTPUT);
        pinMode(DATA, OUTPUT);
        pinMode(RESET, OUTPUT);
        pulseHigh(RESET);
        pulseHigh(W_CLK);
        pulseHigh(FQ_UD);  // this pulse enables serial mode on the AD9850 - Datasheet page 12.
        sendFrequency(1000000); //tes frekuensi 1MHz
        ///////////////AD9850 
 
      Serial.begin(9600);
    lcd.begin(16,2);
}

void loop()
{
       
        //lcd.clear();
        Serial.print(freq_cek);
        Serial.print(" ");
        Serial.println(freq_satuan);
        lcd.setCursor(0,0);   
        lcd.print("Freq DDS AD9850");
        lcd.setCursor(0,1);   
        lcd.print("Freq= ");
        lcd.print(freq_cek);
        lcd.print(" ");
        lcd.print(freq_satuan);
        //delay(500);
}


//////////////untuk handle interrupt counter dan timer
ISR(TIMER0_COMPA_vect){//timer0 interrupt
 
timer0++; 
if (timer0==1000) {    //setiap 1 detik dicek jumlah pulsanya
  if (mega>0){
    freq_cek=((float)mega+((float)kilo/1000) + ((float)TCNT1/1000000))*1;    //dikali 1 supaya 1 detik
    freq_satuan = "MHz  ";
  }else if (kilo>0){
    freq_cek=((float)kilo + ((float)TCNT1/1000))*1;    //dikali 1 supaya 1 detik
    freq_satuan = "KHz  ";
  }else {
    freq_cek = ((float)TCNT1) * 1;
    freq_satuan = "Hz   ";
  } 
  timer0=0;
  kilo=0;
  mega=0;
  TCNT1=0;
  TCNT0=0;
}
}

ISR(TIMER1_COMPA_vect){//counter1 interrupt
 
kilo++;
if (kilo==1000){
  mega++;
  kilo=0;
}
}
//////////////untuk handle interrupt counter dan timer


/////////////////////AD9850
// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) { 
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850.  

  for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
  pulseHigh(FQ_UD);  // Done!  Should see output
}
// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data)
{
  for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
}
/////////////////////AD9850

Hasil:
DDS AD9850 dapat membangkitkan gelombang sinus dan kotak. Berikut pengambilan data menggunakan ADC pada frekuensi rendah (0,5 Hz; 1 Hz; 2Hz)
 - Mungkin akan dijabarkan diposting terpisah :)

Hasil keluaran DDS AD9850 gelombang sinus dan kotak

Hasil keluaran DDS AD9850 sine 1 dan sine 2

Hasil pengukuran frekuensi oleh Arduino Uno menggunakan Counter dan Timer1:

Pengukuran Nilai Frekuensi keluaran DDS AD9850 (di tes pada 1 MHz)
Pengukuran Nilai Frekuensi keluaran DDS AD9850 (di tes pada 1 Hz)
Pengukuran Nilai Frekuensi keluaran DDS AD9850 (dites pada 2,25 MHz)


Beberapa referensi utama:
http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
http://www.ad7c.com/projects/ad9850-dds-vfo/

Jumat, 22 November 2013

Belajar interface serial menggunakan Visual Basic .Net (2012)

Ok, langsung saja Sy akan share bagaimana cara komunikasi menggunakan serial port dengan Visual Basic 2012. Codingnya Sy buat dengan mengacu dari beberapa referensi yg Sy peroleh, dengan modifikasi seperlunya.

Program ini Sy buat karena Sy ingin komunikasikan Arduino dengan VB 2012.

Berikut Contoh desain formnya ya:




Public Class Form1

    Dim readBuffer As String

    Private Sub SendBtn_Click(sender As Object, e As EventArgs) Handles SendBtn.Click
        Try
            SerialPort1.Write(TextBox1.Text + Environment.NewLine)

            TextBox3.AppendText(">" + TextBox1.Text + Environment.NewLine)
            TextBox3.ScrollToCaret()

            TextBox1.Text = String.Empty

        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim portName() As String
        Dim i As Integer

        Try
            portName = System.IO.Ports.SerialPort.GetPortNames()
            For i = 0 To i >= (portName.Length)
                ComList.Items.Add(portName(i))
            Next i

            ComList.SelectedText = ComList.Items(0)
            disBtn.Enabled = False
        Catch ex As Exception
            MsgBox("Belum Ada Serial Port Aktif, Silahkan Cek Koneksi Serial Anda")
        End Try
    Private Sub ConBtn_Click(sender As Object, e As EventArgs) Handles ConBtn.Click
        If SerialPort1.IsOpen Then
            SerialPort1.Close()
        End If

        Try
            With SerialPort1
                .PortName = ComList.Text
                .BaudRate = 9600
                .Parity = IO.Ports.Parity.None
                .DataBits = 8
                .StopBits = IO.Ports.StopBits.One
                .Open()
            End With
            Label1.Text = ComList.Text + " Connected"
            ConBtn.Enabled = False
            disBtn.Enabled = True

        Catch ex As Exception
            MsgBox(ex.ToString)

        End Try
    End Sub

    Private Sub disBtn_Click(sender As Object, e As EventArgs) Handles disBtn.Click
        Try
            SerialPort1.DiscardInBuffer() 'mengosongkan input buffer
            SerialPort1.Close()
            ConBtn.Enabled = True
            disBtn.Enabled = False
            Label1.Text = "  Disconnected"
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End Sub
    ''' <summary>
    ''' async read on secondary thread
    ''' </summary>
    Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, _
                                         ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
                                         Handles SerialPort1.DataReceived
        If SerialPort1.IsOpen Then
            Try
                readBuffer = SerialPort1.ReadLine()
                'data to UI thread
                Me.Invoke(New EventHandler(AddressOf DoUpdate))
            Catch ex As Exception
                MsgBox("read " & ex.Message)
            End Try
        End If
    End Sub

    ''' <summary>
    ''' update received string in UI
    ''' ini subrutine tambahan
    ''' </summary>

    Public Sub DoUpdate(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim temp As Decimal
        temp = CInt(readBuffer) / 1024 * 5 * 100
        TextBox2.Text = Int(temp)
        TextBox4.Text = CInt(readBuffer)

    End Sub

End Class


Jangan lupa dihubungkan dulu port serialnya dengan mirkrokontrol sehingga akan terdetek port yang aktif. Untuk kode mikrokontrolernya Sy menggunakan Arduino. Bisa pakai kode di example nya. Untuk komunikasi serial.

Selamat berkreasi :)

Sumber referensi:
http://students.netindonesia.net/blogs/sapikuda/archive/2012/07/25/membuat-program-koneksi-ke-plc-menggunakan-c.aspx

http://code.msdn.microsoft.com/windowsdesktop/SerialPort-Sample-in-VBNET-fb040fb2

http://msdn.microsoft.com/en-us/library/vstudio/s2dy91zy.aspx

Selasa, 19 November 2013

ARDUINO & LM35DZ & LCD16X2 & RUNNING TEXT

Posting ini adalah tentang menggunakan Arduino (Uno R3) untuk memperoleh temperatur dengan menggunakan sensor LM35DZ. Maaf karena belum lama belajarnya hehe.

Proyek ini menggunkan sensor suhu LM35DZ untuk mendapatkan besaran voltage yang merupakan representasi dari suhu. Kemudian di setting pada suhu tertentu sehingga Led Merah akan menyala pada saat suhu lebih besar dari batas atas dan menyala bila lebih kecil dari batas bawah.

Proyek ini juga bisa disambungkan pada motor DC sehingga motor akan berputar dengan kecepatan tergantung suhu. Karena belum punya motor DC maka Saya ganti dengan Led warna kuning. Led warna kuning akan mati apabila suhu berada dibawah batas bawah dan akan menyala maksimal apabila sama atau lebih besar dari batas atas. Nah jika diantaranya maka Led akan menyala dari redup ke paling terang sesuai nilai suhu yang terdetek sensor.


Berikut sintax untuk mengontrol led:

if(temp>=upperLimit) {
        digitalWrite(ledWarning,HIGH);
        intensity=255;
    }else if(temp>=lowerLimit){
        digitalWrite(ledWarning, LOW);
        intensity=(temp-lowerLimit)*255/(upperLimit-lowerLimit);
    }else{
        digitalWrite(ledWarning, HIGH);
        intensity=0;
    }

analogWrite(ledFading,intensity);

ledFading ==> Led warna kuning
ledWarning ==> Led warna merah

Jangan lupa, untuk Led warna kuning harus menggunakan port PWM ya. Kalo Led Merah boleh di port Digital.

Yang bikin Saya agak bingung adalah gimana cara buat running text (text berjalan) yang jumlah karakternya panjang (maklum masih pemula). Setelah cari referensi sana sini, ada beberapa referensi yang mirip tapi gak sama persis yg Sy harapkan :'(... Inilah yang bikin capek... Ingat running text ini bisa sangat panjang. Karena di LCD16x2 kalo textnya panjang banget akan berantakan baris pertama dan keduanya :'(.. Akhirnya Sy buat sendiri fungsi untuk running text nya :) jadi penasaran sendiri akhirnya.


void runningText(int sizeColLcd, char message[], int row, int timerefresh){
  int textSize=strlen(message);
  char tempLcd[sizeColLcd];
  int tempPos =0;
  int iter;
 
  iter=textSize+sizeColLcd;
 
  for(int i=0; i<=iter; i++){
    if(i<sizeColLcd){
      memcpy(tempLcd, &message[0], i+1);
      lcd.setCursor(sizeColLcd-(i+1),row);
      lcd.print(tempLcd);
    }else {
      memcpy(tempLcd, &message[tempPos], sizeColLcd);
      lcd.setCursor(0,row);
      lcd.print(tempLcd);
      tempPos +=1;
    }
  
    delay(timerefresh);
    
  }
}


Gara-gara "memcpy -- library String.h" jadi puyeng. Yaaaa mau gak mau sih, karena memcpy adalah kunci fungsi yang Sy buat di atas. Dan fungsi runningText di atas adalah versi pertama yang Sy buat. Silahkan dimodif sendiri ya (biar sama-sama belajar) :). Alhamdulillah hasilnya memuaskan.

Sorry kalo bhs inggrisnya kacau.hehe. Karena niatnya sekalian belajar bahasa inggris jadi sintaxnya bahasa inggris... :)

Untuk skema rangkaian standar, silahkan disearch di google. Berikut contoh tampilannya....


Thanks for watching :).............
Gut nite.....
i am Indonesian :)

Cara mengetahui ip address raspberry atau perangkat lain yg terhubung pada wifi yg sama

1. Install nmap [jika belum ada]: sudo apt install nmap 2. Cek ip address komputer (yg akses ke wifi yang sama): ip addr misal hasilnya 192....