Baca Disclaimer sebelum membaca / menonton video.
Halo Rek! Kali Ruang Teknik akan share konversi rangkaian PLC untuk diimplementasikan ke dalam Arduino, seperti diketahui penggunaan PLC sangat membantu mengurangi cost biaya Relay/Kontaktor dalam sistem otomasi, sehingga sangat bermanfaat jika kita ingin membuat rangkaian listrik yang membutuhkan banyak Relay/Kontaktor.
Untuk video demo rangkaian bisa dicek disini
Ok, tanpa panjang kali lebar :) silahkan dicek rangkaian On dan Off + LED kedip dengan satu saklar.
Setelah dikonversi ke dalam bahasa pemrograman hasil seperti dibawah ini:
Berikut kodingannya
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t timerOF=0;
#define OVERSAMPLES 10
static volatile uint16_t adcData;
static volatile uint16_t ADCtotal;
static volatile uint8_t adcDataL;
static volatile uint8_t adcDataH;
static volatile uint8_t sample_count;
ISR(TIMER0_OVF_vect){timerOF=1;}
ISR(ADC_vect)
{
adcDataL = ADCL;
adcDataH = ADCH;
adcData = 0;
adcData = adcData | adcDataH;
adcData = adcData << 8;
adcData = adcData | adcDataL;
ADCtotal = ADCtotal+adcData;
sample_count ++;
}
int16_t do_math(int16_t A,int16_t B,char Operator)
{
int32_t result = 0;
if (Operator == '+'){result = A+B;}
if (Operator == '-'){result = A-B;}
if (Operator == '*'){result = A*B;}
if (Operator == '/'){result = A/B;}
// if (Operator == '='){result = A = B;}
int16_t i = ((result >> 0) & 0xffff);
return i;
}
uint16_t read_adc(uint8_t channel)
{
ADMUX = channel;// set channel
ADMUX |= (1<<REFS0);// sets ref volts to Vcc
ADCSRA |= (1<<ADEN); // enable the ADC
sample_count = 0; ADCtotal = 0;//clear sample count
ADCSRA |= (1<<ADSC);//start conversion
//read adcData done in interrupt
while (sample_count < OVERSAMPLES){asm volatile ("nop"::);}//wait for completion
ADCSRA &=~ (1<<ADEN); // stop the ADC
return (ADCtotal/OVERSAMPLES); //mx osamples = 63 othewise will overflow total register with 10 bit adc results
}
int main()
{
//set up ADC
ADCSRA |= ( (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) );// sets adc clock prescaler to 128 //checked
ADCSRA |= (1<<ADIE); // enable ADC conversion complete interrupt
ADCSRA |= (1<<ADATE);// set to auto trigger (free running by default)
DDRD |= (1<<5);
DDRD |= (1<<6);
DDRD |= (1<<7);
DDRB |= (1<<0);
DDRB |= (1<<3);
DDRB |= (1<<4);
DDRB |= (1<<5);
PORTC |= (1<<4);
PORTC |= (1<<5);
PORTD |= (1<<2);
PORTD |= (1<<3);
PORTD |= (1<<4);
//set up loop timer:
TIMSK0 |= (1<<TOIE0);// overflow capture enable
TCNT0 = 101;// start at this
TCCR0B |= ((1<<CS10)|(1<<CS12));// timer started with /1024 prescaler
sei();
uint8_t cont_saklar_NO = 0;
uint8_t output_R1 = 0;
uint8_t branch_1_0 = 0;
uint8_t cont_R1_NO = 0;
uint8_t branch_2_0 = 0;
uint8_t cont_R2_NO = 0;
uint8_t branch_1_2 = 0;
uint8_t cont_R1_NC = 1;
uint8_t branch_2_2 = 0;
uint8_t cont_R3_NC = 1;
uint8_t output_R2 = 0;
uint8_t branch_3_0 = 0;
uint8_t cont_R3_NO = 0;
uint8_t branch_4_0 = 0;
uint8_t output_R3 = 0;
uint8_t cont_R5_NC = 1;
uint8_t cont_R4_NC = 1;
uint8_t output_LED = 0;
uint8_t Timer_T1 = 0;
uint16_t setpoint_Timer_T1 = 50;
uint16_t reg_Timer_T1 = 0;
uint8_t prev_rungstate_Timer_T1 = 0;
uint8_t rungstate_Timer_T1 = 0;
uint8_t run_Timer_T1 = 0;
uint8_t output_R4 = 0;
uint8_t cont_R4_NO = 0;
uint8_t Timer_T2 = 0;
uint16_t setpoint_Timer_T2 = 50;
uint16_t reg_Timer_T2 = 0;
uint8_t prev_rungstate_Timer_T2 = 0;
uint8_t rungstate_Timer_T2 = 0;
uint8_t run_Timer_T2 = 0;
uint8_t output_R5 = 0;
uint8_t W = 1;
while (1)
{
if (timerOF == 1)
{
timerOF=0;//reset timer flag
TCNT0 = 101;// start at this
//inputs:
cont_saklar_NO =~ PINC &(1<<4);
if(output_R1 == 1){
cont_R1_NO=1;}
else {
cont_R1_NO=0;} //link name
if(output_R2 == 1){
cont_R2_NO=1;}
else {
cont_R2_NO=0;} //link name
if(output_R1 == 0){
cont_R1_NC=1;}
else {
cont_R1_NC=0;} //link name
if(output_R3 == 0){
cont_R3_NC=1;}
else {
cont_R3_NC=0;} //link name
if(output_R1 == 1){
cont_R1_NO=1;}
else {
cont_R1_NO=0;} //link name
if(output_R3 == 1){
cont_R3_NO=1;}
else {
cont_R3_NO=0;} //link name
if(output_R1 == 0){
cont_R1_NC=1;}
else {
cont_R1_NC=0;} //link name
if(output_R2 == 1){
cont_R2_NO=1;}
else {
cont_R2_NO=0;} //link name
if(output_R2 == 1){
cont_R2_NO=1;}
else {
cont_R2_NO=0;} //link name
if(output_R5 == 0){
cont_R5_NC=1;}
else {
cont_R5_NC=0;} //link name
if(output_R2 == 1){
cont_R2_NO=1;}
else {
cont_R2_NO=0;} //link name
if(output_R5 == 0){
cont_R5_NC=1;}
else {
cont_R5_NC=0;} //link name
if(output_R4 == 0){
cont_R4_NC=1;}
else {
cont_R4_NC=0;} //link name
if(output_R2 == 1){
cont_R2_NO=1;}
else {
cont_R2_NO=0;} //link name
if(output_R5 == 0){
cont_R5_NC=1;}
else {
cont_R5_NC=0;} //link name
if(output_R4 == 1){
cont_R4_NO=1;}
else {
cont_R4_NO=0;} //link name
if(output_R4 == 1){
cont_R4_NO=1;}
else {
cont_R4_NO=0;} //link name
//Start of Ladder:
//rung at 0
W = 1;
if(cont_saklar_NO == 0){W = 0;}
output_R1 = W;
//end rung
//rung at 1
W = 1;
branch_1_0 = 1;
if(cont_R1_NO == 0){branch_1_0 = 0;}
branch_2_0 = 1;
if(cont_R2_NO == 0){branch_2_0 = 0;}
if( (branch_2_0 == 0) && (branch_1_0 == 0 )) {W = 0;} //node_[1, 0]
if( (branch_2_0 == 2) || (branch_1_0 == 2 )) {W = 1;} //node_[1, 0] if is latching element
branch_1_2 = 1;
if(cont_R1_NC == 0){branch_1_2 = 0;}
branch_2_2 = 1;
if(cont_R3_NC == 0){branch_2_2 = 0;}
if( (branch_2_2 == 0) && (branch_1_2 == 0 )) {W = 0;} //node_[1, 2]
if( (branch_2_2 == 2) || (branch_1_2 == 2 )) {W = 1;} //node_[1, 2] if is latching element
output_R2 = W;
//end rung
//rung at 3
W = 1;
branch_3_0 = 1;
if(cont_R1_NO == 0){branch_3_0 = 0;}
if(cont_R3_NO == 0){branch_3_0 = 0;}
branch_4_0 = 1;
if(cont_R1_NC == 0){branch_4_0 = 0;}
if(cont_R2_NO == 0){branch_4_0 = 0;}
if( (branch_4_0 == 0) && (branch_3_0 == 0 )) {W = 0;} //node_[3, 2]
if( (branch_4_0 == 2) || (branch_3_0 == 2 )) {W = 1;} //node_[3, 2] if is latching element
output_R3 = W;
//end rung
//StateUser
//connected to rung at 5
W = 1;
if(cont_R2_NO == 0){W = 0;}
if(cont_R5_NC == 0){W = 0;}
rungstate_Timer_T1 = W;
if((prev_rungstate_Timer_T1 == 0) && (rungstate_Timer_T1 == 1)){
run_Timer_T1=1;}
if(run_Timer_T1 == 1){
reg_Timer_T1++;
if (reg_Timer_T1 == 65535) {reg_Timer_T1--;}//avoid overrun
if (setpoint_Timer_T1 <= reg_Timer_T1) {Timer_T1=1;}
}
if((prev_rungstate_Timer_T1 == 1) && (rungstate_Timer_T1 == 0)){
reg_Timer_T1=0; Timer_T1=0; run_Timer_T1=0;} //reset
prev_rungstate_Timer_T1 = rungstate_Timer_T1;
//end rung
//rung at 5
W = 1;
if(cont_R2_NO == 0){W = 0;}
if(cont_R5_NC == 0){W = 0;}
if(cont_R4_NC == 0){W = 0;}
output_LED = W;
//end rung
//output brnch connected to rung at 5
W = 1;
if(cont_R2_NO == 0){W = 0;}
if(cont_R5_NC == 0){W = 0;}
if(Timer_T1 == 0){W = 0;}
output_R4 = W;
//end rung
//StateUser
//connected to rung at 7
W = 1;
if(cont_R4_NO == 0){W = 0;}
rungstate_Timer_T2 = W;
if((prev_rungstate_Timer_T2 == 0) && (rungstate_Timer_T2 == 1)){
run_Timer_T2=1;}
if(run_Timer_T2 == 1){
reg_Timer_T2++;
if (reg_Timer_T2 == 65535) {reg_Timer_T2--;}//avoid overrun
if (setpoint_Timer_T2 <= reg_Timer_T2) {Timer_T2=1;}
}
if((prev_rungstate_Timer_T2 == 1) && (rungstate_Timer_T2 == 0)){
reg_Timer_T2=0; Timer_T2=0; run_Timer_T2=0;} //reset
prev_rungstate_Timer_T2 = rungstate_Timer_T2;
//end rung
//rung at 7
W = 1;
if(cont_R4_NO == 0){W = 0;}
if(Timer_T2 == 0){W = 0;}
output_R5 = W;
//end rung
//outputs:
if(output_LED == 0){PORTD &=~ (1<<5);}
else {PORTD |= (1<<5);}
}
}
}
copy paste seluruh coding dan paste ke dalam software Arduino IDE kosongan tanpa void setup dan void loop seperti dibawah ini:
Pastikan ikuti posisi Pin seperti pada gambar dibawah ini:
Tidak ada komentar:
Posting Komentar