[python] Python Arduino and serial communication

[python] pyserial error

enter image description here

[python] Python Arduino and serial communication

파이썬으로 아두이노와 시리얼통신 코드를 작성하는데 디버깅에 시간을 보낸 부분이 있어서 정리해 본다.
우선 파이썬으로 시리얼 통신하려면 pyserial 이라는 라이브러리를 설치해야 한다.
pip로 serial 또는 Serial 이라는 이름으로도 설치가 되는데 때문에 충돌이 발생한다.
이전 에러 포스팅 참조
https://maduinos.blogspot.com/2021/10/python-importerror-cannot-import-name.html
https://maduinos.blogspot.com/2023/05/python-attributeerror-module-serial-has.html

python으로 시리얼 통신을 통해 아두이노에 문자열을 보내고 다시 아두이노에서 에코 동작으로 문자열을 피드백 했는데 아두이노가 피드백이 바로 되지 않아서 디버깅에 시간을 보내 간단한 예제 코드로 정리해 본다.

결론만 얘기하면 시리얼통신을 아두이노와 시작하면 희한하게(?) 아두이노가 재부팅 되는 것으로 보인다.
때문에 파이썬에서 시리얼통신으로 바로 보내버리면 아두이노가 초기화(setup() 부분)이 끝나기도 전에 데이터를 보내게 되고 때문에 아두이노는 제대로된 데이터를 받지 못하는 문제가 생긴다.

해결방법은 파이썬에서 시리얼통신 시작 후 아두이노 부팅 끝날 때 까지 기다려주면 된다.
단순하게 지연시간으로 기다려도 되고 아두이노에서 스타트코드 받아도 되지만 시리얼통신이 아두이노를 리셋시킨다는 꺼림찍함 때문에 가능하면 유연성 높은 파이썬 코드에서 지연시간으로만 진행하면 좋을 듯 하다.

예제 코드

python code

import serial
import time

# 시리얼 포트와 보드레이트 설정
serial_port = 'COM29'  # 시리얼 포트 이름 (Windows의 경우)
baud_rate = 115200

try:
    # 시리얼 포트 열기
    ser = serial.Serial(serial_port, baud_rate)
    print(f"Serial port {serial_port} opened successfully.")
    time.sleep(2) # 이부분이 중요

    count = 0
    while True:
        # 문자열과 카운트 값 조합하여 보내기
        send_string = f"Count: {count}, Hello, Arduino!\n"
        ser.write(send_string.encode())
        print(f"Sent: {send_string.strip()}")  # 개행 문자를 제외한 문자열 출력
        
        # 카운트 증가
        count += 1

        # 아두이노로부터 문자열 읽기
        received_string = ser.readline().decode().strip()
        print(f"Received: {received_string}")

        # 1초 대기
        time.sleep(1)

except Exception as e:
    print(f"Error: {e}")
finally:
    # 시리얼 포트 닫기
    ser.close()
    print("Serial port closed.")

arduino code

#include <EEPROM.h>

const int MAX_STRING_LENGTH = 100;  // 최대 문자열 길이 설정
const int EEPROM_ADDRESS = 0;       // EEPROM 주소 설정

void setup() {
  Serial.begin(115200);  // 시리얼 통신 시작
  //Serial.println("Arduino started."); // 시작 메시지 출력
}

void loop() {
  if (Serial.available() > 0) {
    // 시리얼로부터 문자열 읽기
    String receivedString = Serial.readStringUntil('\n');

    // EEPROM에 데이터 저장
    writeDataToEEPROM(receivedString);
    printDataFromEEPROM();
  }
}

void writeDataToEEPROM(String newData) {
  // 문자열을 EEPROM에 저장
  for (int i = 0; i < newData.length(); ++i) {
    EEPROM.write(EEPROM_ADDRESS + i, newData[i]);
  }

  // 문자열 끝을 나타내는 널 문자('\0')를 저장
  EEPROM.write(EEPROM_ADDRESS + newData.length(), '\0');
}

void printDataFromEEPROM() {
  // EEPROM에서 데이터를 읽어옴
  String storedString;
  char ch;
  int address = EEPROM_ADDRESS;
  while ((ch = EEPROM.read(address)) != '\0') {
    storedString += ch;
    address++;
  }

  // 읽은 데이터를 시리얼로 출력
  Serial.println(storedString);
}

도움이 되셨다면 더 좋은 정보 공유를 위해 광고 클릭 부탁 드립니다 :)

댓글 쓰기

0 댓글