//Controlled with a joystick IrDA // ESP32C3 // #include #include #include #include #include "yamazen.h" //#define DEBUG true //シーケンスデバッグプリント #define KHZ 38 //変調周波数(kHz) #define PIN_SEND 6 //制御PIN(GPIO3) IRsend irsend(PIN_SEND); #define MAXOFFSET (4095) #define XOFFSET (2360) #define YOFFSET (2335) #define DEFAREA (1300) #define JOYSTICK_VRx 0 //GPIO0(ADC1_0) #define JOYSTICK_VRy 1 //GPIO1(ADC1_1) #define JOYSTICK_SW 2 //GPIO2 #define RETBTN_SW 3 //GPIO3 //JOYSTICK Direction // 7 8 9 // 4 5 6 // 1 2 3 //#define ALL_DIRECTION true //8方向判定 #define JS_DIR_CENTER 5 //Center #define JS_DIR_RIGHT 6 //Right #define JS_DIR_UP 8 //Up #define JS_DIR_LEFT 4 //Left #define JS_DIR_DOWN 2 //Down int joyDirec(int x, int y) { float r, t; int num; //距離を1/10にして計算 x /= 10; y /= 10; r = sqrt((float)x * x + (float)y * y); //0の場合の処理 if(x == 0) { if(y > 0) { t = 90; } else if(y < 0) { t = 270; } else { t = 0; } } else { t = atan((float)y / x) / 3.1415926 * 180.0; //t = atan2(y, x) / 3.1415926 * 180.0; if(x < 0) { t += 180; } else if(y < 0) { t += 360; } } #ifndef ALL_DIRECTION //4エリア判定 if(r > DEFAREA/10) { if(t < 45) { num = JS_DIR_RIGHT; //6:Right } else if(t < 135) { num = JS_DIR_UP; //8:Up } else if(t < 225) { num = JS_DIR_LEFT; //4:Left } else if(t < 315) { num = JS_DIR_DOWN; //2:Down } else { num = JS_DIR_RIGHT; //6:Right } } else { num = JS_DIR_CENTER; //5:Center } #else //8エリア判定 if(r > DEFAREA/10) { if(t < 22) { num = JS_DIR_RIGHT; //6:Right } else if(t < 67) { num = 9; } else if(t < 112) { num = JS_DIR_UP; //8:Up } else if(t < 157) { num = 7; } else if(t < 202) { num = JS_DIR_LEFT; //4:Left } else if(t < 247) { num = 1; } else if(t < 292) { num = JS_DIR_DOWN; //2:Down } else if(t < 337) { num = 3; } else { num = JS_DIR_RIGHT; //6:Right } } else { num = JS_DIR_CENTER; //5:Center } #endif #if 0 if(r > DEFAREA/10) { Serial.print("x = "); Serial.print(x); Serial.print(", y = "); Serial.print(y); Serial.print(", r = "); Serial.print(r); Serial.print(", t = "); Serial.println(t); } #endif return(num); } //送信4Byte(カスタマーコード2Byte+リモコンコード+反転リモコンコード) void send_cmd(uint32_t cmd) { uint64_t send = 0; send = (uint64_t)reverseBits(rmt_address >> 8, 8) << 24; // カスタマーコード(上位8bit) send += (uint64_t)reverseBits(rmt_address&0xff, 8) << 16; // カスタマーコード(下位8bit) send += reverseBits(cmd, 8) << 8; // リモコンコードを順番入れ替えて送信 send += reverseBits(cmd, 8) ^ 0xff; // リモコンコードのビット反転(パリティ) irsend.sendNEC(send); // 送信 #if 0 // デバッグ表示 Serial.printf("Send IR : 0x%08LX", send); Serial.printf("(customer=0x%04X, ", rmt_address); Serial.printf("command=0x%02X)\n", cmd); #endif } #define bitMask(n) ((uint32_t)(1ULL << (n))) //BIT64()と同じか? //時間復帰は実験用 #ifndef DEBUG #define TIME2SLEEP 3600000UL //スリープ時間(ms)最長は約71.5分(4,294,967,294μS) #else #define TIME2SLEEP 60000UL //デバッグ用 #endif #define uSParS 1000UL //μSからmsへの変換係数 #define TIME2SLEEPBEGIN 20000UL //スリープ開始時間(ms) #define TIME2DELAY 250UL //ウエイト時間(ms) static unsigned long timer_count; static int prev_dir = 5; static int prev_sw = HIGH; static int prev_btn = HIGH; void setup() { #ifdef DEBUG Serial.begin(115200); #endif pinMode(JOYSTICK_VRx, INPUT); pinMode(JOYSTICK_VRy, INPUT); pinMode(JOYSTICK_SW, INPUT_PULLUP); pinMode(RETBTN_SW, INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); #ifdef DEBUG delay(2000); Serial.printf("*BEGIN: timer_count = %d\n", timer_count); #endif timer_count = 0; //時間復帰は実験用 // esp_sleep_enable_timer_wakeup(TIME2SLEEP * uSParS); //タイマー復帰 //ESP32C3の場合は以下,使えるのはGPIO 0-5まで(0,1はシリアルなので利用時は注意) //esp_deep_sleep_enable_gpio_wakeup(BIT64(RETBTN_SW), ESP_GPIO_WAKEUP_GPIO_LOW); //or ESP_GPIO_WAKEUP_GPIO_HIGH //esp_deep_sleep_enable_gpio_wakeup(BIT64(JOYSTICK_SW), ESP_GPIO_WAKEUP_GPIO_LOW); esp_deep_sleep_enable_gpio_wakeup(BIT64(RETBTN_SW)|BIT64(JOYSTICK_SW), ESP_GPIO_WAKEUP_GPIO_LOW); digitalWrite(LED_BUILTIN, HIGH); irsend.begin(); } void loop() { int vrx, vry, sw, btn; int dir; #ifndef CENTER_POINT_VALUE vrx = analogRead(JOYSTICK_VRx) - XOFFSET; vry = YOFFSET - analogRead(JOYSTICK_VRy); #else //中心値確認版 vrx = analogRead(JOYSTICK_VRx); vry = analogRead(JOYSTICK_VRy); Serial.print("X = "); Serial.print(vrx); Serial.print(", Y = "); Serial.println(vry); delay(1000); #endif sw = digitalRead(JOYSTICK_SW); btn = digitalRead(RETBTN_SW); dir = joyDirec(vrx, vry); //無操作確認 if(btn == HIGH && prev_btn == HIGH && sw == HIGH && prev_sw == HIGH && dir == JS_DIR_CENTER && prev_dir == JS_DIR_CENTER) { //入力なし if(timer_count >= TIME2SLEEPBEGIN) { //スリープ開始 #ifdef DEBUG Serial.printf("*SLEEP: timer_count = %d\n", timer_count); delay(2000); #endif digitalWrite(LED_BUILTIN, LOW); esp_deep_sleep_start(); } timer_count += TIME2DELAY; } else { if(prev_btn != btn) { prev_btn = btn; if(prev_btn == LOW) { //return botton ON //irsend.sendRaw(return_raw, sizeof(return_raw) / sizeof(uint16_t), KHZ); #ifdef DEBUG Serial.printf("*BUTTON: RETURN\n"); Serial.flush(); #endif send_cmd(return_cmd); } } else if(prev_sw != sw) { prev_sw = sw; if(prev_sw == LOW) { //swicth ON //irsend.sendRaw(select_raw, sizeof(select_raw) / sizeof(uint16_t), KHZ); #ifdef DEBUG Serial.printf("*BUTTON: OK\n"); #endif send_cmd(select_cmd); } } else /* else if(dir != prev_dir) */ { //リピートしない場合 #ifdef DEBUG //方向デバック Serial.printf("*JOYSTICK: direct = %d\n", dir); #endif switch(prev_dir = dir) { case 2: //Down //irsend.sendRaw(down_raw, sizeof(down_raw) / sizeof(uint16_t), KHZ); //irsend.sendNEC(0x4040, 0x16, 1); 動作しない send_cmd(down_cmd); break; case 4: //Left //irsend.sendRaw(left_raw, sizeof(left_raw) / sizeof(uint16_t), KHZ); send_cmd(left_cmd); break; case 6: //Right //irsend.sendRaw(right_raw, sizeof(right_raw) / sizeof(uint16_t), KHZ); send_cmd(right_cmd); break; case 8: //Up //irsend.sendRaw(up_raw, sizeof(up_raw) / sizeof(uint16_t), KHZ); send_cmd(up_cmd); break; } #if 0 //XYデバック Serial.print("X = "); Serial.print(vrx); Serial.print(", Y = "); Serial.print(vry); Serial.print(", SW = "); Serial.println(sw); delay(1000); #endif } timer_count = 0; } delay(TIME2DELAY); }