M5Camera에 충전식 배터리 연결

OS/M5Stack 2019. 10. 13. 19:09 Posted by 파란크리스마스

출처

M5Camera에 충전식 배터리 연결

M5Camera에 별도의 배터리를 연결하지 않고 배터리가 내장 되어 있으면 좋겠다고 생각했는데, M5Camera용 내장 배터리제품이 최근에 출시 되어 조립해보았습니다.

한가지 단점이 있다면 스위치가 별도로 없어서 충전된 배터리가 전부 소모 해야 카메라가 꺼진다는 단점이 있습니다.

M5Camera와 M5Camera Battery

M5Camera의 분해

배터리 납땜전

배터리 납땜후

배터리 케이스 조립

M5Camera에 배터리 연결

댓글을 달아 주세요

M5StickC : 손목시계

OS/M5Stack 2019. 9. 21. 01:19 Posted by 파란크리스마스

출처

M5StickC : 손목시계

M5StickC을 이용한 손목시계 오픈소스를 소개 합니다. 

손목시계를 개발한 개발자님은 Nixie 튜브 시계를 만들고 싶지만 비싸고, 전원도 많이 사용되어서 M5StickC구현 했다고 합니다.

Nixie 튜브 숫자이미지를 lcd-image-converter 프로그램으로 c언어 소스를 변환해서 사용했는데, 나중에 시간이 되면 다른 숫자 이미지를 이용해서 만들어 보겠습니다.

실행 영상

댓글을 달아 주세요

M5StickC : BeetleC - Android 원격 제어 (BLE : App Inventor)

OS/M5Stack 2019. 9. 20. 00:53 Posted by 파란크리스마스

출처

M5StickC : BeetleC - Android 원격 제어 (BLE : App Inventor)

M5StickC : BeetleC을 안드로이드 폰으로 제어하기 위해서 BeetleC는 BLE로 구현하고, 안드로이드개발은 App Inventor를 이용해서 개발했습니다.

M5StickC의 BLE 개발은 이전 게시물의 내용을 참고 하시면 됩니다.

M5StickC : BeetleC - BLE 서버 BleBeetleCRcCar.zip

BLE UUID 상수

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

아두이노 소스

#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
#include "carControl.h"

//
int defaultDutyCycle = 20;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

void blink() {
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
  delay(100);
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
  delay(100);
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
}

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic *pCharacteristic) {
    pCharacteristic->setValue("Hello World!");
  }

  void onWrite(BLECharacteristic *pCharacteristic) {

    std::string value = pCharacteristic->getValue();

    if (value.at(0) == 'S') {
      stopMotor();
      return;
    }
    
    int dutyCycle = defaultDutyCycle;
    //M5.Lcd.println(value.substr(2).c_str());
    if(sscanf(value.substr(2).c_str(), "%d", &dutyCycle) != 1)
      dutyCycle = defaultDutyCycle;

    if (value.at(1) == 'C') {
      centerMotor( value.at(0), dutyCycle );
    } else if (value.at(1) == 'L') {
      leftMotor( value.at(0), dutyCycle );
    } else if (value.at(1) == 'R') {
      rightMotor( value.at(0), dutyCycle );
    }
  }
};

void stopMotor() {
  // Stop the DC motor
  Serial.println("Motor stopped");
  leftwheel(0);
  rightwheel(0);
}

void forwardMotor(int dutyCycle) {
  leftwheel(dutyCycle);
  rightwheel(dutyCycle);
}

void backwardMotor(int dutyCycle) {
  leftwheel(dutyCycle * -1);
  rightwheel(dutyCycle * -1);
}

void centerMotor(char cmd, int dutyCycle) {
  // Stop the DC motor
  Serial.println("Motor center");
  if (cmd == 'F') {
    forwardMotor(dutyCycle);
  } else if (cmd == 'B') {
    backwardMotor(dutyCycle);
  }
}

void rightMotor(char cmd, int dutyCycle) {
  if (cmd == 'F') {
    leftwheel(dutyCycle);
    rightwheel(0);
  } else if (cmd == 'B') {
    leftwheel(dutyCycle * -1);
    rightwheel(0);
  }
}

void leftMotor(char cmd, int dutyCycle) {
  if (cmd == 'F') {
    leftwheel(0);
    rightwheel(dutyCycle);
  } else if (cmd == 'B') {
    leftwheel(0);
    rightwheel(dutyCycle * -1);
  }
}

void setup() {
  // initialize the M5StickC object
  M5.begin();
  Wire.begin(0, 26);

  M5.Lcd.fillScreen(WHITE);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(1);
  M5.Lcd.setCursor(40, 20, 1);
  M5.Lcd.setTextSize(1);

  //
  M5.Lcd.println("BeetleC BLE");
  
  blink();

  leftwheel(0);
  rightwheel(0);

  BLEDevice::init("m5-stack");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE |
                                         BLECharacteristic::PROPERTY_NOTIFY |
                                         BLECharacteristic::PROPERTY_INDICATE
                                       );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

// the loop routine runs over and over again forever
void loop() {
}

App Inventor 소스 (안드로이드) m5stack_ble_rccar.zip

App Inventor 디자인

App Inventor 블럭

실행결과

댓글을 달아 주세요

M5StickC : BeetleC 모터제어

OS/M5Stack 2019. 9. 19. 20:48 Posted by 파란크리스마스

출처

M5StickC : BeetleC 모터제어

BeatleC는 두개의 모터 드라이버(STM32F030)와 7 개의 RGB LED, M5StickC (ESP32 기반 Wi-Fi 제어 기능)와 함께 사용하여 가장 작은 RC Car 입니다.

소스 beetleCDeom1.zip

#include <M5StickC.h>
#include "carControl.h"

void blink() {
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
  delay(100);
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
  delay(100);
  for(int num = 0; num < 7; num++) {
    uint32_t color = 0x11 << 16;
    led(num, color);
    delay(100);
    led(num, 0x00);
  }
}

void setup() {
  // initialize the M5StickC object
  M5.begin();
  Wire.begin(0, 26);

  M5.Lcd.fillScreen(WHITE);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(1);
  M5.Lcd.setCursor(40, 20, 1);
  M5.Lcd.setTextSize(2);

  //
  M5.Lcd.println("BeetleC");
  
  blink();

  leftwheel(0);
  rightwheel(0);  
}

// the loop routine runs over and over again forever
void loop() {
  leftwheel(20);
  rightwheel(20);
  delay(500);
  leftwheel(-20);
  rightwheel(-20);
  delay(500);
  leftwheel(0);
  rightwheel(0);
}

실행 영상

댓글을 달아 주세요

M5StickC : HelloWorld

OS/M5Stack 2019. 9. 19. 20:10 Posted by 파란크리스마스

출처

HelloWorld 소스

#include <M5StickC.h>

// the setup routine runs once when M5StickC starts up
void setup(){
  // Initialize the M5StickC object
  M5.begin();

  // LCD display
  M5.Lcd.print("Hello World");
}

// the loop routine runs over and over again forever
void loop() {
}

보드 선택

실행

댓글을 달아 주세요

M5Stack : Lego RC CAR (BLE 통신)

OS/M5Stack 2019. 7. 21. 23:26 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stack : Lego RC CAR (BLE 통신)





배선

M5Stack 아두이노 소스 : BLE 서버, L298N 모터 드라이버 모듈 제어

M5Stack 아두이노 소스

#include <M5Stack.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

// Motor A
int motor1Pin1 = 21; 
int motor1Pin2 = 22; 
int enable1Pin = 26; 

// Motor B
int motor1Pin1B = 16; 
int motor1Pin2B = 17;

//
int defaultDutyCycle = 210;

// Setting PWM properties
const int freq = 10000;
const int pwmChannel = 0;
const int resolution = 8;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

void clearLCD() {
  M5.Lcd.clear(BLACK);
  M5.Lcd.setCursor(0, 0);
}

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      clearLCD();
      M5.Lcd.println("connect");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      clearLCD();
      M5.Lcd.println("disconnect");
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic *pCharacteristic) {
    M5.Lcd.println("read");
    pCharacteristic->setValue("Hello World!");
  }

  // BLE 클라이언트로 명령르 받았을때 호출
  void onWrite(BLECharacteristic *pCharacteristic) {
    M5.Lcd.println("write");
    std::string value = pCharacteristic->getValue();

    // 정지명령을 받았을 때
    if (value.at(0) == 'S') {
      stopMotor();
      return;
    }
    
    // 속도값 추출
    int dutyCycle = defaultDutyCycle;
    //M5.Lcd.println(value.substr(2).c_str());
    if(sscanf(value.substr(2).c_str(), "%d", &dutyCycle) != 1)
      dutyCycle = defaultDutyCycle;

    if (value.at(0) == 'F') {
      forwardMotor(dutyCycle);
    } else if (value.at(0) == 'B') {
      backwardMotor(dutyCycle);
    }

    if (value.at(1) == 'C') {
      centerMotor();
    } else if (value.at(1) == 'L') {
      leftMotor();
    } else if (value.at(1) == 'R') {
      rightMotor();
    }
    
    M5.Lcd.println(value.c_str());
  }
};

// 뒤바뀌가 정지하고, 앞바퀴가 가운데로 설정
void stopMotor() {
  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  centerMotor();
}

// 앞바퀴가 가운데로 설정
void centerMotor() {
  // Stop the DC motor
  Serial.println("Motor center");
  digitalWrite(motor1Pin1B, LOW);
  digitalWrite(motor1Pin2B, LOW);
}

// 뒤바뀌가 정방향으로 설정
void forwardMotor(int dutyCycle) {
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW);
  ledcWrite(pwmChannel, dutyCycle);   
}

// 뒤바뀌가 역방향으로 설정
void backwardMotor(int dutyCycle) {
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, HIGH);
  ledcWrite(pwmChannel, dutyCycle);   
}

// 앞바뀌가 오른쪽으로 설정
void rightMotor() {
  digitalWrite(motor1Pin1B, LOW);
  digitalWrite(motor1Pin2B, HIGH); 
}

// 앞바뀌가 왼쪽으로 설정
void leftMotor() {
  digitalWrite(motor1Pin1B, HIGH);
  digitalWrite(motor1Pin2B, LOW); 
}

void setup() {
  Serial.begin(115200);
  M5.begin();
  M5.setWakeupButton(BUTTON_A_PIN);
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("BLE start.");
  m5.Speaker.mute();

  // sets the pins as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(enable1Pin, OUTPUT);
  pinMode(motor1Pin1B, OUTPUT);
  pinMode(motor1Pin2B, OUTPUT);
  
  // configure LED PWM functionalitites
  ledcSetup(pwmChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(enable1Pin, pwmChannel);

  BLEDevice::init("m5-stack");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE |
                                         BLECharacteristic::PROPERTY_NOTIFY |
                                         BLECharacteristic::PROPERTY_INDICATE
                                       );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  if(M5.BtnA.wasPressed()) {
    M5.powerOFF();
  } else if(M5.BtnC.wasPressed()) {
    clearLCD();
  }
  
  if (deviceConnected) {
    if(M5.BtnB.wasPressed()) {
      M5.Lcd.println("Button B pressed!");
      pCharacteristic->setValue("Button B pressed!");
      pCharacteristic->notify();
    }
  }
  M5.update(); 
}

App Inventor : 안드로이드 어플 제작

App Inventor 디자인

App Inventor - 전역변수 선언 (BLE 서비스, 특성 UUID은 미리 설정)

App Inventor - BLE로 문자열 전달하는 함수 만들기 (메시지를 받아서 BLE 모듈로 호출)

App Inventor - 버튼을 누르고 있는데 터치 다운, 누리고 있다가 띄었을 때 터치 업 이벤트 발생시 위에서 구현 한 함수 호출

App Inventor 블럭 소스

실행 영상

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

  1. 최조영 2019.07.28 18:39  댓글주소  수정/삭제  댓글쓰기

    커넥터들은 직접 만드신건가요?
    멋진 작품입니다.

M5Stack : 레고 Power function 모터 제어(L298N 사용)

OS/M5Stack 2019. 7. 19. 22:31 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stack : 레고 Power function 모터 제어(L298N 사용)

L298N 모듈은 아두이노로 RC Car를 만들기 위해서 많이 사용하는 모터 드라이버 모듈로 정방향과 역방향으로 2개의 모터 제어가 가능하고, 속도 조절도 됩니다.

예제에서는 Lego Power function 모터를 L298N으로 제어하고 L298N은 M5Stack으로 명령을 실행하고 있습니다.

M5Go Port

PORT A : GPIO 21, 22 pin
PORT B : GPIO 26, 36 pin
PORT C : GPIO 16, 17 pin

배선

M-Motor의 경우 별도의 전원 연결이 필요없이, L298N에 C1, C2핀만 연결하면 됩니다.

  • ENA     IN1       IN2
  • 26pin   21pin     22pin

Lego Power function 연결 케이블 핀번호

Lego Power function M-Mortor 연결

L298N 연결

Lego Li-Battery Box 연결

M5Go의 Port A와 Port B에 Grove 캐이블 연결

M5Stack 아두이노 소스

예제는 26번 핀을 PWM제어로 속도를 설정하고, 정방향으로 회전시키고, 다시 역방향으로 회전 시켜보았습니다.

#include <M5Stack.h>

// Motor A
int motor1Pin1 = 21; 
int motor1Pin2 = 22; 
int enable1Pin = 26; 

// Setting PWM properties
const int freq = 10000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 150;

void setup() {

  // 초기화
  M5.begin(true, false, true);
  M5.Lcd.setTextFont(4);
  M5.Lcd.setCursor(40, 100);
  M5.Lcd.print("L298N Motor Driver");
  
  // sets the pins as outputs:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(enable1Pin, OUTPUT);
  
  // configure LED PWM functionalitites
  ledcSetup(pwmChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(enable1Pin, pwmChannel);

  Serial.begin(115200);

  // testing
  Serial.print("Testing DC Motor...");
}

void loop() {

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor forward with increasing speed
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW);
  while (dutyCycle <= 255){
    ledcWrite(pwmChannel, dutyCycle);   
    Serial.print("Forward with duty cycle: ");
    Serial.println(dutyCycle);
    dutyCycle = dutyCycle + 5;
    delay(500);
  }
  dutyCycle = 255;

  // Stop the DC motor
  Serial.println("Motor stopped");
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  delay(1000);

  // Move DC motor forward with increasing speed
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, HIGH);
  while (dutyCycle > 150){
    ledcWrite(pwmChannel, dutyCycle);   
    Serial.print("Backwards with duty cycle: ");
    Serial.println(dutyCycle);
    dutyCycle = dutyCycle - 5;
    delay(500);
  }
  dutyCycle = 150;
}

실행 영상

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

M5Stack : BLE 통신 - App Inventor 2 과 BLE 통신

OS/M5Stack 2019. 7. 19. 22:31 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stack : BLE 통신 - App Inventor 2 과 BLE 통신

M5Stack를 이용해서 BLE 서버를 만들고 App Inventor를 이용해서 안드로이드 용 BLE 클라이언트를 만들어 보았습니다.

BLE통신을 간단하게 설명하면, BLE 서버는 BLE 이름, UUID(고유주소), 거리 정보를 송출하고, 이 정보로 BLE 클라이언트가 접속하면, BLE 기기는 다른 BLE 클라이언트가 접속하지 않도록, BLE 이름을 더 이상 송출하지않고, 서비스목록과 해당 서비스의 특성 정보를 송출합니다. BLE 클라이언트는 필요한 서비스와 특성을 찾아서 용도에 따라 다르겠지만 여기 예제에서는 간단하게 문자열을 주고 받도록 했습니다.

M5Stack BLE 서버 만들기

서비스 UUID, 특성 UUID를 미리 정해야 합니다. 예제 소스에는 상수로 미리 만들어 두었습니다.

BLE 접속상태의 이벤트로 받기 위해서 BLEServerCallbacks 클래스를 상속받아서 구현하고, 서비스의 특성을 이용해서 문자열 수신하는 이벤트를 받기 위해서 BLECharacteristicCallbacks 클래스를 상속 받아서 구현 합니다.

전체 소스

#include <M5Stack.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      M5.Lcd.println("connect");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      M5.Lcd.println("disconnect");
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic *pCharacteristic) {
    M5.Lcd.println("read");
    pCharacteristic->setValue("Hello World!");
  }

  void onWrite(BLECharacteristic *pCharacteristic) {
    M5.Lcd.println("write");
    std::string value = pCharacteristic->getValue();
    M5.Lcd.println(value.c_str());
  }
};

void setup() {
  Serial.begin(115200);
  M5.begin();
  M5.setWakeupButton(BUTTON_A_PIN);
  M5.Lcd.println("BLE start.");
  m5.Speaker.mute();

  BLEDevice::init("m5-stack"); // BLD 이름 설정
  BLEServer *pServer = BLEDevice::createServer(); // BLE 서버 생성
  pServer->setCallbacks(new MyServerCallbacks()); // BLE 상태 콜백 함수 등록 (접속 이벤트 처리)
  BLEService *pService = pServer->createService(SERVICE_UUID); // 서비스 UUID 등록
  pCharacteristic = pService->createCharacteristic( 
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE |
                                         BLECharacteristic::PROPERTY_NOTIFY |
                                         BLECharacteristic::PROPERTY_INDICATE
                                       ); // BLE 특성 등록
  pCharacteristic->setCallbacks(new MyCallbacks()); // BLE 문자열 수신 콜백 함수 등록
  pCharacteristic->addDescriptor(new BLE2902());

  pService->start(); // BLE 서버 실행 -> BLE 이름 노출
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start(); 
}

void loop() {
  if(M5.BtnA.wasPressed()) {
    M5.powerOFF();
  }
  if (deviceConnected) { // BLE가 연결되어 있는 경우
    if(M5.BtnB.wasPressed()) { // M5Stack의 B버튼이 선택한 경우
      M5.Lcd.println("Button B pressed!");
      pCharacteristic->setValue("Button B pressed!"); // BLE 클라이언트에 전달할 문자열 설정
      pCharacteristic->notify(); // BLE 클라이언트에 문자열 전달
    }
  }
  M5.update();
}

App Inventor 2 : BLE 클라이언트 만들기

App Inventor는 MIT에서 만든 블럭 형태의 코딩으로 안드로이드 어플을 쉽게 만들 수 있어서 IOT 개발시 많이 사용됩니다. 기본적으로 BT 통신만 지원했고, BLE 통신은 지원하지 않았지만, 최근에 확장 라이브러리를 통해서 지원하고 있습니다. BLE 확장 라이브러리를 다운 받아서 Import 하시면 BLE 통신을 구현 할 수 있습니다.

예제는 BLE 목록을 조회하고, 조회된 목록에서 M5Stack를 선택하여 BLE 서버에 접속하고, 미리 정해둔 서비스와 특성을 등록하고, M5Stack에서 B버튼을 선택시 전달 받은 문자열을 텍스트박스에 출력하고, 안드로이드 어플에서 문자열을 M5Stack에 전송 합니다.

App Inventor BLE 확장 라이브러리 다운로드

http://appinventor.mit.edu/extensions 에 접속하셔서 BluetoothLE.aix 파일을 다운 받습니다.

App Inventor 프로젝트 만들기 (http://ai2.appinventor.mit.edu/)

http://ai2.appinventor.mit.edu/ 접속해서 [새 프로젝트 시작하기...] 선택합니다.

프로젝트 이름 설정

App Inventor BLE 확장 라이브러리 Import

팔레트 -> Extension -> import extension 에서 파일 선택버튼을 누른 후 위에서 다운받은 bluetoothLE.aix 를 선택해줍니다.

App Inventor 화면 구성

전역 변수 선언 (서비스, 특성 UUID 정의)

[버튼1]을 선택해서 BLE 목록 조회

BLE 목록이 조회되면 목록를 리스트 박스(목록_선택1)에 담기

BLE 목록에서 접속하려고 하는 BLE 기기 선택했을 경우 BLE 주소 UUID(리스트의 문자열 1에서 17의 문자열)를 가지고 와서 해당 BLE에 접속 시도

BLE 기기에 접속하면 BLE로 문자열 수신 이벤트를 받기 위해서 서비스와 특성 등록

BLE 기기에서 문자열을 수신 했을 경우 텍스트 박스(텍스트_상자1)에 수신한 문자열 출력

[버튼3]을 선택해서 텍스트 박스(텍스트_상자2)의 문자열을 BLE기기에 전송

[버튼2]을 선택해서 BLE 연결끊기

App Inventor 전체 소스

실행 영상

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

  1. 김기운 2019.07.24 20:41  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 현재 앱 인벤터에서 ble를 추가하고 블루투스4.0을 연결하기 위해서 어플을 제작하는 중에 있습니다. 그런대 제가 생각한것 만큼 블루투스 연결이 잘 안되는대 혹시 프로젝트 파일이나 apk 공유해주실수 있나요....
    갤럭시 s9+에서 어플을 사용할 예정이고 제가 연결하고 싶은 기기는 TDA7492P 2*25라는 제품으로 디지털 앰프 모듈입니다 일반적인 방법으로 연결이 되지않아 BLE를 사용하려고 합니다

  2. ram 2019.10.29 13:46  댓글주소  수정/삭제  댓글쓰기

    서비스 uuid 특성 uuid값은 임의로 정하신건가요? ble모듈마다 고유의번호가 있나요 어떻게 조회를 하지요?

M5Stack : PWM 이용해서 LED 밝기 조절

OS/M5Stack 2019. 7. 19. 00:58 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stack : PWM 이용해서 LED 밝기 조절

M5Go의 PORT A의 PWM을 이용해서 LED의 밝기 조절하는 예제를 실행해보았습니다. M5Stack의 A버튼을 선택하면 밝기를 높여주고, B버튼을 선택하면 어둡게 해주는 예제입니다.

M5Go Port

PORT A : GPIO 21, 22 pin
PORT B : GPIO 26, 36 pin
PORT C : GPIO 16, 17 pin

소스

#include <M5Stack.h>

int pwmChannel = 1;
int ledPin = 21;
int ledState = 0;

void setup() {
  M5.begin(true, false, true);
  M5.Lcd.setTextFont(4);
  M5.Lcd.setCursor(70, 100);
  M5.Lcd.print("PWM Example");

  ledcSetup(pwmChannel, 10000, 8);
  ledcAttachPin(ledPin, pwmChannel);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (M5.BtnA.isPressed()) {
    ledState += 5;
    if (ledState > 255)
      ledState = 255;
    ledcWrite(pwmChannel, ledState);
    delay(25);
  }
  if (M5.BtnB.isPressed()) {
    ledState -= 5;
    if (ledState < 1)
      ledState = 0;
    ledcWrite(pwmChannel, ledState);
    delay(25);
  }
  M5.update();
}

실행

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

M5Stack : LED 켜고 끄기

OS/M5Stack 2019. 5. 22. 00:37 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

M5Stack : LED 끄고 켜기

M5Go의 PORT A를 이용해서 1초 단위로 LED를 켜고 끄기를 해보았습니다. 간단한 예제이지만 디지탈 On / Off 하는 예제를 만들어 보았습니다.

M5Go Port

PORT A : GPIO 21, 22 pin
PORT B : GPIO 26, 36 pin
PORT C : GPIO 16, 17 pin

소스

#include <M5Stack.h>

int ledPinA = 21;
int ledPinB = 22;

/*
int ledPinA = 26;
int ledPinB = 36; // 미확인
*/
/*
int ledPinA = 16;
int ledPinB = 17;
*/
void setup() {
  M5.begin(true, false, true);
  M5.Lcd.setTextFont(4);
  M5.Lcd.setCursor(100, 100);
  M5.Lcd.print("LED TEST");

  pinMode(ledPinA, OUTPUT);
  pinMode(ledPinB, OUTPUT);
}

void loop() {
  digitalWrite(ledPinA, HIGH);
  digitalWrite(ledPinB, HIGH);
  delay(1000);           
  digitalWrite(ledPinA, LOW);
  digitalWrite(ledPinB, LOW);
  delay(1000);            
}

실행

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

M5Stack Faces 게임파일 (NES 파일) 업로드

OS/M5Stack 2019. 5. 21. 00:15 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stack Faces 게임파일 (NES 파일) 업로드

M5Stack Faces의 GameBoy 키보드로 게임을 하기 위해서 게임파일 (NES 파일)을 M5Stack에 업로드 하는 방법을 정리해 보았습니다.

펌웨어 다운로드

Github에서 firmware.zip이라는 게임 보이 시뮬레이터 펌웨어를 다운로드하십시오. 그리고 firmware.zip의 압축을 풉니다.

게임파일 (NES 파일) 업로드

Open Flash Download Tools Espressif(다운로드)에서 [ESP32 DownloadTool] 옵션을 선택하고 4 개의 파일을 선택한 후 다음 그림과 같이 해당 작업을 실행하십시오. (펌웨어 파일 선택, 직렬 포트, [ERASE] 및 프로그램 플래시[START] )

ESPFlashDownloadTool_v3.6.4.exe 실행 - [ESP32 DownloadTool] 버튼 선택 - 펌웨어파일 선택 - COM포트 / 속도 설정 - [ERASE] 버튼 선택 - [START] 버튼 선택

 


[리셋] 버튼 선택

실행

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요

M5Stick : MPU-9250 (9-Axis IMU) 센서

OS/M5Stack 2019. 5. 19. 02:36 Posted by 파란크리스마스

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stick(MPU-9250 : 9-Axis IMU) 제어

M5Stick에 내장 되어 있는 MPU9250은 MPU6050의 후속 모델로 가속도와 자이로센서로 I2C (Inter Integrated Circuit) 통신 프로토콜을 통해서 데이터를 추출 할 수 있습니다.

아래 예제 아두이노 소스는 M5Stick의 MPU9250 센서의 추출 값을 시리얼 통신으로 값을 전달하고, PC 소스는 시리얼 통신으로 전달 받은 MPU9250 센서값을 화면에 표현해주는 예제입니다.

아두이노 소스

#include >Wire.h<
//#include >TimerOne.h<
#include "esp_system.h"

#define    MPU9250_ADDRESS            0x68
#define    MAG_ADDRESS                0x0C

#define    GYRO_FULL_SCALE_250_DPS    0x00  
#define    GYRO_FULL_SCALE_500_DPS    0x08
#define    GYRO_FULL_SCALE_1000_DPS   0x10
#define    GYRO_FULL_SCALE_2000_DPS   0x18

#define    ACC_FULL_SCALE_2_G        0x00  
#define    ACC_FULL_SCALE_4_G        0x08
#define    ACC_FULL_SCALE_8_G        0x10
#define    ACC_FULL_SCALE_16_G       0x18

hw_timer_t *timer = NULL;

// This function read Nbytes bytes from I2C device at address Address. 
// Put read bytes starting at register Register in the Data array. 
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.endTransmission();
  
  // Read Nbytes
  Wire.requestFrom(Address, Nbytes); 
  uint8_t index=0;
  while (Wire.available())
  Data[index++]=Wire.read();
}


// Write a byte (Data) in device (Address) at register (Register)
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.write(Data);
  Wire.endTransmission();
}



// Initial time
long int ti;
volatile bool intFlag=false;


// Counter
long int cpt=0;

void IRAM_ATTR callback()
{ 
  intFlag=true;
  digitalWrite(13, digitalRead(13) ^ 1);
}

// Initializations
void setup()
{
  // Arduino initializations
  Wire.begin();
  Serial.begin(115200);
  
  // Set accelerometers low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,29,0x06);
  // Set gyroscope low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,26,0x06);
 
  
  // Configure gyroscope range
  I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_1000_DPS);
  // Configure accelerometers range
  I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_4_G);
  // Set by pass mode for the magnetometers
  I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
  
  // Request continuous magnetometer measurements in 16 bits
  I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
  
   pinMode(13, OUTPUT);

  /*
  Timer1.initialize(10000);         // initialize timer1, and set a 1/2 second period
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt
  */

  /* Use 1st timer of 4 */
  /* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
  timer = timerBegin(0, 80, true);

  /* Attach onTimer function to our timer */
  timerAttachInterrupt(timer, &callback, true);

  /* Set alarm to call onTimer function every second 1 tick is 1us
  =< 1 second is 1000000us */
  /* Repeat the alarm (third parameter) */
  timerAlarmWrite(timer, 10000, true);

  /* Start an alarm */
  timerAlarmEnable(timer);
  Serial.println("start timer");

  // Store initial time
  ti=millis();
}

// Main loop, read and display data
void loop()
{
  while (!intFlag);
  intFlag=false;
  
  // Display time
  Serial.print (millis()-ti,DEC);
  Serial.print ("\t");

  
  // _______________
  // ::: Counter :::
  
  // Display data counter
//  Serial.print (cpt++,DEC);
//  Serial.print ("\t");
  
 
 
  // ____________________________________
  // :::  accelerometer and gyroscope ::: 

  // Read accelerometer and gyroscope
  uint8_t Buf[14];
  I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
  
  // Create 16 bits values from 8 bits data
  
  // Accelerometer
  int16_t ax=-(Buf[0]>>8 | Buf[1]);
  int16_t ay=-(Buf[2]>>8 | Buf[3]);
  int16_t az=Buf[4]>>8 | Buf[5];

  // Gyroscope
  int16_t gx=-(Buf[8]>>8 | Buf[9]);
  int16_t gy=-(Buf[10]>>8 | Buf[11]);
  int16_t gz=Buf[12]>>8 | Buf[13];
  
    // Display values
  
  // Accelerometer
  Serial.print (ax,DEC); 
  Serial.print ("\t");
  Serial.print (ay,DEC);
  Serial.print ("\t");
  Serial.print (az,DEC);  
  Serial.print ("\t");
  
  // Gyroscope
  Serial.print (gx,DEC); 
  Serial.print ("\t");
  Serial.print (gy,DEC);
  Serial.print ("\t");
  Serial.print (gz,DEC);  
  Serial.print ("\t");

  
  // _____________________
  // :::  Magnetometer ::: 

  
  // Read register Status 1 and wait for the DRDY: Data Ready
  
  uint8_t ST1;
  do
  {
    I2Cread(MAG_ADDRESS,0x02,1,&ST1);
  }
  while (!(ST1&0x01));

  // Read magnetometer data  
  uint8_t Mag[7];  
  I2Cread(MAG_ADDRESS,0x03,7,Mag);
  
  // Create 16 bits values from 8 bits data
  
  // Magnetometer
  int16_t mx=-(Mag[3]>>8 | Mag[2]);
  int16_t my=-(Mag[1]>>8 | Mag[0]);
  int16_t mz=-(Mag[5]>>8 | Mag[4]);
  
  // Magnetometer
  Serial.print (mx+200,DEC); 
  Serial.print ("\t");
  Serial.print (my-70,DEC);
  Serial.print ("\t");
  Serial.print (mz-700,DEC);  
  Serial.print ("\t");

  // End of line
  Serial.println("");
//  delay(100);    
}

PC 시리얼 통신 소스 예제

main.c 소스

#include <stdio.h>
#include <windows.h>

int main()
{
    HANDLE hSerial = CreateFile("\\\\.\\COM23", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(hSerial==INVALID_HANDLE_VALUE) {
        if(GetLastError()==ERROR_FILE_NOT_FOUND) {
            printf("Device not found\n");
            return -1;
        }
        printf("Error while opening the device\n");
        return -2;
    }
    printf("ok\n");
}

컴파일 실행

$ gcc main.c -o main.exe
$ ./main.exe
Device not found

실행

소스 출처 : MPU-9250 and Arduino (9-Axis IMU) · Lulu's blog

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글을 달아 주세요