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 ... ![]()
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 ... ![]()
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 ... ![]()
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 ... ![]()
Guglielmo
Ho fatto la prova anche con ESP32 collegandolo alla Serial 2 (sulla WeMos D1 Mini ESP32 non è disponibile la Serial 1) ... funziona perfettamente ![]()
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 ![]()
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 ![]()
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 ![]()
Se lo provate fatemi sapere ![]()
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 ![]()
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 ... ![]()
Modifico il codice e pubblico la versione modificata con la getEOF() ...
Guglielmo
Ecco la versione modificata per lavorare con la libreria originale ... ![]()
#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 ... ![]()
Però, quando vanno ... beh ... eccezionale ![]()
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?