SoftwareSerial to HardwareSerial

Переписал библиотеку GitHub - elechouse/VoiceRecognitionV3: Arduino library for elechouse Voice Recognition V3 module
под ESP32-S3, все команды работают кроме самой важной load она возвращает -1 то есть : Load failed or timeout.
На Arduino всё прекрасно работает.

load 0 1 2 3
--------------------------------------------------------------------------------
Load failed or timeout.
--------------------------------------------------------------------------------

Подскажите, в чём проблема?

VoiceRecognitionV3.h

// Edited by Frank Van Hooft 2022 specifically for ESP32 UART2

/**
  ******************************************************************************
  * @file    VoiceRecognitionV2.h
  * @author  Elechouse Team
  * @version V1.0
  * @date    2013-6-6
  * @brief   This file provides all the VoiceRecognitionV2 firmware functions.
  ******************************************************************************
    @note
         This driver is for elechouse Voice Recognition V2 Module(LINKS here)
  ******************************************************************************
  * @section  HISTORY
  
    V1.0    Initial version.
  
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, ELECHOUSE SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2013 ELECHOUSE</center></h2>
  ******************************************************************************
  */
  
#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include "wiring_private.h"

#define DEBUG

#ifdef DEBUG
#define DBGSTR(message)     Serial.print(message)
#define DBGBUF(buf, len)	Serial.write(buf, len)
#define DBGLN(message)		Serial.println(message)
#define DBGFMT(msg, fmt)	Serial.print(msg, fmt)
#define DBGCHAR(c)			Serial.write(c)
#else
#define DBG(message)
#endif // DEBUG

#define VR_DEFAULT_TIMEOUT						(1000)

/***************************************************************************/
#define FRAME_HEAD							(0xAA)
#define FRAME_END							(0x0A)

/***************************************************************************/
#define FRAME_CMD_CHECK_SYSTEM				(0x00)
#define FRAME_CMD_CHECK_BSR					(0x01)
#define FRAME_CMD_CHECK_TRAIN				(0x02)
#define FRAME_CMD_CHECK_SIG					(0x03)

#define FRAME_CMD_RESET_DEFAULT				(0x10)	//reset configuration
#define FRAME_CMD_SET_BR					(0x11)	//baud rate
#define FRAME_CMD_SET_IOM					(0x12)	//IO mode
#define FRAME_CMD_SET_PW					(0x13)	//pulse width
#define FRAME_CMD_RESET_IO					(0x14)	// reset IO OUTPUT					
#define FRAME_CMD_SET_AL					(0x15)	// Auto load

#define FRAME_CMD_TRAIN						(0x20)
#define FRAME_CMD_SIG_TRAIN					(0x21)
#define FRAME_CMD_SET_SIG					(0x22)

#define FRAME_CMD_LOAD						(0x30)	//Load N records
#define FRAME_CMD_CLEAR						(0x31)	//Clear BSR buffer					
#define FRAME_CMD_GROUP						(0x32)  //
	#define FRAME_CMD_GROUP_SET							(0x00)  //
	#define FRAME_CMD_GROUP_SUGRP						(0x01)  //
	#define FRAME_CMD_GROUP_LSGRP						(0x02)  //
	#define FRAME_CMD_GROUP_LUGRP						(0x03)  //
	#define FRAME_CMD_GROUP_CUGRP						(0x04)  //

#define FRAME_CMD_TEST						(0xEE)
	#define FRAME_CMD_TEST_READ							(0x01)	
	#define FRAME_CMD_TEST_WRITE						(0x00)	


#define FRAME_CMD_VR						(0x0D)	//Voice recognized
#define FRAME_CMD_PROMPT					(0x0A)
#define FRAME_CMD_ERROR						(0xFF)

/***************************************************************************/
// #define FRAME_ERR_UDCMD						(0x00)
// #define FRAME_ERR_LEN						(0x01)
// #define FRAME_ERR_DATA						(0x02)
// #define FRAME_ERR_SUBCMD					(0x03)

// //#define FRAME_ERR_
// #define FRAME_STA_SUCCESS					(0x00)
// #define FRAME_STA_FAILED					(0xFF)
/***************************************************************************/


class VR {
public:
	VR(uint8_t receivePin, uint8_t transmitPin);
	
	static VR* getInstance() {
	   return instance;
	}
	
	typedef enum{
		PULSE = 0,
		TOGGLE = 1,
		SET = 2, 
		CLEAR = 3
	}io_mode_t;
	
	typedef enum{
		LEVEL0 = 0,
		LEVEL1,
		LEVEL2, 
		LEVEL3,
		LEVEL4,
		LEVEL5,
		LEVEL6,
		LEVEL7,
		LEVEL8,
		LEVEL9,
		LEVEL10,
		LEVEL11,
		LEVEL12,
		LEVEL13,
		LEVEL14,
		LEVEL15,
	}pulse_width_level_t;
	
	typedef enum{
		GROUP0 = 0,
		GROUP1,
		GROUP2,
		GROUP3,
		GROUP4,
		GROUP5,
		GROUP6,
		GROUP7,
		GROUP_ALL = 0xFF,
	}group_t;
	
    void begin(HardwareSerial* SerialPort);
	int setBaudRate(unsigned long br);
	int setIOMode(io_mode_t mode);
	int resetIO(uint8_t *ios=0, uint8_t len=1);
	int setPulseWidth(uint8_t level);
	int setAutoLoad(uint8_t *records=0, uint8_t len = 0);
    int disableAutoLoad();
	int restoreSystemSettings();
	int checkSystemSettings(uint8_t* buf);
	int recognize(uint8_t *buf, int timeout = VR_DEFAULT_TIMEOUT);
	int train(uint8_t *records, uint8_t len=1, uint8_t *buf = 0);
	int train(uint8_t record, uint8_t *buf = 0);
	int trainWithSignature(uint8_t record, const void *buf, uint8_t len=0, uint8_t *retbuf = 0);
	int load(uint8_t *records, uint8_t len=1, uint8_t *buf = 0);
	int load(uint8_t record, uint8_t *buf = 0);
	int clear();
	int setSignature(uint8_t record, const void *buf=0, uint8_t len=0);
	int deleteSignature(uint8_t record);
    
	int checkSignature(uint8_t record, uint8_t *buf);
	int checkRecognizer(uint8_t *buf);
	int checkRecord(uint8_t *buf, uint8_t *records = 0, uint8_t len = 0);
	
	/** group control */
	int setGroupControl(uint8_t ctrl);
	int checkGroupControl();
	int setUserGroup(uint8_t grp, uint8_t *records, uint8_t len);
	int checkUserGroup(uint8_t grp, uint8_t *buf);
	int loadSystemGroup(uint8_t grp, uint8_t *buf=0);
	int loadUserGroup(uint8_t grp, uint8_t *buf=0);
	
	int test(uint8_t cmd, uint8_t *bsr);
	
	int writehex(uint8_t *buf, uint8_t len);
	
/***************************************************************************/
	/** low level */
	int len(uint8_t *buf);
	int cmp(uint8_t *buf, uint8_t *bufcmp, int len  );
	void cpy(char *buf,  char * pbuf);
	void sort(uint8_t *buf, int len);
	int cleanDup(uint8_t *des, uint8_t *buf, int len);
	void send_pkt(uint8_t *buf, uint8_t len);
	void send_pkt(uint8_t cmd, uint8_t *buf, uint8_t len);
	void send_pkt(uint8_t cmd, uint8_t subcmd, uint8_t *buf, uint8_t len);
	int receive(uint8_t *buf, int len, uint16_t timeout = VR_DEFAULT_TIMEOUT);
	int receive_pkt(uint8_t *buf, uint16_t timeout = VR_DEFAULT_TIMEOUT);
/***************************************************************************/
private:
	static VR*  instance;
};

VoiceRecognitionV3.cpp

// Edited by Frank Van Hooft 2022 specifically for ESP32 UART2

/**
  ******************************************************************************
  * @file    VoiceRecognitionV2.cpp
  * @author  Elechouse Team
  * @version V1.0
  * @date    2013-6-6
  * @brief   This file provides all the VoiceRecognitionV2 firmware functions.
  ******************************************************************************
    @note
         This driver is for elechouse Voice Recognition V2 Module(LINKS here)
  ******************************************************************************
  * @section  HISTORY
  
    V1.0    Initial version.

  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, ELECHOUSE SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2013 ELECHOUSE</center></h2>
  ******************************************************************************
  */
#include "VoiceRecognitionV3.h"
#include <string.h>
#include <inttypes.h>

VR* VR::instance;
HardwareSerial* SERIAL_2;


/** temp data buffer */
uint8_t vr_buf[32];
uint8_t hextab[17]="0123456789ABCDEF";

/**
	@brief VR class constructor.
	@param receivePin --> software serial RX - IGNORED FOR ESP32
		   transmitPin --> software serial TX - IGNORED FOR ESP32
*/
VR::VR(uint8_t receivePin, uint8_t transmitPin)
{
	instance = this;

}

/**
	@brief VR class constructor.
	@param buf --> return data .
			 buf[0]  -->  Group mode(FF: None Group, 0x8n: User, 0x0n:System
             buf[1]  -->  number of record which is recognized. 
             buf[2]  -->  Recognizer index(position) value of the recognized record.
             buf[3]  -->  Signature length
             buf[4]~buf[n] --> Signature
		   timeout --> wait time for receiving packet.
	@retval length of valid data in buf. 0 means no data received.
*/
int VR :: recognize(uint8_t *buf, int timeout)
{
	int ret, i;
	ret = receive_pkt(vr_buf, timeout);
	if(vr_buf[2] != FRAME_CMD_VR){
		return -1;
	}
	if(ret > 0){
		for(i = 0; i < (vr_buf[1] - 3); i++){
			buf[i] = vr_buf[4+i];
		} 
		return i;
	}
	
	return 0;
}


void VR :: begin(HardwareSerial* SerialPort)
{
    SERIAL_2 = SerialPort;

}


/**
	@brief train records, at least one.
	@param records --> record data buffer pointer.
		   len --> number of records.
           buf --> pointer of return value buffer, optional.
		   buf[0]  -->  number of records which are trained successfully.
             buf[2i+1]  -->  record number
             buf[2i+2]  -->  record train status.
                00 --> Trained 
                FE --> Train Time Out
                FF --> Value out of range"
             (i = 0 ~ len-1 )
	@retval '>0' --> length of valid data in buf. 
            0 --> success, and no data received.
            '<0' --> failed.
                -1 --> data format error.
                -2 --> train timeout.
*/
int VR :: train(uint8_t *records, uint8_t len, uint8_t *buf)
{
	int ret;
	unsigned long start_millis;
	if(len == 0){
		return -1;
	}
	
	send_pkt(FRAME_CMD_TRAIN, records, len);
	start_millis = millis();
	while(1){
		ret = receive_pkt(vr_buf);
		if(ret>0){
			switch(vr_buf[2]){
				case FRAME_CMD_PROMPT:
					DBGSTR("Record:\t");
					DBGFMT(vr_buf[3], DEC);
					DBGSTR("\t");
					DBGBUF(vr_buf+4, ret-4);
					break;
				case FRAME_CMD_TRAIN:
					if(buf != 0){
						memcpy(buf, vr_buf+3, vr_buf[1]-2);
						return vr_buf[1]-2;
					}
					DBGSTR("Train finish.\r\nSuccess: \t");
					DBGFMT(vr_buf[3], DEC);
					DBGSTR(" \r\n");
					return 0;
					break;
				default:
					break;
			}
			start_millis = millis();
		}
		if(millis()-start_millis > 8000){
			return -2;
		}
	}
	return 0;
}

/**
	@brief train one record.
	@param records --> record data buffer pointer.
		   len --> number of records.
           buf --> pointer of return value buffer, optional.
		   buf[0]  -->  number of records which are trained successfully.
             buf[2i+1]  -->  record number
             buf[2i+2]  -->  record train status.
                00 --> Trained 
                FE --> Train Time Out
                FF --> Value out of range"
             (i = 0 ~ len-1 )
	@retval '>0' --> length of valid data in buf. 
            0 --> success, and no data received.
            '<0' --> failed.
                -1 --> data format error.
                -2 --> train timeout.
*/
int VR :: train(uint8_t record, uint8_t *buf)
{
    return train(&record, 1, buf);
}

/**
	@brief train record and set a signature(alias) for this record.
	@param record --> record value.
           buf --> signature string/data pointer.
		   len --> lenght of buf.
		   retbuf --> return data .
			 retbuf[0]  -->  number of records which are trained successfully.
             retbuf[1]  -->  record number.
             retbuf[2]  -->  record train status.
                00 --> Trained 
                F0 --> Trained, signature truncate
                FE --> Train Time Out
                FF --> Value out of range"
             retbuf[3] ~ retbuf[retval-1] --> Signature.(retval means return value)
	@retval '>0' --> length of valid data in buf. 
            0 --> success, and no data received.
            '<0' --> failed.
                -1 --> data format error.
                -2 --> train with signature timeout.
*/
int VR :: trainWithSignature(uint8_t record, const void *buf, uint8_t len, uint8_t * retbuf)
{
	int ret;
	unsigned long start_millis;
	if(len){
		send_pkt(FRAME_CMD_SIG_TRAIN, record, (uint8_t *)buf, len);
	}else{
		if(buf == 0){
			return -1;
		}
		len = strlen((char *)buf);
		if(len>10){
			return -1;
		}
		send_pkt(FRAME_CMD_SIG_TRAIN, record, (uint8_t *)buf, len);
	}
	
	start_millis = millis();
	while(1){
		ret = receive_pkt(vr_buf);
		if(ret>0){
			switch(vr_buf[2]){
				case FRAME_CMD_PROMPT:
					DBGSTR("Record:\t");
					DBGFMT(vr_buf[3], DEC);
					DBGSTR("\t");
					DBGBUF(vr_buf+4, ret-4);
					break;
				case FRAME_CMD_SIG_TRAIN:
					if(retbuf != 0){
						memcpy(retbuf, vr_buf+3, vr_buf[1]-2);
						return vr_buf[1]-2;
					}
				
					DBGSTR("Train finish.\r\nSuccess: \t");
					DBGFMT(vr_buf[3], DEC);
					DBGSTR(" \r\n");
					writehex(vr_buf, vr_buf[1]+2);
					return 0;
					break;
				default:
					break;
			}
			start_millis = millis();
		}
		if(millis()-start_millis > 8000){
			return -2;
		}
	}
	return 0;
}

/**
    @brief Load records to recognizer.
    @param records --> record data buffer pointer.
           len --> number of records.
           buf --> pointer of return value buffer, optional.
             buf[0]    -->  number of records which are load successfully.
             buf[2i+1]  -->  record number
             buf[2i+2]  -->  record load status.
                00 --> Loaded 
                FC --> Record already in recognizer
                FD --> Recognizer full
                FE --> Record untrained
                FF --> Value out of range"
             (i = 0 ~ '(retval-1)/2' )
	@retval '>0' --> length of valid data in buf. 
            0 --> success, buf=0, and no data returned.
            '<0' --> failed.
*/
int VR :: load(uint8_t *records, uint8_t len, uint8_t *buf)
{
	uint8_t ret;
	send_pkt(FRAME_CMD_LOAD, records, len);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_LOAD){
		return -1;
	}
	if(buf != 0){
		memcpy(buf, vr_buf+3, vr_buf[1]-2);
		return vr_buf[1]-2;
	}
	return 0;
}

/**
    @brief Load one record to recognizer.
    @param record --> record value.
           buf --> pointer of return value buffer, optional.
             buf[0]    -->  number of records which are load successfully.
             buf[2i+1]  -->  record number
             buf[2i+2]  -->  record load status.
                00 --> Loaded 
                FC --> Record already in recognizer
                FD --> Recognizer full
                FE --> Record untrained
                FF --> Value out of range"
             (i = 0 ~ '(retval-1)/2' )
	@retval '>0' --> length of valid data in buf. 
            0 --> success, buf=0, and no data returned.
            '<0' --> failed.
*/
int VR :: load(uint8_t record, uint8_t *buf)
{
	uint8_t ret;
	send_pkt(FRAME_CMD_LOAD, &record, 1);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_LOAD){
		return -1;
	}
	if(buf != 0){
		memcpy(buf, vr_buf+3, vr_buf[1]-2);
		return vr_buf[1]-2;
	}
	return 0;
}

/**
    @brief set signature(alias) for a record.
    @param record --> record value.
           buf --> signature buffer.
           len --> length of buf.
    @retval 0 --> success, buf=0, and no data returned.
            '<0' --> failed.
*/
int VR :: setSignature(uint8_t record, const void *buf, uint8_t len)
{
	int ret;
	
	if(len == 0 && buf == 0){
		/** delete signature */
	}else if(len == 0 && buf != 0){
		if(buf == 0){
			return -1;
		}
		len = strlen((char *)buf);
		if(len>10){
			return -1;
		}
	}else if(len != 0 && buf != 0){
		
	}else{
		return -1;
	}
	send_pkt(FRAME_CMD_SET_SIG, record, (uint8_t *)buf, len);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_SET_SIG){
		return -1;
	}
	return 0;
}

/**
    @brief delete signature(alias) of a record.
    @param record --> record value.
    @retval  0 --> success
            -1 --> failed
*/
int VR :: deleteSignature(uint8_t record)
{
    return setSignature(record);
}

/**
    @brief check the signature(alias) of a record.
    @param record --> record value.
           buf --> signature, return value buffer.
    @retval '>0' --> length of valid data in buf. 
            0 --> success, buf=0, and no data returned.
            '<0' --> failed.
*/
int VR :: checkSignature(uint8_t record, uint8_t *buf)
{
	int ret;
	if(record < 0){
		return -1;
	}
	send_pkt(FRAME_CMD_CHECK_SIG, record, 0, 0);
	ret = receive_pkt(vr_buf);
	
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_CHECK_SIG){
		return -1;
	}

	if(vr_buf[4]>0){
		memcpy(buf, vr_buf+5, vr_buf[4]);
		return vr_buf[4];
	}else{
		return 0;
	}
}

/**
    @brief clear recognizer.
    @retval  0 --> success
            -1 --> failed
*/
int VR :: clear()
{	
	int len;
	send_pkt(FRAME_CMD_CLEAR, 0, 0);
	len = receive_pkt(vr_buf);
    
	if(len<=0){
		Serial.println("Clear returned nothing\r\n");
        return -1;
	}

	if(vr_buf[2] != FRAME_CMD_CLEAR){
        Serial.println("Clear returned ");
        Serial.print(vr_buf[0], HEX);
        Serial.print(vr_buf[1], HEX);
        Serial.print(vr_buf[2], HEX);
        Serial.print(vr_buf[3], HEX);
        Serial.print("\r\n");
		return -1;
	}
	//DBGLN("VR Module Cleared");
	return 0;
}

/**
    @brief clear recognizer.
    @param buf --> return value buffer.
             buf[0]     -->  Number of valid voice records in recognizer
             buf[i+1]   -->  Record number.(0xFF: Not loaded(Nongroup mode), or not set (Group mode)) 
                (i= 0, 1, ... 6)
             buf[8]     -->  Number of all voice records in recognizer
             buf[9]     -->  Valid records position indicate.
             buf[10]    -->  Group mode indicate(FF: None Group, 0x8n: User, 0x0n:System
    @retval '>0' --> success, length of data in buf 
            -1 --> failed
*/
int VR :: checkRecognizer(uint8_t *buf)
{
	int len;
	send_pkt(FRAME_CMD_CHECK_BSR, 0, 0);
	len = receive_pkt(vr_buf);
	if(len<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_CHECK_BSR){
		return -1;
	}
	
	if(vr_buf[1] != 0x0D){
		return -1;
	}
	
	memcpy(buf, vr_buf+3, vr_buf[1]-2);
	
	return vr_buf[1]-2;
}

/**
    @brief check record train status.
    @param buf --> return value
             buf[0]     -->  Number of checked records
             buf[2i+1]  -->  Record number.
             buf[2i+2]  -->  Record train status. (00: untrained, 01: trained, FF: record value out of range)
             (i = 0 ~ buf[0]-1 )
    @retval Number of trained records
*/
int VR :: checkRecord(uint8_t *buf, uint8_t *records, uint8_t len)
{
	int ret;
	int cnt = 0;
	unsigned long start_millis;
	if(records == 0 && len==0){
        memset(buf, 0xF0, 255);
		send_pkt(FRAME_CMD_CHECK_TRAIN, 0xFF, 0, 0);
		start_millis = millis();
		while(1){
			len = receive_pkt(vr_buf);
			if(len>0){
				if(vr_buf[2] == FRAME_CMD_CHECK_TRAIN){
                    for(int i=0; i<vr_buf[1]-3; i+=2){
                        buf[vr_buf[4+i]]=vr_buf[4+i+1];
                    }
					cnt++;
					if(cnt == 51){
						return vr_buf[3];
					}
				}else{
					return -3;
				}
				start_millis = millis();
			}
			
			if(millis()-start_millis > 500){
				if(cnt>0){
					buf[0] = cnt*5;
					return vr_buf[3];
				}
				return -2;
			}
			
		}
		
	}else if(len>0){
		ret = cleanDup(vr_buf, records, len);
		send_pkt(FRAME_CMD_CHECK_TRAIN, vr_buf, ret);
		ret = receive_pkt(vr_buf);
		if(ret>0){
			if(vr_buf[2] == FRAME_CMD_CHECK_TRAIN){
				memcpy(buf+1, vr_buf+4, vr_buf[1]-3);
				buf[0] = (vr_buf[1]-3)/2;
				return vr_buf[3];
			}else{
				return -3;
			}
		}else{
			return -1;
		}
	}else{
		return -1;
	}
	
}

/****************************************************************************/
/******************************* GROUP CONTROL ******************************/
/**
    @brief set group control by external IO function
    @param ctrl --> group control by external IO
                0 --> disable group control by external IO
                1 --> user group control by external IO
                2 --> system group control by external IO
    @retval  0 --> success
            -1 --> failed
*/
int VR :: setGroupControl(uint8_t ctrl)
{
	int ret;
	if(ctrl>2){
		return -1;
	}
	
	send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_SET, &ctrl, 1);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_GROUP){
		return -1;
	}
	return 0;
}

/**
    @brief check group control by external IO function
    @param ctrl --> group control by external IO
    @retval  0 --> group control by external IO disabled
             1 --> user group control by external IO status
             2 --> system group control by external IO status
            -1 --> failed
*/
int VR :: checkGroupControl()
{
	uint8_t cmd;
	int ret;
	cmd = 0xFF;
	send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_SET, &cmd, 1);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_GROUP){
		return -1;
	}
	ret = vr_buf[5];
	if(ret == 0xFF){
		ret = 0;
	}
	return ret;
}

/**
    @brief set user gruop content.
    @param grp --> user group number.
           records --> pointer of records buffer.
           len --> length of reocrds
    @retval  0 --> success
            -1 --> failed
*/
int VR :: setUserGroup(uint8_t grp, uint8_t *records, uint8_t len)
{
	int ret;
	if(len == 0 || records == 0){
		return -1;
	}
	if(grp >= 8){
		return -1;
	}
	vr_buf[0] = grp;
	memcpy(vr_buf+1, records, len);
	send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_SUGRP, vr_buf, len+1);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_GROUP){
		return -1;
	}
	return 0;
}

/**
    @brief check user gruop content.
    @param grp --> user group number.
           buf --> return value
             buf[8i]    -->  group number.
             buf[8i+1]  -->  group position 0 status.
             buf[8i+2]  -->  group position 1 status.
               ...                ...
             buf[8i+6]  -->  group position 5 status.
             buf[8i+7]  -->  group position 6 status.
             (i = 0 ~ @retval)
    @retval '>0' --> number of checked user group
            '<0' --> failed
*/
int VR :: checkUserGroup(uint8_t grp, uint8_t *buf)
{
	int ret;
	int cnt = 0;
	unsigned long start_millis;
	
	if(grp == GROUP_ALL){
		send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_CUGRP, 0, 0);
		start_millis = millis();
		while(1){
			ret = receive_pkt(vr_buf);
			if(ret>0){
				if(vr_buf[2] == FRAME_CMD_GROUP && vr_buf[1] == 10){
					memcpy(buf+8*cnt, vr_buf+3, vr_buf[1]-2);
					cnt++;
					if(cnt == 8){
						return cnt;
					}
				}else{
					return -3;
				}
				start_millis = millis();
			}
			
			if(millis()-start_millis > 500){
				if(cnt>0){
					return cnt;
				}
				return -2;
			}
			
		}
	}else if(grp <= GROUP7){
		send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_CUGRP, &grp, 1);
		ret = receive_pkt(vr_buf);
		if(ret>0){
			if(vr_buf[2] == FRAME_CMD_GROUP && vr_buf[1] == 10){
				memcpy(buf+8*cnt, vr_buf+3, vr_buf[1]-2);
				return 1;
			}else{
				return -3;
			}
		}else{
			return -2;
		}
	}else{
		return -1;
	}
}

/**
    @brief load system gruop content to recognizer.
    @param grp --> syestem group number.
           buf  -->  return value.
             buf[0]     -->  Number of valid voice records in recognizer.
             buf[i+1]   -->  Record number.(0xFF: Not loaded(Nongroup mode), or not set (Group mode)) 
                (i= 0, 1, ... 6)
             buf[8]     -->  Number of all voice records in recognizer
             buf[9]     -->  Valid records position indicate.
             buf[10]    -->  Group mode indicate(FF: None Group, 0x8n: User, 0x0n:System
             (i = 0 ~ @retval)
    @retval '>0' --> length of buf
            '<0' --> failed
*/
int VR :: loadSystemGroup(uint8_t grp, uint8_t *buf)
{
	int ret;
	if(grp > 10){
		return -1;
	}
	send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_LSGRP, &grp, 1);
	ret = receive_pkt(vr_buf);
	
	if(ret <= 0){
		return -1;
	}
	
	if(vr_buf[2] != FRAME_CMD_GROUP){
		return -1;
	}
	
	if(buf != 0){
		vr_buf[3] = 0;
		for(int i=0; i<8; i++){
			if(vr_buf[12]&(1<<i)){
				vr_buf[3]++;
			}
		}
		memcpy(buf, vr_buf+3, vr_buf[1]-2);
		return vr_buf[1]-2;
	}
	
	return 0;
}

/**
    @brief load user gruop content to recognizer.
    @param grp --> user group number.
           buf  -->  return value.
             buf[0]     -->  Number of valid voice records in recognizer.
             buf[i+1]   -->  Record number.(0xFF: Not loaded(Nongroup mode), or not set (Group mode)) 
                (i= 0, 1, ... 6)
             buf[8]     -->  Number of all voice records in recognizer
             buf[9]     -->  Valid records position indicate.
             buf[10]    -->  Group mode indicate(FF: None Group, 0x8n: User, 0x0n:System)
             (i = 0 ~ @retval)
    @retval '>0' --> length of buf
            '<0' --> failed
*/
int VR :: loadUserGroup(uint8_t grp, uint8_t *buf)
{
	int ret;
	if(grp > GROUP7){
		return -1;
	}
	send_pkt(FRAME_CMD_GROUP, FRAME_CMD_GROUP_LUGRP, &grp, 1);
	ret = receive_pkt(vr_buf);
	
	if(ret <= 0){
		return -1;
	}
	
	if(vr_buf[2] != FRAME_CMD_GROUP){
		return -1;
	}
	
	if(buf != 0){
		vr_buf[3] = 0;
		for(int i=0; i<8; i++){
			if(vr_buf[12]&(1<<i)){
				vr_buf[3]++;
			}
		}
		memcpy(buf, vr_buf+3, 11);
		return 1;
	}
	
	return 0;
}

/**
    @brief reset system setting to default
    @retval  0 --> success
            -1 --> failed
*/
int VR :: restoreSystemSettings()
{
	int len;
	send_pkt(FRAME_CMD_RESET_DEFAULT, 0, 0);
	len = receive_pkt(vr_buf);
	if(len<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_RESET_DEFAULT){
		return -1;
	}

	return 0;
}

/**
    @brief check system settings
    @param buf --> return value
            buf[0] --> baud rate. (0-9600 1-2400 2-4800 3-9600 4-19200 5-38400)
            buf[1] --> output io mode(0-pulse 1-toggle 2-clear 3-set)
            buf[2] --> pulse width level
            buf[3] --> auto load(0,0xFF-disable 1-enable)
            buf[4] --> Group control by external IO(0-disable 1-system group 2-user group)
    @retval '>0' --> buf length
            -1 --> failed
*/
int VR :: checkSystemSettings(uint8_t* buf)
{
	int len;
	if(buf == 0){
		return -1;
	}
	send_pkt(FRAME_CMD_CHECK_SYSTEM, 0, 0);
	len = receive_pkt(vr_buf);
	if(len<=0){
		return -1;
	}
	
	if(vr_buf[2] != FRAME_CMD_CHECK_SYSTEM){
		return -1;
	}

	memcpy(buf, vr_buf+4, vr_buf[1]-3);
	return vr_buf[1]-3;

	return 0;
}

/**
    @brief set module baud rate.
    @param br --> module baud rate.(0-9600 1-2400 2-4800 3-9600 4-19200 5-38400)
    @retval 0 --> success
            -1 --> failed
            
    This changes the baud rate of the module, but not of the ESP32 serial port!        
*/
int VR :: setBaudRate(unsigned long br)
{
	uint8_t baud_rate;
	int ret;
	switch(br){
		case 2400:
			baud_rate = 1;
			break;
		case 4800:
			baud_rate = 2;
			break;
		case 9600:
			baud_rate = 0;
			//baud_rate = 3;
			break;
		case 19200:
			baud_rate = 4;
			break;
		case 38400:
			baud_rate = 5;
			break;
		default:
			return -1;
			break;
	}
	
	send_pkt(FRAME_CMD_SET_BR, baud_rate, 0, 0);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_SET_BR){
		return -1;
	}
	//DBGLN("VR Module Cleared");
	return 0;
	
}

/**
    @brief set module output IO mode.
    @param mode --> module output IO mode.(must be PULSE, TOGGLE, SET, CLEAR)
    @retval 0 --> success
            -1 --> failed
*/
int VR :: setIOMode(io_mode_t mode)
{
	if(mode > 3){
		return -1;
	}
	int ret;
	
	send_pkt(FRAME_CMD_SET_IOM, mode, 0, 0);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_SET_IOM){
		return -1;
	}
	return 0;
}

/**
    @brief resset module output IO.
    @param ios --> output IO buffer.
           len --> length of ios.
    @retval 0 --> success
            -1 --> failed
*/
int VR :: resetIO(uint8_t *ios, uint8_t len)
{
	int ret;
	if(len == 1 && ios == 0){
		send_pkt(FRAME_CMD_RESET_IO, 0xFF, 0, 0);
	}else if(len != 0 && ios != 0){
		send_pkt(FRAME_CMD_RESET_IO, ios, len);
	}else{
		return -1;
	}

	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_RESET_IO){
		return -1;
	}
	return 0;
}

/**
    @brief set module pulse width(PULSE mode).
    @param level --> pulse width level.(LEVEL0~LEVEL15)
           len --> length of ios.
    @retval 0 --> success
            -1 --> failed
*/
int VR :: setPulseWidth(uint8_t level)
{
	int ret;
	
	if(level > VR::LEVEL15){
		return -1;
	}
	
	send_pkt(FRAME_CMD_SET_PW, level, 0, 0);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}

	if(vr_buf[2] != FRAME_CMD_SET_PW){
		return -1;
	}
	return 0;
}

/**
    @brief set autoload.
    @param records --> record buffer.
           len --> records length.
    @retval 0 --> success
            -1 --> failed
*/
int VR :: setAutoLoad(uint8_t *records, uint8_t len)
{
	int ret;
	uint8_t map;
	if(len == 0 && records == 0){
		map = 0;
	}else if(len != 0 && records != 0){
		map = 0;
		for(int i=0; i<len; i++){
			map |= (1<<i);
		}
	}else{
		return -1;
	}
	
	send_pkt(FRAME_CMD_SET_AL, map, records, len);
	ret = receive_pkt(vr_buf);
	if(ret<=0){
		return -1;
	}
	if(vr_buf[2] != FRAME_CMD_SET_AL){
		return -1;
	}
	return 0;
}

/**
    @brief disable autoload.
    @param records --> record buffer.
           len --> records length.
    @retval 0 --> success
            -1 --> failed
*/
int VR :: disableAutoLoad()
{
    return setAutoLoad();
}

int VR :: test(uint8_t cmd, uint8_t *bsr)
{
	int len, i;
	unsigned long start_millis;
	switch(cmd){
		case FRAME_CMD_TEST_READ:
			vr_buf[0] = FRAME_CMD_TEST_READ;
			send_pkt(FRAME_CMD_TEST, vr_buf, 1);
			start_millis = millis();
			while(1){
				len = receive_pkt(vr_buf);
				if(len>0){
					switch(vr_buf[2]){
						case FRAME_CMD_TEST:
							memcpy(bsr+vr_buf[3]*20, vr_buf+4, 20);
							if(vr_buf[3] == 9){
								return 0;
							}
							break;
						default:
							DBGLN("TEST ERROR");
							return -1;
							break;
					}
					start_millis = millis();
				}
				if(millis()-start_millis > 4000){
					return -2;
				}
			}
			break;
		case FRAME_CMD_TEST_WRITE:
			for(i=0; i<10; i++){
				vr_buf[0] = i;
				memcpy(vr_buf+1, bsr+20*i, 20);
				send_pkt(FRAME_CMD_TEST, FRAME_CMD_TEST_WRITE, vr_buf, 21);
				start_millis = millis();
				while(1){
					len = receive_pkt(vr_buf);
					if(len>0){
						if(vr_buf[2] == FRAME_CMD_TEST){
							break;
						}else{
							DBGLN("TEST ERROR");
							return -1;
						}
						start_millis = millis();
					}
					if(millis()-start_millis > 4000){
						return -2;
					}
				}
			}
			break;
		default:
			break;
	}
	return 0;
}

/**flash operation function (strlen)*/
int VR :: len(uint8_t *buf)
{
	int i=0;
	while(pgm_read_byte_near(buf++)){
		i++;
	}
	return i;
}

/**flash operation function (strcmp)*/
int VR :: cmp(uint8_t *buf, uint8_t *bufcmp, int len  )
{
	int i;
	for(i=0; i<len; i++){
		if(buf[i] != pgm_read_byte_near(bufcmp+i)){
			return -1;
		}
	}
	return 0;
}

/**flash operation function (strcpy)*/
void VR :: cpy(char *buf, char * pbuf)
{
  int i=0;
  while(pgm_read_byte_near(pbuf)){
    buf[i] = pgm_read_byte_near(pbuf++);
    i++;
  }
}

/** ascending sort */
void VR :: sort(uint8_t *buf, int len)
{
	int i, j;
	uint8_t tmp;
	for(i=0; i<len; i++){
		for(j=i+1; j<len; j++){
			if(buf[j] < buf[i]){
				tmp = buf[i];
				buf[i] = buf[j]; 
				buf[j] = tmp;
			}
		}
	}
}

/** remove duplicates */
int VR :: cleanDup(uint8_t *des, uint8_t *buf, int len)
{	
	if(len<1){
		return -1;
	}
	
	int i, j, k=0;
	for(i=0; i<len; i++){
		for(j=0; j<k; j++){
			if(buf[i] == des[j]){
				break;
			}
		}
		if(j==k){
			des[k] = buf[i];
			k++;
		}
	}
	return k;
#if 0
	int i=0, j=1, k=0;
	sort(buf, len);
	for(; j<len; ){
		des[k] = buf[i];
		k++;
		while(buf[i]==buf[j]){
			j++;
			if(j==len){
				return k;
			}
		}
		i=j;
	}
	return k;
#endif
}

/** Serial print in HEX format */
int VR :: writehex(uint8_t *buf, uint8_t len)
{
	int i;
	for(i=0; i<len; i++){
		DBGCHAR(hextab[(buf[i]&0xF0)>>4]);
		DBGCHAR(hextab[(buf[i]&0x0F)]);
		DBGCHAR(' ');
	}
	return len;
}

/**
    @brief send data packet in Voice Recognition module protocol format.
    @param cmd --> command 
           subcmd --> subcommand
           buf --> data area
           len --> length of buf
*/
void VR :: send_pkt(uint8_t cmd, uint8_t subcmd, uint8_t *buf, uint8_t len)
{
	while(SERIAL_2->available()){
		SERIAL_2->read();// replace flush();
	}
	SERIAL_2->write(FRAME_HEAD);
	SERIAL_2->write(len+3);
	SERIAL_2->write(cmd);
	SERIAL_2->write(subcmd);
	SERIAL_2->write(buf, len);
	SERIAL_2->write(FRAME_END);
}

/**
    @brief send data packet in Voice Recognition module protocol format.
    @param cmd --> command 
           buf --> data area
           len --> length of buf
*/
void VR :: send_pkt(uint8_t cmd, uint8_t *buf, uint8_t len)
{
	while(SERIAL_2->available()){
		SERIAL_2->read();// replace flush();
	}
	SERIAL_2->write(FRAME_HEAD);
	SERIAL_2->write(len+2);
	SERIAL_2->write(cmd);
	SERIAL_2->write(FRAME_END);
}

/**
    @brief send data packet in Voice Recognition module protocol format.
    @param buf --> data area
           len --> length of buf
*/
void VR :: send_pkt(uint8_t *buf, uint8_t len)
{
	while(SERIAL_2->available()){
		SERIAL_2->read();// replace flush();
	}
	SERIAL_2->write(FRAME_HEAD);
	SERIAL_2->write(len+1);
	SERIAL_2->write(buf, len);
	SERIAL_2->write(FRAME_END);
}

/**
    @brief receive a valid data packet in Voice Recognition module protocol format.
    @param buf --> return value buffer.
           timeout --> time of receiving (ms)
    @retval '>0' --> success, packet length(length of all data in buf)
            '<0' --> failed
*/
int VR :: receive_pkt(uint8_t *buf, uint16_t timeout)
{
	int ret;
    
	ret = receive(buf, 2, timeout);
	if(ret != 2){
		return -1;
	}
	if(buf[0] != FRAME_HEAD){
		return -2;
	}
	if(buf[1] < 2){
		return -3;
	}
	ret = receive(buf+2, buf[1], timeout);
	if(buf[buf[1]+1] != FRAME_END){
		return -4;
	}
	
//	DBGBUF(buf, buf[1]+2);
	
	return buf[1]+2;
}

/**
    @brief receive data .
    @param buf --> return value buffer.
           len --> length expect to receive.
           timeout --> time of reveiving
    @retval number of received bytes, 0 means no data received.
*/
int VR::receive(uint8_t *buf, int len, uint16_t timeout)
{
  int read_bytes = 0;
  int ret;
  unsigned long start_millis;
  
  while (read_bytes < len) {
    start_millis = millis();
    
    do {
      ret = SERIAL_2->read();
      if (ret >= 0) {
        break;
     }
    } while( (millis() - start_millis ) < timeout);
    
    if (ret < 0) {
      return read_bytes;
    }
    
    buf[read_bytes] = (char)ret;
    read_bytes++;
  }
  
  return read_bytes;
}

код для ввода команд через консоль vr_sample_train.ino

/**
 ******************************************************************************
 * @file    vr_sample_train.ino
 * @author  JiapengLi
 * @brief   This file provides a demostration on 
 * how to train VoiceRecognitionModule to record your voice
 ******************************************************************************
 * @note:
 * Use serial command to control VoiceRecognitionModule. '
 * All commands are case insensitive. Default serial baud rate 115200.
 * 
 * COMMAND        FORMAT                        EXAMPLE                    Comment
 * 
 * train          train (r0) (r1)...            train 0 2 45               Train records
 * load           load (r0) (r1) ...            load 0 51 2 3              Load records
 * clear          clear                         clear                      remove all records in  Recognizer
 * record         record / record (r0) (r1)...  record / record 0 79       Check record train status
 * vr             vr                            vr                         Check recognizer status
 * getsig         getsig (r)                    getsig 0                   Get signature of record (r)
 * sigtrain       sigtrain (r) (sig)            sigtrain 0 ZERO            Train one record(r) with signature(sig)
 * settings       settings                      settings                   Check current system settings
 ******************************************************************************
 * @section  HISTORY
 * 
 * 2013/06/13    Initial version.
 */

#include "VoiceRecognitionV3.h"
HardwareSerial SERIAL_4(1);
/**        
 * Connection
 * Arduino    VoiceRecognitionModule
 * 2   ------->     TX
 * 3   ------->     RX
 */
VR myVR(2,3);    // 2:RX 3:TX, you can choose your favourite pins.

/***************************************************************************/
/** declare print functions */
void printSeperator();
void printSignature(uint8_t *buf, int len);
void printVR(uint8_t *buf);
void printLoad(uint8_t *buf, uint8_t len);
void printTrain(uint8_t *buf, uint8_t len);
void printCheckRecognizer(uint8_t *buf);
void printUserGroup(uint8_t *buf, int len);
void printCheckRecord(uint8_t *buf, int num);
void printCheckRecordAll(uint8_t *buf, int num);
void printSigTrain(uint8_t *buf, uint8_t len);
void printSystemSettings(uint8_t *buf, int len);
void printHelp(void);

/***************************************************************************/
// command analyze part
#define CMD_BUF_LEN      64+1
#define CMD_NUM     10
typedef int (*cmd_function_t)(int, int);
uint8_t cmd[CMD_BUF_LEN];
uint8_t cmd_cnt;
uint8_t *paraAddr;
int receiveCMD();
int checkCMD(int len);
int checkParaNum(int len);
int findPara(int len, int paraNum, uint8_t **addr);
int compareCMD(uint8_t *para1 , uint8_t *para2, int len);

int cmdTrain(int len, int paraNum);
int cmdLoad(int len, int paraNum);
int cmdTest(int len, int paraNum);
int cmdVR(int len, int paraNum);
int cmdClear(int len, int paraNum);
int cmdRecord(int len, int paraNum);
int cmdSigTrain(int len, int paraNum);
int cmdGetSig(int len, int paraNum);
int cmdSettings(int len, int paraNum);
int cmdHelp(int len, int paraNum);
/** cmdList, cmdLen, cmdFunction has correspondence */
const char cmdList[CMD_NUM][10] = {  // command list table
  {
    "train"  }
  ,
  {
    "load"  }
  , 
  {
    "clear"  }
  ,
  {
    "vr"  }
  ,
  {
    "record"  }
  ,
  {
    "sigtrain"  }
  ,
  {
    "getsig"  }
  ,
  {
    "Settings"  }
  ,
  {
    "test"  }
  ,
  {
    "help"  }
  ,
};
const char cmdLen[CMD_NUM]= {    // command length
  5,  //  {"train"},
  4,  //  {"load"}, 
  5,  //  {"clear"},
  2,  //  {"vr"},
  6,  //  {"record"},
  8,  //  {"sigtrain"},
  6,  //  {"getsig"},
  8,  //  {"Settings"},
  4,  //  {"test"},
  4,  //  {"help"}
};
cmd_function_t cmdFunction[CMD_NUM]={      // command handle fuction(function pointer table)
  cmdTrain,
  cmdLoad,
  cmdClear,
  cmdVR,
  cmdRecord,
  cmdSigTrain,
  cmdGetSig,
  cmdSettings,
  cmdTest,
  cmdHelp,
};

/***************************************************************************/
/** temprory data */
uint8_t buf[255];
uint8_t records[7]; // save record

void setup(void)
{
  SERIAL_4.begin(9600, SERIAL_8N1, 42, 39);
    
    myVR.begin(&SERIAL_4);

  /** initialize */
  Serial.begin(115200);
  Serial.println(F("Elechouse Voice Recognition V3 Module \"train\" sample."));

  printSeperator();
  Serial.println(F("Usage:"));
  printSeperator();
  printHelp();
  printSeperator();
  cmd_cnt = 0;
}

void loop(void)
{
  int len, paraNum, paraLen, i;

  /** receive Serial command */
  len = receiveCMD();
  if(len>0){
    /** check if the received command is valid */
    if(!checkCMD(len)){

      /** check parameter number of the received command  */
      paraNum = checkParaNum(len);

      /** display the receved command back */
      Serial.write(cmd, len);

      /** find the first parameter */
      paraLen = findPara(len, 1, &paraAddr);

      /** compare the received command with command in the list */
      for(i=0; i<CMD_NUM; i++){
        /** compare command length */
        if(paraLen == cmdLen[i]){
          /** compare command content */
          if( compareCMD(paraAddr, (uint8_t *)cmdList[i], paraLen) == 0 ){
            /** call command function */
            if( cmdFunction[i](len, paraNum) != 0){
              printSeperator();
              Serial.println(F("Command Format Error!"));
              printSeperator();
            }
            break;
          }
        }
      }

      /** command is not supported*/
      if(i == CMD_NUM){ 
        printSeperator();
        Serial.println(F("Unkonwn command"));
        printSeperator();
      }
    }
    else{
      /** received command is invalid */
      printSeperator();
      Serial.println(F("Command format error"));
      printSeperator();
    }
  }

  /** try to receive recognize result */
  int ret;
  ret = myVR.recognize(buf, 50);
  if(ret>0){
    /** voice recognized, print result */
    printVR(buf);
  }
}

/**
 * @brief   receive command from Serial.
 * @param   NONE.
 * @retval  command length, if no command receive return -1.
 */
int receiveCMD()
{
  int ret;
  int len;
  unsigned long start_millis;
  start_millis = millis();
  while(1){
    ret = Serial.read();
    if(ret>0){
      start_millis = millis();
      cmd[cmd_cnt] = ret;
      if(cmd[cmd_cnt] == '\n'){
        len = cmd_cnt+1;
        cmd_cnt = 0;
        return len;
      }
      cmd_cnt++;
      if(cmd_cnt == CMD_BUF_LEN){
        cmd_cnt = 0;
        return -1;
      }
    }

    if(millis() - start_millis > 100){
      cmd_cnt = 0;
      return -1;
    }
  }
}

/**
 * @brief   compare two commands, case insensitive.
 * @param   para1  -->  command buffer 1
 * para2  -->  command buffer 2
 * len    -->  buffer length
 * @retval  0  --> equal
 * -1  --> unequal
 */
int compareCMD(uint8_t *para1 , uint8_t *para2, int len)
{
  int i;
  uint8_t res;
  for(i=0; i<len; i++){
    res = para2[i] - para1[i];
    if(res != 0 && res != 0x20){
      res = para1[i] - para2[i];
      if(res != 0 && res != 0x20){
        return -1;
      }
    }
  }
  return 0;
}

/**
 * @brief   Check command format.
 * @param   len  -->  command length
 * @retval  0  -->  command is valid
 * -1  -->  command is invalid
 */
int checkCMD(int len)
{
  int i;
  for(i=0; i<len; i++){
    if(cmd[i] > 0x1F && cmd[i] < 0x7F){

    }
    else if(cmd[i] == '\t' || cmd[i] == ' ' || cmd[i] == '\r' || cmd[i] == '\n'){

    }
    else{
      return -1;
    }
  }
  return 0;
}

/**
 * @brief   Check the number of parameters in the command
 * @param   len  -->  command length
 * @retval  number of parameters
 */
int checkParaNum(int len)
{
  int cnt=0, i;
  for(i=0; i<len; ){
    if(cmd[i]!='\t' && cmd[i]!=' ' && cmd[i] != '\r' && cmd[i] != '\n'){
      cnt++;
      while(cmd[i] != '\t' && cmd[i] != ' ' && cmd[i] != '\r' && cmd[i] != '\n'){
        i++;
      }
    }
    i++;
  }
  return cnt;
}

/**
 * @brief   Find the specified parameter.
 * @param   len       -->  command length
 * paraIndex -->  parameter index
 * addr      -->  return value. position of the parameter
 * @retval  length of specified parameter
 */
int findPara(int len, int paraIndex, uint8_t **addr)
{
  int cnt=0, i, paraLen;
  uint8_t dt;
  for(i=0; i<len; ){
    dt = cmd[i];
    if(dt!='\t' && dt!=' '){
      cnt++;
      if(paraIndex == cnt){
        *addr = cmd+i;
        paraLen = 0;
        while(cmd[i] != '\t' && cmd[i] != ' ' && cmd[i] != '\r' && cmd[i] != '\n'){
          i++;
          paraLen++;
        }
        return paraLen;
      }
      else{
        while(cmd[i] != '\t' && cmd[i] != ' ' && cmd[i] != '\r' && cmd[i] != '\n'){
          i++;
        }
      }
    }
    else{
      i++;
    }
  }
  return -1;
}

int cmdHelp(int len, int paraNum)
{
  if(paraNum != 1){
    return -1;
  }
  printSeperator();
  printHelp();
  printSeperator();
  return 0;
}

/**
 * @brief   Handle "train" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdTrain(int len, int paraNum)
{
  int i, ret;
  if(paraNum < 2 || paraNum > 8 ){
    return -1;
  }

  for(i=2; i<=paraNum; i++){
    findPara(len, i, &paraAddr);
    records[i-2] = atoi((char *)paraAddr);
    if(records[i-2] == 0 && *paraAddr != '0'){
      return -1;
    }
  }
  printSeperator();
  ret = myVR.train(records, paraNum-1, buf);
  //  ret = myVR.train(records, paraNum-1);
  if(ret >= 0){
    printTrain(buf, ret);
  }
  else if(ret == -1){
    Serial.println(F("Train failed."));
  }
  else if(ret == -2){
    Serial.println(F("Train Timeout."));
  }
  printSeperator();
  return 0;
}

/**
 * @brief   Handle "load" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdLoad(int len, int paraNum)
{
  int i, ret;
  if(paraNum < 2 || paraNum > 8 ){
    return -1;
  }

  for(i=2; i<=paraNum; i++){
    findPara(len, i, &paraAddr);
    records[i-2] = atoi((char *)paraAddr);
    if(records[i-2] == 0 && *paraAddr != '0'){
      return -1;
    }
  }
  //  myVR.writehex(records, paraNum-1);
  ret = myVR.load(records, paraNum-1, buf);
  printSeperator();
  if(ret >= 0){
    printLoad(buf, ret);
  }
  else{
    Serial.println(F("Load failed or timeout."));
  }
  printSeperator();
  return 0;
}

/**
 * @brief   Handle "clear" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdClear(int len, int paraNum)
{
  if(paraNum != 1){
    return -1;
  }
  if(myVR.clear() == 0){
    printSeperator();
    Serial.println(F("Recognizer cleared."));
    printSeperator();
  }
  else{
    printSeperator();
    Serial.println(F("Clear recognizer failed or timeout."));
    printSeperator();
  }
  return 0;
}

/**
 * @brief   Handle "vr" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdVR(int len, int paraNum)
{
  int ret;
  if(paraNum != 1){
    return -1;
  }
  ret = myVR.checkRecognizer(buf);
  if(ret<=0){
    printSeperator();
    Serial.println(F("Check recognizer failed or timeout."));
    printSeperator();
    return 0;
  }
  printSeperator();
  printCheckRecognizer(buf);
  printSeperator();
  return 0;
}

/**
 * @brief   Handle "record" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdRecord(int len, int paraNum)
{
  int ret;
  if(paraNum == 1){
    ret = myVR.checkRecord(buf);
    printSeperator();
    if(ret>=0){
      printCheckRecordAll(buf, ret);
    }
    else{
      Serial.println(F("Check record failed or timeout."));
    }
    printSeperator();
  }
  else if(paraNum < 9){
    for(int i=2; i<=paraNum; i++){
      findPara(len, i, &paraAddr);
      records[i-2] = atoi((char *)paraAddr);
      if(records[i-2] == 0 && *paraAddr != '0'){
        return -1;
      }      
    }

    ret = myVR.checkRecord(buf, records, paraNum-1);    // auto clean duplicate records
    printSeperator();
    if(ret>=0){
      printCheckRecord(buf, ret);
    }
    else{
      Serial.println(F("Check record failed or timeout."));
    }
    printSeperator();
  }
  else{
    return -1;
  }
  return 0;
}

/**
 * @brief   Handle "sigtrain" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdSigTrain(int len, int paraNum)
{
  int ret, sig_len;
  uint8_t *lastAddr;
  if(paraNum < 2){
    return -1;
  }

  findPara(len, 2, &paraAddr);
  records[0] = atoi((char *)paraAddr);
  if(records[0] == 0 && *paraAddr != '0'){
    return -1;
  }

  findPara(len, 3, &paraAddr);
  sig_len = findPara(len, paraNum, &lastAddr);
  sig_len +=( (unsigned int)lastAddr - (unsigned int)paraAddr );

  printSeperator();
  ret = myVR.trainWithSignature(records[0], paraAddr, sig_len, buf);
  //  ret = myVR.trainWithSignature(records, paraNum-1);
  if(ret >= 0){
    printSigTrain(buf, ret);
  }
  else{
    Serial.println(F("Train with signature failed or timeout."));
  }
  printSeperator();

  return 0;
}

/**
 * @brief   Handle "getsig" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdGetSig(int len, int paraNum)
{
  int ret;
  if(paraNum != 2){
    return -1;
  }

  findPara(len, 2, &paraAddr);
  records[0] = atoi((char *)paraAddr);
  if(records[0] == 0 && *paraAddr != '0'){
    return -1;
  }

  ret = myVR.checkSignature(records[0], buf);

  printSeperator();
  if(ret == 0){
    Serial.println(F("Signature isn't set."));
  }
  else if(ret > 0){
    Serial.print(F("Signature:"));
    printSignature(buf, ret);
    Serial.println();
  }
  else{
    Serial.println(F("Get sig error or timeout."));
  }
  printSeperator();

  return 0;
}

/**
 * @brief   Handle "test" command
 * @param   len     --> command length
 * paraNum --> number of parameters
 * @retval  0 --> success
 * -1 --> Command format error
 */
int cmdTest(int len, int paraNum)
{
  printSeperator();
  Serial.println(F("TEST is not supported."));
  printSeperator();
  return 0;
}

int cmdSettings(int len, int paraNum)
{
  int ret;
  if(paraNum != 1){
    return -1;
  }
  ret = myVR.checkSystemSettings(buf);
  if( ret > 0){
    printSeperator();
    printSystemSettings(buf, ret);
    printSeperator();
  }
  else{
    printSeperator();
    Serial.println(F("Check system settings error or timeout"));
    printSeperator();
  }
  return 0;
}

/*****************************************************************************/
/**
 * @brief   Print signature, if the character is invisible, 
 * print hexible value instead.
 * @param   buf     --> command length
 * len     --> number of parameters
 */
void printSignature(uint8_t *buf, int len)
{
  int i;
  for(i=0; i<len; i++){
    if(buf[i]>0x19 && buf[i]<0x7F){
      Serial.write(buf[i]);
    }
    else{
      Serial.print(F("["));
      Serial.print(buf[i], HEX);
      Serial.print(F("]"));
    }
  }
}

/**
 * @brief   Print signature, if the character is invisible, 
 * print hexible value instead.
 * @param   buf  -->  VR module return value when voice is recognized.
 * buf[0]  -->  Group mode(FF: None Group, 0x8n: User, 0x0n:System
 * buf[1]  -->  number of record which is recognized. 
 * buf[2]  -->  Recognizer index(position) value of the recognized record.
 * buf[3]  -->  Signature length
 * buf[4]~buf[n] --> Signature
 */
void printVR(uint8_t *buf)
{
  Serial.println(F("VR Index\tGroup\tRecordNum\tSignature"));

  Serial.print(buf[2], DEC);
  Serial.print(F("\t\t"));

  if(buf[0] == 0xFF){
    Serial.print(F("NONE"));
  }
  else if(buf[0]&0x80){
    Serial.print(F("UG "));
    Serial.print(buf[0]&(~0x80), DEC);
  }
  else{
    Serial.print(F("SG "));
    Serial.print(buf[0], DEC);
  }
  Serial.print(F("\t"));

  Serial.print(buf[1], DEC);
  Serial.print(F("\t\t"));
  if(buf[3]>0){
    printSignature(buf+4, buf[3]);
  }
  else{
    Serial.print(F("NONE"));
  }
  Serial.println(F("\r\n"));
}

/**
 * @brief   Print seperator. Print 80 '-'.
 */
void printSeperator()
{
  for(int i=0; i<80; i++){
    Serial.write('-');
  }
  Serial.println();
}

/**
 * @brief   Print recoginizer status.
 * @param   buf  -->  VR module return value when voice is recognized.
 * buf[0]     -->  Number of valid voice records in recognizer
 * buf[i+1]   -->  Record number.(0xFF: Not loaded(Nongroup mode), or not set (Group mode)) (i= 0, 1, ... 6)
 * buf[8]     -->  Number of all voice records in recognizer
 * buf[9]     -->  Valid records position indicate.
 * buf[10]    -->  Group mode indicate(FF: None Group, 0x8n: User, 0x0n:System)
 */
void printCheckRecognizer(uint8_t *buf)
{
  Serial.print(F("All voice records in recognizer: "));
  Serial.println(buf[8], DEC);
  Serial.print(F("Valid voice records in recognizer: "));
  Serial.println(buf[0], DEC);
  if(buf[10] == 0xFF){
    Serial.println(F("VR is not in group mode."));
  }
  else if(buf[10]&0x80){
    Serial.print(F("VR is in user group mode:"));
    Serial.println(buf[10]&0x7F, DEC);
  }
  else{
    Serial.print(F("VR is in system group mode:"));
    Serial.println(buf[10], DEC);
  }
  Serial.println(F("VR Index\tRecord\t\tComment"));
  for(int i=0; i<7; i++){
    Serial.print(i, DEC);
    Serial.print(F("\t\t"));
    if(buf[i+1] == 0xFF){
      if(buf[10] == 0xFF){
        Serial.print(F("Unloaded\tNONE"));
      }
      else{
        Serial.print(F("Not Set\t\tNONE"));
      }
    }
    else{
      Serial.print(buf[i+1], DEC);
      Serial.print(F("\t\t"));
      if(buf[9]&(1<<i)){
        Serial.print(F("Valid"));
      }
      else{
        Serial.print(F("Untrained"));
      }
    }

    Serial.println();
  } 
}

/**
 * @brief   Print record train status.
 * @param   buf  -->  Check record command return value
 * buf[0]     -->  Number of checked records
 * buf[2i+1]  -->  Record number.
 * buf[2i+2]  -->  Record train status. (00: untrained, 01: trained, FF: record value out of range)
 * (i = 0 ~ buf[0]-1 )
 * num  -->  Number of trained records
 */
void printCheckRecord(uint8_t *buf, int num)
{
  Serial.print(F("Check "));
  Serial.print(buf[0], DEC);
  Serial.println(F(" records."));

  Serial.print(num, DEC);
  if(num>1){
    Serial.println(F(" records trained."));
  }
  else{
    Serial.println(F(" record trained."));
  }

  for(int i=0; i<buf[0]*2; i += 2){
    Serial.print(buf[i+1], DEC);
    Serial.print(F("\t-->\t"));
    switch(buf[i+2]){
    case 0x01:
      Serial.print(F("Trained"));
      break;
    case 0x00:
      Serial.print(F("Untrained"));
      break;
    case 0xFF:
      Serial.print(F("Record value out of range"));
      break;
    default:
      Serial.print(F("Unknown Stauts"));
      break;
    }
    Serial.println();
  }
}

/**
 * @brief   Print record train status.
 * @param   buf  -->  Check record command return value
 * buf[0]     -->  Number of checked records
 * buf[2i+1]  -->  Record number.
 * buf[2i+2]  -->  Record train status. (00: untrained, 01: trained, FF: record value out of range)
 * (i = 0 ~ buf[0]-1 )
 * num  -->  Number of trained records
 */
void printCheckRecordAll(uint8_t *buf, int num)
{
  Serial.print(F("Check 255"));
  Serial.println(F(" records."));

  Serial.print(num, DEC);
  if(num>1){
    Serial.println(F(" records trained."));
  }
  else{
    Serial.println(F(" record trained."));
  }
  myVR.writehex(buf, 255);
  for(int i=0; i<255; i++){
    if(buf[i] == 0xF0){
      continue;
    }
    Serial.print(i, DEC);
    Serial.print(F("\t-->\t"));
    switch(buf[i]){
    case 0x01:
      Serial.print(F("Trained"));
      break;
    case 0x00:
      Serial.print(F("Untrained"));
      break;
    case 0xFF:
      Serial.print(F("Record value out of range"));
      break;
    default:
      Serial.print(F("Unknown Stauts"));
      break;
    }
    Serial.println();
  }
}

/**
 * @brief   Print check user group result.
 * @param   buf  -->  Check record command return value
 * buf[8i]    -->  group number.
 * buf[8i+1]  -->  group position 0 status.
 * buf[8i+2]  -->  group position 1 status.
 * ...                ...
 * buf[8i+6]  -->  group position 5 status.
 * buf[8i+7]  -->  group position 6 status.
 * (i = 0 ~ len)
 * len  -->  number of checked groups
 */
void printUserGroup(uint8_t *buf, int len)
{
  int i, j;
  Serial.println(F("Check User Group:"));
  for(i=0; i<len; i++){
    Serial.print(F("Group:"));
    Serial.println(buf[8*i]);
    for(j=0; j<7; j++){
      if(buf[8*i+1+j] == 0xFF){
        Serial.print(F("NONE\t"));
      }
      else{
        Serial.print(buf[8*i+1+j], DEC);
        Serial.print(F("\t"));
      }
    }
    Serial.println();
  }
}

/**
 * @brief   Print "load" command return value.
 * @param   buf  -->  "load" command return value
 * buf[0]    -->  number of records which are load successfully.
 * buf[2i+1]  -->  record number
 * buf[2i+2]  -->  record load status.
 * 00 --> Loaded 
 * FC --> Record already in recognizer
 * FD --> Recognizer full
 * FE --> Record untrained
 * FF --> Value out of range"
 * (i = 0 ~ (len-1)/2 )
 * len  -->  length of buf
 */
void printLoad(uint8_t *buf, uint8_t len)
{
  if(len == 0){
    Serial.println(F("Load Successfully."));
    return;
  }
  else{
    Serial.print(F("Load success: "));
    Serial.println(buf[0], DEC);
  }
  for(int i=0; i<len-1; i += 2){
    Serial.print(F("Record "));
    Serial.print(buf[i+1], DEC);
    Serial.print(F("\t"));
    switch(buf[i+2]){
    case 0:
      Serial.println(F("Loaded"));
      break;
    case 0xFC:
      Serial.println(F("Record already in recognizer"));
      break;
    case 0xFD:
      Serial.println(F("Recognizer full"));
      break;
    case 0xFE:
      Serial.println(F("Record untrained"));
      break;
    case 0xFF:
      Serial.println(F("Value out of range"));
      break;
    default:
      Serial.println(F("Unknown status"));
      break;
    }
  }
}

/**
 * @brief   Print "train" command return value.
 * @param   buf  -->  "train" command return value
 * buf[0]    -->  number of records which are trained successfully.
 * buf[2i+1]  -->  record number
 * buf[2i+2]  -->  record train status.
 * 00 --> Trained 
 * FE --> Train Time Out
 * FF --> Value out of range"
 * (i = 0 ~ len-1 )
 * len  -->  length of buf
 */
void printTrain(uint8_t *buf, uint8_t len)
{
  if(len == 0){
    Serial.println(F("Train Finish."));
    return;
  }
  else{
    Serial.print(F("Train success: "));
    Serial.println(buf[0], DEC);
  }
  for(int i=0; i<len-1; i += 2){
    Serial.print(F("Record "));
    Serial.print(buf[i+1], DEC);
    Serial.print(F("\t"));
    switch(buf[i+2]){
    case 0:
      Serial.println(F("Trained"));
      break;
    case 0xFE:
      Serial.println(F("Train Time Out"));
      break;
    case 0xFF:
      Serial.println(F("Value out of range"));
      break;
    default:
      Serial.print(F("Unknown status "));
      Serial.println(buf[i+2], HEX);
      break;
    }
  }
}

/**
 * @brief   Print "sigtrain" command return value.
 * @param   buf  -->  "sigtrain" command return value
 * buf[0]  -->  number of records which are trained successfully.
 * buf[1]  -->  record number
 * buf[2]  -->  record train status.
 * 00 --> Trained 
 * F0 --> Trained, signature truncate
 * FE --> Train Time Out
 * FF --> Value out of range"
 * buf[3] ~ buf[len-1] --> Signature.
 * len  -->  length of buf
 */
void printSigTrain(uint8_t *buf, uint8_t len)
{
  if(len == 0){
    Serial.println(F("Train With Signature Finish."));
    return;
  }
  else{
    Serial.print(F("Success: "));
    Serial.println(buf[0], DEC);
  }
  Serial.print(F("Record "));
  Serial.print(buf[1], DEC);
  Serial.print(F("\t"));
  switch(buf[2]){
  case 0:
    Serial.println(F("Trained"));
    break;
  case 0xF0:
    Serial.println(F("Trained, signature truncate"));
    break;
  case 0xFE:
    Serial.println(F("Train Time Out"));
    break;
  case 0xFF:
    Serial.println(F("Value out of range"));
    break;
  default:
    Serial.print(F("Unknown status "));
    Serial.println(buf[2], HEX);
    break;
  }
  Serial.print(F("SIG: "));
  Serial.write(buf+3, len-3);
  Serial.println();
}

/**
 * @brief   Print "settings" command return value.
 * @param   buf  -->  "settings" command return value
 * buf[0]  -->  number of records which are trained successfully.
 * buf[1]  -->  record number
 * buf[2]  -->  record train status.
 * 00 --> Trained 
 * F0 --> Trained, signature truncate
 * FE --> Train Time Out
 * FF --> Value out of range"
 * buf[3] ~ buf[len-1] --> Signature.
 * len  -->  length of buf
 */

const unsigned int io_pw_tab[16]={
  10,  15,  20,  25,  30,  35,  40,  45, 
  50,  75,  100, 200, 300, 400, 500, 1000
};

void printSystemSettings(uint8_t *buf, int len)
{

  switch(buf[0]){
  case 0:
  case 3:
    Serial.println(F("Baud rate: 9600"));
    break;
  case 1:
    Serial.println(F("Baud rate: 2400"));
    break;
  case 2:
    Serial.println(F("Baud rate: 4800"));
    break;
  case 4:
    Serial.println(F("Baud rate: 19200"));
    break;
  case 5:
    Serial.println(F("Baud rate: 38400"));
    break;
  default:
    Serial.println(F("Baud rate: UNKONOWN"));
    break;
  }

  switch(buf[1]){
  case 0:
  case 0xFF:
    Serial.println(F("Outpu IO Mode: Pulse"));
    break;
  case 1:
    Serial.println(F("Outpu IO Mode: Toggle"));
    break;
  case 2:
    Serial.println(F("Outpu IO Mode: Clear(When recognized) "));
    break;
  case 3:
    Serial.println(F("Outpu IO Mode: Set(When recognized)"));
    break;
  default:
    Serial.println(F("Output IO Mode: UNKONOWN"));
    break;
  }

  if(buf[2] > 15){
    Serial.println(F("Pulse width: UNKONOWN"));
  }
  else{
    Serial.print(F("Pulse Width: "));
    Serial.print(io_pw_tab[buf[2]], DEC);
    Serial.println(F("ms"));
  }

  if(buf[3] == 0 || buf[3] == 0xFF){
    Serial.println(F("Auto Load: disable"));
  }
  else{
    Serial.println(F("Auto Load: enable"));
  }

  switch(buf[4]){
  case 0:
  case 0xFF:
    Serial.println(F("Group control by external IO: disabled"));
    break;
  case 1:
    Serial.println(F("Group control by external IO: system group selected"));
    break;
  case 2:
    Serial.println(F("Group control by external IO: user group selected"));
    break;
  default:
    Serial.println(F("Group control by external IO: UNKNOWN STATUS"));
    break;
  }
}

void printHelp(void)
{
  Serial.println(F("COMMAND        FORMAT                        EXAMPLE                    Comment"));
  printSeperator();
  //  Serial.println(F("--------------------------------------------------------------------------------------------------------------"));
  Serial.println(F("train          train (r0) (r1)...            train 0 2 45               Train records"));
  Serial.println(F("load           load (r0) (r1) ...            load 0 51 2 3              Load records"));
  Serial.println(F("clear          clear                         clear                      remove all records in  Recognizer"));
  Serial.println(F("record         record / record (r0) (r1)...  record / record 0 79       Check record train status"));
  Serial.println(F("vr             vr                            vr                         Check recognizer status"));
  Serial.println(F("getsig         getsig (r)                    getsig 0                   Get signature of record (r)"));
  Serial.println(F("sigtrain       sigtrain (r) (sig)            sigtrain 0 ZERO            Train one record(r) with signature(sig)"));
  Serial.println(F("settings       settings                      settings                   Check current system settings"));
  Serial.println(F("help           help                          help                       print this message"));
}

Ну, видимо, в том, что в коде был комментарий:

// Edited by Frank Van Hooft 2022 specifically for ESP32 UART2

а после того, как Вы эту библиотеку “написали” он исчез и сейчас на гитхабе его нет.
.
Думаю, что это кармическая проблема и простыми техническими средствами её не решить.

Если речь об этом,

То его библиотека написана под Serial2, я еë не тестировал, так как у моего модуля serial2 занят дисплеем, поэтом пришлось переписывать оригинал под HardwareSerial

Ну и сам модуль который я использую T-Display-S3 AMOLED — плата ESP32-S3 с 1,9-дюймовым AMOLED-дисплеем. – CNXSoft- новости Android-приставок и встраиваемых систем

Вставьте Serial.printf(…) по коду load везде, чтобы понять, в каком месте возвращается -1

Слабо понимаю, о чем этот код вообще.

А к каким пинам подключен ваш модуль VR? Совпадает с дефолтовыми пинами в Serial(1)?

Речь о первой строке кода, который Вы привели в стартовом сообщении и о том, что в гитхабе этой строки почему-то нет.

Для начала видимо надо посмотреть распиновку вашего девайса в аддоне:

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <stdint.h>
#include "soc/soc_caps.h"

#define USB_VID 0x303a
#define USB_PID 0x1001

#define EXTERNAL_NUM_INTERRUPTS 46
#define NUM_DIGITAL_PINS        48
#define NUM_ANALOG_INPUTS       20

#define analogInputToDigitalPin(p)  (((p)<20)?(analogChannelToDigitalPin(p)):-1)
#define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
#define digitalPinHasPWM(p)         (p < 46)

static const uint8_t BUTTON_1 = 0;
static const uint8_t BUTTON_2 = 14;
static const uint8_t BAT_VOLT = 4;

static const uint8_t TX = 43;
static const uint8_t RX = 44;

static const uint8_t SDA = 18;
static const uint8_t SCL = 17;

static const uint8_t SS    = 10;
static const uint8_t MOSI  = 11;
static const uint8_t MISO  = 13;
static const uint8_t SCK   = 12;

static const uint8_t TP_RESET = 21;
static const uint8_t TP_INIT = 16;

// ST7789 IPS TFT 170x320
static const uint8_t LCD_BL = 38;
static const uint8_t LCD_D0 = 39;
static const uint8_t LCD_D1 = 40;
static const uint8_t LCD_D2 = 41;
static const uint8_t LCD_D3 = 42;
static const uint8_t LCD_D4 = 45;
static const uint8_t LCD_D5 = 46;
static const uint8_t LCD_D6 = 47;
static const uint8_t LCD_D7 = 48;
static const uint8_t LCD_WR = 8;
static const uint8_t LCD_RD = 9;
static const uint8_t LCD_DC = 7;
static const uint8_t LCD_CS = 6;
static const uint8_t LCD_RES = 5;
static const uint8_t LCD_POWER_ON = 15;

// P1
static const uint8_t PIN_43 = 43;
static const uint8_t PIN_44 = 44;
static const uint8_t PIN_18 = 18;
static const uint8_t PIN_17 = 17;
static const uint8_t PIN_21 = 21;
static const uint8_t PIN_16 = 16;

// P2
static const uint8_t PIN_1  = 1;
static const uint8_t PIN_2  = 2;
static const uint8_t PIN_3  = 3;
static const uint8_t PIN_10 = 10;
static const uint8_t PIN_11 = 11;
static const uint8_t PIN_12 = 12;
static const uint8_t PIN_13 = 13;

// Analog
static const uint8_t A0  = 1;
static const uint8_t A1  = 2;
static const uint8_t A2  = 3;
static const uint8_t A9  = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;


// Touch
static const uint8_t T1  = 1;
static const uint8_t T2  = 2;
static const uint8_t T3  = 3;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;

#endif /* Pins_Arduino_h */

Я так понимаю по умолчанию первый уарт на других пинах:

Прежде чем написать на форум я кучу раз пробовал разные варианты, в том числе и копировать блоки кода из гитхаба Frank Van
плюс я делал это до 6 утра, поэтому не мудрено, что какие-то куски остались от других библиотек.
Я даже пробовал отправлять команды на прямую

SERIAL_4.write(FRAME_HEAD);
SERIAL_4.write(3)
SERIAL_4.write(012300004)
SERIAL_4.write(FRAME_END) 

И добавлять delay(2) как у и Frank Van экспериментировать с задержкой.

Ни чего из этого не помогло.

Да и в этом к сожалению проблема.

ну так перетащите на 15 и 16 GPIO, где порт изначально находится, может заработает

Хорошо, вечером отпишусь о результате.

Объявление метода HardwareSerial::begin() для esp32 выглядит вот так:

  // When pins are changed, it will detach the previous ones
  // if pin is negative, it won't be set/changed and will be kept as is
  // timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
  // invert will invert RX/TX polarity
  // rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
  void begin(
    unsigned long baud, 
    uint32_t config = SERIAL_8N1, 
    int8_t rxPin = -1, 
    int8_t txPin = -1, 
    bool invert = false, 
    unsigned long timeout_ms = 20000UL,
    uint8_t rxfifo_full_thrhd = 112
  );

Т.е. не обязательно использовать пины по умолчанию, можно задать свои

автор указал, что у него в библиотеке в методе begin пины указаны непосредственно

Это именно то, о чём я и говорил. У Вас кармическая, а не техническая проблема :frowning:

мне другое интересно, на 0 уарте задействованы и RTS-CTS а их то как инициализируют?

Если интересно - открываешь исходники ядра и смотришь :wink:

не льсти мне, я жеж по верхушкам нахватался )))

У меня вообще ни опыта, ни образования, так что эти вопросы не ко мне ))

Вроде в Краснодарской сельхозакадемии Си Шарп в почёте, не?

Где та академия, а где я? Я когда-то (еще в советское время) слегка поучился в политехе, но никаких Си, хоть с плюсами, хоть с шарпами, там тогда не было. Делал одну лабу на pl/2 (кажется), и одну на фортране. И фсе )))