이번에 Jetson Nano와 아두이노 간 I2C 통신을 해보러고 한다.
이유는 현재 내가 구현한 기구가 Jetson Nano와 아두이노가 시리얼 통신으로 데이터를 주고 받기 때문이다.
시리얼 통신은 고속이지만 현재 나는 하나의 젯슨 나노에서 5개정도의 아두이노를 다루고 있고, 이는 USB 포트 부족뿐 아니라 아두이노에 전원 공급이 USB로는 5V를 주기 때문에 DC 잭으로 주어 안정적인 시스템을 구축하고 싶기 때문이다.
개발 환경
- 아두이노 메가 2560
- 젯슨나노 B01 4GB
- 우분투 20.04
먼저 간단한거 먼저 시작해보자!
Jetson Nano를 Master, Arduino를 Slave로 설정하자!
일단 아두이노를 Slave로 만들어주자
#include <Wire.h>
#define LED 13
// Slave address
#define SLAVE_ADDRESS 0x57
// Register address
#define WRITE_REGISTER 0x01
#define READ_REGISTER 0x02
// LED control
#define LED_ON 0xAC
#define LED_OFF 0x1F
bool ledState = false;
void setup() {
pinMode(LED, OUTPUT);
Wire.begin(SLAVE_ADDRESS);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
}
void loop() {
// Do any other tasks here if needed
delay(100);
}
void receiveEvent() {
int registerAddress = Wire.read();
if (registerAddress == WRITE_REGISTER) {
int value = Wire.read();
if (value == LED_ON){
digitalWrite(LED, HIGH);
ledState = true;
}
else if (value == LED_OFF){
digitalWrite(LED, LOW);
ledState = false;
}
}
}
void requestEvent() {
Wire.write(ledState ? LED_ON : LED_OFF);
}
나는 Arduino Mage2560에 내장된 LED를 사용하였다.
I2C를 사용할 때 아두이노는 풀업저항이 내장되어 있지만, 일반 다른 보드는 확인해보고 풀업저항이 내장되어있지 않을경우 10k옴 정도를 달아주면 된다. (보드마다 다름)
먼저 아두이노의 슬레이브 주소값을 지정해준다. (나는 0x57로 했음)
또한 LED를 껏다 켰다 하게끔 간지나게 레지스터 주소마냥 정해주었다.
I2C의 함수들에 대한 설명은 아래 블로그를 참고하라
https://blog.naver.com/dkwltmdgus/220776103020
그리고 업로드를 진행한다.
다음으로 젯슨나노에서 아두이노가 인식되는지 확인한다.
젯슨나노에서 아두이노 I2C주소 확인하기
아두이노와 젯슨나노를 I2C 연결한다.
* 그라운드 연결해주는거 잊지마세요
여기서 아두이노는 DC잭으로 연결해주었다.
젯슨나노의 pinout은 다음을 참고하라
https://jetsonhacks.com/nvidia-jetson-nano-j41-header-pinout/
연결 후 다음 명령어를 터미널에 입력해줘라
sudo i2cdetect -r -y 1
나는 젯슨나노 pin 3,5번에 연결했으므로 i2c 1번이기 때문에 명령어 맨 뒤에 1를 작성해주었다.
위에 아두이노 주소인 57번이 뜬것을 확인했으면 인식이 잘 되고 있는 것이다.
이제 젯슨나노에서 코드를 짜주자
젯슨나노에 아두이노 제어 코드 올리기
젯슨나노에 먼저 i2c라이브러리를 설치해주자
sudo apt-get install libi2c-dev
이후 아무 이름을 정해서 아래 코드를 실행해봐라
#include <iostream> // 표준 입력 및 출력을 위한 헤더. std::cout, std::cin을 사용하여 콘솔 입출력을 처리합니다.
#include <fcntl.h> // 파일 제어를 위한 헤더. open() 함수에 사용됩니다.
#include <unistd.h> // POSIX 운영 체제 API에 대한 정의를 포함하는 헤더. close(), sleep() 함수를 사용합니다.
#include <linux/i2c-dev.h> // I2C 장치를 제어하기 위한 정의를 포함하는 헤더. I2C 관련 상수와 구조체를 제공합니다.
#include <sys/ioctl.h> // 장치 제어를 위한 헤더. ioctl() 함수를 사용하여 I2C 슬레이브 주소 설정에 사용됩니다.
#include <signal.h> // 시그널 처리를 위한 헤더. Ctrl+C와 같은 인터럽트를 처리하기 위해 사용됩니다.
#include <cstring> // 문자열 관련 함수들에 대한 정의를 포함하는 헤더. 필요 시 문자열 비교 등에 사용될 수 있습니다.
#define I2C_DEVICE "/dev/i2c-1" // Jetson Nano의 I2C 포트
#define SLAVE_ADDRESS 0x57 // 아두이노의 I2C 주소
#define WRITE_REGISTER 0x01 // LED 제어를 위한 레지스터 주소
#define LED_ON 0xAC // LED 켜기 명령
#define LED_OFF 0x1F // LED 끄기 명령
int file; // I2C 파일 디스크립터
// I2C 장치 열기
int openI2CDevice() {
int f = open(I2C_DEVICE, O_RDWR);
if (f < 0) {
std::cerr << "I2C 장치를 열 수 없습니다." << std::endl;
return -1;
}
// 슬레이브 주소 설정
if (ioctl(f, I2C_SLAVE, SLAVE_ADDRESS) < 0) {
std::cerr << "슬레이브 주소를 설정할 수 없습니다." << std::endl;
close(f);
return -1;
}
return f;
}
// LED 제어 함수
void controlLED(bool turnOn) {
unsigned char buffer[2];
buffer[0] = WRITE_REGISTER;
buffer[1] = turnOn ? LED_ON : LED_OFF;
if (write(file, buffer, 2) != 2) {
std::cerr << "데이터 전송에 실패했습니다." << std::endl;
} else {
std::cout << "LED " << (turnOn ? "켜기" : "끄기") << " 명령을 보냈습니다." << std::endl;
}
}
// 프로그램 종료 시 클린업
void cleanup(int signum) {
if (file >= 0) {
close(file);
}
std::cout << "\n프로그램을 종료합니다." << std::endl;
exit(0);
}
int main() {
// 시그널 핸들러 등록
signal(SIGINT, cleanup);
file = openI2CDevice();
if (file < 0) return -1;
std::string command;
while (true) {
std::cout << "명령어를 입력하세요 (ON/OFF): ";
std::cin >> command;
if (command == "ON") {
controlLED(true);
} else if (command == "OFF") {
controlLED(false);
} else {
std::cout << "유효하지 않은 명령어입니다. 'ON' 또는 'OFF'를 입력하세요." << std::endl;
}
}
cleanup(0); // 프로그램 종료 시 클린업 함수 호출
return 0;
}
코드를 작성한후 컴파일을 해준다.
g++ master_led_13.cpp -o master_led_13 -li2c
실행 파일 이름을 나는 master_led_13으로 하고 싶어서 저렇게 지었고, 다른 이름으로 해도 된다.
그리고 뒤에 -li2c는 i2c-lib를 링크하기 위한 옵션이다.
마지막으로 코드를 실행해주면 된다.
sudo ./master_led_13
이렇게 LED가 ON을 입력하면 켜지고, OFF을 입력하면 꺼진다.
아래 영상은 시연영상이다.
https://www.youtube.com/watch?v=rbFhOjCtU30
다음 포스터에서 2개의 아두이노 메가를 I2C통신으로 동작하는 것을 포스팅하겠다
'i2cProject_with_Jetson' 카테고리의 다른 글
i2c로 받은 데이터 server에 post - send data with Jetson nano (0) | 2024.11.11 |
---|---|
제품 변경 (아두이노 Due) (2) | 2024.11.07 |
Jetson Nano and Arduino Due (0) | 2024.11.05 |
Jetson Nano와 아두이노 간의 I2C 통신 3) (0) | 2024.11.05 |
Jetson Nano와 아두이노 간의 I2C 통신 2) (0) | 2024.11.03 |