안녕하세요 땜블리의 공작소에 땜블리 입니다.
라즈베리파이 피코 / 피코W 를 arduino IDE를 이용하여 듀얼코어 활용방법에 대해서 알아보겠습니다.
본 작성내용에서 확인 가능한 내용입니다.
1. rp2040 MCU 구조 및 핀맵
2. 라즈베리파이 피코 / 피코W 핀맵
3. arduino IDE를 이용한 피코보드 개발환경
4. 피코 / 피코W 보드를 이용한 듀얼코어 활용방법
먼저 라즈베리파이 피코의 메인 MCU인 rp2040과 라즈베리파이 피코 보드에 대해서 알아보겠습니다.
rp2040은 아래와 같은 내부 구조를 가지고 있습니다.
rp2040 datasheet 는 아래에서 확인이 가능합니다. :
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
다음은 블록도에 보이는 Bus Fabric입니다.
위 그림에서 보시는거와 같이 Cortex-M0+ Core0, Cortex-M0+ Core1 두개의 코어를 가지고 있습니다. 이는 코어 두 개의 코어가 동시에 동작을 가능하게 합니다. 또한 개별적으로 구동이 가능합니다.
아래 그림에서는 핀 아웃 및 핀 기능에 대한 설명입니다.
각 핀에 대한 설명입니다.
내부 USB드라이브를 이용하여 Full Speed와 LOW Speed 통신을 지원 한다고 합니다. 피코보드에서 USB를 이용하여 펌웨어를 다운로드 하듯이 SWCLK and SWDIO를 이용하여 디버그와 코드를 다운로드 할 수 있다고 합니다. 또한 gpio용 전원공급이 1.8V ~ 3.3V 라고 하네요.
라즈베리파이 피코에 내장되어있는 MCU RP2040의 구조와 핀맵은 위와 같은 구조로 이루어져 있습니다. 상단에 링크되어있는 데이터시트를 확인하여 내부 설계 주의사항등도 확인을 할 수 있습니다. 사용자 설계를 위해서는 데이터시트를 확인해야 합니다.
다음은 라즈베리파이 피코 와 피코W 의 핀 맵을 확인 하겠습니다.
라즈베리파이 피코는 아래와 같은 구성으로 이루져 있습니다.
현재 국내 KC인증을 획득하여 판매되는 모델은 1번 3번 모델입니다.
이 또한 핀 헤더 부착과 미부착으로 구분되어 판매가 되고 있습니다.
위 피코보드들을 연결하기 위해서 도킹보드들이 있으며 아래는 저희가 실습을 위하여 사용할 도킹 보드입니다.
라즈베리 파이 피코 도킹 보드 / 마이크로 파이썬 라즈베리 파이 피코 도킹 보드 : 포레스텍
[포레스텍] IoT에 관한 모든것 아두이노 라즈베리파이 시제품 제작 부품 및 센서 등등
smartstore.naver.com
라즈베리파이 피코 핀맵
라즈베리파이 피코W 핀맵
라즈베리파이 피코와 피코W보드의 핀맵은 모두 동일합니다.
다른점은 디버그 핀의 위치와 와이파이 모듈이 내장되어있다는 것입니다.
라즈베리파이 피코W에 내장된 와이파이 모듈은 와이파이+블루투스(BLE) 콤보모듈입니다.
현재 마이크로파이썬과 썻킷파이썬에서는 작성되는 시점에서 블루투스 구동이 안되는 것으로 알고 있습니다.
하지만 아두이노 IDE에서는 예제와 함께 구동되는 것을 확인 하였습니다.
라즈베리파이 피코W 보드에 내장된 통신모듈은 CYW43439 칩을 내장하고 있습니다.
아래는 라즈베리파이 홈페이지에서 발취하여 번역한 내용입니다.
추 후 지원을 한다고 되어있습니다. 위에서 언급 하였드시 현재 아두이노 IDE에서는 지원을 하고 있습니다. 참조하시기 바랍니다.
arduino IDE를 활용한 라즈베리파이 피코에서 듀얼코어 사용방법은 완전 간단한데 위에서 서론이 너무 길었네요.
죄송.........
듀얼코어 활용을 위한 피코보드 arduino IDE 개발환경을 준비 하겠습니다.
arduino IDE를 활용한 라즈베리파이 피코 또는 피코W 보드를 이용한 듀얼코어 사용실습을 위해서는 아두이노 IDE(사용버번은 1.8.19입니다.), 라즈베리파이 피코 또는 피코W, 베이직 트레이닝 보드(없어도 가능함.)입니다.
아두이노를 다운로드 한다. 현재 최신버전이 2.0.4입니다. 최신 버전도 좋은데 제가 화면에 익숙하지 않아서 1.8.19버전으로 확인을 합니다.
arduino.cc에 접속하시면 아래 화면이 나옵니다.
Arduino - Home
www.arduino.cc
아래 보시된 부분을 클릭합니다.(SOFTWARE)
그럼 아래와 같이 현재 가장 최신버전의 아두이노 IDE(2.0.4)를 소개 합니다.
마우스를 이용해서 아래로 스크롤을 하면 우측 그림과 같이 Legacy IDE(1.8.X) 아래에 Arduino IDE 1.8.19가있습니다.
여기에서 원하는 OS와 방식으로 다운로드하여 설치를 진행합니다.
우측의 “Windows Zip file“ 을 클릭하여 사용자 PC에 저장하고 압축을 해제 하여
바로 실행 하시면 됩니다. 또는 PC에 바로 설치가 이루어지는 방법을 선택 하시면 됩니다.
설치하시기 어려우시면 아두이노 IDE 설치하시는 방법은 아래 링크에서 확인이 가능하십니다.
피코보드 준비
피코보드는 저는 두 가지를 보유 하고 있습니다. 실습에서는 피코W를 기준으로 진행하겠습니다. 진행 방법은 피코나 피코W나 동일합니다. 피코 보드를 구동하기 위해서 위에서 말씀드린 피코 도킹보드 / 도킹보드와 피코보드를 연결한 상태입니다.
구동 실습을 위해서 사용될 베이직트레이닝보드입니다. 베이직 트레이닝 보드는 준비를 안하셔도 되고 준비를 하셔도 됩니다.
도킹보드와 베이직트레이닝보드의 핀맵과 사용법은 아래에 링크되어 있습니다. 참조하세요.
이제 arduinoIDE를 실행 합니다.
실행 후에 우측 사진과 같이 IDE의
툴 => 보드
를 보면 RP2040이 없는 것을 확인 할 수 있습니다.
이제 라즈베리파이피코를 아두이노IDE에서 사용할 수 있도록 환경설정을 진행합니다.
파일 => 환경설정 => 체크 클릭 => 아래 환경설정 URL 삽입 => 확인
URL은 아래 사이크 주소를 복사하여 붙여넣기 하시면 됩니다.
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
환경설정이 완료 되었으면 arduinoIDE를 종료했다 다시 실행을 합니다.
그럼 아래와 같이 확인을 할 수 있습니다.
여기서 피코보드는 “Raspberry Pi Pico” 피코W보드는 “Raspberry Pi Pico W”를 선택 하시면 됩니다.
그럼 준비는 완료 되었습니다.
이제 환경설정과 피코보드의 연결이 모두 정상적으로 구동을 하는지 확인해 보겠습니다.
먼저 피코보드의 “bootBotton” 누른상태에서 “reset botton”을 눌러 줍니다.
그럼
파일탐색기의 => 내 PC => RPI-RP2라는 드라이브 생성이 됩니다.
그리고
arduinoIDE를 실행 =>
아래와 같이 실행 => 툴 => 포트 => UF2 Board 실행
아래와 같이 업로드 버튼 체크 항목을 클릭 합니다.
그럼 피코보드에 내장되어 있는 LED가 1초 간격으로 ON/OFF를 반복합니다.
이렇게 진행이 되셨다면 설정이 완료되었습니다.
(툴 항목에 있는 많은 설정들은 기본으로 두고 진행을 하였습니다.)
(업로드하는 시간이 엄청길다는거 잊지 마세요. 혹시나 예전에 아두이노 프로젝트를 해보신분이라면 아주 지겨울 겁니다. 아주 오래전 이야기입니다.)
이제 듀얼코어 예제를 확인해보겠습니다.
듀얼코어 예제는 아래와 같이 설정이 가능합니다.
먼저 추가로 한 가지 더 설정을 합니다.
USB 커넥터를 완전 제거 후 다시 연결을 합니다.
그리고 앞에서 말씀 드린 순서대로
툴 => 포트 => 피코보드가 연결된 COM포트를 설정합니다.
처음에는 UF2 board라 표시가 되었으나 업로드를 하면서 자동으로 COM포트가 설정이 되었습니다.
이제 모든 arduino IDE를 활용한 예제는 다운로드 전에 포트가 정확한지 확인 하시고 진행 하시면 됩니다.
그럼 다시 본론으로 돌아와서
파일 => 예제 => rp2040 => multicore를 실행하여 업로드 합니다.
그럼 아래와 같은 결과가 출력이 됩니다.
이게 뭐? 라는 결과가 나오겠지요. 일단 기본예제 소스에 대해서 간략히 설명 드리고 듀얼코어의 활용을 위한 예제로 넘어 가겠습니다.
아두이노는 하나의 setup() / 하나의 loop() 로 이루어져 있습니다.
하지만 아래 예제소스를 보시면 알겠지만 추가적으로 setup1() / loop1() 이 있습니다.
이는 위에서 언급드린 rp2040의 내부에 코어가 core0 / core1로 두 개의 코어를 가지고 있어서 서로 동시에 제어가 가능하다는 이야기입니다.
// The normal, core0 setup
void setup() { //전원 인가시 한 번만 실행
Serial.begin(115200); // 시리얼 통신 속도를 115200으로 설정
delay(5000); // 최초 전원 인가시에 5초 대기
}
void loop() { // 무한루프 구간으로 연속 실행이 됩니다.
Serial.printf("C0: Blue leader standing by...\n");
// 시리얼 포트로 C0: Blue leader standing by... 출력
delay(1000); //1초 간격으로 출력
}
// Running on core1
void setup1() { //전원 인가시 한 번만 실행
delay(5000); // 최초 전원인가시에 5초 대기
Serial.printf("C1: Red leader standing by...\n");
// 시리얼 포트로 C1: Red leader standing by... 출력
}
void loop1() { // 무한루프 구간으로 연속 실행이 됩니다.
Serial.printf("C1: Stay on target...\n");
// 시리얼 포트로 C1: Stay on target... 출력
delay(500); //0.5초 간격으로 출력
}
즉, 무슨말이냐 하면 최초 전원 인가시에 실행이 되는 setup()/setup1()을 먼저 실행 이는 5초 후에
C1: Red leader standing by... 출력
그 다음 core0의 무한루프 loop() 에 있는
C0: Blue leader standing by... 출력
1초 대기
C1: Stay on target... 출력
0.5초 대기
C1: Stay on target... 출력
0.5초 대기
C0: Blue leader standing by... 출력
1초 대기
..........
계속 무한루프가 돕니다.
설명하는 져도 어떻게 말씀드려야 할지 모르겠네요.
그럼 좀 더 명확히 혹시 WS2812라는 풀 컬러 LED를 아시나요? 이 풀 컬러 LED는 통신을 이용하여 색상을 변경합니다.
근데 잘 아시는거와 같이 프로그램은 순차적으로 이동을 합니다. 무한루프에서 컬러를 표현하고 있을 때 표현하는 함수가 종료되기 전에는 다음 동작을 수행 하지 않습니다.
만약 풀컬러 LED가 계속 실행 중이고 ADC가변저항의 데이터를 수집 하고 싶을 때 어떻게 해야 될까요?
예제 실험을 하기 위해서는 라이브러리를 설치해야 합니다. 설치되는 라이브러리는 WS2812를 이용하기 위한 “neopixel“입니다.
설치 방법은 아래와 같습니다.
위와 같은 경로를 통하여 라이브러리 관리를 실행 합니다.
설치를 클릭하면 adafruit........ all 설치를 선택하시면 됩니다.
이제 진행해 보겠습니다.
하나의 코어에서는 아래와 같은 동작을 구성 할 수 있습니다.
아래 펌웨어는 하나의 코어를 사용하여 순차 동작하는 구조를 구현했습니다.
펌웨어 개발하시는 분들이 이렇게 개발은 하시지 않겠지만.
이런 식의 기능을 구현 하고자 할 때는 실시간 데이터를 받기가 어렵습니다.
예제를 활용하여 아래와 같이 업로드 하였습니다.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define LED_PIN 13
#define LED_COUNT 4
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void rainbow(int wait) {
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
strip.rainbow(firstPixelHue);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// The normal, core0 setup
void setup() {
Serial.begin(115200);
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
delay(5000);
}
void loop() {
Serial.printf("Core0 loop()\n");
rainbow(10);
colorWipe(strip.Color(0, 0, 0), 1);
Serial.printf("Core0 ADC : %d \n\n",analogRead(A0));
//Serial.println(analogRead(A0));
delay(5000);
}
동작 결과입니다.
직접 업로드 하여 테스트 진행해 보세요.
동작은 WS2812를 레인보우 구동을 하면서 VR을 이용하여 ADC데이터를 읽어오는 동작입니다.
예제를 실행해 보시면 가변저항 값을 변경하여도 수정된 데이터는 레인보우 동작이 완료 된 후 측정된 ADC 데이터만 출력이 됩니다.
그럼 듀얼코어를 이용하여 레인보우 동작 중 가변저항 데이터를 받아오는 결과를 확인 하겠습니다.
아래는 듀얼코어를 이용하여 작성된 소스입니다.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define LED_PIN 13
#define LED_COUNT 4
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void rainbow(int wait) {
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
strip.rainbow(firstPixelHue);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// The normal, core0 setup
void setup() {
Serial.begin(115200);
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
delay(5000);
}
void loop() {
Serial.printf("Core0 loop()\n");
rainbow(10);
colorWipe(strip.Color(0, 0, 0), 1);
Serial.printf("Core0 rainbow OFF\n",analogRead(A0));
//Serial.println(analogRead(A0));
delay(1000);
}
// Running on core1
void setup1() {
delay(5000);
//Serial.printf("Core1 setup1()...\n");
}
void loop1() {
Serial.printf("Core1 loop1()...\n");
Serial.printf("Core1 ADC : %d \n\n",analogRead(A0));
delay(100);
}
결과 데이터입니다.
지금까지 arduino IDE 듀얼코어 활용에 대해서 정리를 해보았습니다.
내용중에 혹시 잘못된부분들이 있으면 알려주세요. 감사히 가르침 받고 수정토록 하겠습니다.
수고하세요.
댓글