분류 | 설명 |
---|---|
모듈 보드명 | GY-521 |
IC 이름 | MPU6050 |
하나의 센서에 두 가지 센싱이 가능하다.
각의 속도를 알 수 있다.
ex) 초당 각도의 변화량 측정
기울기를 감지할 때 사용한다.
ex) 핸들 돌렸을 때 인지
mpu6050 | esp32 pin |
---|---|
VCC | 3.3V |
GND | GND |
SCL | I2C SCL (GPIO22) |
SDA | I2C SDA (GPIO21) |
EspMQTTClient
: mqtt 용 라이브러리
Adafruite MPU6050
: MPU6050 라이브러리
앞으로 기능을 구현하면서 또 다른 센서에서 값을 지속적으로 읽어와야 할 수 있기 때문에, thread로 만들기 위해 ArduinoThread
도 받아준다.
mpu class
sensors_vec_t
구조체에 담긴 값을 읽어 왼쪽으로 틀어져있는지, 오른쪽으로 틀어져있는지 확인한다.Thread
를 상속받아서 run()
을 구현했다. 실제 스레드가 시작될 때 수행되는 구간이다. Thread 코드 내부를 보니 default는 0인 듯했다.Thread(void (*callback)(void) = NULL, unsigned long _interval = 0);
COMMAND_XXX
는 값이 바뀌지 않는 한 mqtt 송신을 한 번만 보내도록 하기 위해 만든 bool 변수로 volatile
키워드를 추가해 과하게 똑똑한 컴파일러의 방해(!)를 차단했다.command_direction_all_false()
를 통해 함수 하나를 호출하면서 상태 bool 값을 모두 false로 만들고, 입력된 커맨드에 따라 하나씩 수정하는 식으로 재사용했다. #include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include "Thread.h"
#include "ThreadController.h"
#include <Arduino.h>
// 한 번만 보내기 위한 flg 변수
volatile bool COMMAND_LEFT_MIN = false,
COMMAND_LEFT_MAX = false,
COMMAND_RIGHT_MIN = false,
COMMAND_RIGHT_MAX = false,
COMMAND_MID = false;
void command_direction_all_false(void) {
left_to_false();
right_to_false();
COMMAND_MID = false;
}
class MPUThread : public Thread {
public:
sensors_event_t a, g, temp;
void cmd_mpu_check(sensors_vec_t ac) {
if (ac.y > 3) {
if (ac.y > 8 && !COMMAND_LEFT_MAX) {
// Serial.println("left_max");
tx(CMD_TOPIC, "left_max");
command_direction_all_false();
COMMAND_LEFT_MAX = true;
}
else if (ac.y <= 6 && !COMMAND_LEFT_MIN) {
// Serial.println("left_min");
tx(CMD_TOPIC, "left_min");
command_direction_all_false();
COMMAND_LEFT_MIN = true;
}
}
else if (ac.y < -3) {
if (ac.y < -8 && !COMMAND_RIGHT_MAX) {
// Serial.println("right_max");
tx(CMD_TOPIC, "right_max");
command_direction_all_false();
COMMAND_RIGHT_MAX = true;
}
else if (ac.y >= -6 && !COMMAND_RIGHT_MIN) {
// Serial.println("right_min");
tx(CMD_TOPIC, "right_min");
command_direction_all_false();
COMMAND_RIGHT_MIN = true;
}
}
else if (-2 < ac.y && ac.y < 2 && !COMMAND_MID) {
tx(CMD_TOPIC, "mid");
command_direction_all_false();
COMMAND_MID = true;
}
}
void run() {
mpu.getEvent(&a, &g, &temp);
cmd_mpu_check(a.acceleration);
runned();
}
};
setup & loop
command
로 설정했다. -> 라즈베리파이에서 설정한 topic 과 같아야 함loop
에서 controller.run()
을 해주면 등록된 스레드 객체가 모두 start (run) 된다.#include <Wire.h>
#include "EspMQTTClient.h"
EspMQTTClient client(
"wifi SSID",
"wifi password",
"MQTT Broker server ip or aws iot endpoint",
"MQTT Client ID",
"MQTT Client PW",
"MQTT Client Name",
1883);
char *CMD_TOPIC = "command";
// mqtt 송신용 tx()
void tx(char *topic, char *cmd) {
client.publish(topic, cmd); //topic , cmd
}
// create thread
MPUThread mpu_th = MPUThread();
ThreadController controller = ThreadController();
// This is the callback for the Timer
void timerCallback() {
controller.run();
}
void setup(void) {
Serial.begin(115200); // serial monitor begin
// mqtt client enable
client.enableHTTPWebUpdater();
client.enableOTA();
controller.add(&mpu_th);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
// Try to initialize!
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
Serial.println("MPU6050 Found!");
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(100);
}
void onConnectionEstablished() {
//client.loop() 에 의해 호출되는 API
}
void loop() {
controller.run();
client.loop();
}