이 Arduino 프로젝트에서는 Arduino, MEMS 자력계 및 Processing IDE를 사용하여 멋진 모양의 나침반을 만드는 방법을 알아봅니다. 다음은 나침반 데모 비디오입니다. 이전 포스팅과 마찬가지로 우리는 Nano 33 BLE Sense 보드를 사용해서 프로그래밍을 합니다. 따라서 작성한 코드를 표시하고 이 코드를 Nano 33 BLE Sense 보드의 자기장 센서 Magnetomer에 맞도록 수정합니다. 마지막으로 Processing에서 자기장 데이터를 받아 데모를 진행합니다.
이 프로젝트에 필요한 것은 지구 자기장 측정을위한 MEMS 자력계, Arduino 보드 및 일부 점퍼 와이어입니다. 예를 들어 GY–80 브레이크 아웃 보드에 통합된 3 축 자력계 인 HMC5883L을 사용합니다.

Arduino 부품 먼저 I2C 프로토콜을 통해 Arduino 보드를 사용하여 센서에서 데이터를 가져와야합니다 . 그런 다음 센서의 X – 축 및 Y – 축 값을 사용하여 Heading을 계산하고 직렬 포트를 통해 Processing IDE에 값을 보냅니다. 다음 코드가 해당 작업을 수행합니다.
/* Arduino Compass
*
* by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
*/
#include <Wire.h> //I2C Arduino Library
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float heading, headingDegrees, headingFiltered, declination;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //I2C 7bit address of HMC5883
void setup(){
//Initialize Serial and I2C communications
Serial.begin(115200);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Select mode register
Wire.write(0x00); // Continuous measurement mode
Wire.endTransmission();
}
void loop(){
//---- X-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ1 = Wire.read();
}
//---- X-Axis
mX1=mX1<<8;
mX_out =mX0+mX1; // Raw data
// From the datasheet: 0.92 mG/digit
Xm = mX_out*0.00092; // Gauss unit
//* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
//---- Y-Axis
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;
//---- Z-Axis
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;
// ==============================
//Calculating Heading
heading = atan2(Ym, Xm);
// Correcting the heading with the declination angle depending on your location
// You can find your declination angle at: https://www.ngdc.noaa.gov/geomag-web/
// At my location it's 4.2 degrees => 0.073 rad
declination = 0.073;
heading += declination;
// Correcting when signs are reveresed
if(heading <0) heading += 2*PI;
// Correcting due to the addition of the declination angle
if(heading > 2*PI)heading -= 2*PI;
headingDegrees = heading * 180/PI; // The heading in Degrees unit
// Smoothing the output angle / Low pass filter
headingFiltered = headingFiltered*0.85 + headingDegrees*0.15;
//Sending the heading value through the Serial Port to Processing IDE
Serial.println(headingFiltered);
delay(50);
}
MEMS 자력계의 작동 방식과 데이터를 얻는 방법에 대한 자세한 내용이 필요하면 MEMS 센서 자습서를 확인하십시오 .
위 코드를 Nano 33 BLE Sense 보드에서 동일한 출력을 내도록 코드를 작성하는 일이 우리가 원하는 일이었죠? 일단 예제 샘플을 불러오겠습니다. 파일 - 예제 - Arduino_LSM9DS1 - SimpleMagnetometer 파일을 엽니다.
/*
Arduino LSM9DS1 - Simple Magnetometer
The circuit:
- Arduino Nano 33 BLE Sense
*/
#include <Arduino_LSM9DS1.h>
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Started");
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
Serial.print("Magnetic field sample rate = ");
Serial.print(IMU.magneticFieldSampleRate());
Serial.println(" uT");
Serial.println();
Serial.println("Magnetic Field in uT");
Serial.println("X\tY\tZ");
}
void loop() {
float x, y, z;
if (IMU.magneticFieldAvailable()) {
IMU.readMagneticField(x, y, z);
Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);
}
}
코드에서 Heading 계산하는 부분을 추가해야 합니다. microTesla 판독 값을 0-360도 나침반 방향으로 변환하려면 atan2 () 함수를 사용하여 Y 및 X 축 판독 값으로 정의 된 벡터 각도를 계산할 수 있습니다. 결과는 라디안으로 표시되므로 180도를 곱하고 Pi로 나누어 각도로 변환합니다.(참고)
float heading = (atan2 (event.magnetic.y, event.magnetic.x) * 180) / Pi;
일단 읽는 값은 0~ 360도가 나오는데 동작은 정확하지 않기도 하고, 테스트를 잘 못하는지 도통 모드겠습니다. 일단 코드를 옮깁니다.
/*
Arduino LSM9DS1 - Simple Magnetometer
This example reads the magnetic field values from the LSM9DS1
sensor and continuously prints them to the Serial Monitor
or Serial Plotter.
The circuit:
- Arduino Nano 33 BLE Sense
created 10 Jul 2019
by Riccardo Rizzo
This example code is in the public domain.
*/
#include <Arduino_LSM9DS1.h>
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Started");
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
Serial.print("Magnetic field sample rate = ");
Serial.print(IMU.magneticFieldSampleRate());
Serial.println(" uT");
Serial.println();
Serial.println("Magnetic Field in uT");
Serial.println("X\tY\tZ");
}
float Pi = 3.14159;
void loop() {
float x, y, z;
if (IMU.magneticFieldAvailable()) {
IMU.readMagneticField(x, y, z);
/*Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);*/
float Pi = 3.14159;
// Calculate the angle of the vector y,x
float heading = (atan2(y, x) * 180) / Pi;
// Normalize to 0-360
if (heading < 0) {
heading = 360 + heading;
}
Serial.println(heading);
}
}
Processing 소스코드 부분

여기서 먼저 직렬 포트에서 오는 Heading 값을 받아야 합니다. 이 작업을 수행하는 방법에 대한 자세한 내용은 Arduino 및 Processing Tutorial을 확인하십시오 . 나침반은 실제로 이미지이거나보다 정확하게는 Processing IDE에로드 된 여러 개의 투명한 이미지로 구성됩니다. 이미지는 스케치의 작업 디렉터리에 있습니다. image () 함수를 사용하여 draw () 섹션에서 이미지 객체를 정의한 후 배경 이미지를 로드합니다 (선택 사항이며 배경에 간단한 색상만 사용할 수 있음). 그런 다음 rotateZ () 함수를 사용하여 제목 값과 함께 회전되는 나침반 이미지가 로드됩니다. 그 위에 나침반 화살표 이미지가 로드됩니다. Processing IDE 코드는 다음과 같습니다.
/* Arduino Compass
*
* by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
*/
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
PImage imgCompass;
PImage imgCompassArrow;
PImage background;
String data="";
float heading;
void setup() {
size (1920, 1080, P3D);
smooth();
imgCompass = loadImage("Compass.png");
imgCompassArrow = loadImage("CompassArrow.png");
background = loadImage("Background.png");
myPort = new Serial(this, "COM4", 115200); // starts the serial communication
myPort.bufferUntil('\n');
}
void draw() {
image(background,0, 0); // Loads the Background image
pushMatrix();
translate(width/2, height/2, 0); // Translates the coordinate system into the center of the screen, so that the rotation happen right in the center
rotateZ(radians(-heading)); // Rotates the Compass around Z - Axis
image(imgCompass, -960, -540); // Loads the Compass image and as the coordinate system is relocated we need need to set the image at -960x, -540y (half the screen size)
popMatrix(); // Brings coordinate system is back to the original position 0,0,0
image(imgCompassArrow,0, 0); // Loads the CompassArrow image which is not affected by the rotateZ() function because of the popMatrix() function
textSize(30);
text("Heading: " + heading,40,40); // Prints the value of the heading on the screen
delay(40);
}
// starts reading data from the Serial Port
void serialEvent (Serial myPort) {
data = myPort.readStringUntil('\n');// reads the data from the Serial Port and puts it into the String variable "data".
heading = float(data); // Convering the the String value into Float value
}
필요한 이미지와 Arduino소스코드 파일을 올려드립니다. 출처는 참고 문서 1번입니다.
참고
1. 번역하기 이전의 문서

'개발자 > Arduino' 카테고리의 다른 글
| Adafruit Feather nRF52840 Express 03. Arduino IDE 환경 설정 (0) | 2022.02.07 |
|---|---|
| Arduino를 사용하는 RS-485 구현 (0) | 2021.12.13 |
| Adafruit Feather nRF52840 Express 02. Hardware 설계와 참고자료 (0) | 2021.12.08 |
| Adafruit Feather nRF52840 Express 01. 소개 (0) | 2021.12.06 |
| Adafruit TCS34725 컬러 센서로 빛과 색상 측정 (0) | 2021.11.01 |
| 방수 초음파 센서 사용 거리 측정 Waterproof Ultrasonic Sensors (0) | 2021.10.12 |
| Nano 33 IoT HC-SR04 거리 센서 코드 (7) | 2021.10.09 |
| LPS22HB 압력 센서 아두이노 실습하기 (0) | 2021.10.06 |
취업, 창업의 막막함, 외주 관리, 제품 부재!
당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약,
아이디어는 있지만 구현할 기술이 없는 막막함.
우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.
이제 고민을 멈추고, 캐어랩을 만나세요!
코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.
제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!
귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.
캐어랩