这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » [Let'sDo第3期]DIY一个电子测光表-过程帖-基础驱动及逻辑控制实现

共1条 1/1 1 跳转至

[Let'sDo第3期]DIY一个电子测光表-过程帖-基础驱动及逻辑控制实现

菜鸟
2024-12-01 00:52:25     打赏

教学视频里面是通过cpy 进行驱动编写及测试的,由于固件不支持ble,所以放弃了,转使用arduino+platformio进行开发

cpy 固件下载地址

https://circuitpython.org/board/adafruit_feather_esp32s3_tft/

https://learn.adafruit.com/adafruit-esp32-s3-tft-feather/circuitpython

双击rst 进入刷入uf2文件模式

将上面下载的固件拖入即可 这里留作备用

硬件相关资料

硬件相关信息可以通过 https://github.com/adafruit/Adafruit-ESP32-S3-TFT-Feather-PCB 进行查看,主控使用的esp32s3  4M flash  2M psram

image.png

原理图

image.png

板载信息

image.png


软件开发及调试屏幕适配


采用tft_espi 库进行驱动

1.修改管脚,根据原理图进行修改user_setup.h

#define TFT_MISO  37  // Automatically assigned with ESP8266 if not defined
#define TFT_MOSI  35  // Automatically assigned with ESP8266 if not defined
#define TFT_SCLK  36  // Automatically assigned with ESP8266 if not defined

#define TFT_CS    7  // Chip select control pin D8
#define TFT_DC    39  // Data Command control pin
#define TFT_RST   40  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1     // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V


#define TFT_BL 45  // LED back-light (only for ST7789 with backlight control pin)

使能驱动

驱动模式

设置 长宽


简单的点灯加量屏

#include <Arduino.h>
#include <Wire.h>
#include <TFT_eSPI.h>  // 引入 TFT_eSPI 库

TFT_eSPI tft;  // 创建 TFT_eSPI 对象

void setup()
{
  // initialize LED digital pin as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  tft.init();  // 初始化 TFT 屏幕
  tft.setRotation(1);           // 调整屏幕方向,根据需要选择合适的值(0、1、2、3)
  tft.fillScreen(TFT_BLACK);    // 设置屏幕背景颜色为黑色
  tft.setTextSize(2);           // 设置文本大小
  tft.setTextColor(TFT_YELLOW);  // 设置文本颜色为白色

}

void loop()
{

    tft.fillScreen(TFT_BLACK);  // 清空屏幕,将屏幕填充为黑色
    tft.setCursor(0, 10);            // 设置文本光标位置,参数:x 坐标,y 坐标
    tft.println("Hello EEPW,I am Chris!");  // 打印文本,参数:文本内容
    // turn the LED on (HIGH is the voltage level)
    digitalWrite(LED_BUILTIN, HIGH);
    // wait for a second
    delay(1000);
    // turn the LED off by making the voltage LOW
    digitalWrite(LED_BUILTIN, LOW);
    // wait for a second
    delay(1000);
}
蓝牙驱动

首先参考蓝牙例程,添加相关头函数

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

指定BLE uuid 及相关变量

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;

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

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

设定接收callback ,收到蓝牙消息是进行舵机控制,server的callback 用于实时检测ble 是否有断开和连接

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

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

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial0.println("*********");
        Serial0.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial0.print(rxValue[i]);
        servo_control();

        Serial0.println();
        Serial0.println("*********");
      }
    }
};

在setup中进行初始化,指定名称,创建相关server 并进行初始化及启动

  // Create the BLE Device
  BLEDevice::init("UART Service");

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

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
										CHARACTERISTIC_UUID_TX,
										BLECharacteristic::PROPERTY_NOTIFY
									);
                      
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
											 CHARACTERISTIC_UUID_RX,
											BLECharacteristic::PROPERTY_WRITE
										);

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");

在主循环中进行连接性判断,如果连接 则进行光lux 信息,传给上位机

    if (deviceConnected) {
        
        pTxCharacteristic->setValue(light_lux);
        pTxCharacteristic->notify();
		delay(10); // bluetooth stack will go into congestion, if too many packets are sent
	}

    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
		// do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
BH1750光传感器

这里采用的是claws/BH1750@^1.3.0 库函数

调用过程如下:

首先调用头函数,声明变量

#include <BH1750.h>
#include <Wire.h>
BH1750 lightMeter;

然后在setup中进行初始化模式,这里库依赖wire 库,需要指定iic 使用的引脚,我板卡连接的是42 41

  Wire.setPins(42,41);
  Wire.begin();
  lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE);

一共支持 6种模式,主要进行针对不同的亮度场景调整精度及测量时间

然后在主循环种检测测量是否完成,完成后,将转换的结果输出给全局变量,然后可以通过全局变量,同步给蓝牙上位机及屏幕

    if (lightMeter.measurementReady(true)) {
        float lux = lightMeter.readLightLevel();
        Serial0.print(F("Light: "));
        Serial0.print(lux);
        Serial0.println(F(" lx"));
        lightMeter.configure(BH1750::ONE_TIME_HIGH_RES_MODE);
        if (lux < 0) {
            Serial0.println(F("Error condition detected"));
        }
        else
        {
            light_lux= (int)lux;
        }
    }
屏幕菜单驱动

屏幕菜单这里调用的是arduinoMenu 库,此库依赖自家的streamflow ,两个库都需求进行安装

neu-rah/ArduinoMenu library @ ^4.21.5
neu-rah/streamFlow @ 0.0.0-alpha+sha.bf16ce8926

首先引用头函数

#include <menu.h>
#include <menuIO/TFT_eSPIOut.h>
#include <menuIO/serialIO.h>

进行一些颜色定义,屏幕信息定义,用于后续创建服务及菜单使用

using namespace Menu;

#define Black RGB565(0,0,0)
#define Red	RGB565(255,0,0)
#define Green RGB565(0,255,0)
#define Blue RGB565(0,0,255)
#define Gray RGB565(128,128,128)
#define LighterRed RGB565(255,150,150)
#define LighterGreen RGB565(150,255,150)
#define LighterBlue RGB565(150,150,255)
#define DarkerRed RGB565(150,0,0)
#define DarkerGreen RGB565(0,150,0)
#define DarkerBlue RGB565(0,0,150)
#define Cyan RGB565(0,255,255)
#define Magenta RGB565(255,0,255)
#define Yellow RGB565(255,255,0)
#define White RGB565(255,255,255)

#define MAX_DEPTH 2
#define GFX_WIDTH 240
#define GFX_HEIGHT 135
#define fontW 10
#define fontH 16


serialIn serial(Serial0);
idx_t serialTops[MAX_DEPTH]={0};
serialOut outSerial(Serial0,serialTops);
TFT_eSPI tft;  // 创建 TFT_eSPI 对象


const colorDef<uint16_t> display_colors[6] MEMMODE = {
  //{{disabled normal,disabled selected},{enabled normal,enabled selected, enabled editing}}
  {{(uint16_t)Black, (uint16_t)Black}, {(uint16_t)Black, (uint16_t)Red,   (uint16_t)Red}}, //bgColor
  {{(uint16_t)White, (uint16_t)White},  {(uint16_t)White, (uint16_t)White, (uint16_t)White}},//fgColor
  {{(uint16_t)Red, (uint16_t)Red}, {(uint16_t)Yellow, (uint16_t)Yellow, (uint16_t)Yellow}}, //valColor
  {{(uint16_t)White, (uint16_t)White}, {(uint16_t)White, (uint16_t)White, (uint16_t)White}}, //unitColor
  {{(uint16_t)White, (uint16_t)Gray},  {(uint16_t)Black, (uint16_t)Red,  (uint16_t)White}}, //cursorColor
  {{(uint16_t)White, (uint16_t)Yellow}, {(uint16_t)Black,  (uint16_t)Red,   (uint16_t)Red}}, //titleColor
};

//控制BH1750 设置接口
result high_lux()
{
     // reduce measurement time - needed in direct sun light
    lightMeter.setMTreg(32);
    return proceed;
}
result Mid_lux()
{
     // typical light environment
    lightMeter.setMTreg(32);
    return proceed;
}
result Low_lux()
{
     // very low light environment
    lightMeter.setMTreg(32);
    return proceed;
}



//customizing a prompt look!
//by extending the prompt class
//this prompt will count seconds and update himself on the screen.
class altPrompt:public prompt {
public:
  unsigned int t=0;
  unsigned int last=0;
  altPrompt(constMEM promptShadow& p):prompt(p) {}
  Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override {
    last=t;
    return out.printRaw(String(t).c_str(),len);
  }
  virtual bool changed(const navNode &nav,const menuOut& out,bool sub=true) {
    t=millis()/1000;
    return last!=t;
  }
};

int selTest=0;
SELECT(selTest,LuxSelect,"LigthMode",doNothing,noEvent,noStyle
  ,VALUE("High",0,high_lux,noEvent)
  ,VALUE("Mid",1,Mid_lux,noEvent)
  ,VALUE("Low",2,Low_lux,noEvent)
);

主菜单设置

MENU(mainMenu,"2024 Let's go No.3",doNothing,noEvent,wrapStyle
  ,SUBMENU(setLed)
  ,OP("servo On",servo_control,enterEvent)
  //,OP("LED Off",myLedOff,enterEvent)
  ,SUBMENU(LuxSelect)
  //,MENU(light_menu)
  ,FIELD(light_lux,"Light: "," lux",0,65535,10,1,doNothing,anyEvent,noStyle)
  //,altOP(altPrompt,"",doNothing,anyEvent)
  ,EXIT("<Back")
);

空闲设置界面

//when menu is suspended
//this function is called when entering or leaving suspended state
// with idleStart and idleend cases
//and at least once in between them (idling case)
//it might also be called for every pool (when in suspended state, idling case)
//for output devices that require refresh (repeated draw, idling case)
result idle(menuOut &o, idleEvent e) {
  o.clear();
  switch(e) {
    case idleStart:o.println("suspending menu!");break;
    case idling:o.println("suspended...");break;
    case idleEnd:o.println("resuming menu.");break;
  }
  return proceed;
}
const panel panels[] MEMMODE = {{0, 0, GFX_WIDTH / fontW, GFX_HEIGHT / fontH}};
navNode* nodes[sizeof(panels) / sizeof(panel)]; //navNodes to store navigation status
panelsList pList(panels, nodes, sizeof(panels) / sizeof(panel)); //a list of panels and nodes
idx_t eSpiTops[MAX_DEPTH]={0};
TFT_eSPIOut eSpiOut(tft,display_colors,eSpiTops,pList,fontW,fontH+1);
menuOut* constMEM outputs[] MEMMODE={&outSerial,&eSpiOut};//list of output devices
outputsList out(outputs,sizeof(outputs)/sizeof(menuOut*));//outputs list controller
NAVROOT(nav,mainMenu,MAX_DEPTH,serial,out);

主循环添加如下代码用于界面动态绘制

    nav.poll();//this device only draws when needed
按键驱动

按键使用poelstra/MultiButton @ ^1.3.0

首先进行include

#include <PinButton.h>

指定管脚并进行对象创建

PinButton btnUp(BTN_UP);
PinButton btnDwn(BTN_DWN);

编写loop函数,用于检测按键状态

void button_loop()
{
    // Check for button presses
    // btnUp.loop();
    // btnDwn.loop();
    btnDwn.update();
    btnUp.update();

    if(btnUp.isSingleClick())
    {
         nav.doNav(upCmd); 
    }
    if(btnUp.isLongClick())
    {
        nav.doNav(enterCmd);
    }
    if(btnDwn.isSingleClick())
    {
         nav.doNav(downCmd); 
    }
    if(btnDwn.isLongClick())
    {
        nav.doNav(escCmd);
    }

}

我这里设置了短按是上下菜单切换,长按是进入和退出操作,将上述检测加入主循环即可

电机控制

此次活动我使用的是180*电机,控制舵机的旋转角度是需要一个周期为20ms左右的脉冲,通过控制脉冲的高电平就能控制旋转角度,控制逻辑如下;

0.5ms ---0度

1ms   --- 45度

1.5ms --- 90度

2ms    --- 135度

2.5ms  --- 180度

这里记录下线的连接方法:三根线:GND(棕色,接负极)、VCC(红色,接电源正极,电压在4.8V~6V之间)和SIG(黄色,信号线)。

这里使用的是 madhephaestus/ESP32Servo @ ^3.0.5

首先进行库引入,申请变量

#include <ESP32Servo.h>
Servo servo1;

setup中进行timer及周期设置

//Allow allocation of all timers
    ESP32PWM::allocateTimer(0);
    ESP32PWM::allocateTimer(1);
    ESP32PWM::allocateTimer(2);
    ESP32PWM::allocateTimer(3);
    servo1.setPeriodHertz(50);      // Standard 50hz servo 20ms
    servo1.attach(servo1Pin, minUs, maxUs);

这里控制实现就是从0到180,然后从180在 到0进行回旋

void servo_control(void)
{
    for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
        // in steps of 1 degree
        servo1.write(pos);
        delay(15);             // waits 20ms for the servo to reach the position
    }
    for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
        servo1.write(pos);
        delay(15);
    }
}

这里实现代码如下

#include <Arduino.h>
#include <Wire.h>
#include <TFT_eSPI.h>  // 引入 TFT_eSPI 库
#include <BH1750.h>
#include <menu.h>
#include <menuIO/TFT_eSPIOut.h>
#include <menuIO/serialIO.h>
#include <PinButton.h>
#include <ESP32Servo.h>

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







#define BTN_UP 5 // Pinnumber for button for up/previous and select / enter actions (don't change this if you want to use the onboard buttons)
#define BTN_DWN 6 // Pinnumber for button for down/next and back / exit actions (don't change this if you want to use the onboard buttons)
using namespace Menu;

#define Black RGB565(0,0,0)
#define Red RGB565(255,0,0)
#define Green RGB565(0,255,0)
#define Blue RGB565(0,0,255)
#define Gray RGB565(128,128,128)
#define LighterRed RGB565(255,150,150)
#define LighterGreen RGB565(150,255,150)
#define LighterBlue RGB565(150,150,255)
#define DarkerRed RGB565(150,0,0)
#define DarkerGreen RGB565(0,150,0)
#define DarkerBlue RGB565(0,0,150)
#define Cyan RGB565(0,255,255)
#define Magenta RGB565(255,0,255)
#define Yellow RGB565(255,255,0)
#define White RGB565(255,255,255)

#define MAX_DEPTH 2
#define GFX_WIDTH 240
#define GFX_HEIGHT 135
#define fontW 10
#define fontH 16
serialIn serial(Serial0);
idx_t serialTops[MAX_DEPTH]={0};
serialOut outSerial(Serial0,serialTops);
TFT_eSPI tft;  // 创建 TFT_eSPI 对象
BH1750 lightMeter;
int ledCtrl=LOW;
int light_lux =1;
int cur_s =0;
//Button2 btnUp(BTN_UP); // Initialize the up button
//Button2 btnDwn(BTN_DWN); // Initialize the down button
PinButton btnUp(BTN_UP);
PinButton btnDwn(BTN_DWN);
// create four servo objects 
Servo servo1;
// Published values for SG90 servos; adjust if needed
int minUs = 1000;
int maxUs = 2000;
int servo1Pin = 9;
int pos = 0;      // position in degrees



BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;

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

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"



const colorDef<uint16_t> display_colors[6] MEMMODE = {
  //{{disabled normal,disabled selected},{enabled normal,enabled selected, enabled editing}}
  {{(uint16_t)Black, (uint16_t)Black}, {(uint16_t)Black, (uint16_t)Red,   (uint16_t)Red}}, //bgColor
  {{(uint16_t)White, (uint16_t)White},  {(uint16_t)White, (uint16_t)White, (uint16_t)White}},//fgColor
  {{(uint16_t)Red, (uint16_t)Red}, {(uint16_t)Yellow, (uint16_t)Yellow, (uint16_t)Yellow}}, //valColor
  {{(uint16_t)White, (uint16_t)White}, {(uint16_t)White, (uint16_t)White, (uint16_t)White}}, //unitColor
  {{(uint16_t)White, (uint16_t)Gray},  {(uint16_t)Black, (uint16_t)Red,  (uint16_t)White}}, //cursorColor
  {{(uint16_t)White, (uint16_t)Yellow}, {(uint16_t)Black,  (uint16_t)Red,   (uint16_t)Red}}, //titleColor
};


result high_lux()
{
     // reduce measurement time - needed in direct sun light
    lightMeter.setMTreg(32);
    return proceed;
}
result Mid_lux()
{
     // typical light environment
    lightMeter.setMTreg(32);
    return proceed;
}
result Low_lux()
{
     // very low light environment
    lightMeter.setMTreg(32);
    return proceed;
}



// result myLedOn() {
//   ledCtrl= LOW;
//   return proceed;
// }
// result myLedOff() {
//   ledCtrl= HIGH;
//   return proceed;
// }
TOGGLE(ledCtrl,setLed,"Led: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle
  ,VALUE("On",HIGH,doNothing,noEvent)
  ,VALUE("Off",LOW,doNothing,noEvent)
);

//customizing a prompt look!
//by extending the prompt class
//this prompt will count seconds and update himself on the screen.
class altPrompt:public prompt {
public:
  unsigned int t=0;
  unsigned int last=0;
  altPrompt(constMEM promptShadow& p):prompt(p) {}
  Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override {
    last=t;
    return out.printRaw(String(t).c_str(),len);
  }
  virtual bool changed(const navNode &nav,const menuOut& out,bool sub=true) {
    t=millis()/1000;
    return last!=t;
  }
};

int selTest=0;
SELECT(selTest,LuxSelect,"LigthMode",doNothing,noEvent,noStyle
  ,VALUE("High",0,high_lux,noEvent)
  ,VALUE("Mid",1,Mid_lux,noEvent)
  ,VALUE("Low",2,Low_lux,noEvent)
);
void servo_control(void)
{
    for (pos = 0; pos <= 180; pos += 1) { // sweep from 0 degrees to 180 degrees
        // in steps of 1 degree
        servo1.write(pos);
        delay(15);             // waits 20ms for the servo to reach the position
    }
    for (pos = 180; pos >= 0; pos -= 1) { // sweep from 180 degrees to 0 degrees
        servo1.write(pos);
        delay(15);
    }
}

MENU(mainMenu,"2024 Let's go No.3",doNothing,noEvent,wrapStyle
  ,SUBMENU(setLed)
  ,OP("servo On",servo_control,enterEvent)
  //,OP("LED Off",myLedOff,enterEvent)
  ,SUBMENU(LuxSelect)
  //,MENU(light_menu)
  ,FIELD(light_lux,"Light: "," lux",0,65535,10,1,doNothing,anyEvent,noStyle)
  //,altOP(altPrompt,"",doNothing,anyEvent)
  ,EXIT("<Back")
);

//when menu is suspended
//this function is called when entering or leaving suspended state
// with idleStart and idleend cases
//and at least once in between them (idling case)
//it might also be called for every pool (when in suspended state, idling case)
//for output devices that require refresh (repeated draw, idling case)
result idle(menuOut &o, idleEvent e) {
  o.clear();
  switch(e) {
    case idleStart:o.println("suspending menu!");break;
    case idling:o.println("suspended...");break;
    case idleEnd:o.println("resuming menu.");break;
  }
  return proceed;
}


const panel panels[] MEMMODE = {{0, 0, GFX_WIDTH / fontW, GFX_HEIGHT / fontH}};
navNode* nodes[sizeof(panels) / sizeof(panel)]; //navNodes to store navigation status
panelsList pList(panels, nodes, sizeof(panels) / sizeof(panel)); //a list of panels and nodes
idx_t eSpiTops[MAX_DEPTH]={0};
TFT_eSPIOut eSpiOut(tft,display_colors,eSpiTops,pList,fontW,fontH+1);
menuOut* constMEM outputs[] MEMMODE={&outSerial,&eSpiOut};//list of output devices
outputsList out(outputs,sizeof(outputs)/sizeof(menuOut*));//outputs list controller
NAVROOT(nav,mainMenu,MAX_DEPTH,serial,out);


void button_loop()
{
    // Check for button presses
    // btnUp.loop();
    // btnDwn.loop();
    btnDwn.update();
    btnUp.update();

    if(btnUp.isSingleClick())
    {
         nav.doNav(upCmd); 
    }
    if(btnUp.isLongClick())
    {
        nav.doNav(enterCmd);
    }
    if(btnDwn.isSingleClick())
    {
         nav.doNav(downCmd); 
    }
    if(btnDwn.isLongClick())
    {
        nav.doNav(escCmd);
    }

}



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

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

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial0.println("*********");
        Serial0.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial0.print(rxValue[i]);
        servo_control();

        Serial0.println();
        Serial0.println("*********");
      }
    }
};

void setup()
{

  Wire.setPins(42,41);
  Wire.begin();
  lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
  // initialize LED digital pin as an output.
  pinMode(LED_BUILTIN, OUTPUT);
   Serial0.begin(115200);
  while (!Serial0);
  Serial0.println("MENU CONFIG DEMO");
  Serial0.flush();

  Serial0.flush();
  Serial0.println();
  Serial0.print("Digkey&PPEW Let's Go No.3");




  tft.init();  // 初始化 TFT 屏幕
  tft.setRotation(3);           // 调整屏幕方向,根据需要选择合适的值(0、1、2、3)
  tft.fillScreen(TFT_BLACK);    // 设置屏幕背景颜色为黑色
  tft.setTextSize(2);           // 设置文本大小
  tft.setTextColor(TFT_YELLOW,TFT_BLACK);  // 设置文本颜色为白色
  nav.idleTask = idle;//point a function to be used when menu is suspended
  nav.showTitle = true;
  Serial0.println("DONE");

    //Allow allocation of all timers
    ESP32PWM::allocateTimer(0);
    ESP32PWM::allocateTimer(1);
    ESP32PWM::allocateTimer(2);
    ESP32PWM::allocateTimer(3);
    servo1.setPeriodHertz(50);      // Standard 50hz servo 20ms
    servo1.attach(servo1Pin, minUs, maxUs);



  // Create the BLE Device
  BLEDevice::init("UART Service");

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

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
                                        CHARACTERISTIC_UUID_TX,
                                        BLECharacteristic::PROPERTY_NOTIFY
                                    );
                      
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID_RX,
                                            BLECharacteristic::PROPERTY_WRITE
                                        );

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");

}




void loop()
{
    button_loop();
    cur_s =millis()/1000;
    if (lightMeter.measurementReady(true)) {
        float lux = lightMeter.readLightLevel();
        Serial0.print(F("Light: "));
        Serial0.print(lux);
        Serial0.println(F(" lx"));
        lightMeter.configure(BH1750::ONE_TIME_HIGH_RES_MODE);
        if (lux < 0) {
            Serial0.println(F("Error condition detected"));
        }
        else
        {
            light_lux= (int)lux;
        }
    }
    //Serial0.print("hello world\n");
    nav.poll();//this device only draws when needed
    digitalWrite(LED_BUILTIN,ledCtrl);
    if (deviceConnected) {
        
        pTxCharacteristic->setValue(light_lux);
        pTxCharacteristic->notify();
        delay(10); // bluetooth stack will go into congestion, if too many packets are sent
    }

    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }

}
环境搭建效果



ccc449a84e65dfe225e62e0cd13a17d.jpg








共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]