ESP32をArduino IDEから使う時のTipsのメモ

ESP32をArduino IDEで開発する際に気がついたちょっとしたTipsのメモ
自分の覚書も兼ねているので随時更新していく予定

# サーボ関連

サーボ関数は動かないのでLEDコントロールを使う。サンプルは以下。

``` survoTest.ino
//ESP32 Servo Control sample

//use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0 0
//use 10 bit precission for LEDC timer
#define LEDC_TIMER_BIT 10
//use 50 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 50
//ServoPWM pin
#define SRV_PIN 13

int min = 26; // (26/1024)*20ms = 0.5 ms (-90deg)
int max = 122; // (122/1024)*20ms = 2.4 ms (+90deg)

void setup() {

// Setup timer and attach timer to a led pin
 ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_BIT);
 ledcAttachPin(SRV_PIN, LEDC_CHANNEL_0);

ledcWrite(0, min);

}

void loop() {

ledcWrite(0, min);

for(int n = min; n <= max; n++){
 ledcWrite(0, n);
 delay(20);
 }
}
```

# Neopixel(WS2812)関連
基本はAdafruitのNeopixel Libraryが使える
https://github.com/adafruit/Adafruit_NeoPixel

ESP32で使う場合はshow()メソッドの前にdelay(1)を入れると安定する
割り込みでエラーが出る場合の対処方法は以下を参考
https://github.com/adafruit/Adafruit_NeoPixel/issues/139

Mr.MartyMacGyverのライブラリも使える
https://github.com/MartyMacGyver/ESP32-Digital-RGB-LED-Drivers
安定しているが記述が複雑なので、Adafruitのライブラリの方が簡単
 
# I2C関連
 I2Cを使う時はESP32標準のwire関数の引数にピンを指定する

[Unopuino32](https://thousandiy.wordpress.com/2017/07/05/esp-wroom-32-breakout-board-unopuino32s-cp2102-version/)の場合は以下のピンを割り当てている

```
int SDA32 = 22;
int SCL32 = 23;
Wire.begin(SDA32, SCL32);
```
## I2C OLED(SSD1306)用のライブラリ
https://github.com/squix78/esp8266-oled-ssd1306
Unopuino32用であればI2Cピン指定を以下の様に修正

```
SSD1306 display(0x3c, 22, 23); // slvAdr, SDA, SCL
```

小型OLEDはaitendoやebayから数百円で購入する事が可能。但し、ピンの並び順が”VCC-GND-SCL-SDA”になっている必要あり。

2017/9/23時点で以下のものはピン配置確認済
aitendo: http://www.aitendo.com/product/14959
ebay: http://www.ebay.com/itm/281740440799
aliexpressで購入すると商品写真とピン配置が異なる事があるので要注意
 

# タイマー割り込み

タイマー割り込みを使う場合は、ESP32 example sketchの”RepeatTimer”を参考に以下のコードを追加

```
// Timer Interrupt setting
hw_timer_t * timer = NULL;

volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

void IRAM_ATTR onTimer(){
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);

  /*** ここにタイマー割り込みで実行するコードを記載 ***/

  portEXIT_CRITICAL_ISR(&timerMux);
  // Give a semaphore that we can check in the loop
  xSemaphoreGiveFromISR(timerSemaphore, NULL);
  // It is safe to use digitalRead/Write here if you want to toggle an output
}

void setup() {
  // Create semaphore to inform us when the timer has fired
  timerSemaphore = xSemaphoreCreateBinary();

  // Use 1st timer of 4 (counted from zero).
  // Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more info).
  timer = timerBegin(0, 80, true);

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

  // Set alarm to call onTimer function every second (value in microseconds).
  // Repeat the alarm (third parameter)
  timerAlarmWrite(timer, 1000, true);

  // Start an alarm
  timerAlarmEnable(timer);
}
```

# analogWrite()問題

“Arduino core for the ESP32″ではanalogWrite()関数をサポートしていない

代わりに、ledcWrite()関数を使用する事でPWM出力が可能
ESP32の場合LEDCは任意のピンに割り当てることが出来る

ESP32 example sketchの”LEDCSoftwareFade”を参考に以下の様に記述する

```
const int LED_PIN = 27; // PWM出力するPin No.
// use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0 0
// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT 13
// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 5000

// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
 // calculate duty, 8191 from 2 ^ 13 - 1
 uint32_t duty = (8191 / valueMax) * min(value, valueMax);

// write duty to LEDC
 ledcWrite(channel, duty);
}

void setup() {
 // Setup timer and attach timer to a led pin
 ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
 ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);
}

void loop(){
  for(int i=0; i<256; i++){
    ledcAnalogWrite(LEDC_CHANNEL_0, i);
    delay(10); // change delay time can breath faster or slower
   }
}
```

# Wifi経由でIFTTTを使う
以下の手順で出来る
[Wifi経由でIFTTTへ接続しLINEへ通知](https://thousandiy.wordpress.com/2017/10/17/esp32_ifttt_line/)

# BLEライブラリを使ってみる

自分の過去記事を参照
[Arduino IDEでBLEライブラリを導入](https://qiita.com/tomorrow56/items/afa06e206eec9fafcc7a)
[ESP32 ArduinoIDEでBLE経由で温度を通知](https://qiita.com/tomorrow56/items/6c023d56b298b7cac64a)

#WiFiのSSID、パスワードを外部から設定しアクセスポイントに接続

##ESP-TOUCHを使う
ESP32のサンプルスケッチの”WiFiSmartConfig”を参考にする
“ESP-TOUCH”という仕組みを使いスケッチ内にSSID、パスワードを記述せずにスマホのアプリからAPに接続可能
[ESP-TOUCH Overview](http://espressif.com/en/products/software/esp-touch/overview)
[ESP-TOUCHユーザーガイド](http://espressif.com/sites/default/files/documentation/30b-esp-touch_user_guide_en_v1.1_20160412_0.pdf)

設定用アプリ
[Espressif Esptouch (iOS)](https://itunes.apple.com/jp/app/espressif-esptouch/id1071176700?mt=8)
[ESPert SmartConfig (Android)](https://play.google.com/store/apps/details?id=io.espert.espertapp.smartconfig)

##WifiManagerを使う
こちらを使えばブラウザ経由で任意のAPに接続できる
[WifiManager-ESP32](https://github.com/zhouhan0126/WIFIMANAGER-ESP32)
具体的な手順はQiitaの投稿を参照
[ESP32 WiFiのSSID、パスワードを外部から設定しアクセスポイントに接続](https://qiita.com/tomorrow56/items/8c2dfdf61d4741ba91de)