CH376S USB example has issues...

There are few of us out here that have noticed a problem when appending to a file using the example from this tutorial...

https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html

Around every 512th byte written, the file closes and the data written will be truncated. The program does not clearly state that the response from command (0x2D) is the actual number of bytes written. I was sending 36 characters and getting a response of 0x24 for most of my lines. Then every few minutes, I would see a response of 9 after sending the 36 characters...??? And when you looked at the log file, it would look like:

1,2,3,4,5,6.00,08/30/2018,15:51:22
1,2,3,4,5,6.00,08/30/2018,15:51:32
1,2,3,4,5,6.00,08/30/2018,15:51:42
1,2,3,4,5,6.00,08/30/2018,15:51:52
1,2,3,4,5,6.00,08/30/2018,15:52:02
1,2,3,4,5,6.00,08/30/2018,15:52:12
1,2,3,4,5,6.00,08/30/2018,15:52:22
1,2,3,4,5,6.00,08/30/2018,15:52:32
1,2,3,4,5,6.00,08/30/2018,15:52:42
1,2,3,4,5,6.00,08/30/2018,15:52:52
1,2,3,4,5,6.00,08/30/2018,15:53:02
1,2,3,4,5,6.00,08/30/2018,15:53:12
1,2,3,4,51,2,3,4,5,6.00,08/30/2018,15:53:32
1,2,3,4,5,6.00,08/30/2018,15:53:42
1,2,3,4,5,6.00,08/30/2018,15:53:52
1,2,3,4,5,6.00,08/30/2018,15:54:02

To fix this problem I changed fileWrite to a function that returns the actual number of bytes written. I capture the response from the 0x2D command and return that value. I appendFile, I then compare the returned value to data.length(). If it is smaller, I rerun the appendFile routine after modifying "data" to only resend the truncated portion. Here is the original example from that tutorial with my mods.

I wanted to attach the entire example but it went beyond the 9000 character limit so here are the highlights....

/* ===============================================================
      Project: CH376S USB Read/Write Module testing ground
       Author: Scott C
      Created: 1st May 2015
  Arduino IDE: 1.6.2
      Website: http://arduinobasics.blogspot.com/p/arduino-basics-projects-page.html
  Description: This project will allow you to perform many of the functions available on the CH376S module.
               Checking connection to the module, putting the module into USB mode, resetting the module, 
               reading, writing, appending text to files on the USB stick. This is very useful alternative to
               SD card modules, plus it doesn't need any libraries.
=================================================================


//appendFile()====================================================================================
//is used to write data to the end of the file, without erasing the contents of the file.
void appendFile(String fileName, String data){
    resetALL();                     //Reset the module
    set_USB_Mode(0x06);             //Set to USB Mode
    diskConnectionStatus();         //Check that communication with the USB device is possible
    USBdiskMount();                 //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations.
    setFileName(fileName);          //Set File name
    fileOpen();                     //Open the file
    filePointer(false);             //filePointer(false) is to set the pointer at the end of the file.  filePointer(true) will set the pointer to the beginning.
    byte numWr = fileWrite(data);   //Write data to the end of the file and return num bytes written
    fileClose(0x01);                //Close the file using 0x01 - which means to update the size of the file on close. 
    if (numWr < data.length()){//not all bytes were written, some 512 byte barrier broken...???
      //resend the lost data...
      delay(100);
      diskConnectionStatus();         //Check that communication with the USB device is possible
      //USBdiskMount();                 //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations.
      setFileName(fileName);          //Set File name
      fileOpen();                     //Open the file
      filePointer(false);             //filePointer(false) is to set the pointer at the end of the file.  filePointer(true) will set the pointer to the beginning.
      data = data.substring(numWr);    //remove the written data and write the truncated portion
      fileWrite(data);
      fileClose(0x01);
    }
   
}

//fileWrite=======================================================================================
//are the commands used to write to the file
byte fileWrite(String data){
  byte numByteWr = 0;
  Serial.println("Writing to file:");
  byte dataLength = (byte) data.length();         // This variable holds the length of the data to be written (in bytes)
  Serial.println(data);
  Serial.print("Data Length:");
  Serial.println(dataLength);
  delay(100);
  // This set of commands tells the CH376S module how many bytes to expect from the Arduino.  (defined by the "dataLength" variable)
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x3C);
  USB.write((byte) dataLength);
  USB.write((byte) 0x00);
  if(waitForResponse("setting data Length")){      // Wait for an acknowledgement from the CH376S module before trying to send data to it
    if(getResponseFromUSB()==0x1E){                // 0x1E indicates that the USB device is in write mode.
      USB.write(0x57);
      USB.write(0xAB);
      USB.write(0x2D);
      USB.print(data);                             // write the data to the file
  
      if(waitForResponse("writing data to file")){   // wait for an acknowledgement from the CH376S module
      }
      numByteWr = USB.read();
      Serial.print("Write code.. (number bytes written) and 14 : ");
      Serial.print(numByteWr);                // code is number of bytes written to disk
      Serial.print(",");
      USB.write(0x57);
      USB.write(0xAB);
      USB.write(0x3D);                             // This is used to update the file size. Not sure if this is necessary for successful writing.
      if(waitForResponse("updating file size")){   // wait for an acknowledgement from the CH376S module
      }
      Serial.println(USB.read(),HEX);              //code is normally 0x14
    }
  }
  return(numByteWr);
}

I did not modify the library as I did not want to use the library so I could manipulate some of the routines for my nefarious purposes...

Luke

Around every 512th byte written, the file closes and the data written will be truncated.

I doubt that you can even write 512 bytes on an UNO with that code. It wastes 1745 bytes mostly for holding constant strings in RAM. If you build a string with 512 bytes content to be written by that code you already ran into a memory overflow so the result is not foreseeable.

The example works ok. It's just to familiarize your self with the operation. Someone posted a way to make all the strings into F() strings and save RAM. I never wrote 512 bytes to the thumb drive at once... I wrote 36 bytes 15 times and would see odd recording behavior. I'm using a teensy so I have plenty of ram and all the strings help me debug. Most of the strings will be weened out in the end...

The point is, if you want to successfully use the CH376 this is ONE way to make it work better.

Luke

When I wrote that tutorial, there was basically no information on the internet on how to use it or how to make it work. Actually, that is not true. There were a couple of sketchy articles. I had to do a lot of trial and error and piecing bits together.
I definitely had issues with the module, and I did not resolve all of them. The comments section of that article provides some additional insights from the Arduino community. I think someone posted a fix for the 512 byte issue. Am not sure if it is different to your solution. But it is in there somewhere.

Thank you very much for posting your solution.
I might update the tutorial one day to provide all the bug fixes so far.

ArduinoBasics:
I might update the tutorial one day to provide all the bug fixes so far.

I have a new version with 6 pins instead of 3. From what I can see from circuit diagram, to use it in UART mode I should put a jumper on pins 2 and 3 in P_S row, then pin 1 of S row will be RX and pin 3 in this row will be TX.
So I connected it to an Arduino Nano, using SoftwareSerial configured for 9600 speed.

However, using oscilloscope I can see the packets sent by Nano on CH376S's RX pin but TX pin remains silent. What I'm doing wrong? Or maybe the board is just broken?

Hi ljbeng, As per your suggestion After 2D comment (USB.READ) supposed to return current written data

length(Buffer), But Unfortunately It is Not Returning , except 255 , So please help me out to solve 512 byte

writing issue .Thanks in advance.

/* ===============================================================
Project: CH376S USB Read/Write Module testing ground
Author: Scott C
Created: 1st May 2015
Arduino IDE: 1.6.2
Website: http://arduinobasics.blogspot.com/p/arduino-basics-projects-page.html
Description: This project will allow you to perform many of the functions available on the CH376S module.
Checking connection to the module, putting the module into USB mode, resetting the module,
reading, writing, appending text to files on the USB stick. This is very useful alternative to
SD card modules, plus it doesn't need any libraries.

//appendFile()====================================================================================
//is used to write data to the end of the file, without erasing the contents of the file.
void appendFile(String fileName, String data){
resetALL(); //Reset the module
set_USB_Mode(0x06); //Set to USB Mode
diskConnectionStatus(); //Check that communication with the USB device is possible
USBdiskMount(); //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations.
setFileName(fileName); //Set File name
fileOpen(); //Open the file
filePointer(false); //filePointer(false) is to set the pointer at the end of the file. filePointer(true) will set the pointer to the beginning.
byte numWr = fileWrite(data); //Write data to the end of the file and return num bytes written
fileClose(0x01); //Close the file using 0x01 - which means to update the size of the file on close.
if (numWr < data.length()){//not all bytes were written, some 512 byte barrier broken...???
//resend the lost data...
delay(100);
diskConnectionStatus(); //Check that communication with the USB device is possible
//USBdiskMount(); //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations.
setFileName(fileName); //Set File name
fileOpen(); //Open the file
filePointer(false); //filePointer(false) is to set the pointer at the end of the file. filePointer(true) will set the pointer to the beginning.
data = data.substring(numWr); //remove the written data and write the truncated portion
fileWrite(data);
fileClose(0x01);
}

}

//fileWrite=======================================================================================
//are the commands used to write to the file
byte fileWrite(String data){
byte numByteWr = 0;
Serial.println("Writing to file:");
byte dataLength = (byte) data.length(); // This variable holds the length of the data to be written (in bytes)
Serial.println(data);
Serial.print("Data Length:");
Serial.println(dataLength);
delay(100);
// This set of commands tells the CH376S module how many bytes to expect from the Arduino. (defined by the "dataLength" variable)
USB.write(0x57);
USB.write(0xAB);
USB.write(0x3C);
USB.write((byte) dataLength);
USB.write((byte) 0x00);
if(waitForResponse("setting data Length")){ // Wait for an acknowledgement from the CH376S module before trying to send data to it
if(getResponseFromUSB()==0x1E){ // 0x1E indicates that the USB device is in write mode.
USB.write(0x57);
USB.write(0xAB);
USB.write(0x2D);
USB.print(data); // write the data to the file

if(waitForResponse("writing data to file")){ // wait for an acknowledgement from the CH376S module
}
numByteWr = USB.read();
Serial.print("Write code.. (number bytes written) and 14 : ");
Serial.print(numByteWr); // code is number of bytes written to disk
Serial.print(",");
USB.write(0x57);
USB.write(0xAB);
USB.write(0x3D); // This is used to update the file size. Not sure if this is necessary for successful writing.
if(waitForResponse("updating file size")){ // wait for an acknowledgement from the CH376S module
}
Serial.println(USB.read(),HEX); //code is normally 0x14
}
}
return(numByteWr);
}

vkozlov:
I have a new version with 6 pins instead of 3. From what I can see from circuit diagram, to use it in UART mode I should put a jumper on pins 2 and 3 in P_S row, then pin 1 of S row will be RX and pin 3 in this row will be TX.
So I connected it to an Arduino Nano, using SoftwareSerial configured for 9600 speed.

However, using oscilloscope I can see the packets sent by Nano on CH376S's RX pin but TX pin remains silent. What I'm doing wrong? Or maybe the board is just broken?

Use this scheme:

i had the same problem, until used a voltmeter yet :wink:
дай боже здоров'я тим виробникам!)

ljbeng:
Around every 512th byte written, the file closes and the data written will be truncated.

I had the same problem, after use your fix, it all worked, thanks.
But i think, need to rewrite the source based on the manual :slight_smile: https://www.mpja.com/download/CH376DS1.pdf

Nope, still have error, now with 1024 byte writing

Im also facing the same problem for every 512 bytes of data. The 0x2d command mostly returns 0xFF as response. How to get the exact number of bytes written?

Can someone help me to fix this please?

Thanks.

Hi everyone. If the reading/writing problem still persist, you can check my lib, i hope it helps :wink:
Ch376msc

From now the lib is ready for SPI communication. Let me know if you find any problem with the lib or if you have any idea with it.
Cheers,
György

djusee:
From now the lib is ready for SPI communication. Let me know if you find any problem with the lib or if you have any idea with it.
Cheers,
György

Great! Could you please confirm the pin connections?

Arduino nano -> Ch376S module

MISO (12) -> D7
MOSI (11) ->D6
SCK (13) -> D5
10 -> D3
9 -> D4
GND -> RD (as per datasheet to select SPI mode)
GND -> WR (as per datasheet to select SPI mode)

Correct?

vkozlov:
Great! Could you please confirm the pin connections?

Arduino nano -> Ch376S module

MISO (12) -> D7
MOSI (11) ->D6
SCK (13) -> D5
10 -> D3
9 -> D4
GND -> RD (as per datasheet to select SPI mode)
GND -> WR (as per datasheet to select SPI mode)

Correct?

Yes, thats correct if you dont want to share the SPI port with another slave device, otherwise you have to use one more pin to detect any incoming interrupt request from the control chip.

Cool, it works just fine. Great job! Thanks!

Btw, how could we add hot-swap of the usb sticks? when I disconnect and then reconnect usb drive, I have to reset Arduino, I think it would be nice to have a some kind of "re-init" when .checkDrive() fails.

Thanks! With calling checkDrive() function you get back a boolean value, false = thumb drive disconnected, true = connceted.I had a problem on breadboard with long wires connected to module, that is the reason why i use !slower comm speed (125kHz)

 if(flashDrive.checkDrive()){ 
        // flash drive connected
    } else {
       // usb flash drive disconnected
}

I have found a problem on higher clock rate in the meantime. Code is updated :blush:

Hello everyone, my name is Jonathan from Buenos Aires, Argentina, and I am interacting with the CH376S chip for the first time, for which the libraries were very useful. Now I want to update them to add the option to copy a file from the SD memory to the PENDRIVE. Does anyone know if it is possible to perform this task ?, the idea is to use the CH376S in a datalogger that will store the information in an SD memory and download it in a PENDRIVE when it is entered.

I appreciate any comments in advance.
Best regards,

ADICHIP_net:
Hello everyone, my name is Jonathan from Buenos Aires, Argentina, and I am interacting with the CH376S chip for the first time, for which the libraries were very useful. Now I want to update them to add the option to copy a file from the SD memory to the PENDRIVE. Does anyone know if it is possible to perform this task ?, the idea is to use the CH376S in a datalogger that will store the information in an SD memory and download it in a PENDRIVE when it is entered.

I appreciate any comments in advance.
Best regards,

Hi Jonathan, make a buffer variable, read data from sd card and put them to the buffer, and then write it to the flash drive. Check the example files in the lib.
Cheers,
György