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나 라즈베리파이에서 아두이노를 동작시키면서 멀티 쓰레드를 고려해 봐야 한다.

+ Recent posts