0. 개요
OpenPLC 아두이노의 Modbus 값을 4 Digits 7 segment와 LED에 표시하자.
1. 연결
"[아우이노] 74HC595와 4 Digit 7 Segment" 연결에 OpenPLC 아두이노를 추가하고 시리얼 연결을 한다.
https://it-technician.tistory.com/20
[아두이노] 74HC595와 4 Digit 7 Segment
1. 4 Digit 7 Segment 1개 배선 Arduino 74HC595 4 digit 7 segment 1 (Q1) 7 (B segment) 2 (Q2) 4 (C segment) 3 (Q3) 2 (D segment) 4 (Q4) 1 (E segment) 5 (Q5) 10 (F segment) 6 (Q6) 5 (G segment) 7 (Q7) 3 (DP segment) GND 8 (GND) 9 (Q7') VCC 10 (MR) D10 11 (
it-technician.tistory.com
OpenPLC 아두이노 핀 | 일반 아두이노 핀 |
1 (TX) | 7 |
0 (RX) | 8 |
GND | GND |
2. OpenPLC 아두이노 Modbus 설정 및 프로그램
"[OpenPLC] Modbus 아두이노 통신"을 참고한다.
https://it-technician.tistory.com/21
3. 일반 아두이노 프로그래밍
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
ModbusMaster node;
SoftwareSerial mySerial(3, 4); // RX, TX
//a,b,c,d,e,f,g 상태값
byte segValue[11] = {
0b11111100, //0
0b01100000, //1
0b11011010, //2
0b11110010, //3
0b01100110, //4
0b10110110, //5
0b10111110, //6
0b11100000, //7
0b11111110, //8
0b11110110, //9
0b00000000, //10
};
int bitIndex = 0;
bool isButton1Pressed = false;
bool isButton2Pressed = false;
byte digitPin[4] = { 2, 5, 6, 13 }; //segment 위치 핀
int dataPin = 9; //DS Pin
int clockPin = 10; //SH_CP Pin
int latchPin = 11; //ST_CP Pin
int bitPin = 12;
int button1Pin = 7;
int button2Pin = 8;
int mode = 0;
/*
d[0][0] : 첫 번째 7 Segment 1 자리 숫자
d[0][1] : 첫 번째 7 Segment 10 자리 숫자
d[0][2] : 첫 번째 7 Segment 100 자리 숫자
d[0][3] : 첫 번째 7 Segment 1000 자리 숫자
d[1][0] : 두 번째 7 Segment 1 자리 숫자
d[1][1] : 두 번째 7 Segment 10 자리 숫자
d[1][2] : 두 번째 7 Segment 100 자리 숫자
d[1][3] : 두 번째 7 Segment 1000 자리 숫자
*/
int d[2][4] = {{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }};
void setup()
{
mySerial.begin(57600);
node.begin(1, mySerial);
for (int j = 0; j < 4; j++)
{
pinMode(digitPin[j], OUTPUT);
digitalWrite(digitPin[j], HIGH);
}
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(bitPin, OUTPUT);
pinMode(button1Pin, INPUT);
pinMode(button2Pin, INPUT);
}
uint16_t data[9];
byte coils = 0;
byte contacts = 0;
byte bits = 0;
int contacts5 = 0;
int currentModbus = 0;
void loop()
{
static uint32_t i;
uint8_t j, result;
uint16_t newValue = millis() / 1000;
if(newValue != data[0]) {
node.setTransmitBuffer(0, newValue);
result = node.writeMultipleRegisters(0, 1);
}
if(digitalRead(button1Pin) == HIGH)
{
if(isButton1Pressed == false)
{
isButton1Pressed = true;
if(mode == 3)
mode = 0;
else
mode++;
}
}
else
{
if(isButton1Pressed == true)
{
isButton1Pressed = false;
}
}
switch(mode)
{
case 0:
setNumber(data[0], d[0]);
break;
case 1:
setNumber(data[1], d[0]);
break;
case 2:
setNumber(data[2], d[0]);
break;
case 3:
setNumber(-1, d[0]);
break;
}
setNumber(mode, d[1]); //두 번째 7 Segment 출력값은 mode 값이다.
segOutput(3, bits, d[0][0], d[1][0], 0); //1의 자리
segOutput(2, bits, d[0][1], d[1][1], 0); //10의 자리
segOutput(1, bits, d[0][2], d[1][2], 0); //100의 자리
segOutput(0, bits, d[0][3], d[1][3], 0); //1000의 자리
digitalWrite(bitPin, contacts5);
}
void setNumber(long number, int* dArray)
{
if (number >= 0)
dArray[0] = number % 10; //1의 자리
else
dArray[0] = 10;
if (number >= 10)
dArray[1] = (number / 10) % 10; //10의 자리
else
dArray[1] = 10;
if (number >= 100)
dArray[2] = (number / 100) % 10; //100의 자리
else
dArray[2] = 10;
if (number >= 1000)
dArray[3] = (number / 1000) % 10; //1000의 자리
else
dArray[3] = 10;
}
//LED 초기화
void segClear()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, 0);
shiftOut(dataPin, clockPin, LSBFIRST, 0);
shiftOut(dataPin, clockPin, LSBFIRST, 0);
digitalWrite(latchPin, HIGH);
}
//LED 출력
void segOutput(int d, byte bitValue, int Number1, int Number2, int dp)
{
segClear();
digitalWrite(digitPin[d], LOW);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, bitValue);
shiftOut(dataPin, clockPin, LSBFIRST, segValue[Number1]);
shiftOut(dataPin, clockPin, LSBFIRST, segValue[Number2]);
digitalWrite(latchPin, HIGH);
readModbus();
digitalWrite(digitPin[d], HIGH);
}
void readModbus()
{
uint8_t result;
if(currentModbus++ > 10)
{
currentModbus = 0;
result = node.readHoldingRegisters(0, 1);
if (result == node.ku8MBSuccess)
{
for (int j = 0; j < 1; j++)
{
data[j] = node.getResponseBuffer(j);
}
}
result = node.readCoils(0, 8);
if (result == node.ku8MBSuccess)
{
coils = node.getResponseBuffer(0) & 0b00001111;
}
result = node.readDiscreteInputs(0, 8);
if (result == node.ku8MBSuccess)
{
contacts = node.getResponseBuffer(0);
if(contacts & 0b00010000)
contacts5 = 1;
else
contacts5 = 0;
contacts = contacts & 0b00001111;
contacts = contacts << 4;
}
bits = contacts | coils;
}
else
{
delayMicroseconds(1000);
}
}
프로그램을 아두이노에 업로드한다.
4. 실행
프로그램을 실행하면 7 Segment가 깜빡인다.
깜빡임을 없애려면 ESP32나 라즈베리파이에서 아두이노를 동작시키면서 멀티 쓰레드를 고려해 봐야 한다.
'IOT > PLC' 카테고리의 다른 글
[OpenPLC] KITS ESP32 EDU 디바이스에서 Blink 예제 실행 (0) | 2024.12.13 |
---|---|
[OpenPLC] ESP32에서 Blink 예제 실행 (0) | 2024.12.07 |
[OpenPLC] Modbus 아두이노 통신 (1) | 2024.01.05 |
[XGemPro] dotNet6.0 실행시 dll오류 (0) | 2023.12.26 |
[OpenPLC] 아두이노 우노 PLC 예제 (0) | 2023.11.17 |