Modulo CH376S leggere/scrivere penne USB

Ho comprato dai soliti cinesi questo modulo e sono riuscito ad usarlo tramite questa guida (modalità seriale TX/RX):
http://arduinobasics.blogspot.it/2015/05/ch376s-usb-readwrite-module.html

datasheet del chip: http://www.mpja.com/download/ch376ds1.pdf

Il modulo in mio possesso ha il connettore sul fianco non a 3 pin ma a 6
Le due file si chiamano P_S ed S. Bisogna ponticellare sulla fila P_S i due pin verso l’oscillatore.
Poi sulla fila S il primo verso l’usb è TX mentre l’ultimo verso l’oscillatore è RX. Il centrale non collegatelo.

Il codice che c’e’ al link di cui sopra è un demo (non una libreria) e, secondo me, ha molti difetti, primo tra tutti l’uso di String e stringhe costanti senza uso di macro F(). E’ un demo, accetta da monitor seriale i comandi da 1 a 9, facilmente lo switch() nella loop spiega cosa fanno.
Posto quindi la mia “versione” modificata:

setup e loop:

/* ===============================================================
 Project: CH376S USB Read/Write Module testing ground
 Author: Scott C
 Created: 1st May 2015 modifiche Noro Igor il 22/4/2016
 ================================================================== */

#include <SoftwareSerial.h>

byte computerByte;           //used to store data coming from the computer
byte USB_Byte;               //used to store data coming from the USB stick
int LED = 13;                //the LED is connected to digital pin 13 
int timeOut = 2000;          //TimeOut is 2 seconds. This is the amount of time you wish to wait for a response from the CH376S module.
char* wrData = "What is the meaning of life ?";     //We will write this data to a newly created file.
char* wrData2 = "42";                                   //We will append this data to an already existing file.

SoftwareSerial USB(10, 11);                           // Digital pin 10 on Arduino (RX) connects to TXD on the CH376S module
// Digital pin 11 on Arduino (TX) connects to RXD on the CH376S module
// GND on Arduino to GND on CH376S module
// 5V on Arduino to 5V on CH376S module
//==============================================================================================================================================
void setup() 
{ 
  delay(1000);
  Serial.begin(9600);                                 // Setup serial communication with the computer (using a baud rate of 9600 on serial monitor)
  USB.begin(9600);                                    // Setup serial communication with the CH376S module (using the default baud rate of 9600)
  pinMode(LED,OUTPUT);                                // Define digital pin 13 as an OUTPUT pin - so that we can use it with an LED
  digitalWrite(LED,LOW);                              // Turn off the LED
}

//================================================================================================================================================
void loop() 
{
  if(Serial.available())
  {
    computerByte = Serial.read();                      //read any incoming bytes from the Serial monitor, and store this byte in the variable called computerByte
    Serial.println(F("======================\n"));
    switch(computerByte)
    { 
    case '1':
      Serial.println(F("COMMAND1: CHECK CONNECTION"));
      checkConnection(0x01);                           // Check for successful connection and communication with the CH376S module.
      break;
    case '2':
      Serial.println(F("COMMAND2: set_USB_Mode"));
      set_USB_Mode(0x06);                              // Code used to enable read/write communication and monitoring of the USB stick
      break;
    case '3':
      Serial.println(F("COMMAND3: resetALL"));
      resetALL();                                      // Reset the USB device
      break;
    case '4':
      Serial.println(F("COMMAND4: Create and Write to File : TEST4.TXT"));
      writeFile("TEST4.TXT", wrData);                  // Create a file called TEST4.TXT and then Write the contents of wrData to this file
      break;
    case '5':
      Serial.println(F("COMMAND5: Read File: TEST4.TXT"));
      readFile("TEST4.TXT");                           // Read the contents of this file on the USB disk, and display contents in the Serial Monitor
      break;
    case '6':
      Serial.println(F("COMMAND6: Append data to file: TEST4.TXT"));
      appendFile("TEST4.TXT", wrData2);                // Append data to the end of the file.
      break;
    case '7':
      Serial.println(F("COMMAND7: Delete File: TEST4.TXT"));
      fileDelete("TEST4.TXT");                         // Delete the file named TEST4.TXT
      break;
    case '8':
      Serial.println(F("COMMAND8: Read File: TEST2.TXT"));
      readFile("TEST2.TXT");                           // Read the contents of the TEST2.TXT file on the USB disk, and display contents in the Serial Monitor
      break;
    case '9':
      Serial.println(F("COMMAND9: Read File: TEST3.TXT"));
      readFile("TEST3.TXT");                           // Read the contents of the TEST3.TXT file on the USB disk, and display contents in the Serial Monitor
      break;
    }
  }
  if(USB.available())                                 // This is here to capture any unexpected data transmitted by the CH376S module
  { 
    Serial.print(F("CH376S has just sent this code:"));
    Serial.println(USB.read(), HEX);
  }
}

funzioni 1:

//This function is used to check for successful communication with the CH376S module. This is not dependant of the presence of a USB stick.
//Send any value between 0 to 255, and the CH376S module will return a number = 255 - value. 
void checkConnection(byte value)
{ USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x06);
  USB.write(value);
  if(waitForResponse("checking connection"))       //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
  { if(getResponseFromUSB()==(255-value))
    { Serial.println(F(">Connection to CH376S was successful."));
      blinkLED();                               //blink the LED for 1 second if the connection was successful
    } 
    else 
    { Serial.print(F(">Connection to CH376S - FAILED."));
    }
  }
}

void set_USB_Mode (byte value) //Make sure that the USB is inserted when using 0x06 as the value in this specific code sequence
{ USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x15);
  USB.write(value);
  delay(20);
  if(USB.available())
  { 
    USB_Byte=USB.read();
    //Check to see if the command has been successfully transmitted and acknowledged.
    if(USB_Byte==0x51)                                           // If true - the CH376S has acknowledged the command.
    { Serial.println(F("set_USB_Mode command acknowledged"));    //The CH376S will now check and monitor the USB port
      USB_Byte = USB.read();
      //Check to see if the USB stick is connected or not.
      if(USB_Byte==0x15)                               // If true - there is a USB stick connected
      { Serial.println(F("USB is present"));
        blinkLED();                                     // If the process was successful, then turn the LED on for 1 second 
      } 
      else 
      { Serial.print(F("USB Not present. Error code:"));   // If the USB is not connected - it should return an Error code = FFH
        Serial.print(USB_Byte, HEX);
        Serial.println("H");
      }
    } 
    else 
    { Serial.print("CH3765 error!   Error code:");
      Serial.print(USB_Byte, HEX);
      Serial.println("H");
    }   
  }
  delay(20);
}

void resetALL() //This will perform a hardware reset of the CH376S module - which usually takes about 35 msecs =====
{ USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x05);
  Serial.println(F("The CH376S module has been reset !"));
  delay(200);
}


void readFile(char* fileName) //This will send a series of commands to read data from a specific file (defined by fileName)
{ 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 for reading
  int fs = getFileSize();         //Get the size of the file
  fileRead();                     //***** Send the command to read the file ***
  fileClose(0x00);                //Close the file
}

//is used to create a new file and then write data to that file. "fileName" is a variable used to hold the name of the file (e.g TEST.TXT). "data" should not be greater than 255 bytes long. 
void writeFile(char* fileName, char* 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
  if(fileCreate()){               //Try to create a new file. If file creation is successful
    fileWrite(data);              //write data to the file.
  } 
  else 
  { Serial.println(F("File could not be created, or it already exists"));
  }
  fileClose(0x01);
}

//is used to write data to the end of the file, without erasing the contents of the file.
void appendFile(char* fileName, char* 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.
  fileWrite(data);                //Write data to the end of the file
  fileClose(0x01);                //Close the file using 0x01 - which means to update the size of the file on close. 
}

void setFileName(char* fileName) //This sets the name of the file to work with
{ Serial.print(F("Setting filename to:"));
  Serial.println(fileName);
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x2F);
  USB.write(0x2F);         // Every filename must have this byte to indicate the start of the file name.
  USB.print(fileName);     // "fileName" is a variable that holds the name of the file.  eg. TEST.TXT
  USB.write((byte)0x00);   // you need to cast as a byte - otherwise it will not compile.  The null byte indicates the end of the file name.
  delay(20);
}

void diskConnectionStatus()  //Check the disk connection status
{ Serial.println(F("Checking USB disk connection status"));
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x30);
  if(waitForResponse("Connecting to USB disk")){       //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
    if(getResponseFromUSB()==0x14)                     //CH376S will send 0x14 if this command was successful
    { Serial.println(F(">Connection to USB OK"));
    } 
    else 
    { Serial.println(F(">Connection to USB - FAILED."));
    }
  }
}

//initialise the USB disk and check that it is ready - this process is required if you want to find the manufacturing information of the USB disk
void USBdiskMount()
{ Serial.println(F("Mounting USB disk"));
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x31);
  if(waitForResponse("mounting USB disk")){       //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
    if(getResponseFromUSB()==0x14){               //CH376S will send 0x14 if this command was successful
      Serial.println(F(">USB Mounted - OK"));
    } 
    else 
    { Serial.println(F(">Failed to Mount USB disk."));
    }
  }
}

//opens the file for reading or writing
void fileOpen()
{ Serial.println("Opening file.");
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x32);
  if(waitForResponse("file Open")){                 //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
    if(getResponseFromUSB()==0x14){                 //CH376S will send 0x14 if this command was successful  
      Serial.println(F(">File opened successfully."));
    } 
    else {
      Serial.println(F(">Failed to open file."));
    }
  }
}

//This function is required if you want to read data from the file. 
boolean setByteRead(byte numBytes)
{ boolean bytesToRead=false;
  int timeCounter = 0;

  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x3A);
  USB.write((byte)numBytes);   //tells the CH376S how many bytes to read at a time
  USB.write((byte)0x00);
  if(waitForResponse("setByteRead")){       //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
    if(getResponseFromUSB()==0x1D){         //read the CH376S message. If equal to 0x1D, data is present, so return true. Will return 0x14 if no data is present.
      bytesToRead=true;
    }
  }
  return(bytesToRead);
}

funzioni 2:

//getFileSize() - writes the file size to the serial Monitor.
int getFileSize()
{ int fileSize=0;

  Serial.println(F("Getting File Size"));
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x0C);
  USB.write(0x68);
  delay(100);
  Serial.print("FileSize =");
  if(USB.available()) fileSize = fileSize + USB.read();
  if(USB.available()) fileSize = fileSize + (USB.read()*255);
  if(USB.available()) fileSize = fileSize + (USB.read()*255*255);
  if(USB.available()) fileSize = fileSize + (USB.read()*255*255*255);
  Serial.println(fileSize);
  delay(10);
  return(fileSize);
}

//fileRead() - read the contents of the file
void fileRead()
{ byte firstByte = 0x00;                     //Variable to hold the firstByte from every transmission.  Can be used as a checkSum if required.
  byte numBytes = 0x40;                      //The maximum value is 0x40  =  64 bytes
  
  Serial.println("Reading file:");
  while(setByteRead(numBytes)){              //This tells the CH376S module how many bytes to read on the next reading step. In this example, we will read 0x10 bytes at a time. Returns true if there are bytes to read, false if there are no more bytes to read.
    USB.write(0x57);
    USB.write(0xAB);
    USB.write(0x27);                          //Command to read ALL of the bytes (allocated by setByteRead(x))
    if(waitForResponse("reading data")){      //Wait for the CH376S module to return data. TimeOut will return false. If data is being transmitted, it will return true.
      firstByte=USB.read();                 //Read the first byte
      while(USB.available()){
        Serial.write(USB.read());           //Send the data from the USB disk to the Serial monitor
        delay(1);                           //This delay is necessary for successful Serial transmission
      }
    }
    if(!continueRead()){                       //prepares the module for further reading. If false, stop reading.
      break;                                   //You need the continueRead() method if the data to be read from the USB device is greater than numBytes.
    }
  }
  Serial.println();
  Serial.println("NO MORE DATA");
}

//fileWrite=======================================================================================
//are the commands used to write to the file
void fileWrite(char* data){
  Serial.println("Writing to file:");
  byte dataLength = strlen(data);         // 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
      }
      Serial.print(F("Write code (normally FF and 14): "));
      Serial.print(USB.read(),HEX);                // code is normally 0xFF
      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
    }
  }
}

boolean continueRead() // continue to read the file : I could not get this function to work as intended.
{ boolean readAgain = false;

  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x3B);
  if(waitForResponse("continueRead")){       //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false.
    if(getResponseFromUSB()==0x14){         //CH376S will send 0x14 if this command was successful
      readAgain=true;
    }
  }
  return(readAgain);
} 

boolean fileCreate() //the command sequence to create a file
{ boolean createdFile = false;

  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x34);
  if(waitForResponse("creating file"))       //wait for a response from the CH376S. If file has been created successfully, it will return true.
  { if(getResponseFromUSB()==0x14)           //CH376S will send 0x14 if this command was successful
    { createdFile=true;
    }
  }
  return(createdFile);
}

void fileDelete(char* fileName) //the command sequence to delete a file
{ setFileName(fileName);
  delay(20);
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x35);
  if(waitForResponse("deleting file")){       //wait for a response from the CH376S. If file has been created successfully, it will return true.
    if(getResponseFromUSB()==0x14){          //CH376S will send 0x14 if this command was successful
      Serial.println("Successfully deleted file");
    }
  }
}

//is used to set the file pointer position. true for beginning of file, false for the end of the file.
void filePointer(boolean fileBeginning)
{ USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x39);
  if(fileBeginning)
  { USB.write((byte)0x00);             //beginning of file
    USB.write((byte)0x00);
    USB.write((byte)0x00);
    USB.write((byte)0x00);
  } 
  else 
  { USB.write((byte)0xFF);             //end of file
    USB.write((byte)0xFF);
    USB.write((byte)0xFF);
    USB.write((byte)0xFF);
  }
  if(waitForResponse("setting file pointer"))       //wait for a response from the CH376S. 
  { if(getResponseFromUSB()==0x14)                  //CH376S will send 0x14 if this command was successful
    { Serial.println(F("Pointer successfully applied"));
    }
  }
}

//closes the file
void fileClose(byte closeCmd)
{ Serial.println("Closing file:");
  USB.write(0x57);
  USB.write(0xAB);
  USB.write(0x36);
  USB.write((byte)closeCmd);                                // closeCmd = 0x00 = close without updating file Size, 0x01 = close and update file Size
  if(waitForResponse("closing file"))                       // wait for a response from the CH376S. 
  { byte resp = getResponseFromUSB();
    if(resp==0x14){                                        // CH376S will send 0x14 if this command was successful
      Serial.println(F(">File closed successfully."));
    } 
    else {
      Serial.print(F(">Failed to close file. Error code:"));
      Serial.println(resp, HEX);
    }  
  }
}

//is used to wait for a response from USB. Returns true when bytes become available, false if it times out.
boolean waitForResponse(char* errorMsg)
{ boolean bytesAvailable = true;
  int counter=0;
  while(!USB.available())     //wait for CH376S to verify command
  { delay(1);
    counter++;
    if(counter>timeOut)
    { Serial.print(F("TimeOut waiting for response: Error while: "));
      Serial.println(errorMsg);
      bytesAvailable = false;
      break;
    }
  }
  delay(1);
  return(bytesAvailable);
}

//is used to get any error codes or messages from the CH376S module (in response to certain commands)
byte getResponseFromUSB()
{ byte response = byte(0x00);
  if (USB.available()) response = USB.read();
  return(response);
}

void blinkLED()  //Turn an LED on for 1 second
{ digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED,LOW);
}