14_Arduino-ESP32_BLE充当LVGL输入设备

629 阅读3分钟

1_BLE充当LVGL输入设备

安装库

NimBLE-Arduino

SC01-Plus_BLE.ino

#include <NimBLEDevice.h>
#include <lvgl.h>
#include "demos/lv_demos.h"
#include <ArduinoJson.h>
#include "LovyanGFX_Driver.h"

LGFX tft;

static NimBLEServer *pServer;

static uint16_t touch_x = 0;
static uint16_t touch_y = 0;
static uint8_t touch_click = 0;

// 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"

class MyServerCallbacks : public NimBLEServerCallbacks {
  void onConnect(NimBLEServer *pServer) {
    NimBLEDevice::startAdvertising();
  };
  void onDisconnect(NimBLEServer *pServer) {
    NimBLEDevice::startAdvertising();
  };
};

class MyCallbacks : public NimBLECharacteristicCallbacks {
  void onWrite(NimBLECharacteristic *pCharacteristic) {
    String stringjson = pCharacteristic->getValue().c_str();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, stringjson);
    // json解析
    touch_x = (uint16_t)doc["x"];
    touch_y = (uint16_t)doc["y"];
    touch_click = 1;    
  };
};

TaskHandle_t Task;

/*更改为您的屏幕分辨率*/
static const uint32_t screenWidth = 480;
static const uint32_t screenHeight = 320;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[2][screenWidth * 30];

#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *fn_name, const char *dsc) {
  Serial.printf("%s(%s)@%d->%s\r\n", file, fn_name, line, dsc);
  Serial.flush();
}
#endif

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  if (tft.getStartCount() == 0) {
    tft.endWrite();
  }

  tft.pushImageDMA(area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1, (lgfx::swap565_t *)&color_p->full);

  lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}

/*Read the touchpad*/
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
  uint16_t touchX, touchY;
  touchX = touch_x;
  touchY = touch_y;

  if (!touch_click) {
    data->state = LV_INDEV_STATE_REL;
  } else {
    data->state = LV_INDEV_STATE_PR;

    /*Set the coordinates*/
    data->point.x = touchX;
    data->point.y = touchY;
    touch_click = 0;
  }
}

void setup() {
  Serial.begin(115200);

  tft.init();
  tft.initDMA();
  tft.startWrite();

  lv_init();

  lv_disp_draw_buf_init(&draw_buf, buf[0], buf[1], screenWidth * 30);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  /*Change the following line to your display resolution*/
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_t *indev = lv_indev_drv_register(&indev_drv);
  lv_obj_t *cursor_img = lv_img_create(lv_scr_act());
  lv_img_set_src(cursor_img, LV_SYMBOL_OK);
  lv_indev_set_cursor(indev, cursor_img);

  lv_demo_widgets();

  xTaskCreatePinnedToCore(
    Taskcode, /* Task function. */
    "Task",   /* name of task. */
    10000,    /* Stack size of task */
    NULL,     /* parameter of the task */
    0,        /* priority of the task */
    &Task,    /* Task handle to keep track of created task */
    0);       /* pin task to core 1 */
}

void loop() {
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
}

//Taskcode
void Taskcode(void *pvParameters) {

  // Create the BLE Device
  NimBLEDevice::init("NimBLE-Arduino");

  NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND);

  // Create the BLE Server
  pServer = NimBLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  NimBLEService* pDeadService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  NimBLECharacteristic* pCharacteristic = pDeadService->createCharacteristic(
    CHARACTERISTIC_UUID,
    NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC);

  pCharacteristic->setCallbacks(new MyCallbacks());
  // Start the service
  pDeadService->start();

  // Start advertising
    NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(SERVICE_UUID);
    pAdvertising->setScanResponse(true);
    pAdvertising->start();

  for (;;) {
  /** 在这里做你的事,这只是向所有连接的客户端发送垃圾邮件通知*/
    if(pServer->getConnectedCount()) {
        NimBLEService* pSvc = pServer->getServiceByUUID(SERVICE_UUID);
        if(pSvc) {
            NimBLECharacteristic* pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
            if(pChr) {
                pChr->notify(true);
            }
        }
    }

  delay(2000);
  }
}

LovyanGFX_Driver.h

#define LGFX_USE_V1
#include <LovyanGFX.hpp>

class LGFX : public lgfx::LGFX_Device {

  lgfx::Panel_ST7796 _panel_instance;

  lgfx::Bus_Parallel8 _bus_instance;

  lgfx::Light_PWM _light_instance;

public:
  LGFX(void) {
    {
      auto cfg = _bus_instance.config();

      cfg.port = 0;
      cfg.freq_write = 40000000;
      cfg.pin_wr = 47;  // WR を接続しているピン番号
      cfg.pin_rd = -1;  // RD を接続しているピン番号
      cfg.pin_rs = 0;   // RS(D/C)を接続しているピン番号
      cfg.pin_d0 = 9;   // D0を接続しているピン番号
      cfg.pin_d1 = 46;  // D1を接続しているピン番号
      cfg.pin_d2 = 3;   // D2を接続しているピン番号
      cfg.pin_d3 = 8;   // D3を接続しているピン番号
      cfg.pin_d4 = 18;  // D4を接続しているピン番号
      cfg.pin_d5 = 17;  // D5を接続しているピン番号
      cfg.pin_d6 = 16;  // D6を接続しているピン番号
      cfg.pin_d7 = 15;  // D7を接続しているピン番号

      _bus_instance.config(cfg);               // 設定値をバスに反映します。
      _panel_instance.setBus(&_bus_instance);  // バスをパネルにセットします。
    }

    {                                       // 表示パネル制御の設定を行います。
      auto cfg = _panel_instance.config();  // 表示パネル設定用の構造体を取得します。

      cfg.pin_cs = -1;    // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst = 4;    // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy = -1;  // BUSYが接続されているピン番号 (-1 = disable)

      // ※ 以下の設定値はパネル毎に一般的な初期値が設定さ BUSYが接続されているピン番号 (-1 = disable)れていますので、不明な項目はコメントアウトして試してみてください。

      cfg.memory_width = 320;    // ドライバICがサポートしている最大の幅
      cfg.memory_height = 480;   // ドライバICがサポートしている最大の高さ
      cfg.panel_width = 320;     // 実際に表示可能な幅
      cfg.panel_height = 480;    // 実際に表示可能な高さ
      cfg.offset_x = 0;          // パネルのX方向オフセット量
      cfg.offset_y = 0;          // パネルのY方向オフセット量
      cfg.offset_rotation = 1;   //值在旋转方向的偏移0~7(4~7是倒置的)
      cfg.dummy_read_pixel = 8;  // 在读取像素之前读取的虚拟位数
      cfg.dummy_read_bits = 1;   // 读取像素以外的数据之前的虚拟读取位数
      cfg.readable = false;      // 如果可以读取数据,则设置为 true
      cfg.invert = true;         // 如果面板的明暗反转,则设置为 true
      cfg.rgb_order = false;     // 如果面板的红色和蓝色被交换,则设置为 true
      cfg.dlen_16bit = false;    // 对于以 16 位单位发送数据长度的面板,设置为 true
      cfg.bus_shared = false;    // 如果总线与 SD 卡共享,则设置为 true(使用 drawJpgFile 等执行总线控制)

      _panel_instance.config(cfg);
    }

    {                                       // バックライト制御の設定を行います。(必要なければ削除)
      auto cfg = _light_instance.config();  // バックライト設定用の構造体を取得します。

      cfg.pin_bl = 45;      // バックライトが接続されているピン番号
      cfg.invert = false;   // バックライトの輝度を反転させる場合 true
      cfg.freq = 44100;     // バックライトのPWM周波数
      cfg.pwm_channel = 1;  // 使用するPWMのチャンネル番号

      _light_instance.config(cfg);
      _panel_instance.setLight(&_light_instance);  // バックライトをパネルにセットします。
    }

    setPanel(&_panel_instance);  // 使用するパネルをセットします。
  }
};