diff --git a/arduino/include/UNIT_HBRIDGE.h b/arduino/include/UNIT_HBRIDGE.h new file mode 100644 index 0000000..d640e2d --- /dev/null +++ b/arduino/include/UNIT_HBRIDGE.h @@ -0,0 +1,50 @@ +#ifndef __UNIT_HBRIDGE_H +#define __UNIT_HBRIDGE_H + +#include "Arduino.h" +#include "Wire.h" + +#define HBRIDGE_ADDR 0x20 +#define DRIVER_CONFIG_REG 0x00 +#define MOTOR_ADC_8BIT_REG 0x10 +#define MOTOR_ADC_12BIT_REG 0x20 +#define MOTOR_CURRENT_REG 0x30 +#define JUMP_TO_BOOTLOADER_REG 0xFD +#define HBRIDGE_FW_VERSION_REG 0xFE +#define HBRIDGE_I2C_ADDRESS_REG 0xFF + +#define DIR_STOP 0 +#define DIR_FORWARD 1 +#define DIR_REVERSE 2 + +typedef enum { _8bit = 0, _12bit } hbridge_anolog_read_mode_t; + +class UNIT_HBRIDGE { + private: + uint8_t _addr; + TwoWire* _wire; + uint8_t _scl; + uint8_t _sda; + uint8_t _speed; + void writeBytes(uint8_t addr, uint8_t reg, uint8_t* buffer, uint8_t length); + void readBytes(uint8_t addr, uint8_t reg, uint8_t* buffer, uint8_t length); + + public: + bool begin(TwoWire* wire = &Wire, uint8_t addr = HBRIDGE_ADDR, + uint8_t sda = 21, uint8_t scl = 22, uint32_t speed = 100000L); + uint8_t getDriverDirection(void); + uint8_t getDriverSpeed8Bits(void); + uint16_t getDriverSpeed16Bits(void); + void setDriverDirection(uint8_t dir); + void setDriverSpeed8Bits(uint8_t speed); + void setDriverSpeed16Bits(uint16_t speed); + uint16_t getDriverPWMFreq(void); + void setDriverPWMFreq(uint16_t freq); + float getMotorCurrent(void); + uint16_t getAnalogInput(hbridge_anolog_read_mode_t bit); + void jumpBootloader(void); + uint8_t getFirmwareVersion(void); + uint8_t getI2CAddress(void); +}; + +#endif diff --git a/arduino/src/UNIT_HBRIDGE.cpp b/arduino/src/UNIT_HBRIDGE.cpp new file mode 100644 index 0000000..ab19756 --- /dev/null +++ b/arduino/src/UNIT_HBRIDGE.cpp @@ -0,0 +1,135 @@ +#include "UNIT_HBRIDGE.h" + +void UNIT_HBRIDGE::writeBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, + uint8_t length) { + _wire->beginTransmission(addr); + _wire->write(reg); + for (int i = 0; i < length; i++) { + _wire->write(*(buffer + i)); + } + _wire->endTransmission(); +} + +void UNIT_HBRIDGE::readBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, + uint8_t length) { + uint8_t index = 0; + _wire->beginTransmission(addr); + _wire->write(reg); + _wire->endTransmission(); + _wire->requestFrom(addr, length); + for (int i = 0; i < length; i++) { + buffer[index++] = _wire->read(); + } +} + +bool UNIT_HBRIDGE::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl, + uint32_t speed) { + _wire = wire; + _addr = addr; + _sda = sda; + _scl = scl; + _speed = speed; + _wire->begin(_sda, _scl, _speed); + delay(10); + _wire->beginTransmission(_addr); + uint8_t error = _wire->endTransmission(); + if (error == 0) { + return true; + } else { + return false; + } +} + +uint8_t UNIT_HBRIDGE::getDriverDirection(void) { + uint8_t data[4]; + readBytes(_addr, DRIVER_CONFIG_REG, data, 1); + return data[0]; +} + +uint8_t UNIT_HBRIDGE::getDriverSpeed8Bits(void) { + uint8_t data[4]; + readBytes(_addr, DRIVER_CONFIG_REG + 1, data, 1); + return data[0]; +} + +uint16_t UNIT_HBRIDGE::getDriverSpeed16Bits(void) { + uint8_t data[4]; + readBytes(_addr, DRIVER_CONFIG_REG + 2, data, 2); + return (data[0] | (data[1] << 8)); +} + +uint16_t UNIT_HBRIDGE::getDriverPWMFreq(void) { + uint8_t data[4]; + readBytes(_addr, DRIVER_CONFIG_REG + 4, data, 2); + return (data[0] | (data[1] << 8)); +} + +void UNIT_HBRIDGE::setDriverPWMFreq(uint16_t freq) { + uint8_t data[4]; + data[0] = (freq & 0xff); + data[1] = ((freq >> 8) & 0xff); + writeBytes(_addr, DRIVER_CONFIG_REG + 4, data, 2); +} + +void UNIT_HBRIDGE::setDriverDirection(uint8_t dir) { + uint8_t data[4]; + data[0] = dir; + writeBytes(_addr, DRIVER_CONFIG_REG, data, 1); +} + +void UNIT_HBRIDGE::setDriverSpeed8Bits(uint8_t speed) { + uint8_t data[4]; + data[0] = speed; + writeBytes(_addr, DRIVER_CONFIG_REG + 1, data, 1); +} + +void UNIT_HBRIDGE::setDriverSpeed16Bits(uint16_t speed) { + uint8_t data[4]; + data[0] = speed; + data[1] = (speed >> 8); + writeBytes(_addr, DRIVER_CONFIG_REG + 2, data, 2); +} + +uint16_t UNIT_HBRIDGE::getAnalogInput(hbridge_anolog_read_mode_t bit) { + if (bit == _8bit) { + uint8_t data; + readBytes(_addr, MOTOR_ADC_8BIT_REG, &data, 1); + return data; + } else { + uint8_t data[2]; + readBytes(_addr, MOTOR_ADC_12BIT_REG, data, 2); + return (data[0] | (data[1] << 8)); + } +} + +// Only V1.1 can use this +float UNIT_HBRIDGE::getMotorCurrent(void) { + uint8_t data[4]; + float c; + uint8_t *p; + + readBytes(_addr, MOTOR_CURRENT_REG, data, 4); + p = (uint8_t *)&c; + memcpy(p, data, 4); + + return c; +} + +uint8_t UNIT_HBRIDGE::getFirmwareVersion(void) { + uint8_t data[4]; + readBytes(_addr, HBRIDGE_FW_VERSION_REG, data, 1); + return data[0]; +} + +uint8_t UNIT_HBRIDGE::getI2CAddress(void) { + uint8_t data[4]; + readBytes(_addr, HBRIDGE_I2C_ADDRESS_REG, data, 1); + return data[0]; +} + +// Only V1.1 can use this +void UNIT_HBRIDGE::jumpBootloader(void) { + uint8_t value = 1; + + writeBytes(_addr, JUMP_TO_BOOTLOADER_REG, (uint8_t *)&value, 1); +} diff --git a/arduino/src/main.cpp b/arduino/src/main.cpp index 469c9ab..2a76a79 100644 --- a/arduino/src/main.cpp +++ b/arduino/src/main.cpp @@ -1,9 +1,12 @@ -#include +//#include #include #include #include #include -#include +//#include +#include +#include "M5_ENV.h" +#include "UNIT_HBRIDGE.h" #include #include @@ -13,6 +16,12 @@ AsyncWebServer server(80); StaticJsonDocument<192> json_doc; HTTPClient http_session; HTTPClient http_sensor; +SHT3X unitsht30; +QMP6988 unitqmp6988; +SHT3X hatsht30; +QMP6988 hatqmp6988; +UNIT_HBRIDGE driver; + const int update_interval_sec = 30; @@ -20,13 +29,23 @@ bool drying = false; long long timer = 0; -float RoomTemp, RoomHumi, ShoeTemp, ShoeHumi; +float RoomTemp, RoomHumi, RoomPre, ShoeTemp, ShoeHumi, ShoePre; +float volt = 0.0; //デバッグ用 +int debug_flag = 0; void setup() { json_doc["device_id"] = DEVICE_ID; M5.begin(); Serial.begin(115200); + Wire1.end(); + Wire.begin(32,33); // Wire init, adding the I2C bus. Wire初始化, 加入i2c总线 + Wire1.begin(0, 26); + hatsht30.init(0x44, &Wire1); + unitsht30.init(0x44, &Wire); + hatqmp6988.init(QMP6988_SLAVE_ADDRESS_L,&Wire1); + unitqmp6988.init(QMP6988_SLAVE_ADDRESS_H,&Wire); + driver.begin(&Wire, HBRIDGE_ADDR, 32, 33, 100000L); // WiFi Setup @@ -39,16 +58,29 @@ void setup() { delay(1000); // Serial.println("Connecting to WiFi..."); M5.Lcd.fillScreen(BLACK); // 画面の塗りつぶし +#if 0 M5.Lcd.setCursor(0, 0); // 文字列の書き出し位置 M5.Lcd.setTextSize(1); // 文字サイズを設定 M5.Lcd.printf("Connecting to WiFi..."); // シリアルモニタ +#endif + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(MAROON, BLACK); + M5.Lcd.setCursor(15, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Setting"); } M5.Lcd.fillScreen(BLACK); // 画面の塗りつぶし +#if 0 M5.Lcd.setCursor(0, 0); // 文字列の書き出し位置 M5.Lcd.setTextSize(1); // 文字サイズを設定 M5.Lcd.printf("WiFi Success"); // シリアルモニタ - +#endif + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(RED, BLACK); + M5.Lcd.setCursor(15, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Setting"); // リクエストに応じてJSON形式のデータを返すエンドポイントの設定 server.on("/data", HTTP_GET, [](AsyncWebServerRequest *request) { char exporter_plain_json[1536]; @@ -123,23 +155,82 @@ void main_func() { if (drying) { // 乾燥実行中 if (current_drying) { // 靴が湿気ている + //乾燥続行 + driver.setDriverDirection(1); + driver.setDriverSpeed8Bits(255); send_to_server(json_doc); + if(debug_flag == 0){ + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(GREEN, BLACK); + M5.Lcd.setCursor(20, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Drying!"); + } } else { // 靴が湿気ていない + //乾燥終了 + driver.setDriverDirection(0); + driver.setDriverSpeed8Bits(0); drying = false; json_doc["drying"] = drying; send_to_server(json_doc); + if(debug_flag == 0){ + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(BLUE, BLACK); + M5.Lcd.setCursor(0, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Complete"); + } } } else { // 乾燥未実行 if (current_drying) { // 靴が湿気ている + //乾燥開始 + driver.setDriverDirection(1); + driver.setDriverSpeed8Bits(255); drying = true; json_doc["drying"] = drying; json_doc["session_id"] = get_session_id(); send_to_server(json_doc); + if(debug_flag == 0){ + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(GREEN, BLACK); + M5.Lcd.setCursor(20, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Drying!"); + } + } + else{ + if(debug_flag == 0){ + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setRotation(3); + M5.Lcd.setTextColor(ORANGE, BLACK); + M5.Lcd.setCursor(20, 45); + M5.Lcd.setTextSize(5); // 文字サイズを設定 + M5.Lcd.printf("Waiting"); + } } } + if(debug_flag == 1){ + //デバッグ用 + M5.Lcd.setRotation(3); + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setCursor(0, 20); + M5.Lcd.setTextSize(2); + M5.Lcd.setTextColor(WHITE, BLACK); + volt = driver.getAnalogInput(_12bit) / 4095.0f * 3.3f / 0.09f; + M5.Lcd.printf("Room T:%2.1f, H:%2.0f%%, P:%2.0fPa\r\n", + RoomTemp, RoomHumi, RoomPre); + M5.Lcd.printf("Shoe T:%2.1f, H:%2.0f%%, P:%2.0fPa\r\n", + ShoeTemp, ShoeHumi, ShoePre); + + M5.Lcd.printf("Voltage:%.2fV\r\n", volt); + } + } void sample() { @@ -168,10 +259,49 @@ void sample() { } } +void scan() { + Serial.println(WiFi.localIP()); + + //drying = true; + json_doc["drying"] = drying; + + json_doc["session_id"] = get_session_id(); + //Hatが室内環境計測 + RoomPre = hatqmp6988.calcPressure(); + if (hatsht30.get() == 0) { + RoomTemp = hatsht30.cTemp; + RoomHumi = hatsht30.humidity; + } else {//温湿度取れない場合は気圧もクリア + RoomTemp = 0, RoomHumi = 0, RoomPre = 0; + } + //Unitが室内環境計測 + ShoePre = unitqmp6988.calcPressure(); + if (unitsht30.get() == 0) {// 温湿度取得 + ShoeTemp = unitsht30.cTemp; + ShoeHumi = unitsht30.humidity; + } else {//温湿度取れない場合は気圧もクリア + ShoeTemp = 0, ShoeHumi = 0, ShoePre = 0; + } + Serial.println(send_to_server(json_doc)); + + //delay(2000); +} + void loop() { + M5.update(); + if (M5.BtnA.wasPressed()) { + debug_flag = 0; + main_func(); + } else if (M5.BtnB.wasPressed()) { + debug_flag = 1; + main_func(); + } + if (millis() - timer > update_interval_sec * 1000) { timer = millis(); - sample(); + scan(); + + main_func(); } } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 5de7386..85bc8d6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -3,8 +3,7 @@ ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages -; Advanced options: extra scriptingl - +; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html @@ -19,16 +18,18 @@ data_dir = ./arduino/data test_dir = ./arduino/test [common] -lib_deps = - adafruit/DHT sensor library@^1.4.4 +lib_deps = + ;adafruit/DHT sensor library@^1.4.4 me-no-dev/ESP Async WebServer @ ^1.2.3 bblanchon/ArduinoJson@^6.21.3 - m5stack/M5Stickc@^0.2.5 + m5stack/M5Unit-ENV@^0.0.9 + m5stack/M5StickCPlus@^0.1.0 [env:m5stickc] platform = espressif32 board = m5stick-c framework = arduino monitor_speed = 115200 -lib_deps = +lib_deps = ${common.lib_deps} +