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("시리얼 포트가 안전하게 닫혔습니다.")
#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}")
"""
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()
#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);
}
}
}
}
=> 한 컴퓨터에서 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 등으로 지정하고 접속한다.