반응형

시리얼 통신을 모니터링해 보자.

 

hterm-windows.zip
2.14MB

 

 

 

 

 

 

 

※ 참고

HTerm

Arduino Hex 명령

CRC16 계산기

CRC 계산기 (시리얼 통신용 CRC는 'CRC-16/MODBUS'를 확인하면 된다)

 

반응형
Posted by J-sean
:
반응형

USB Serial Port를 사용해 보자.

 

 

AX781x0_MCS78x0_Win11_64bit_Driver_v3.22.2.0.zip
1.08MB

Windows 11(x64)

 

포트에 아무것도 연결하지 않은 상태에서 간단히 테스트할 수 있는 코드를 작성해 보자.

import serial
import time
import sys

serials = []
ports = ['COM2', 'COM7', 'COM8', 'COM9', 'COM10', 'COM11', 'COM12', 'COM13']
baudrate = 9600
databit = serial.EIGHTBITS
stopbit = serial.STOPBITS_ONE
parity = serial.PARITY_NONE

try:
    ser1 = serial.Serial(ports[0], baudrate, databit, parity, stopbit, timeout=1)
    ser2 = serial.Serial(ports[1], baudrate, databit, parity, stopbit, timeout=1)
    ser3 = serial.Serial(ports[2], baudrate, databit, parity, stopbit, timeout=1)
    ser4 = serial.Serial(ports[3], baudrate, databit, parity, stopbit, timeout=1)
    ser5 = serial.Serial(ports[4], baudrate, databit, parity, stopbit, timeout=1)
    ser6 = serial.Serial(ports[5], baudrate, databit, parity, stopbit, timeout=1)
    ser7 = serial.Serial(ports[6], baudrate, databit, parity, stopbit, timeout=1)
    ser8 = serial.Serial(ports[7], baudrate, databit, parity, stopbit, timeout=1)

    time.sleep(2)  # 장치 초기화 대기

    # 각 포트 연결 상태 확인
    for ser in [ser1, ser2, ser3, ser4, ser5, ser6, ser7, ser8]:
        if ser.is_open:
            print(f"{ser.port} 포트에 성공적으로 연결되었습니다.")
        else:
            print(f"{ser.port} 포트에 연결할 수 없습니다.")
            sys.exit(1)

    # 테스트 신호 5회 반복 전송
    for _ in range(5):
        for ser in [ser1, ser2, ser3, ser4, ser5, ser6, ser7, ser8]:
            test_signal = b"Test Signal\r\n"
            ser.write(test_signal)
            #print(f"{ser.port} 포트에 데이터 전송 완료: {test_signal}")
            time.sleep(0.2)

    """
    # 수신 데이터 확인 (응답이 있을 경우 출력)
    time.sleep(0.5)
    for ser in [ser1, ser2, ser3, ser4, ser5, ser6, ser7, ser8]:
        if ser.in_waiting > 0:
            response = ser.readline()
            print(f"{ser.port} 포트에서 수신된 데이터: {response}")
    """

    # 연결 종료
    for ser in [ser1, ser2, ser3, ser4, ser5, ser6, ser7, ser8]:
        ser.close()
        print(f"{ser.port} 포트를 안전하게 닫았습니다.")

except serial.SerialException as e:
    print(f"시리얼 포트 오류: {e}")
    
except Exception as e:
    print(f"오류 발생: {e}")

 

Tx LED가 순서대로 깜빡거린다.

 

 

이번엔 FIS 센서를 연결하고 데이터를 수신해 보자.

 

2026.05.15 - [Raspberry Pi & Arduino] - [Arduino] FIS Low concentration solvent gas sensor module

 

FIS 센서는 TTL 시그널을 사용하므로 RS232 - TTL 컨버터가 필요하다.

 

RS232 - TTL Converter

 

FIS Sensor RS232 - TTL Converter Power
1 VDD VCC VCC(5V)
2 VSS(GND) GND GND
6 SERIAL TXD  
7 RST   VCC(5V)

 

※ 주의

FIS Sensor의 6번(SERIAL) 핀은 Converter의 TXD에 연결해야 한다. RXD에 연결하면 안 된다.

센서에서 데이터가 계속 생성되도록 7번(RST) 핀은 VCC에 연결한다.

 

import serial
import time
import sys

try:
    serialPort = serial.Serial('COM2', 9600, 8, 'N', 1, timeout=1)
    # 시리얼 통신 설정. COM3 포트, 9600 보드레이트, 8 데이터 비트, 패리티 없음, 1 스톱 비트, 타임아웃 1초.
    time.sleep(1)  # 시리얼 연결이 초기화될 때까지 대기

except Exception as e:
    print("Serial error: ", e)
    sys.exit(0)

try:
    while (serialPort.readable()): # 시리얼 포트가 읽을 수 있는 상태인지 확인.
        if (serialPort.in_waiting > 0): # 시리얼 버퍼에 대기 중인 데이터가 있는지 확인.
            print(serialPort.readline().decode("utf-8", errors="ignore"), end="")
            # readline() 메서드를 사용하여 시리얼 포트에서 한 줄씩 데이터를 읽고 UTF-8로 디코딩하여 출력.
            # 오류가 발생할 경우 무시하도록 설정.
        else:
            print("No data waiting in the serial buffer.")

        time.sleep(0.2)

except KeyboardInterrupt:
    print("\n[알림] Ctrl+C 입력 감지. 프로그램을 종료합니다.")

finally:
    if 'serialPort' in locals() and serialPort.is_open:
        # locals() 함수를 사용하여 serialPort 변수가 정의되어 있는지 확인하고, 시리얼 포트가 열려 있는지 확인.
        serialPort.close()
        print("시리얼 포트가 안전하게 닫혔습니다.")

 

H0196에 알코올을 감지했다.

 

 

※ 참고

드라이버 다운로드 및 설치방법

 

반응형
Posted by J-sean
:
반응형

사용 중인 시리얼 포트를 확인해 보자.

 

장치관리자에서 확인해 보면 3개의 포트가 사용 중이다.

 

콘솔창에서 mode 명령어로 간단히 확인할 수 있다.

 

 

C++, CreateFile 예제

#include <windows.h>
#include <iostream>
#include <string>

int main() {
	std::cout << "Available COM Ports: \n";

	for (int i = 1; i < 256; ++i) {
		std::string portName = "\\\\.\\COM" + std::to_string(i);
		// \\.\com (코드 작성 시 이스케이프 문자를 적용한 \\\\.\\com)는 Windows 운영체제에서 직렬 포트(Serial Port)나 병렬 포트(LPT) 같은 하드웨어 장치에 직접 접근하기 위한 경로 형식이다.
		// 이 경로는 일반적으로 COM 포트에 접근할 때 사용된다. 예를 들어, COM1 포트에 접근하려면 "\\\\.\\COM1"과 같은 형식으로 경로를 지정한다.
		// 이 방식은 Windows에서 하드웨어 장치와 통신하기 위해 사용되는 표준적인 방법 중 하나이다.
		// 포트 번호가 10 이하인 경우에는 "COM1", "COM2"와 같이 간단히 사용할 수 있지만, 포트 번호가 10 이상인 경우에는 "\\\\.\\COM10"과 같이 전체 경로를 사용해야 한다.

		HANDLE hComm = CreateFileA(
			portName.c_str(), // 만들거나 열 파일 또는 디바이스의 이름.
			GENERIC_READ | GENERIC_WRITE, //파일 또는 디바이스에 대한 요청된 액세스이며 읽기, 쓰기, 둘 다 또는 0으로 요약할 수 있다.
			NULL, // 파일 또는 디바이스의 요청된 공유 모드.
			NULL, // 보안 속성에 대한 포인터.
			OPEN_EXISTING, // 파일이 존재하는 경우에만 열고, 그렇지 않으면 실패.
			NULL, // 파일 또는 디바이스에 대한 플래그 및 속성.
			NULL); // 템플릿 파일 핸들 또는 디바이스 핸들로 사용할 수 있는 유효한 핸들. 이 매개변수는 CreateFile이 새 파일을 만들 때만 사용. 이 매개변수는 일반적으로 NULL로 설정.

		if (hComm != INVALID_HANDLE_VALUE) {
			std::cout << "-> COM" << i << " is available.\n";
			CloseHandle(hComm);
		}
	}

	return 0;
}

 

 

C, QueryDosDevice 예제

#include <windows.h>
#include <stdio.h>

int main() {
	char deviceName[256];
	char comPort[16];
	char openPortName[32];

	printf("--- 사용 가능한 COM 포트 목록 ---\n");

	// COM1부터 COM256까지 가능한 포트 번호를 순회하며 확인
	for (int i = 1; i < 256; i++) {
		sprintf_s(comPort, sizeof(comPort), "COM%d", i);

		// QueryDosDevice를 이용해 해당 포트가 존재하는지 확인
		DWORD result = QueryDosDeviceA(comPort, deviceName, sizeof(deviceName));
		// CreateFile 함수로 포트를 열 때는 \\\\.\\COM10 형식을 써야 하지만, QueryDosDevice로
		// 시스템에 등록된 장치 이름을 조회할 때는 접두사(\\.\)를 붙이면 안된다.
		// 이 함수는 순수한 커널 장치 이름(예: COM1, COM10)만 인자로 받도록 설계되어 있다.

		if (result != 0) { // result는 deviceName에 복사된 문자열의 길이.
			// 실제 포트를 열거나 사용할 때는 "\\\\.\\" 접두사를 붙여서 출력 및 활용한다.
			sprintf_s(openPortName, sizeof(openPortName), "\\\\.\\%s", comPort);
			printf("%s 연결됨 (장치명: %s)\n", openPortName, deviceName);
		}
	}

	return 0;
}

 

 

어떤 프로그램이 시리얼 포트를 사용 중인지 조사할 때 File Handle의 이름으로 위 그림의 해당 장치명을 지정해야 찾을 수 있다.

Process Explorer - Find - Find Handle or DLL... 클릭 - Handle or DLL substring에 장치명을 입력하고 Search 클릭

시리얼 포트가 사용중이라면 사용하고 있는 프로세스가 표시된다. python.exe가 사용 중이다.

 

장치관리자에서는 포트 - 속성 - 자세히 - 서비스 - 값에 표시된 이름을 이용하자.

 

 

C# 예제

using System;
using System.IO.Ports;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // PC에서 사용 가능한 모든 시리얼 포트 배열 가져오기
            string[] ports = SerialPort.GetPortNames();

            Console.WriteLine("사용 가능한 시리얼 포트:");
            foreach (string port in ports)
            {
                Console.WriteLine(port);
            }

            // GetPortNames()는 PC에 잡혀있는 모든 포트를 반환하므로, 특정 포트가 현재 다른 프로그램에서
            // 사용 중이거나 연결 가능한 상태인지 확인하려면 직접 Open()을 시도해 봐야 한다.
            Console.WriteLine(Environment.NewLine + "연결 가능한 시리얼 포트:");
            foreach (string port in ports)
            {
                using (SerialPort serialPort = new SerialPort(port))
                {
                    try
                    {
                        serialPort.Open();
                        Console.WriteLine($"{port} : 연결 가능 (사용 가능)");
                        serialPort.Close();
                    }
                    catch (UnauthorizedAccessException)
                    {
                        Console.WriteLine($"{port} : 접근 거부 (다른 프로그램에서 사용 중)");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"{port} : 오류 발생 - {ex.Message}");
                    }
                }
            }
        }
    }
}

 

 

다른 프로그램에서 사용중인 경우

 

Python, pyserial 예제

import serial.tools.list_ports

# 사용 가능한 포트 리스트 가져오기
ports = serial.tools.list_ports.comports()

print("연결된 시리얼 포트 목록:")
print("-" * 30)
if ports:
    for port in ports:
        print(f"포트 이름: {port.device}")
        print(f"설명: {port.description}")
        print(f"하드웨어 ID: {port.hwid}")
        print("-" * 30)
else:
    print("사용 가능한 시리얼 포트가 없습니다.")

"""
# 각 포트에 대해 연결 가능 여부 확인
import serial

try:
    for port in ports:
        ser = serial.Serial(port.device)
        if ser.is_open:
            print(f"{port.device} : 연결 가능 (사용 가능)")
            ser.close()
        else:
            print(f"{port.device} : 연결 불가능 (사용 중)")

except serial.SerialException as e:
    print(f"시리얼 포트 확인 중 오류 발생: {e}")
"""

 

 

반응형
Posted by J-sean
:
반응형

USB to UART Converter를 사용해 시리얼 통신을 해 보자.

 

 

링크에서 드라이버를 다운로드받거나 아래 파일을 다운로드받고 설치한다.

CP210x_Windows_Drivers.zip
6.84MB

 

 

드라이버 설치 후 USB to UART Converter를 컴퓨터에 연결하면 정상적으로 포트에 잡힌다.

 

FIS Sensor를 연결하고 테스트해 보자.

FIS Sensor USB to UART Converter
1 VDD 5V
2 VSS(GND) GND
6 SERIAL RXD
7 RST 5V

 

센서 자체에서 시리얼 통신으로 데이터를 보내오기 때문에 아두이노 같은 컨트롤러가 필요 없다.

아래 파이썬 코드를 입력하고 실행한다.

import serial
import time
import sys

try:
    serialPort = serial.Serial('COM4', 9600, 8, 'N', 1, timeout=1)
    # 시리얼 통신 설정. COM4 포트, 9600 보드레이트, 8 데이터 비트, 패리티 없음, 1 스톱 비트, 타임아웃 1초.
    time.sleep(2)  # 시리얼 연결이 초기화될 때까지 대기

except Exception as e:
    print("Serial error: ", e)
    sys.exit(0)

while (serialPort.readable()): # 시리얼 포트가 읽을 수 있는 상태인지 확인.
    if (serialPort.in_waiting > 0): # 시리얼 버퍼에 대기 중인 데이터가 있는지 확인.
        print(serialPort.readline().decode("utf-8", errors="ignore"), end="")
        # readline() 메서드를 사용하여 시리얼 포트에서 한 줄씩 데이터를 읽고 UTF-8로 디코딩하여 출력.
        # 오류가 발생할 경우 무시하도록 설정.
    
    time.sleep(0.1)

serialPort.close()

 

 

반응형
Posted by J-sean
:

[RetroPie] Runcommand Script

Embedded 2026. 5. 20. 23:21 |
반응형

Runcommand Script는 게임이 실행되기 전과 후에 사용자 스크립트를 실행할 수 있다. 스크립트는 반드시 /opt/retropie/configs/all/에 존재해야 한다.

 

https://retropie.org.uk/docs/Runcommand/

 

Runcommand - RetroPie Docs

runcommand The runcommand is the script responsible to launch your emulators/games. This page shows the runcommand's configurations and features. Runcommand Launch Menu Each time you load a ROM there is an option to open what is called the Runcommand Launc

retropie.org.uk

 

runcommand-onstart.zip
0.00MB

 

 

※ 참고

Runcommand

모니터 회전&수평센서

 

반응형
Posted by J-sean
:

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

반응형

C#과 아두이노 시리얼 통신을 해 보자.

 

 

 

적외선 온도센서 GY-906을 아두이노에 연결한다.

 

VIN - 5V

GND - GND

SCL - A5

SDA - A4

 

#include <Adafruit_MLX90614.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  mlx.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Ambient Temp: ");
  Serial.println(mlx.readAmbientTempC());
  Serial.print("Object Temp: ");
  Serial.println(mlx.readObjectTempC());
  delay(1000);
}

아두이노에 위 코드를 업로드한다.

 

using System;
using System.Threading;
using System.IO.Ports;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            SerialPort serialPort = new SerialPort();

            try
            {
                serialPort.PortName = "COM3"; // 시리얼 포트 이름을 "COM3"으로 설정한다. 실제로 사용하려는 시리얼 포트 이름이다.
                serialPort.BaudRate = 9600; // 시리얼 통신의 전송 속도를 9600 보드로 설정한다. 이는 일반적으로 사용되는 보드레이트 중 하나이다.
                serialPort.DataBits = 8; // 8비트의 데이터 비트를 사용하여 데이터를 전송한다. 이는 일반적으로 가장 많이 사용되는 데이터 비트 설정이다.
                serialPort.StopBits = StopBits.One; // 1비트의 정지 비트를 사용하여 데이터 전송이 끝났음을 나타낸다.
                serialPort.Parity = Parity.None; // 패리티 비트를 사용하지 않는다. 데이터 전송에서 오류 검출을 위해 패리티 비트를 사용할 수 있지만, 여기서는 사용하지 않는다.

                Thread.Sleep(2000); // 시리얼 포트 설정이 완료된 후 잠시 대기하여 안정적으로 연결될 수 있도록 한다.
                serialPort.Open(); // 시리얼 포트를 연다. 이 단계에서 설정된 포트 이름과 통신 속도 등이 적용되어 시리얼 통신이 시작된다.
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }

            while (serialPort.IsOpen)
            {
                try
                {
                    string data = serialPort.ReadLine(); // 시리얼 포트에서 한 줄의 데이터를 읽어온다. 데이터가 줄 바꿈 문자로 끝날 때까지 읽는다.
                    Console.WriteLine(data);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                }

                Thread.Sleep(100);
            }
        }
    }
}

C# 코드를 입력하고 실행한다.

 

 

※ 참고

2026.05.15 - [Raspberry Pi & Arduino] - [Arduino] FIS Low concentration solvent gas sensor module

 

반응형
Posted by J-sean
:
반응형

 

Luckfox Pico Mini A
Luckfox Pico Plus

 

Luckfox Pico Mini A/B나 Plus 모델은 Rockchip RV1103 chip 기반의 저비용 리눅스 개발 보드다.

 

※ 기본 튜토리얼

Luckfox Tutorial

 

※ 참고 사이트

Build a Ubuntu Linux Server For Less Than $20

 

● Buildroot

ID: root

Password: luckfox

IP: 172.32.0.93

ex) ssh root@172.32.0.93

 

● Ubuntu

ID: pico

Password: luckfox

IP: 172.32.0.70

ex) ssh pico@172.32.0.70

 

Luckfox Pico Plus에 Buidroot를 설치하면 처음엔 잘 되지만 몇 번 로그인을 하고 나면 아래와 같은 메세지가 나타나면서 로그인이 되지 않는다.(2025-02-28)

kex_exchange_identification: read: Connection reset

Connection reset by 172.32.0.70 port 22

어떤 경우엔 처음 한 번만 네트워크 장치로 잡히고 다시 되지 않는 경우도 있다.

=> 한 컴퓨터에서 Luckfox Pico Mini 와 Plus를 바꿔가면서 계속 ssh 접속 테스트를 해서 그럴지도 모르겠다.

   C:\Users\sean\.ssh\known_hosts 파일이 꼬이는거 같다.

 

부트 이미지를 구울때 update.img는 제외한다.

 

Luckfox Pico Mini B/Plus는 SD카드로 부팅 시 SPI NAND Flash 메모리를 삭제해야 한다.

삭제하기 위해 컴퓨터에 연결 시, SD카드는 삽입 되어 있어도 되고 없어도 된다.

 

Luckfox Pico Plus는 이더넷 케이블 연결이 가능하므로 컴퓨터 연결 없이 전원만 공급하면 된다.

Luckfox Pico Mini A/B는 이더넷 케이블 연결이 불가능 하므로 컴퓨터에 연결하고 '제어판 - 네트워크 및 인터넷 - 네트워크 연결'에서 네트워크 장치로 잡히면, '속성 - 인터넷 프로토콜 버전 4(TCP/IPv4)'에서 IP 주소를 172.32.0.100 등으로 지정하고 접속한다.

 

 

 

반응형
Posted by J-sean
: