Problemi con CH376S

Ciao, non voglio andare troppo OT.
Io avevo già quel modulino (comprato anni fa). Collegato Arduino Uno (versione a 3,3V) in SPI tutto okay (e mi dice versione 69)
Ma in SoftwareSerial non riesco a farlo andare (nessuna delle 3 velocità)
Voi avete avuto problemi ?

@nid69ita : ho separato il tuo post creando un thread dedicato dato che è un argomento che merita il dovuto approfondimento.

Come hai collegato il modulo ed a quale Arduino?

Guglielmo

Ostia...
Sono stato il primo a parlarne ma il mio non è ancora arrivato...

Per scelta ( dato che è un passatempo non un lavoro) non scelgo mai spedizioni rapide o fornitori vicini ma cari

Dimenticavo. Arduino Uno di Itead, Studio, ha switch per andare a 5V o 3,3V. Settato a 3,3V

Mmm ... e la schedina come la alimenti? Perché, gli I/O devono essere a 3.3V, ma, causa il regolatore di tensione, il modulo va comunque alimentato a 5V.

Guglielmo

La Itead sembra l'ideale. Con switch a 3.3V comunque sul pin 5V escono i 5V (o quasi, con tester senza carichi leggo 4.6V)

E con collegamento SPI funziona

Allora, c'ho messo un po' per fare le prove ...
... premmeto che sto usando un vecchio Seeeduino MEGA, così ho le 4 seriali HW e la possibilità di avere gli I/O a 3.3V.

L'ho collegato alla seriale fisica Serial1, sto usando il programma di esempio "basicUsageHwSerial" e ... ha un comportamento strano:

... riconosce correttamente l'attach ed il detach della chiavetta USB, ma ... durante l'uso, casualmente, la considera "detached" e, per per poterla riutilizzare, tocca scollegarla e ricollegarla, però, il LED sulla schedina rimane rosso (quindi la vede) ... non vorrei fosse un problema della libreria (sembra che se non fai nulla per qualche secondo, la consideri staccata).

Devo indigare studiandomi i sorgenti ... comunque, a grandi linee, funziona ... a parte questo "timeout" che la fa considerare scollegata ... :roll_eyes:

Guglielmo

Che firmware c'e' sul chip ? Prova la funzione getChipVer()

Allora, la versione dovrebbe essere 0x43 e, utilizzando un'altra chiavetta formattata FAT32 invece che FAT16 ... sembra che tutto funzioni bene ... :smiley:

Quindi ... con la seriale hardware funziona bene (sto andando a 57600, ma ho provato anche a 9600).

Magari prima era un problema di vecchia chiavetta difettosa ... :roll_eyes:

Guglielmo

... confermo che è un problema di chiavetta (... molto vecchia) che, anche se formattata FAT32, da sempre problemi, mentre l'altra funziona sempre.

Ora ho ordinato un po' di chiavette nuove (sono rimasto senza) e vediamo come vanno ... :roll_eyes:

Guglielmo

Ho fatto la prova anche con ESP32 collegandolo alla Serial 2 (sulla WeMos D1 Mini ESP32 non è disponibile la Serial 1) ... funziona perfettamente :smiley:

Guglielmo

Allora ...
... intanto ho trovato un bel buco nella libreria per la gestione del CH376S nel metodo readFileUntil().

Il codice originale è questo:

bool Ch376msc::readFileUntil(char trmChar, char* buffer, uint8_t b_size){//buffer for reading, buffer size
	char tmpBuff[2];//temporary buffer to read string and analyze
	bool readMore = true;
	uint8_t charCnt = 0;
	b_size --;// last byte is reserved for NULL terminating character
	if(!_deviceAttached) return false;
	for(; charCnt < b_size; charCnt ++){
		readMore = readFile(tmpBuff, sizeof(tmpBuff));
		buffer[charCnt] = tmpBuff[0];
		if((tmpBuff[0] == trmChar) || !readMore){// reach terminate character or EOF
			readMore = false;
			break;
		}
	}
	buffer[charCnt+1] = 0x00;//string terminate
	return readMore;
}

... come si vede, ritorna false sia che sia effettivamente finito il file, sia che si sia incontrato il terminatore; in questo modo è impossibile leggere record a record fino alla fine del file perché, appena incontra il terminatore di record, comunque da false.

Ho modificato il metodo in questo modo:

bool Ch376msc::readFileUntil(char trmChar, char* buffer, uint8_t b_size){//buffer for reading, buffer size
	char tmpBuff[2];//temporary buffer to read string and analyze
	bool readMore = true;
	uint8_t charCnt = 0;
	b_size --;// last byte is reserved for NULL terminating character
	if(!_deviceAttached) return false;
	for(; charCnt < b_size; charCnt ++){
		readMore = readFile(tmpBuff, sizeof(tmpBuff));
		buffer[charCnt] = tmpBuff[0];
		if(!readMore) { // reach EOF
			readMore = false;
			break;
		}
		if(tmpBuff[0] == trmChar){ // reach terminate character
			break;
		}
	}
	buffer[charCnt+1] = 0x00;//string terminate
	return readMore;
}

... affinché ritorni true quando ritorna un record e false quando incontra il EOF :slight_smile:

Consigli di apportare la modifica a tutti gli utilizzatori della libreria.

Guglielmo

Detto questo ... ho realizzato quanto @Standardoil chiedeva ... lettura da chiavetta USB con CH376S di file di comandi ed esecuzione con la SerialCmd :grinning:

Il codice di prova, molto semplice e sicuramente migliorabile, che ho usato è il seguente:

#define MAX_BUFFER	255                               // Record buffer max size
#define LED_OFF      LOW                               // Adjust for your board
#define LED_ON      HIGH                               // Adjust for your board

#if defined ( ESP_PLATFORM )
#pragma message "Compiling for ESP32"
#include <HardwareSerial.h>
#endif
#include <Ch376msc.h>
#include <SerialCmd.h>

SerialCmd mySerCmd ( Serial );                         // Initialize the SerialCmd constructor using the "Serial" port

#if defined ( ESP_PLATFORM )
HardwareSerial mySerial ( 2 );
Ch376msc flashDrive ( mySerial );                      // Ch376 object with hardware Serial2 on ESP32 baudrate: 9600, 19200, 57600, 115200
#else
Ch376msc flashDrive ( Serial1, 57600 );                // Ch376 object with hardware Serial1 on arduino mega baudrate: 9600, 19200, 57600, 115200
#endif

uint16_t dataSize = 0;
bool     fAttached  = false;
bool     moreData   = false;
char     recordBuffer[MAX_BUFFER];                     // max length 255 = 254 char + 1 NULL character

void set_LEDON ( void ) {
   digitalWrite ( LED_BUILTIN, LED_ON );
}

void set_LEDOF ( void ) {
   digitalWrite ( LED_BUILTIN, LED_OFF );
}

void set_DELAY ( void ) {
   char *   sParam;
   uint32_t delayTime;
   //
   sParam = mySerCmd.ReadNext();
   if ( sParam == NULL )
      return;
   delayTime = strtoul ( sParam, NULL, 10 );
   delay ( delayTime );
}

void setup() {
   delay ( 500 );
   //
   pinMode ( LED_BUILTIN, OUTPUT );
   digitalWrite ( LED_BUILTIN, LED_OFF );
   //
   Serial.begin ( 115200 );
   delay ( 50 );
#if defined ( ESP_PLATFORM )
   mySerial.begin ( 57600, SERIAL_8N1, 16, 17 );
   delay ( 100 );
#else
   Serial1.begin ( 57600 );
#endif
   //
   mySerCmd.AddCmd ( "LEDON", SERIALCMD_FROMALL, set_LEDON );
   mySerCmd.AddCmd ( "LEDOF", SERIALCMD_FROMALL, set_LEDOF );
   mySerCmd.AddCmd ( "DELAY", SERIALCMD_FROMALL, set_DELAY );
   //
   flashDrive.init();
   delay ( 100 );
   mySerCmd.Print ( "INFO: Program started ... \r\n" );
}

void loop() {
   //
   // Check if USB drievr is connected or disconnected
   if ( flashDrive.checkIntMessage() ) {
      if ( flashDrive.getDeviceStatus() ) {
         mySerCmd.Print ( "INFO: Flash drive attached! \r\n" );
         fAttached = true;
      } else {
         mySerCmd.Print ( "INFO: Flash drive detached! \r\n" );
         fAttached = false;
      }
   }
   //
   //
   if ( fAttached ) {
      if ( flashDrive.driveReady() ) {
         flashDrive.setFileName ( "BLINK.TXT" );          // set the file name to Open
         if ( flashDrive.openFile() == ANSW_USB_INT_SUCCESS ) {
            // File successfully opened ...
            mySerCmd.Print ( "INFO: File opened ... \r\n" );
            moreData = true;
            while ( moreData ) {
               moreData = flashDrive.readFileUntil ( 0x0A, recordBuffer, MAX_BUFFER );
               // remove 0x0D and 0x0A at end of record record
               dataSize = strlen ( recordBuffer );
               if ( recordBuffer[dataSize - 2] == 0x0D )
                  recordBuffer[dataSize - 2] = 0x00;
               //
               mySerCmd.Print ( recordBuffer );
               mySerCmd.Print ( " \r\n" );
               mySerCmd.ReadString ( recordBuffer );
            }
            flashDrive.closeFile();                       // at the end, Close the file
            mySerCmd.Print ( "INFO: File closed. \r\n" );
         } else {
            // File Open Error ...
            mySerCmd.Print ( "ERROR opening file \r\n" );
         }
         //
         digitalWrite ( LED_BUILTIN, LED_OFF );
         delay ( 5000 );
      }
   }
}

... il file BLINK.TXT condiene una serie di righe:

LEDON
DELAY,1000
LEDOF

... ripetute più volte. Ogni riga finisce con 0x0D 0x0A ... per questo ho dovuto inserire la modifica che va ad eliminare i due ultimi caratteri. In funzione del Sistema Opertaivo con cui si crea il file è necessario verificare ed eventualmente correggere :slight_smile:

Se lo provate fatemi sapere :wink:

Guglielmo

Scusa, per capire meglio. Windows mette di solito 0D e 0A a fine riga, mac/linux ne mette uno solo, quale dei due ? 0D o 0A ? (se mette solo 0A mi pare il tuo codice funziona lo stesso, no?)

... difatti il file, per provare, l'ho scritto con notepad sotto Win10 :grin:

Se ben ricordo, sia Linux che macOS dovrebbero usare SOLO 0x0A che però ... andrebbe comunque eliminato, altrimenti te lo ritrovi nella stringa da passare e non viene riconosciuto (la ReadString(), contrariamete alla ReadSer(), non si aspetta un terminatore di linea, dato che gli si passa direttamente la stringa con il comando).

Comunque è cosa banale da aggiungere prima del if che già c'è per lo 0x0D ...

if ( recordBuffer[dataSize - 1] == 0x0A )
   recordBuffer[dataSize - 1] = 0x00;

Guglielmo

Ho fatto qualcosa di simile ma da riga di comando sempre, ma ho dovuto modificare la SerialCmd perché uso come terminatore tra comandi uso il ;
Altra cosa stavo provando con micros() per vedere quanto ci impiega a trovare il comando. Ci sono comandi più lunghi che sembra vengano trovati più rapidamente di quelli corti, forse sbaglio ad usare micros. Comunque stiamo (al simulatore) 80us ÷ 170us che mi pare ottimo.

Misuro il tempo così:

   // metodo read()
    uint32_t mtime = micros();
    mp_buffer[mp_bufferIdx] = 0x00;
    mp_cmd = strtok_r ( mp_buffer, mp_sepCh, &mp_lastCmd );

Prima della chiamata a funzione (spero si capisca)

                mtime = micros() - mtime; // prima di chiamata funzione
                CBptr->uFunction();  

Ciao.

Ok, studiano un po' gli esempi ho capito che in realtà, secondo l'autore, il booleano ritornato dalla readFileUntil() in realtà serve solo per capire SE si è trovato il terminatore cercato e/o si è raggiunto il EOF.

Invece, per capire se si è arrivati al EOF, occorre usare un altro metodo, getEOF() e quindi legare il while() NON al booleano tornato dalla read, ma a quello tornato da tale ultimo metodo.

Non so, potrebbe essere una cosa corretta ... anche se a me piace più la soluzione con la mia modifica.

Vedete voi quale strada preferite, forse, per ragione di compatibilità e aggiornamenti, conviene usare la strada dell'autore, altrimenti, per ogni versione, poi tocca ricordarsi di modificare la libreria e ... NON è una bella cosa ... :roll_eyes:

Modifico il codice e pubblico la versione modificata con la getEOF() ...

Guglielmo

Ecco la versione modificata per lavorare con la libreria originale ... :slight_smile:

#define MAX_BUFFER	255                               // Record buffer max size
#define LED_OFF      LOW                               // Adjust for your board
#define LED_ON      HIGH                               // Adjust for your board

#if defined ( ESP_PLATFORM )
#pragma message "Compiling for ESP32"
#include <HardwareSerial.h>
#endif
#include <Ch376msc.h>
#include <SerialCmd.h>

SerialCmd mySerCmd ( Serial );                         // Initialize the SerialCmd constructor using the "Serial" port

#if defined ( ESP_PLATFORM )
HardwareSerial mySerial ( 2 );
Ch376msc flashDrive ( mySerial );                      // Ch376 object with hardware Serial2 on ESP32 baudrate: 9600, 19200, 57600, 115200
#else
Ch376msc flashDrive ( Serial1, 57600 );                // Ch376 object with hardware Serial1 on arduino mega baudrate: 9600, 19200, 57600, 115200
#endif

uint16_t dataSize = 0;
bool     fAttached  = false;
char     recordBuffer[MAX_BUFFER];                     // max length 255 = 254 char + 1 NULL character

void set_LEDON ( void ) {
   digitalWrite ( LED_BUILTIN, LED_ON );
}

void set_LEDOF ( void ) {
   digitalWrite ( LED_BUILTIN, LED_OFF );
}

void set_DELAY ( void ) {
   char *   sParam;
   uint32_t delayTime;
   //
   sParam = mySerCmd.ReadNext();
   if ( sParam == NULL )
      return;
   delayTime = strtoul ( sParam, NULL, 10 );
   delay ( delayTime );
}

void setup() {
   delay ( 500 );
   //
   pinMode ( LED_BUILTIN, OUTPUT );
   digitalWrite ( LED_BUILTIN, LED_OFF );
   //
   Serial.begin ( 9600 );
   delay ( 50 );
#if defined ( ESP_PLATFORM )
   mySerial.begin ( 57600, SERIAL_8N1, 16, 17 );
   delay ( 100 );
#else
   Serial1.begin ( 57600 );
#endif
   //
   mySerCmd.AddCmd ( "LEDON", SERIALCMD_FROMALL, set_LEDON );
   mySerCmd.AddCmd ( "LEDOF", SERIALCMD_FROMALL, set_LEDOF );
   mySerCmd.AddCmd ( "DELAY", SERIALCMD_FROMALL, set_DELAY );
   //
   flashDrive.init();
   delay ( 100 );
   mySerCmd.Print ( "INFO: Program started ... \r\n" );
}

void loop() {
   //
   // Check if USB drievr is connected or disconnected
   if ( flashDrive.checkIntMessage() ) {
      if ( flashDrive.getDeviceStatus() ) {
         mySerCmd.Print ( "INFO: Flash drive attached! \r\n" );
         fAttached = true;
      } else {
         mySerCmd.Print ( "INFO: Flash drive detached! \r\n" );
         fAttached = false;
      }
   }
   //
   //
   if ( fAttached ) {
      if ( flashDrive.driveReady() ) {
         flashDrive.setFileName ( "BLINK.TXT" );          // set the file name to Open
         if ( flashDrive.openFile() == ANSW_USB_INT_SUCCESS ) {
            // File successfully opened ...
            mySerCmd.Print ( "INFO: File opened ... \r\n" );
            while ( !flashDrive.getEOF() ) {
               flashDrive.readFileUntil ( 0x0A, recordBuffer, MAX_BUFFER );
               // remove both 0x0D and 0x0A at end of record
               dataSize = strlen ( recordBuffer );
               if ( recordBuffer[dataSize - 1] == 0x0A )
                  recordBuffer[dataSize - 1] = 0x00;
               if ( recordBuffer[dataSize - 2] == 0x0D )
                  recordBuffer[dataSize - 2] = 0x00;
               //
               mySerCmd.Print ( recordBuffer );
               mySerCmd.Print ( " \r\n" );
               mySerCmd.ReadString ( recordBuffer );
            }
            flashDrive.closeFile();                       // at the end, Close the file
            mySerCmd.Print ( "INFO: File closed. \r\n" );
         } else {
            // File Open Error ...
            mySerCmd.Print ( "ERROR opening file \r\n" );
         }
         //
         digitalWrite ( LED_BUILTIN, LED_OFF );
         delay ( 5000 );
      }
   }
}

Guglielmo

Comunque ... questo CH376S (FW 0x43) è piuttosto "permaloso" con le chiavette USB ... alcune da 16GB, che su PC o su Mac vanno benissimo (FAT32), non le vuole proprio e come le attacchi, cerca di metterle in linea e poi dice subito "Flash drive detached!" e non le vede ... tocca stare attenti con che chievette si usano ... :roll_eyes:

Però, quando vanno ... beh ... eccezionale :grinning:

Guglielmo

è arrivato, è arrivato

è arrivato il mio dalla Cina

comincio gli esperimenti adesso...

cosa ne direbbe la moderazione se creassi un nuovo treahd e lo usassi quasi come un blog?

chessò, si potrebbe chiamare USB USB delle mie brame, dovè il file del mio reame?