BASIC4MCU | 질문게시판 | 아두이노 코드 합치기 문의 드립니다..!
페이지 정보
작성자 블람 작성일2020-06-21 22:32 조회9,527회 댓글3건본문
안녕하세요
아두이노 메가보드에 MPU6050, HC-06 (블루투스), 심장박동센서를 이용해
걸음수 측정 및 맥박을 체크하는 스마트 밴드를 만들어 보려고 합니다 ( 완성되면 어플과 블루투스 통신을 해 데이터를 보내려고 합니다.)
혼자 나름 시도를 해보았으나 진척이 없고 해결책을 알아보려 검색을 하다 우연히 이 사이트를 알게되어
전문가님에게 도움을 받을수 있을까 해서 질문 드려봅니다.
이쪽으로 진로를 바꿔 입문한지 얼마 안되 많이 부족합니다...
아래는 제가 시도했던 방법입니다..
1.retroband 오픈소스와 retroband 어플을 이용해 블루투스 통신으로 걸음수가 측정되는 것을 확인했습니다.
2.심박센서를 메가보드에 연결후 PulseSensorPlayground 의 Getting_BPM_to_Monitor 예제를 이용해 BPM이 정상 출력되는것을 확인했습니다.
3. 1번과 2번의 기능을 각각 정상출력되는것을 확인후 두가지 코드를 합치기 위해 다음과 같이 진행했습니다
3-1 . void setup() 윗부분
void setup()
void loop()
이렇게 세부분으로 나누어 BPM의 코드가 짧아 주석을 제거한 후 세부분에 맞게 나누어 각 부분 맨 밑부분에 추가 하였고 ,
Serial.begin(9600); 이 중복되어 하나를 삭제하였습니다.
메가보드에 각 센서들을 연결하고 기대를 하고 컴파일을 했으나 에러가 나와버리네요 ㅜㅜ..
이것이 제가 조합한 코드입니다.
#include <math.h>
#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(2, 3);
#define SENDING_INTERVAL 1000
#define SENSOR_READ_INTERVAL 50
unsigned long prevSensoredTime = 0;
unsigned long curSensoredTime = 0;
#define ACCEL_BUFFER_COUNT 125
byte aAccelBuffer[ACCEL_BUFFER_COUNT];
int iAccelIndex = 2;
#define MPU6050_ACCEL_XOUT_H 0x3B
#define MPU6050_PWR_MGMT_1 0x6B
#define MPU6050_PWR_MGMT_2 0x6C
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_I2C_ADDRESS 0x68
typedef union accel_t_gyro_union {
struct {
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;
struct {
int x_accel;
int y_accel;
int z_accel;
int temperature;
int x_gyro;
int y_gyro;
int z_gyro;
} value;
};
#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>
const int PulseWire = 0;
int Threshold = 550;
PulseSensorPlayground pulseSensor;
void setup() {
int error;
uint8_t c;
Serial.begin(9600);
Wire.begin();
BTSerial.begin(9600);
error = MPU6050_read(MPU6050_WHO_AM_I, &c, 1);
Serial.print(F("WHO_AM_I : "));
Serial.print(c, HEX);
Serial.print(F(", error = "));
Serial.println(error, DEC);
error = MPU6050_read(MPU6050_PWR_MGMT_2, &c, 1);
Serial.print(F("PWR_MGMT_2 : "));
Serial.print(c, HEX);
Serial.print(F(", error = "));
Serial.println(error, DEC);
MPU6050_write_reg(MPU6050_PWR_MGMT_1, 0);
initBuffer();
pulseSensor.analogInput(PulseWire);
pulseSensor.setThreshold(Threshold);
if (pulseSensor.begin()) {
Serial.println("We created a pulseSensor Object !");
}
}
void loop() {
curSensoredTime = millis();
if (curSensoredTime - prevSensoredTime > SENSOR_READ_INTERVAL) {
readFromSensor();
prevSensoredTime = curSensoredTime;
if (iAccelIndex >= ACCEL_BUFFER_COUNT - 3) {
sendToRemote();
initBuffer();
Serial.println("------------- Send 20 accel data to remote");
}
}
int myBPM = pulseSensor.getBeatsPerMinute();
if (pulseSensor.sawStartOfBeat()) {
Serial.println("♥ A HeartBeat Happened ! ");
Serial.print("BPM: ");
Serial.println(myBPM);
}
delay(20);
}
void sendToRemote() {
BTSerial.write("accel");
BTSerial.write((char*)aAccelBuffer);
}
void readFromSensor() {
int error;
double dT;
accel_t_gyro_union accel_t_gyro;
error = MPU6050_read(MPU6050_ACCEL_XOUT_H, (uint8_t*)&accel_t_gyro, sizeof(accel_t_gyro));
if (error != 0) {
Serial.print(F("Read accel, temp and gyro, error = "));
Serial.println(error, DEC);
}
uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
SWAP(accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
SWAP(accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
SWAP(accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
SWAP(accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
SWAP(accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
SWAP(accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
SWAP(accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
Serial.print(F("accel x,y,z: "));
Serial.print(accel_t_gyro.value.x_accel, DEC);
Serial.print(F(", "));
Serial.print(accel_t_gyro.value.y_accel, DEC);
Serial.print(F(", "));
Serial.print(accel_t_gyro.value.z_accel, DEC);
Serial.print(F(", at "));
Serial.print(iAccelIndex);
Serial.println(F(""));
if (iAccelIndex < ACCEL_BUFFER_COUNT && iAccelIndex > 1) {
int tempX = accel_t_gyro.value.x_accel;
int tempY = accel_t_gyro.value.y_accel;
int tempZ = accel_t_gyro.value.z_accel;
char temp = (char)(tempX >> 8);
if (temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempX);
if (temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempY >> 8);
if (temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempY);
if (temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempZ >> 8);
if (temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempZ);
if (temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
}
int MPU6050_read(int start, uint8_t* buffer, int size)
{
int i, n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS);
n = Wire.write(start);
if (n != 1)
return (-10);
n = Wire.endTransmission(false);
if (n != 0)
return (n);
Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
i = 0;
while (Wire.available() && i < size)
{
buffer[i++] = Wire.read();
}
if (i != size)
return (-11);
return (0); // return : no error
}
int MPU6050_write(int start, const uint8_t* pData, int size)
{
int n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS);
n = Wire.write(start);
if (n != 1)
return (-20);
n = Wire.write(pData, size);
if (n != size)
return (-21);
error = Wire.endTransmission(true);
if (error != 0)
return (error);
return (0); // return : no error
}
int MPU6050_write_reg(int reg, uint8_t data)
{
int error;
error = MPU6050_write(reg, &data, 1);
return (error);
}
//void initBuffer() {
iAccelIndex = 2;
for (int i = iAccelIndex; i < ACCEL_BUFFER_COUNT; i++) {
aAccelBuffer[i] = 0x00;
}
aAccelBuffer[0] = 0xfe;
aAccelBuffer[1] = 0xfd;
aAccelBuffer[122] = 0xfd;
aAccelBuffer[123] = 0xfe;
aAccelBuffer[124] = 0x00;
}
혹시 도움이 될까 해서 각각의 코드도 올려봅니다 ..
1.RetroBand (걸음수 측정)
#include <math.h>
#include <Wire.h>
#include <SoftwareSerial.h>
/* Bluetooth */
SoftwareSerial BTSerial(2, 3); //Connect HC-06. Use your (TX, RX) settings
/* time */
#define SENDING_INTERVAL 1000
#define SENSOR_READ_INTERVAL 50
unsigned long prevSensoredTime = 0; // unsigned long 범위: 0 ~ 4,294,967,295
unsigned long curSensoredTime = 0; // unsigned long 범위: 0 ~ 4,294,967,295
/* Data buffer */
#define ACCEL_BUFFER_COUNT 125
byte aAccelBuffer[ACCEL_BUFFER_COUNT]; // byte: 1바이트 숫자 자료형
int iAccelIndex = 2;
/* MPU-6050 sensor */
#define MPU6050_ACCEL_XOUT_H 0x3B // R //59
#define MPU6050_PWR_MGMT_1 0x6B // R/W //107
#define MPU6050_PWR_MGMT_2 0x6C // R/W //108
#define MPU6050_WHO_AM_I 0x75 // R //117
#define MPU6050_I2C_ADDRESS 0x68 //104
typedef union accel_t_gyro_union {
struct {
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;
struct {
int x_accel;
int y_accel;
int z_accel;
int temperature;
int x_gyro;
int y_gyro;
int z_gyro;
} value;
};
void setup() {
int error;
uint8_t c;
Serial.begin(9600);
Wire.begin();
BTSerial.begin(9600); // set the data rate for the BT port
// default at power-up:
// Gyro at 250 degrees second
// Acceleration at 2g
// Clock source at internal 8MHz
// The device is in sleep mode.
//
error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
Serial.print(F("WHO_AM_I : "));
Serial.print(c,HEX);
Serial.print(F(", error = ")); // 프로그램 메모리(Flash)에 저장할 수 있도록 F() 함수를 이용
Serial.println(error,DEC);
// According to the datasheet, the 'sleep' bit
// should read a '1'. But I read a '0'.
// That bit has to be cleared, since the sensor
// is in sleep mode at power-up. Even if the
// bit reads '0'.
error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
Serial.print(F("PWR_MGMT_2 : "));
Serial.print(c,HEX);
Serial.print(F(", error = "));
Serial.println(error,DEC);
// Clear the 'sleep' bit to start the sensor.
MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
initBuffer();
}
void loop() {
curSensoredTime = millis();
// Read from sensor
if(curSensoredTime - prevSensoredTime > SENSOR_READ_INTERVAL) {
readFromSensor(); // Read from sensor
prevSensoredTime = curSensoredTime;
// Send buffer data to remote
if(iAccelIndex >= ACCEL_BUFFER_COUNT - 3) {
sendToRemote();
initBuffer();
Serial.println("------------- Send 20 accel data to remote");
}
}
}
/**************************************************
* BT Transaction
**************************************************/
void sendToRemote() {
// Write gabage bytes
BTSerial.write( "accel" );
// Write accel data
BTSerial.write( (char*)aAccelBuffer );
// Flush buffer
//BTSerial.flush();
}
/**************************************************
* Read data from sensor and save it
**************************************************/
void readFromSensor() {
int error;
double dT;
accel_t_gyro_union accel_t_gyro;
error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
if(error != 0) {
Serial.print(F("Read accel, temp and gyro, error = "));
Serial.println(error,DEC);
}
// Swap all high and low bytes.
// After this, the registers values are swapped,
// so the structure name like x_accel_l does no
// longer contain the lower byte.
uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
// Print the raw acceleration values
Serial.print(F("accel x,y,z: "));
Serial.print(accel_t_gyro.value.x_accel, DEC);
Serial.print(F(", "));
Serial.print(accel_t_gyro.value.y_accel, DEC);
Serial.print(F(", "));
Serial.print(accel_t_gyro.value.z_accel, DEC);
Serial.print(F(", at "));
Serial.print(iAccelIndex);
Serial.println(F(""));
if(iAccelIndex < ACCEL_BUFFER_COUNT && iAccelIndex > 1) {
int tempX = accel_t_gyro.value.x_accel;
int tempY = accel_t_gyro.value.y_accel;
int tempZ = accel_t_gyro.value.z_accel;
/*
// Check min, max value
if(tempX > 16380) tempX = 16380;
if(tempY > 16380) tempY = 16380;
if(tempZ > 16380) tempZ = 16380;
if(tempX < -16380) tempX = -16380;
if(tempY < -16380) tempY = -16380;
if(tempZ < -16380) tempZ = -16380;
// We dont use negative value
tempX += 16380;
tempY += 16380;
tempZ += 16380;
*/
char temp = (char)(tempX >> 8);
if(temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempX);
if(temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempY >> 8);
if(temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempY);
if(temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempZ >> 8);
if(temp == 0x00)
temp = 0x7f;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
temp = (char)(tempZ);
if(temp == 0x00)
temp = 0x01;
aAccelBuffer[iAccelIndex] = temp;
iAccelIndex++;
}
// The temperature sensor is -40 to +85 degrees Celsius.
// It is a signed integer.
// According to the datasheet:
// 340 per degrees Celsius, -512 at 35 degrees.
// At 0 degrees: -512 - (340 * 35) = -12412
// Serial.print(F("temperature: "));
// dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;
// Serial.print(dT, 3);
// Serial.print(F(" degrees Celsius"));
// Serial.println(F(""));
// Print the raw gyro values.
// Serial.print(F("gyro x,y,z : "));
// Serial.print(accel_t_gyro.value.x_gyro, DEC);
// Serial.print(F(", "));
// Serial.print(accel_t_gyro.value.y_gyro, DEC);
// Serial.print(F(", "));
// Serial.print(accel_t_gyro.value.z_gyro, DEC);
// Serial.println(F(""));
}
/**************************************************
* MPU-6050 Sensor read/write
**************************************************/
int MPU6050_read(int start, uint8_t *buffer, int size)
{
int i, n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS);
n = Wire.write(start);
if (n != 1)
return (-10);
n = Wire.endTransmission(false); // hold the I2C-bus
if (n != 0)
return (n);
// Third parameter is true: relase I2C-bus after data is read.
Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
i = 0;
while(Wire.available() && i<size)
{
buffer[i++]=Wire.read();
}
if ( i != size)
return (-11);
return (0); // return : no error
}
int MPU6050_write(int start, const uint8_t *pData, int size)
{
int n, error;
Wire.beginTransmission(MPU6050_I2C_ADDRESS);
n = Wire.write(start); // write the start address
if (n != 1)
return (-20);
n = Wire.write(pData, size); // write data bytes
if (n != size)
return (-21);
error = Wire.endTransmission(true); // release the I2C-bus
if (error != 0)
return (error);
return (0); // return : no error
}
int MPU6050_write_reg(int reg, uint8_t data)
{
int error;
error = MPU6050_write(reg, &data, 1);
return (error);
}
/**************************************************
* Utilities
**************************************************/
void initBuffer() {
iAccelIndex = 2;
for(int i=iAccelIndex; i<ACCEL_BUFFER_COUNT; i++) {
aAccelBuffer[i] = 0x00;
}
aAccelBuffer[0] = 0xfe;
aAccelBuffer[1] = 0xfd;
aAccelBuffer[122] = 0xfd;
aAccelBuffer[123] = 0xfe;
aAccelBuffer[124] = 0x00;
}
2. 심장박동센서 기본예제
/* Getting_BPM_to_Monitor prints the BPM to the Serial Monitor, using the least lines of code and PulseSensor Library.
* Tutorial Webpage: https://pulsesensor.com/pages/getting-advanced
*
--------Use This Sketch To------------------------------------------
1) Displays user's live and changing BPM, Beats Per Minute, in Arduino's native Serial Monitor.
2) Print: "♥ A HeartBeat Happened !" when a beat is detected, live.
2) Learn about using a PulseSensor Library "Object".
4) Blinks LED on PIN 13 with user's Heartbeat.
--------------------------------------------------------------------*/
#define USE_ARDUINO_INTERRUPTS true // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h> // Includes the PulseSensorPlayground Library.
// Variables
const int PulseWire = 0; // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int LED13 = 13; // The on-board Arduino LED, close to PIN 13.
int Threshold = 550; // Determine which Signal to "count as a beat" and which to ignore.
// Use the "Gettting Started Project" to fine-tune Threshold Value beyond default setting.
// Otherwise leave the default "550" value.
PulseSensorPlayground pulseSensor; // Creates an instance of the PulseSensorPlayground object called "pulseSensor"
void setup() {
Serial.begin(9600); // For Serial Monitor
// Configure the PulseSensor object, by assigning our variables to it.
pulseSensor.analogInput(PulseWire);
pulseSensor.blinkOnPulse(LED13); //auto-magically blink Arduino's LED with heartbeat.
pulseSensor.setThreshold(Threshold);
// Double-check the "pulseSensor" object was created and "began" seeing a signal.
if (pulseSensor.begin()) {
Serial.println("We created a pulseSensor Object !"); //This prints one time at Arduino power-up, or on Arduino reset.
}
}
void loop() {
int myBPM = pulseSensor.getBeatsPerMinute(); // Calls function on our pulseSensor object that returns BPM as an "int".
// "myBPM" hold this BPM value now.
if (pulseSensor.sawStartOfBeat()) { // Constantly test to see if "a beat happened".
Serial.println("♥ A HeartBeat Happened ! "); // If test is "true", print a message "a heartbeat happened".
Serial.print("BPM: "); // Print phrase "BPM: "
Serial.println(myBPM); // Print the value inside of myBPM.
}
delay(20); // considered best practice in a simple sketch.
}
바쁘실텐데 긴 글 읽어주셔서 감사합니다 .
도움을 주신다면 정말 큰 도움이 될 것 같습니다.
다시 한번 감사합니다.
댓글 3
조회수 9,527master님의 댓글
master 작성일
PC 고장으로 새롭게 프로그램을 설치하면서 아두이노는 현재 설치되어 있지 않은 상태입니다.
아두이노는 거의 사용하지 않으므로 설치해야 할 우선순위가 낮은 상태이고요
오류가 뭔지 오류 메시지를 적어보세요
블람님의 댓글
블람
빠른 답변 감사드립니다.
127번 라인의 error = MPU6050_read(MPU6050_ACCEL_XOUT_H, (uint8_t*)&accel_t_gyro, sizeof(accel_t_gyro)); 이 형광 표시 되며 'MPU6050_read'was not declared in this scope
라고 나옵니다
아래는 오류 메시지를 복사 한 것 입니다.
아두이노:1.8.12 (Windows 10), 보드:"Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"
C:\Users\user\Documents\Arduino\integration_version1\integration_version1.ino: In function 'void setup()':
integration_version1:69:13: error: 'MPU6050_read' was not declared in this scope
error = MPU6050_read(MPU6050_WHO_AM_I, &c, 1);
^~~~~~~~~~~~
integration_version1:81:5: error: 'MPU6050_write_reg' was not declared in this scope
MPU6050_write_reg(MPU6050_PWR_MGMT_1, 0);
^~~~~~~~~~~~~~~~~
integration_version1:83:5: error: 'initBuffer' was not declared in this scope
initBuffer();
^~~~~~~~~~
C:\Users\user\Documents\Arduino\integration_version1\integration_version1.ino:83:5: note: suggested alternative: 'aAccelBuffer'
initBuffer();
^~~~~~~~~~
aAccelBuffer
C:\Users\user\Documents\Arduino\integration_version1\integration_version1.ino: In function 'void loop()':
integration_version1:104:13: error: 'initBuffer' was not declared in this scope
initBuffer();
^~~~~~~~~~
C:\Users\user\Documents\Arduino\integration_version1\integration_version1.ino:104:13: note: suggested alternative: 'aAccelBuffer'
initBuffer();
^~~~~~~~~~
aAccelBuffer
C:\Users\user\Documents\Arduino\integration_version1\integration_version1.ino: In function 'void readFromSensor()':
integration_version1:127:13: error: 'MPU6050_read' was not declared in this scope
error = MPU6050_read(MPU6050_ACCEL_XOUT_H, (uint8_t*)&accel_t_gyro, sizeof(accel_t_gyro));
^~~~~~~~~~~~
integration_version1:191:1: error: a function-definition is not allowed here before '{' token
{
^
integration_version1:216:1: error: a function-definition is not allowed here before '{' token
{
^
integration_version1:236:1: error: a function-definition is not allowed here before '{' token
{
^
exit status 1
'MPU6050_read' was not declared in this scope
이 리포트는 파일 -> 환경설정에 "컴파일중 자세한 출력보이기"를
활성화하여 더 많은 정보를
보이게 할 수 있습니다.
master님의 댓글
master
MPU6050_read() 함수를 호출하기 전에 함수 선언이 윗쪽에 있어야 오류가 발생하지 않습니다.
셋업함수와 루프 함수를 제일 아래로 이동해보세요