본문 바로가기

p5.js/p5.js

[2단계-2] 아두이노->p5.js 로 데이터(0~255) 송수신(가변저항)

반응형

 아두이노에서 가변저항, 조도센서, 초음파 센서 등의 센서값(0~255)를 전송하고 p5.js에서 이를 수신하여 제어하는 과정입니다.

 

=> 먼저 p5.js 에디터에서 index.html에서 <script>~</script> 뒤에 붙여넣기 한 후  저장한다.

<script src="https://unpkg.com/p5-webserial@0.1.1/build/p5.webserial.js"></script>

 

(1) 가변저항 값 숫자로 송수신하기

 

- 아두이노 회로

 

- 아두이노 소스

// 아두이노: 가변저항값 송신

#define VARIABLE_R A0

void setup() {
  pinMode(VARIABLE_R, INPUT);
  Serial.begin(9600);
}

void loop() {
  int value = analogRead(VARIABLE_R);
  value = map(value, 0, 1023, 0, 255);
  Serial.write(value);
  delay(30);    // 전송속도 지연
}

 

- p5.js 소스

// p5.js: 가변저항값 수신하여 표시

let port = new p5.WebSerial();
let value = 0;

function setup( ) {
  createCanvas(500, 200);
  port.getPorts();
  port.on('noport', makePortButton);
  port.on('portavailable', openPort);
  port.on('data', serialEvent);
}

function draw() {
  background(0);
  fill(255, 255, 0);
  textAlign(CENTER, CENTER);
  textSize(30);
  text("가변저항값: " + nf(value, 3), width/2, height/2);
}

// 수신값이 있으면 자동 호출
function serialEvent() {
  value = port.read();
}

function makePortButton() {
  let portButton = createButton('포트선택');
  portButton.mousePressed(choosePort);
  function choosePort() {
    port.requestPort();
  }
}

function openPort() {
  port.open().then(initiateSerial);
  function initiateSerial() {
    console.log('포트 오픈');
  }
}

 

- 결과

 

(2) 가변저항으로 원 이동하기

 

- p5.js 소스

// 가변저항값 수신하여 표시

let port = new p5.WebSerial();
let value = 0;

function setup( ) {
  createCanvas(500, 500);
  port.getPorts();
  port.on('noport', makePortButton);
  port.on('portavailable', openPort);
  port.on('data', serialEvent);
}

function draw() {
  background(0);
  fill(255, 255, 0);
  textSize(30);
  text('Value:' + nf(value, 3), 10,50);
  ellipse(value, height/2, 50,50);
  // ellipse(width/2, value, 50,50);
  // ellipse(value, value, 50,50);
  // ellipse(width/2, height/2, value,value);
}

function serialEvent() {
  value = port.read();
  value = int(map(value, 0, 255, 0, width));
}

function makePortButton() {
  let portButton = createButton('포트선택');
  portButton.mousePressed(choosePort);
  function choosePort() {
    port.requestPort();
  }
}

function openPort() {
  port.open().then(initiateSerial);
  function initiateSerial() {
    console.log('포트 오픈');
  }
}

 

(3) 가변저항으로 원 회전 운동하기

- p5.js 소스

// 가변저항값 수신하여 표시

let port = new p5.WebSerial();
let value = 0, degree=0;

function setup( ) {
  createCanvas(500, 500);
  port.getPorts();
  port.on('noport', makePortButton);
  port.on('portavailable', openPort);
  port.on('data', serialEvent);
}

function draw() {
  // background(0);
  let theta=radians(degree);
  let x = width/2 + value * cos(theta);
  let y = height/2 + value * sin(theta);
  fill(255, 255, 0);
  textSize(30);
  text('radius:' + nf(value, 3), 10,50);
  ellipse(x, y, 50,50);
  degree++;
}

function serialEvent() {
  value = port.read();
  value = int(map(value, 0, 255, 0, width/2));
}

function makePortButton() {
  let portButton = createButton('포트선택');
  portButton.mousePressed(choosePort);
  function choosePort() {
    port.requestPort();
  }
}

function openPort() {
  port.open().then(initiateSerial);
  function initiateSerial() {
    console.log('포트 오픈');
  }
}

 

- 결과

 

 

 

(4) 가변저항 2개 값 숫자로 송수신하기

- 아두이노 회로

  위의 회로도 참고, 가변저항1(VCC, A0, GND), 가번져항2(VCC, A1, GND)

 

- 아두이노 소스

// 아두이노: 가변저항값 2개 송신 1

#define VARIABLE_R1 A0
#define VARIABLE_R2 A1

void setup() {
  pinMode(VARIABLE_R1, INPUT);
  pinMode(VARIABLE_R2, INPUT);
  Serial.begin(9600);
}

void loop() {
  int value1 = analogRead(VARIABLE_R1);	// 가변저항값1 읽기
  int value2 = analogRead(VARIABLE_R2);	// 가변저항값2 읽기
  value1 = map(value1, 0, 1023, 0, 255);	// 1바이트(0∼255)로 값 변환
  value2 = map(value2, 0, 1023, 0, 255);	// 1바이트(0∼255)로 값 변환
  Serial.write('A');				// 동기신호 ‘A’를 송신
  Serial.write(value1);				// 가변저항1의 1바이트(0∼255) 전송
  Serial.write(value2);				// 가변저항2의 1바이트(0∼255) 전송
  delay(30);					// 전송속도 지연
}

 

- p5.js소스(좌우이동, 상하이동, 동시-상하좌우 이동)

// 가변저항값 수신하여 표시

let port = new p5.WebSerial();
let value = 0, degree=0;

function setup( ) {
  createCanvas(500, 500);
  port.getPorts();
  port.on('noport', makePortButton);
  port.on('portavailable', openPort);
  port.on('data', serialEvent);
}

function draw() {
  background(0);
  let theta=radians(degree);
  let x = width/2 + value * cos(theta);
  let y = height/2 + value * cos(theta);
  fill(255, 255, 0);
  textSize(30);
  text('radius:' + nf(value, 3), 10,50);
  ellipse(x, y, 50,50);
  degree++;
}

function serialEvent() {
  value = port.read();
  value = int(map(value, 0, 255, 0, width/2));
}

function makePortButton() {
  let portButton = createButton('포트선택');
  portButton.mousePressed(choosePort);
  function choosePort() {
    port.requestPort();
  }
}

function openPort() {
  port.open().then(initiateSerial);
  function initiateSerial() {
    console.log('포트 오픈');
  }
}

 

- 결과

 

 

- p5.js소스(원 색상 변경)

// p5.js: 가변저항값 2개 수신하여 원 이동 1

let port = new p5.WebSerial();		// 시리얼 통신을 위한 객체 생성
let value1 = 0, value2 = 0;

function setup() {
  createCanvas(500, 500);
  port.getPorts();			// 포트 사용 가능 여부 확인
  port.on('noport', makePortButton);	// 기존 선택한 포트가 없으면 makePortButton() 호출
  port.on('portavailable', openPort);	// 사용 가능한 포트가 있으면 openPort() 자동 호출
  // port.on('data', serialEvent);		// 수신값이 있으면 serialEvent() 자동 호출
}

function draw() {
  background(0, 10);			// 페이딩 효과 (투명도 10 부여)
  while (port.available() >= 3) {		// 수신값이 3바이트 이상일 때
    let signal = port.readChar();	// 수신값 읽기
    if (signal === 'A') {			// 수신값이 동기신호('A')일 때
      value1 = port.read();		// 가변저항1 값 읽기
      value2 = port.read();		// 가변저항2 값 읽기
      value1 = map(value1, 0, 255, 0, width);
      value2 = map(value2, 0, 255, 0, height);
    }  
  }
  noStroke();				// 외곽선 제거 (부드러운 페이딩 효과) 
  fill(value1, value2, 0); 
  ellipse(width/2, height/2, 300, 300);	// 가변저항값 두 개를 원의 x,y 좌표에 적용
}

// function serialEvent() {			// 시리얼 버퍼에 값이 들어오면 자동 호출
//   while (port.available() >= 3) {		// 수신값이 3바이트 이상일 때
//     let signal = port.readChar();	// 수신값 읽기
//     if (signal === 'A') {			// 수신값이 동기신호('A')일 때
//       value1 = port.read();		// 가변저항1 값 읽기
//       value2 = port.read();		// 가변저항2 값 읽기
//       value1 = map(value1, 0, 255, 0, width);
//       value2 = map(value2, 0, 255, 0, height);
//     }
//   }
// }

function makePortButton() {			// 포트 첫 연결 시 포트 선택 버튼 생성
  let portButton = createButton('포트 선택');	// 버튼 생성
  portButton.mousePressed(choosePort);	// 버튼 누르면 choosePort() 자동 호출
  function choosePort() {			// 콜백함수
    port.requestPort();				// 시리얼 포트 선택창 오픈
  }
}

function openPort() {				// 콜백함수
  port.open().then(initiateSerial);		// 포트를 오픈 후 initiateSerial() 자동 호출
  function initiateSerial() {			// 콜백함수
    console.log('포트 오픈');
  }
}

- 결과

(5) 가변저항 2개 값을 상-하위 바이트로 나누어 송수신하기

- 아두이노 소스

// 아두이노: 가변저항값 2개 송신 2

#define VARIABLE_R1 A0
#define VARIABLE_R2 A1

void setup() {
  pinMode(VARIABLE_R1, INPUT);
  pinMode(VARIABLE_R2, INPUT);
  Serial.begin(9600);
}

void loop() {
  int value1 = analogRead(VARIABLE_R1);	// 10비트값을 2바이트의 int형 변수에 저장
  int value2 = analogRead(VARIABLE_R2);	// 10비트값을 2바이트의 int형 변수에 저장

  Serial.write(0xff);     			// 동기신호(0xff) 송신
  int high_byte = (value1 & 0xff00) >> 8;	// 가변저항1의 상위 바이트 추출 후 저장 
  int low_byte = value1 & 0x00ff;		// 가변저항1의 하위 바이트 추출 후 저장 
  Serial.write(high_byte);			// 가변저항1의 상위 바이트 송신
  Serial.write(low_byte);			// 가변저항1의 하위 바이트 송신

  high_byte = (value2 & 0xff00) >> 8;		// 가변저항2의 상위 바이트 추출 후 저장 
  low_byte = value2 & 0x00ff;			// 가변저항2의 하위 바이트 추출 후 저장 
  Serial.write(high_byte);			// 가변저항2의 상위 바이트 송신
  Serial.write(low_byte);			// 가변저항2의 하위 바이트 송신
  delay(30);					// 전송속도 지연
}

 

- p5.js 소스(막대그래프 그리기)

// p5.js: 가변저항값 2개 수신하여 막대그래프 그리기

let port = new p5.WebSerial();		// 시리얼 통신을 위한 객체 생성
let value1 = 0, value2 = 0;

function setup() {
  createCanvas(500, 300);
  port.getPorts();			// 포트 사용 가능 여부 확인
  port.on('noport', makePortButton);	// 기존 선택한 포트가 없으면 makePortButton() 호출
  port.on('portavailable', openPort);	// 사용 가능한 포트가 있으면 openPort() 자동 호출
  port.on('data', serialEvent);		// 수신값이 있으면 serialEvent() 자동 호출
}

function draw() {
  background(0, 10);			// 페이딩 효과 (투명도 10 부여) 
  fill(255, 255, 0); 
  rect(100, height, 100, -value1);
  fill(0, 255, 0); 
  rect(300, height, 100, -value2);
  fill(255);
  textAlign(CENTER, CENTER);
  textSize(30);
  text(int(value1), 150, 280);
  text(int(value2), 350, 280);
}

function serialEvent() {			// 시리얼 버퍼에 값이 들어오면 자동 호출
  while (port.available() >= 5) {		// 수신값이 5바이트 이상일 때
    let signal = port.read();	// 수신값 읽기
    if (signal === 0xff) {			// 수신값이 동기신호(0xff)일 때
      let high_byte = port.read();		// 가변저항1 상위바이트  읽기
      let low_byte = port.read();		// 가변저항1 하위바이트  읽기
      let two_byte = (high_byte<<8) | low_byte;
      value1 = map(two_byte, 0, 1023, 0, height);

      high_byte = port.read();			// 가변저항2 상위바이트  읽기
      low_byte = port.read();			// 가변저항2 하위바이트  읽기
      two_byte = (high_byte<<8) | low_byte;
      value2 = map(two_byte, 0, 1023, 0, height);
    }
  }
}

function makePortButton() {			// 포트 첫 연결 시 포트 선택 버튼 생성
  let portButton = createButton('포트 선택');	// 버튼 생성
  portButton.mousePressed(choosePort);	// 버튼 누르면 choosePort() 자동 호출
  function choosePort() {			// 콜백함수
    port.requestPort();				// 시리얼 포트 선택창 오픈
  }
}

function openPort() {				// 콜백함수
  port.open().then(initiateSerial);		// 포트를 오픈 후 initiateSerial() 자동 호출
  function initiateSerial() {			// 콜백함수
    console.log('포트 오픈');
  }
}

 

 

- 결과

 

반응형