Coder Social home page Coder Social logo

powerbroker2 / serialtransfer Goto Github PK

View Code? Open in Web Editor NEW
388.0 21.0 63.0 455 KB

Arduino library to transfer dynamic, packetized data fast and reliably via Serial, I2C, or SPI

License: MIT License

C++ 100.00%
serial arduino-library uart packets senddata transfer bytes tx-buffer usart serial-communication

serialtransfer's Introduction

SerialTransfer

GitHub version arduino-library-badge

SerialTransfer is an easy to use Arduino library for transferring packetized data fast and reliably via Serial, I2C, and SPI interfaces. Interconnect your Arduinos today minus the headache with SerialTransfer!

A mirror library is also available for Python!

This library:

  • can be downloaded via the Arduino IDE's Libraries Manager (search "SerialTransfer.h")
  • works with "software-serial", "software-I2C", and "software-SPI" libraries
  • is non blocking
  • uses packet delimiters
  • uses consistent overhead byte stuffing
  • uses CRC-8 (Polynomial 0x9B with lookup table)
  • allows the use of dynamically sized packets (packets can have payload lengths anywhere from 1 to 254 bytes)
  • supports user-specified callback functions
  • can transfer bytes, ints, floats, structs, even large files like JPEGs and CSVs!!

Packet Anatomy:

01111110 00000000 11111111 00000000 00000000 00000000 ... 00000000 10000001
|      | |      | |      | |      | |      | |      | | | |      | |______|__Stop byte
|      | |      | |      | |      | |      | |      | | | |______|___________8-bit CRC
|      | |      | |      | |      | |      | |      | |_|____________________Rest of payload
|      | |      | |      | |      | |      | |______|________________________2nd payload byte
|      | |      | |      | |      | |______|_________________________________1st payload byte
|      | |      | |      | |______|__________________________________________# of payload bytes
|      | |      | |______|___________________________________________________COBS Overhead byte
|      | |______|____________________________________________________________Packet ID (0 by default)
|______|_____________________________________________________________________Start byte (constant)

How To Use:

See the example sketches

  • datum = tx/rx a single object
  • data = tx/rx multiple objects

NOTE:

SPITransfer.h and it's associated features are not supported for the Arduino Nano 33 BLE or DUE and other boards. This header file is disabled by default, but can be enabled by commenting out #define DISABLE_SPI_SERIALTRANSFER 1 within SerialTransfer.h.

serialtransfer's People

Contributors

brainstone avatar brunojoyal avatar iguessthislldo avatar martincizek avatar powerbroker2 avatar robberwick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serialtransfer's Issues

Corruption at > 9600 over SoftwareSerial

Hi there,
I'm another big fan of your library here, but just having an issue with it over Serial, and in particular SoftwareSerial at one end of my link.
I have an Adafruit FeatherM0 HW Serial port connected to a Sparkfun Artemis Global Tracker SoftwareSerial port with SerialTransfer (3.0.8) running over the top. The serial link works fine at 9600, at anything above the data TX'ed from the Artemis is slightly corrupted, such that the Feather is not able to reassemble a packet. I can see this via an FTDI Buddy I have looking at the TX pin on the Artemis. Traffic in the other direction is fine. I am also making sure I am not TX/RX concurrently on the Artemis as I understand that is a limitation of SoftwareSerial.
I ran a basic test just pumping out chars from the Artemis (SoftwareSerial) to the Feather at 115200 no problem, everything received intact.
The issue seems to be only when I use SerialTransfer and configure the link for > 9600.
Best I can tell, when I take the link up to 19200, the initial char that I think should be 0x7E, looks like it is 0xFC on the wire? Likewise the 3rd byte looks like it should be 0xFF (when I look at it at 9600) but is 0xFA when sending at 19200. Everything else in the packet looks low from that point on, i.e. same in 9600 transmission as 19200 transmission. If I turn the speed up to say 38400, corruption appears in more of the packet.

This is the struct I am sending from the Artemis to the Feather;

struct STRUCT { // my datum to tx/rx over SerialTransfer
  char c1;
  char c2;
  char c3;
  char c4;
} STDatumTX, STDatumRX;

for the purposes of this testing I am statically setting it as follows;

  STDatumTX.c1 = 'A';
  STDatumTX.c2 = 't';
  STDatumTX.c3 = 'o';
  STDatumTX.c4 = 'F';

Screen Shot 2021-03-21 at 1 33 31 pm
In the above screenshot the system is running at 19200 for most of that hex capture, and you can see an example in the red box of bad packet. Then a fair way down I switched to 9600 and you can see an example good packet in green.

Also, I have enabled debugging via
STdriverF2A.begin(SerialtoAGT, true, Serial);
on the Feather and
STdriverF2A.begin(SerialtoAGT, true, Serial);
on the Artemis, but neither spits out any output ?

Hopefully its something simple I am doing wrong?

Send picture from one ESP32CAM to another using SPI

TL;DR: All I want is to send the camera's frame buffer to another ESP32CAM. That's it. No streaming, just one photo every few minutes or so.

If you think my approach could be different please tell me, I will gladly consider other options!

I am having a hard time figuring out how to do this, documentation is scarce presumably because most people don't use SPI. (I2C is way too convenient)
However, I found a forum thread which described a similar issue: link

I wish to create a script that would take a picture on both ESP32CAM modules, send the picture from the first one to the second one and then have that one send both pictures to an FTP server. However, I want to use ethernet, since Wi-Fi seems to be really unreliable for some reason (and would like to use PoE) and the W5500 Ethernet modules communicate through SPI.
So unless I can switch from I2C for the ESP to ESP communication to SPI for the Ethernet module... I must use SPI.

I am not very knowledgeable in serial communication so I was hoping someone could help me by giving me some guidance on how to do this. The thread I linked does help, but was written for I2C (correct me if I am wrong) and the code gets a little complicated and combined with the fact I can't find much documentation on this makes me a little uneasy when coding.

Thank you for any and all help!

Receiver code (very unfinished and not working, mostly a cut down example from mentioned thread)

/*Receives picture via serial and saves to ftp*/

#define DEBUG_ESP              //comment out to deactivate debug console

#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif

#include "SPITransfer.h"
SPITransfer myTransfer;
struct img_meta_data{
  uint16_t counter;
  uint16_t imSize;
  uint16_t numLoops;
  uint16_t sizeLastLoop;
} ImgMetaData;
uint16_t packetCounter=1;
uint16_t bufferPointer=0;
char tempImageBuffer[32000];

// FTP Client Lib
#include "ESP32_FTPClient.h"

// FTP Server credentials
char ftp_server[] = "";
char ftp_user[]   = ""; 
char ftp_pass[]   = "";

// picture name
String picPrefix ="";
String pic_name;  

// Connection timeout;
#define CON_TIMEOUT   10*1000                     // milliseconds

ESP32_FTPClient ftp(ftp_server, ftp_user, ftp_pass);

void setup(){
  //Serial.begin(Baud Rate, Data Protocol, Txd pin, Rxd pin);
  Serial.begin(115200);                                                     // Define and start serial monitor
  // 115200,256000,512000,962100

  SPCR |= bit (SPE);
  pinMode(MISO, OUTPUT);
  SPI.attachInterrupt();
  
  myTransfer.begin(SPI);
}

void loop(){
  if(myTransfer.available())  {
    myTransfer.rxObj(ImgMetaData, sizeof(ImgMetaData));
    pDBG("Struct Data: ");
    pDBG(ImgMetaData.counter);
    pDBG(", ");
    pDBG(ImgMetaData.imSize);
    pDBG(", ");  
    pDBG(ImgMetaData.numLoops);
    pDBG(", ");
    pDBG(ImgMetaData.sizeLastLoop);
    pDBG(", PacketCounter: ");
    pDBGln(packetCounter);  

    if(ImgMetaData.counter==1){  
      copyToImageBuff(MAX_PACKET_SIZE-sizeof(ImgMetaData));
    }else{
      if(ImgMetaData.counter==packetCounter){  
        if(packetCounter<ImgMetaData.numLoops){        
          copyToImageBuff(MAX_PACKET_SIZE-sizeof(ImgMetaData));
        }else if(ImgMetaData.counter==packetCounter){
          copyToImageBuff(ImgMetaData.sizeLastLoop);     
        }
      }
    }
 
    if(packetCounter>ImgMetaData.numLoops){  
      pic_name  = picPrefix;
      pic_name += ".jpg";  
      FTP_upload();     
      packetCounter=1;
      bufferPointer=0;
      delay(2000);
      //while(1){}
    }  

  }else if(myTransfer.status < 0) { 
    pDBG("ERROR: ");
    if(myTransfer.status == -1)
      pDBGln(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      pDBGln(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      pDBGln(F("STOP_BYTE_ERROR"));
  }
}
  

void copyToImageBuff(uint16_t dataLenght){
  for(int y=0;y<dataLenght;y++){
    tempImageBuffer[bufferPointer+y] = myTransfer.rxBuff[y+sizeof(ImgMetaData)];
  } 
  bufferPointer+=dataLenght;
  packetCounter++;  

  pDBG("dataLenght: ");
  pDBG(dataLenght);  
  pDBG(", bufferPointer: ");
  pDBGln(bufferPointer);
}

void printBuf(char localBuff){
  pDBG(F("Pixel Values: { "));
  for (uint16_t k=0; k<sizeof(myTransfer.rxBuff); k++){
    pDBG(myTransfer.rxBuff[k]);
    if (k < (sizeof(myTransfer.rxBuff) - 1))
      pDBG(F(", "));
    else
      pDBGln(F(" }"));
  }
}

void FTP_upload(){
  pDBG("Uploading via FTP: "); 
  ftp.OpenConnection();
  //ftp.ChangeWorkDir("/public_html/zyro/");
  //Create a file and write the image data to it;
  ftp.InitFile("Type I");
  const char *f_name = pic_name.c_str();
  ftp.NewFile( f_name ); 
  pDBGln( f_name );    
  ftp.WriteData((unsigned char*)tempImageBuffer, ImgMetaData.imSize);
  ftp.CloseFile();
  // Breath, withouth delay URL failed to update.
  pDBGln("Done... Waiting next transfer...");
  delay(100);
}

Sender (same issue as above):

#define DEBUG_ESP              //comment out to deactivate debug console

#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif

#include "esp_camera.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include "SPITransfer.h"
#include <SPI.h>

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

SPITransfer myTransfer;
//HardwareSerial Comm(1);
struct img_meta_data{
  uint16_t counter;
  uint16_t imSize;
  uint16_t numLoops;
  uint16_t sizeLastLoop;
} ImgMetaData;
const uint16_t PIXELS_PER_PACKET = MAX_PACKET_SIZE - sizeof(ImgMetaData);

void setup(){
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
 
  Serial.begin(115200);                     // Define and start serial monitor
  // 115200,256000,512000,962100
  //Comm.begin(962100, SERIAL_8N1,15,14);     //, Comm_Txd_pin, Comm_Rxd_pin); // Define and start Comm serial port
  //myTransfer.begin(Comm);

  digitalWrite(15, HIGH);
  SPI.begin(14,12,13,15);
  SPI.setClockDivider(SPI_CLOCK_DIV8);

  myTransfer.begin(SPI);
 
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
 
//  if(psramFound()){
//    config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
//    config.jpeg_quality = 10;
//    config.fb_count = 2;
//  } else {
//    config.frame_size = FRAMESIZE_SVGA;
//    config.jpeg_quality = 12;
//    config.fb_count = 1;
//  }

    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 10;
    config.fb_count = 1;
 
  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK){
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
  
  // Change extra settings if required
  sensor_t * s = esp_camera_sensor_get();
  //s->set_vflip(s, 0);       //flip it back
  //s->set_brightness(s, 1);  //up the blightness just a bit
  //s->set_saturation(s, -2); //lower the saturation
  s->set_ae_level(s, -1);       //exposure time -2 to 2
  
}

  
void loop(){
  uint16_t startIndex = 0;
  camera_fb_t * fb = NULL;
  //Take Picture with Camera
  fb = esp_camera_fb_get();
   
  ImgMetaData.imSize       = fb->len;                             //sizeof(myFb);
  ImgMetaData.numLoops     = (fb->len / PIXELS_PER_PACKET) + 1;   //(sizeof(myFb)/PIXELS_PER_PACKET) + 1; 
  ImgMetaData.sizeLastLoop = fb->len % PIXELS_PER_PACKET;         //(sizeof(myFb)%PIXELS_PER_PACKET);

  for(ImgMetaData.counter=1; ImgMetaData.counter<=ImgMetaData.numLoops; ImgMetaData.counter++){
    myTransfer.txObj(ImgMetaData, sizeof(ImgMetaData));
    //printStructBuf();
    stuffPixels(fb->buf, startIndex, sizeof(ImgMetaData), PIXELS_PER_PACKET);
    //stuffPixels(myFb, startIndex, sizeof(ImgMetaData), PIXELS_PER_PACKET);
    //printStructBuf();   
    myTransfer.sendData(MAX_PACKET_SIZE);
    
    pDBGln(F("Sent:"));
    pDBG(F("img.counter: "));      pDBGln((uint16_t)((myTransfer.packet.txBuff[1] << 8) | myTransfer.packet.txBuff[0]));
    pDBG(F("img.imSize: "));       pDBGln((uint16_t)((myTransfer.packet.txBuff[3] << 8) | myTransfer.packet.txBuff[2]));
    pDBG(F("img.numLoops: "));     pDBGln((uint16_t)((myTransfer.packet.txBuff[5] << 8) | myTransfer.packet.txBuff[4]));
    pDBG(F("img.sizeLastLoop: ")); pDBGln((uint16_t)((myTransfer.packet.txBuff[7] << 8) | myTransfer.packet.txBuff[6]));
    
    startIndex += PIXELS_PER_PACKET;    
    delay(100);
    //printBuf();  
  }
  esp_camera_fb_return(fb);   //clear camera memory
  delay(10000);
}

void printStructBuf(){
  pDBG(F("Internal Struct: { "));
  for (uint16_t k=0; k<sizeof(ImgMetaData); k++){
    pDBG(myTransfer.packet.txBuff[k]);
    if (k<(sizeof(ImgMetaData)-1))
      pDBG(F(", "));
    else
      pDBGln(F(" }"));
  }
}

void printBuf(){
  pDBG(F("Pixel Values: { "));
  for (uint16_t k=8; k<MAX_PACKET_SIZE; k++){
    pDBG(myTransfer.packet.txBuff[k]);
    if (k < (MAX_PACKET_SIZE - 1))
      pDBG(F(", "));
    else
      pDBGln(F(" }"));
  }
  pDBGln();
}

void stuffPixels(const uint8_t * pixelBuff, const uint16_t &bufStartIndex, const uint16_t &txStartIndex, const uint16_t &len){
  uint16_t txi = txStartIndex;
  for (uint16_t i=bufStartIndex; i<(bufStartIndex + len); i++)  {
    myTransfer.packet.txBuff[txi] = pixelBuff[i];
    txi++;
  }
}

Getting 0s at Rx in Arduino Uno when connected via software Serial

Describe the bug
Running the attached Examples Arduino file namely rx_multiple_objects.ino and tx_multiple_objects.ino gives 0s instead of struct and array's data at receiving end.
the problem seems to be with myTransfer.txObj() function as the data sent directly via myTransfer.txBuff[0]='h'; seems to appear just fine.

the example was run without any modifications other than using softserial instead of Serial1.

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'Examples and upload tx_multiple_objects and rx_multiple_objects to arduino'
  2. Sample files are attached
    Serial.zip

Expected behavior
Data from array should have appeared on the serial monitor of Arduino.

Screenshots
shot-1

  • OS: Windows 10
  • Arduino IDE [1.8.9]

Reduce library memory usage

Is your feature request related to a problem? Please describe.
I am trying to use this library as part of a project with multiple devices connected with software serial. This libraries large size means I can't use 3 software serials on the Arduino Uno as this makes the memory approx. 110% dynamic memory just to declare all the SerialTransfer instances.

Describe the solution you'd like
Reduce library memory usage.

Describe alternatives you've considered
I could use a Arduino Mega however I don't current have one available.

Additional context
Here is the simplest code for this setup:

#include "SerialTransfer.h"
#include <SoftwareSerial.h>

SerialTransfer sTransfer_a;
SerialTransfer sTransfer_b;
SerialTransfer sTransfer_c;
SerialTransfer sTransfer_d;
SoftwareSerial sSerial_b(2,3);
SoftwareSerial sSerial_c(5,6);
SoftwareSerial sSerial_d(8,9);

void setup()
{
  Serial.begin(115200);
  sSerial_b.begin(115200);
  sSerial_c.begin(115200);
  sSerial_d.begin(115200);
  sTransfer_a.begin(Serial);
  sTransfer_b.begin(sSerial_b);
  sTransfer_c.begin(sSerial_c);
  sTransfer_d.begin(sSerial_d);
}
void loop()
{
}

Error compiling examples on Arduino Nano 33 BLE

Describe the bug
The library will not compile on the Arduino Nano 33 BLE. I tried to compile the uart_tx_data example and got the following error:


/Users/lberndt/Documents/Arduino/libraries/SerialTransfer/src/SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
/Users/lberndt/Documents/Arduino/libraries/SerialTransfer/src/SPITransfer.cpp:115:29: error: 'SPDR' was not declared in this scope
  volatile uint8_t recChar = SPDR;
                             ^~~~
/Users/lberndt/Documents/Arduino/libraries/SerialTransfer/src/SPITransfer.cpp:115:29: note: suggested alternative: 'SPI'
  volatile uint8_t recChar = SPDR;
                             ^~~~
                             SPI
exit status 1
Error compiling for board Arduino Nano 33 BLE.

I think that SPI maybe implemented differently on this board.

To Reproduce
Steps to reproduce the behavior:

  1. Goto examples, board uart_tx_data
  2. Select the Arduino Nano 33 BLE as Board Type
  3. compile

Desktop (please complete the following information):

  • OS: MacOS 1.15.4
  • Arduino: 1.8.13

Licensing

Hey, I'd like to use this library and its siblings in a proprietary commercial product. Which is not possible with the current GPLv3 license.
I'd like to discuss this matter with you in private but I sadly was not able to find contact information for contacting you in private.

I'd prefer you reach out to me over Discord: redacted
If you don't use Discord, you can contact me on my email: redacted
(Note both contact infos are posted here as images to prevent crawlers from seeing them.)

It would be much appreachiated if you delete the issue after you read it or at least got rid of the Discord username and the email.

Thank you for your work and time!

Stop the reading loop as soon as packet.status is not "Continue"

In SerialTransfer::available(), if port->available() is still True when packet has decoded the EndOfFrame byte, the received frame is happily dumped to start receiving the new one.

To Reproduce:
Set the baudrate at 115200 and always send a second EndOfFrame (this was my idea to "ease recovery" in case a byte is not received…). Strangely, this is easier to reproduce with a real UART than with the SerialUSB emulation.

Expected behavior
Whenever a frame is received and ready, I should be able to process it ;-)

Feature Request: Can this work for the Portenta

I have read that the library does not support the Nano33Ble, is that an MBED thing? Could the library possibly support the Portenta ?

If not do you have any suggestions for parsing variables between Portenta's using UART?

Note: txData and rxData both compile version 2.10 MBED core on the Nano33Ble and the Portenta. Tomorrow I will check if they actually send data.

How can I pause serial transfer and then un-pause it ?

So I am running a usb (UART) connection from my arduino(using the serialtransfer.h library) to my pc (using the pyserial transfer library).
This how each cycle of code goes:
I receive the list_ packet and save it to a list on the Arduino . Then the elements in the list are checked and used to control parameters of motor a using GPIO pins. Finally a return message is sent to acknowledge each transfer.

I was hoping to make the return message from Arduino as sort of a flag ; whether to wait or move onto the next transfer, this is on the python side of things. This is not the case as the sending of packets from Arduino is almost instantaneous even with delay functions

The python code is the standard code on your github with few changes to the parameters of rx.obj function
here is the Arduino side of things

#include "SerialTransfer.h"


SerialTransfer myTransfer;
int motor1 = 13;
int motor2 = 10;

int obj_cordinates[9];
char reply [16] = {"Packet Recieved"};
void setup()
{
  Serial.begin(115200);
  pinMode(motor1,OUTPUT);
  pinMode(motor2,OUTPUT);
  
  myTransfer.begin(Serial);
}


void loop()
{
  if(myTransfer.available())
  {
    // use this variable to keep track of how many
    // bytes we've processed from the receive buffer
    uint16_t recSize = 0;
    uint16_t sendSize = 0;

    recSize = myTransfer.rxObj(obj_cordinates, recSize);
    sendSize = myTransfer.txObj(reply, sendSize);
    
     if( obj_cordinates[4] == 15) 
    {
      digitalWrite(motor1, HIGH);
      digitalWrite(motor2, LOW);
      
      delay(5000);
      
      digitalWrite(motor1, LOW);
      digitalWrite(motor2, HIGH);
      delay(5000);
    }

    myTransfer.sendData(sendSize);
  }
  
}

Error sending data with variables

Hi, im newbie in Arduino, i try to sending multiple data with arduino uno and will received by nodemcu, in this case i will use variable data1 and data2, but nodemcu receive like this

nodemcu serialtransfer

this code will be implement to my project with 2 sensor, that's why i need variable for collect the data.

here's my arduino code (tx)

#include "SerialTransfer.h"
#include <SoftwareSerial.h>


SoftwareSerial mySerial(2, 3); // RX, TX
SerialTransfer myTransfer;
int data1 = 1;
int data2 = 2;

void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myTransfer.begin(mySerial);
}


void loop()
{
  myTransfer.txBuff[0] = data1;
  myTransfer.txBuff[1] = data2;
  myTransfer.txBuff[2] = '\n';
  
  myTransfer.sendData(2);
  delay(100);
}

and my nodemcu code (rx)

#include "SerialTransfer.h"
#include <SoftwareSerial.h>


SoftwareSerial mySerial(D6, D5); // RX, TX
SerialTransfer myTransfer;


void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myTransfer.begin(mySerial);
}


void loop()
{
  if(myTransfer.available())
  {
      Serial.print("Data 1 ");
      Serial.write(myTransfer.rxBuff[0]);
      Serial.println();
      Serial.print("Data 2 ");
      Serial.write(myTransfer.rxBuff[1]);
      Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

bytheway sorry for my english :D

Is it possible to add the ability to support RS485 Half Duplex?

Is your feature request related to a problem? Please describe.
Is it possible to adapt the SerialTransfer library to work with a half duplex RS485 network?
I have two networks (one which I currently use the SerialTransfer library for), the 2nd network however is RS485 and hence I am looking at a library with the capabilities of the full duplex SerialTransfer library in a half duplex package.

Describe the solution you'd like
Ability to control the timing and TX/RX enable lines of an RS485 Receiver
Management of transmitting and receiving structured data (ints, floats etc) in a polled network
i.e. looking at the RS485 network having one master and the rest being slaves as opposed to a multi-master network using collision detection

Describe alternatives you've considered
Currently I am looking to manually control the enable TXE/RXE inputs, timing management and node addressing, however thought I would ask the question before going down the rabbit hole!

SerialTransfer::available() only reads 1 byte per call

Alright. Either there's something wrong with your code or I'm going crazy.
But as I read the code calling SerialTransfer::available() only ever reads a single byte instead of trying to fetch the whole packet.

uint8_t SerialTransfer::available()
{
bool valid = false;
uint8_t recChar = 0xFF;
if (port->available())
{
recChar = port->read();
valid = true;
}
bytesRead = packet.parse(recChar, valid);
status = packet.status;
return bytesRead;
}

Now if I am reading that correctly that is in fact an issue. Mainly as my current code only calls that function sparringly (once every 100ms) as there's lots of other stuff to do. Also the description of the method is misleading as that sounds like calling this method takes care of the entirety of the parsing.

Now I also think your intentions were to have this method as a byte by byte method and the prorgammer can determine the state of the parser by reading the state variable.
Not only would this be a prime candidate for an enum but also it never gets set back to the state NO_DATA. (in 2.1.2 it does get reset. I think you just missed the else clause)

Now I'd advise you to have the available function in all 3 interfaces parse either the entire serial data or until it reaches the end of a packet. Then additionally have a byte by byte method for those that want to work that way.

And lastly I really liked the function return an error value instead of setting an internal state on error.

EDIT:

Nevermind on the part about the return value.

Start / End Markers

Hello,

I am considering using your library for a device I am hacking on as your packet format matches the device's packet almost exactly.

On my device start is 0xAA and end is 0x55 .. Your's are different and I can change that but in both implementations there is a possibility of the checksum total could be a value in the stream / packet.

In my situation, then end Char is 0x55, a capital U. There is a real possibility (although small) that U can be part of the message and not the end of message.

Does your library account for this situation or event?

Off to learn about COBS now.

Thank you!!

'Serial1' was not declared in this scope

Hi,

I have been unable to compile my code because I keep receiving the following error:

'Serial1' was not declared in this scope

And yet everywhere I see examples without Serial1 not being declared so I can't understand why this is happening.

My code is as follows:

#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);
}

void loop()
{
  char buff[] = "hi";

  myTransfer.txObj(buff, sizeof(buff));
  myTransfer.sendData(sizeof(buff));
  delay(100);
}

Any ideas?

Thanks in advance.

Giving the library the final polish

I think you might have noticed by now that I really like your library.

And at this point I'd like to give something back to you.
Now I have some decent experience designing libraries and software in general and I have a few suggestions (that I'm all willing to implement myself):

  • Use inheritance for the specializations:
    This is a fun one! Now I like that you separated the package code into its own class. That's good design. However there is one (fairly) big flaw with how you're doing it right now: The classes don't have anything to do with eachother.
    So my suggestion is to make use of inheritance. You have the abstract Packet class (maybe it should be renamed?) that has the pure virtual functions readAvailable (how many bytes are available to read or maybe a plain boolean function is enough), readByte (reads the next available byte), writeBytes (writes the bytes) and printDebug (which prints the debug message (may be just virtual with a default implementation that does nothing)).
    This allows the library to be extended easily to any other hardware platform and the base class can be made without any external dependencies so it can be used for the Linux/Windows variant of the library.
  • Make the CRC library compile time constant.
    That means making sure that the library doesn't need any RAM and that everything is written in the ROM (constexpr magic at play here ;) ). Now with a preprocessor flag I could toggle between a ROM lookup, RAM lookup or live calculation.
    And lastly let's abandon using class instances for this. My suggestion would be to use only static members in a class. If you really want the size and polynomial to be configurable that can be achieved with templates.

Now if you aprove of these suggestions I'll get on to implementing them.

calcOverhead Function Incorrect?

It looks to me like the calcOverhead function actually finds the LAST occurrence of START_BYTE in the payload, not the first one as stated in the comments (and assumed by the unpackPacket function).

To find the FIRST occurrence, do:

void SerialTransfer::calcOverhead(uint8_t arr[], const uint8_t &len) {
  overheadByte = 0xFF;

  for (uint8_t i = 0; i < len; i++) {
    if (arr[i] == START_BYTE) {
      overheadByte = i;
      break;
    }
  }
}

Or, run the existing loop backwards.

Using the ESP32-cam and sending images taken on it to something else.

This seems to be a fairly common project. (Either sending the image to another Arduino, a Raspberry Pi, or a PC) via one of the communication methods this library allows. Since the ESP32-cam is just so useful for how cheap it is. It looks like everybody (including myself) has been referencing the same old forum post with some confusion. And thus it seems like a good idea to have some example on how to do this as it's not trivial.

Aforementioned outdated forum post:
https://forum.arduino.cc/t/transfer-pictures-from-esp32-cam-to-esp32-via-serial/647488/59

I'm currently working on ESP32-cam -> Raspberry PI over UART; so as soon as I get done with that code I'll be happy to contribute it if you see fit.

SerialTransfer <variable> breaks ability to read SD card.

Here's my code: LED_Sequencer_Working_Copy - Copy.txt

Describe the bug
When I activate (uncomment) the line "SerialTransfer myTransfer;", my program can no longer read the DATA.txt file located on the SD card.

To Reproduce
Steps to reproduce the behavior:

  1. I've added in the code from the "tx_simple" under the examples folder. (BTW, I've tested the tx_simple/rx_simple on their own and they work perfectly).
  2. I'm using this example for the SD card shield's pinouts: https://www.mschoeffler.de/2017/02/22/how-to-use-the-microsd-card-adapter-with-the-arduino-uno/
  3. With all of the added code from example file commented out, the program runs fine.
  4. Uncommenting the "#include "SerialTransfer.h"" and it still runs fine.
  5. Uncommenting the "SerialTransfer myTransfer;" line and my code can no longer read the Data.txt file on my SD card.

Expected behavior
For SerialTransfer.h to be used in conjunction with my SD card reader.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: Win 10

Smartphone (please complete the following information):
N/A

Additional context
Add any other context about the problem here.

Make Arduino talk to Pi Pico (MicroPhyton poort?)

Hi! I have been using this library for a project where I share a number of variables between 2 Arduinos.

I'm thinking about changing one of the Arduino's to a Raspberry Pi Pico. The physical layer is handled by MAX488 chips in RS422.

Would it be possible to get this library working on the Pi Pico? I see you made a Phyton version, but i guess its not the same as the MicroPhython on the Pi Pico.

Also, would there be any issues with these 2 MCU's talking to eachother? I guess as long as the baudrate is the same and the strukt is the same, it should work. I need to transfer mostly floats, unsigned longs, intergers, and booleans.

And again, thank you so much for this great library!

uart read data example problem in ESP-01

Describe the bug
I am trying to run the example uart_rx_data in a ESP-01 board. But when I verify the code I obtain this output:

C:\Users\Familia\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
C:\Users\Familia\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp:111:29: error: 'SPDR' was not declared in this scope
volatile uint8_t recChar = SPDR;
^
exit status 1
Error compiling for board Generic ESP8266 Module.

Desktop (please complete the following information):

  • OS: Windows 10
  • Arduino IDE: 1.8.13

Any help to solve this issue.

Thank you

Resend when any transfer error

Hi thank you for your work 😄 ,

I do not know if it is a feature request or documentation request

I see there are callback and error status (CRC_ERROR/PAYLOAD_ERROR/STOP_BYTE_ERROR) but I do not understand if there is a way to ask for resend specific packet if any error happen. and eventually cancel transfer if error is not recoverable

Is this feature missing or I miss read the sources/examples ?

Thank you

IC2 slave examples use reserved address 0

I2C has 16 reserved addresses which nodes should avoid using as their addresses.

The first 8 (0-7) and last 8 addresses are reserved.

In the IC2 receive examples the IC2 node is set up using:

Wire.begin(0);

which is actually using the reserved address '0'.

The first "usable" address for IC2 nodes is 8 so maybe that would be a good choice for the sample.

Details of the reserved address space can be found here:
https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing#reserved

Missing transmission data

Describe the bug
I tried to transfer the char array, but sometimes the data received by rx is missing

To Reproduce
Steps to reproduce the behavior:
Use these codes
RX

#include "SerialTransfer.h"
boolean debugMode = true;
SerialTransfer DataTransfer;
struct STRUCT {
  char text[20];
} send_struct;
void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
  DataTransfer.begin(Serial1);
}
void loop( ) {
  uint16_t recSize = 0;
  if (DataTransfer.available()) {
    DataTransfer.rxObj(send_struct, sizeof(send_struct), recSize);
    recSize += sizeof(send_struct);
    if (debugMode) {
      Serial.println("DEBUG: Get data");
    }
    if (debugMode) {
      for (int i = 0; i < strlen(send_struct.text) ; i ++) {
        printf("%d\n", send_struct.text[i]);
      }
      Serial.println("");
    }
  }
  else if (DataTransfer.status < 0) {
    Serial.print("ERROR: ");
    Serial.println(DataTransfer.status);
  }
}

TX

#include "SerialTransfer.h"
#include <SoftwareSerial.h>
boolean debugMode = true;
SerialTransfer DataTransfer;
SoftwareSerial Serial2(D7, D8);
struct STRUCT {
  char text[20];
} send_struct;
void setup() {
  Serial.begin(115200);
  Serial2.begin(115200);
  DataTransfer.begin(Serial2);
}
void loop() {
  send_struct.text[0] = 168;
  send_struct.text[1] = 116;
  send_struct.text[2] = 192;
  send_struct.text[3] = 93;
  send_data();
}
void send_data() {
  uint16_t sendSize = 0;
  DataTransfer.txObj(send_struct, sizeof(send_struct), sendSize);
  sendSize += sizeof(send_struct);
  DataTransfer.sendData(sendSize);
  if (debugMode) {
    Serial.println("DEBUG: Send data");
  }
  delay(3000);
}

Screenshots
image
The first index of the char array received by rx is usually missing or incomplete

  • SerialTransfer 1.4.1
  • Board: NodeMCU and Arduino due
  • Arduino IDE [1.8.12]

Confused on how to uncomment SPITransfer.h

I'm not sure why SPITransfer.h comes commented out, but uncommenting it is causing issues. I have no idea what parts are needed, and some of the variables are undefined. There seems to be a missing semicolon or curly brackets with contents.

If it matters, I'm compiling for a SAMD21 cortex M0+ board (the Seeeduino Xiao). I'll attach a screenshot of the way I've got it commented out at the moment. Please note that I'm still a noob top coding and this is the first time I've tried this library, so it's very likely that I'm just not seeing how it's intended to work.

spitransfer

I'm getting:

SPITransfer.h: 26:36: error: 'T' does not name a type; did you mean 'Tc'?
uint16_t SPITransfer*: txObj(const T &val, const uint16_t &index=0, const uint16_t &len=sizeof(T))

SPITransfer.h: 26:98: error: expected ';' at end of member declaration
uint16_t SPITransfer*: txObj(const T &val, const uint16_t &index=0, const uint16_t &len=sizeof(T))

SPITransfer.h: 26:96: error: 'T' was not declared in this scope
uint16_t SPITransfer*: txObj(const T &val, const uint16_t &index=0, const uint16_t &len=sizeof(T))
SPITransfer.h:26: note  suggested alternative  Tc
uint16_t SPITransfer*: txObj(const T &val, const uint16_t &index=0, const uint16_t &len=sizeof(T))

Library work with Arduino UNO and ESP32

I cannot transfer different types of data between Arduino Uno and ESP32. If the data is of only one type, for example "float", then everything works, but if I use different types in the structure, for example "float" and "char", then the data on the receiving side (ESP32) is distorted. How to make the library work with different controllers?

Issue With UART Send/Receive

Hi, I really like your SerialTransfer library. I think it would be a great product to integrate into my quadcopter flight controller.

I am using your library to communicate between a Teensy 4.1 and Arduino Nano via XBee3 radios. I am following your uart_rx_datum.ino and uart_tx_datum.ino examples to send a struct from the Teensy to the Nano. I have debug messages enabled and am frequently getting ERROR: CRC_ERROR and ERROR: STOP_BYTE_ERROR messages at the receiver (Nano). These errors are significantly slowing down my data rate, since I assume you discard a packet if an error is encountered. I am not very familiar with the inner workings of your library, and thought I'd bring this issue to your attention. I wonder if I am using it improperly, or if there is a potential issue buried within the code.

Thank you for your time addressing this issue and for creating this great project!

Teensy 4.1 (Transmitter)

#include "SerialTransfer.h"
#define XBEE_UART Serial8
SerialTransfer XbeeTelem;

typedef struct
{
    float mx;
    float my;
    float mz;
} MagnetometerData_s;
MagnetometerData_s DataPacket {1.0f, 2.0f, 3.0f};

void setup()
{
    Serial.begin(115200);
    XBEE_UART.begin(115200);
    XbeeTelem.begin(XBEE_UART, true, Serial);  // send, debug, debug interface
    delay(200);
}

void loop()
{
    XbeeTelem.sendDatum(DataPacket, sizeof(DataPacket));
    delay(50);
}

Arduino Nano (Receiver)

#include <Arduino.h>
#include <SoftwareSerial.h>
#include "SerialTransfer.h"

SoftwareSerial XbeeSerial(2, 3);
SerialTransfer TelemStream;
void PrintData();

typedef struct
{
  float mx;
  float my;
  float mz;
} MagnetometerData_s;
MagData_s RecPacket;

void setup() {
  XbeeSerial.begin(115200);
  Serial.begin(115200);
  TelemStream.begin(XbeeSerial, true, Serial);
delay(200);
}

void loop() {
  if (TelemStream.available()) {
    TelemStream.rxObj(RecPacket);
    PrintData();
  }
}

void PrintData() {
  Serial.print("mx: "); Serial.print(RecPacket.mx, 2);
  Serial.print("  my: "); Serial.print(RecPacket.my, 2);
  Serial.print("  mz: "); Serial.println(RecPacket.mz, 2);
}

Receiver Serial Output (Nano)

mx: 1.00  my: 2.00  mz: 3.00
ERROR: CRC_ERROR
mx: 1.00  my: 2.00  mz: 3.00
ERROR: CRC_ERROR
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00
ERROR: STOP_BYTE_ERROR
ERROR: CRC_ERROR
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00
mx: 1.00  my: 2.00  mz: 3.00

payIndex not reset back to zero by the FSM

Consider a situation where a timeout occurs while in the find_payload state. The timeout handler will reset the FSM back to the find_start_byte state, no problems. However, payIndex is not reset back to zero by anything in the code (with the exception of when payIndex == bytesToRec). This means that RX is broken until enough further data arrives to cause payIndex to spill over and things get reset by overflow. I think that just resetting payIndex back to zero in find_payload_len when doing the state transition into find_start_byte is probably the right fix here?

RX <> TX forwarding

Sorry, I found no way to write you an email. I'm currently working on reading the communication between controller and display of my bafang ebike. The official Arudino commands are way to slow. Maybe the only solution is to directly program in C.. Have a look at my code. Am I doing anything wrong? I tried removing / playing with the delay timings. Nothing helped. The display of my ebike has communication issues and is giving me "Error Code: 30".

Using Robodyn Mega 2560 PRO (Embed)

#include "SerialTransfer.h"
#include <ST_CRC.h>

SerialTransfer serial1;
SerialTransfer serial2;

void setup() {
  Serial1.begin(1200);    //BBSHD controller    @RX18 TX19
  Serial2.begin(1200);    //Display DP-C18      @TX16 RX17

  serial1.begin(Serial1);
  serial2.begin(Serial2);
}

void loop() {
  readDisplay();
  readController();
}

void readDisplay()  {
  if (serial2.available()) {
    for(byte i = 0; i < serial2.bytesRead; i++) {
      serial1.txBuff[i] = serial2.rxBuff[i];
    }
    serial1.sendData(serial2.bytesRead);
	delay(100);
  }
}

void readController() {
  if (serial1.available()) {
    for(byte i = 0; i < serial1.bytesRead; i++) {
      serial2.txBuff[i] = serial1.rxBuff[i];
    }
    serial2.sendData(serial1.bytesRead);
	delay(100);
  }
}

No messages received after buffer overflow

Describe the bug
I my code (with several message types), If for some reason the listening code stops calling available() for enough time to fill the buffer. After I get a CRC ERROR and then no messages are received. Sometimes I get no CRC ERROR but no messages are received.

To Reproduce
Have not tried to reproduce With a simple example yet.

Expected behavior
After an error one or two messages are lost but communication is recovered.

library makes i2c lcd flash

good day sir, thanks so much for the library. but i noticed that it makes my i2c lcd flash. what can i do to resolve this? thanks in advance...

Sending list from arduino UNO to python using SerialTransfer and PySerialTransfer

Hello,
thanks for sharing your libs freely ,
I require some insights,
rather than a bug it is perhaps more lacking info to make run a very simple task, here comes my issue when I try to send a small array with 2 integers in it form an arduibo to a pc:

on the arduino UNO side:

///////////////////////begining of arduino script////////////////
//////I would like to send a list 
#include "SerialTransfer.h"
SerialTransfer myTransfer;
void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

int arry[]={1,4};
void loop()
{
     myTransfer.sendData(arry);
     delay(100);
}
////////////////////////////////end of arduino script////////////////////////////////////////////////////////

On the PC running Python:

######begining of Python script#############################
#### I would like to receive an array with 2 ints in it
import time
from pySerialTransfer import pySerialTransfer as txfer


if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM15')
        
        link.open()
        time.sleep(2) # allow some time for the Arduino to completely reset
        
        while True:
            send_size = 0
            
            ###################################################################
            # given just to define type and lenght of the expected data
            ###################################################################
            list_ = [1, 3]
            list_size = link.tx_obj(list_)
            send_size += list_size

         
            
            ###################################################################
            # Wait for a response and report any errors while receiving packets
            ###################################################################
            while not link.available():
                if link.status < 0:
                    if link.status == txfer.CRC_ERROR:
                        print('ERROR: CRC_ERROR')
                    elif link.status == txfer.PAYLOAD_ERROR:
                        print('ERROR: PAYLOAD_ERROR')
                    elif link.status == txfer.STOP_BYTE_ERROR:
                        print('ERROR: STOP_BYTE_ERROR')
                    else:
                        print('ERROR: {}'.format(link.status))
            
            ###################################################################
            # Parse response list
            ###################################################################
            rec_list_  = link.rx_obj(obj_type=type(list_),obj_byte_size=list_size,list_format='i')

            print('RCVD: {}'.format(rec_list_))
            print(' ')
    
    except KeyboardInterrupt:
        try:
            link.close()
        except:
            pass
    
    except:
        import traceback
        traceback.print_exc()
        
        try:
            link.close()
        except:
            pass

################end of python script##########################

I was not able to send a small array using your libs... here is the error I am getting in python:

Traceback (most recent call last):
  File "C:/Users/admin/Desktop/WPy32-3860/scripts/read_NANO_LIST.py", line 27, in <module>
    while not link.available():
  File "C:\Users\admin\Desktop\WPy32-3860\python-3.8.6\lib\site-packages\pySerialTransfer\pySerialTransfer.py", line 477, in available
    self.rxBuff[self.payIndex] = recChar
IndexError: list assignment index out of range

Thanks for helping me to solve this :)

Keen to understand the reasoning around default 50mS timeout

Hi there,

In Packet.h there is the following line

const uint8_t DEFAULT_TIMEOUT = 50;

I went looking as I was seeing the STALE PACKET error message when running my project.
I am using serialTransfer between an Adafruit Feather m4 express and a Sparkfun Artemis board.
My code is based on the examples that tx and rx a Datum over serial.
It was working fine when I was transferring back and forth a small struct with three chars and one integer. In fact in the Artemis to Feather direction that is still working fine.
But when I expanded the struct I send from the Feather to the Artemis to about 12 int16_t’s (24 payload bytes) I started seeing the Stale Packet message on the Artemis.

reading the library code I arrived at the “timeout” variable and found it defaults to 50mS but is configurable in the begin methods. I changed it to 200mS temporarily to see if my larger strict would arrive intact at the Artemis and it was.

my question is, do you have any guidance around setting the timeout, or see any issues with taking it up to maybe a few 100mS?

I am running my link at 57600 by the way.

Thanks,
Paul

Mirror library for computers/linux

Is your feature request related to a problem? Please describe.
I'd like to be able to use this library to communicate with an arduino from a linux machine. However the project I'd like to implement this in cannot make use of the python mirror library.

Describe the solution you'd like
I'm looking for a computer/linux mirror library.

Describe alternatives you've considered
I've taken a look at using the python library but that's just not working out for me. If worst comes to worst I could imagine trying to port the library myself, but I think it would be to the benefit of everyone to have a C++ mirror library.

How to determine if a file is completely send?

Hi!

Thanks for this great library! I have a question regarding UART though. On the TX side I am opening a file and sending it using this crude bit of code (ESP32) based on the uart_tx_file example:

#include "SerialTransfer.h"
#include "SPIFFS.h"

SerialTransfer myTransfer;


#define RXD2 16
#define TXD2 17

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, RXD2, TXD2);

  // Launch SPIFFS file system  
  if(!SPIFFS.begin()){ 
    Serial.println("An Error has occurred while mounting SPIFFS");  
  }

  
  myTransfer.begin(Serial1);
}


void loop()
{
  char fileName[] = "dslr.jpg";
  File file2 = SPIFFS.open("/dslr.jpg");
  if(!file2){
      Serial.println("Failed to open file for reading");
      return;
  }
  uint16_t i = 0;
  const int fileSize = file2.size();
  char file[fileSize] = "";
  while(file2.available()){
     file[i] = file2.read();
     Serial.print (file[i]); //use for debug
     i++;
  }
  file[i] ='\0';
  // Serial.print (file); //use for debug
  file2.close();
    
    
  
  myTransfer.sendDatum(fileName); // Send filename
  
  uint16_t numPackets = fileSize / (MAX_PACKET_SIZE - 2); // Reserve one byte for current file index
  
  if (fileSize % MAX_PACKET_SIZE) // Add an extra transmission if needed
    numPackets++;
  
  for (uint16_t i=0; i<numPackets; i++) // Send all data within the file across multiple packets
  {
    uint16_t fileIndex = i * MAX_PACKET_SIZE; // Determine the current file index
    uint8_t dataLen = MAX_PACKET_SIZE - 2;

    if ((fileIndex + (MAX_PACKET_SIZE - 2)) > fileSize) // Determine data length for the last packet if file length is not an exact multiple of MAX_PACKET_SIZE-2
      dataLen = fileSize - fileIndex;
    
    uint8_t sendSize = myTransfer.txObj(fileIndex); // Stuff the current file index
    sendSize = myTransfer.txObj(file[fileIndex], sendSize, dataLen); // Stuff the current file data
    
    myTransfer.sendData(sendSize, 1); // Send the current file index and data
    delay(100);
  }
  delay(10000);
  Serial.print("File sent!");
}

Now on the RX side I am receiving all the data. But I want to also put that back in a file. How would I do that? How would I know if the end of the file is reached?

This is my code atm on the RX side (RP2040) based on the uart_rx_file example:

#include "SerialTransfer.h"

SerialTransfer myTransfer;

const int fileSize = 2000;
char file[fileSize];
char fileName[10];

#define RXD2 5
#define TXD2 4

int startTime;
int transferTime;

void setup()
{
  Serial.begin(115200);
  //Serial1.begin(9600, SERIAL_8N1, RXD2, TXD2);
  Serial2.setRX(RXD2);
  Serial2.setTX(TXD2);
  Serial2.begin(115200);
  
  myTransfer.begin(Serial2);
}


void loop()
{
  if (myTransfer.available())
  {
    if (!myTransfer.currentPacketID())
    {
      myTransfer.rxObj(fileName);
      Serial.println();
      Serial.println(fileName);
    }
    else if (myTransfer.currentPacketID() == 1)
      for(uint8_t i=2; i<myTransfer.bytesRead; i++)
        Serial.print((char)myTransfer.packet.rxBuff[i]);
    Serial.println();
  }
  
}

Unable to transmit string correctly

Describe the bug
I tested with nodemcu and due , examples work fine
So I tried to transfer the string ,

To Reproduce
Steps to reproduce the behavior:

  1. Download them and upload to arduino
  2. See error ' ? '

Expected behavior
rx should show the string , but I get a bunch of ' ? '

Screenshots
unknown (5)

  • Board: NodeMCU and Arduino due
  • Arduino IDE [1.8.10]

Trouble using SoftwareSeriel RS485

Describe the bug
Not working with SoftwareSerial being used with RS485 shield http://store.linksprite.com/rs485-shield-for-arduino-v2-1/

using normal SoftwareSerial like:
myRS485Serial.print(dataByte);
works fine

struct STRUCT {
byte dataByte;
}data;

myTransfer.txObj(data, sizeof(data));
myTransfer.sendData(sizeof(data));

doesn't work. getting CRC_ERROR message at RX end

Expected behavior
byte dataByte should be assigned value at RX end

Screenshots

Desktop (please complete the following information):

  • OS: Win10
    -IDE: Arduino 1.8.5
    Additional context
    When using the regular SoftwareSerial code, RS485Serial.print(dataByte); works as expected but RS485Serial.write(dataByte); does not. Looking through this libraries code, I noticed it had port->write in SerialTransfer.cpp. Could this be causing the problem? I have tried both installing library through library manager in IDE and installing folder from Github.

Extended Array Rx/Tx

This may not be a bug, but rather a question (I'm not sure how to change the category of this submission). In short, I'd like to find a way to transfer an array of values from a Teensy 4.1 to python. After investigating the code it looks like the buffer is maxed out to 254 based upon MAX_PACKET_SIZE = 0xFE.

Because I'm ultimately interested in the larger buffers that can be accomodated using the external memory on the Teensy 4.1, it would be great to have an example on how to manage the handling of these large arrays. So this begs the question, how to break the array into chunks and send it with minimal delays and dropped packets?

This clearly requires coordination on the Teensy and Python side but I'm running into my limits and would appreciate any direction that folks can provide.

Teensy Scheme

void SendADCBinary(void) {
  // use this variable to keep track of how many
  // bytes we're stuffing in the transmit buffer
  uint32_t sendSize = 0;
  
  ///////////////////////////////////////// Stuff buffer with array
  //Ideally adcbuffer has more than 10000 elements  
  sendSize = myTransfer.txObj(adcbuffer, sendSize);
  
  ///////////////////////////////////////// Send buffer
  myTransfer.sendData(sendSize);
 
}

Python Code

import numpy as np
import time
from pySerialTransfer import pySerialTransfer as txfer

link = txfer.SerialTransfer('COM10')

link.open()
time.sleep(2) # allow some time for the Arduino to completely reset

send_size = 0
npArray = np.arange(2048)
npArray.dtype = np.uint32
npList = npArray.tolist()
arrSize = link.tx_obj(npList)

Add support for acessing packet ID

Is your feature request related to a problem? Please describe.
I am sending multiple message types, And would like to fill different objects depending on the packetID, Buy IdByte is private.

Describe the solution you'd like
make idByte public or make an access function to it

Describe alternatives you've considered
For now I will use message length to differentiate the messages, but using the packet ID seems like a better option.

Invalid memory access in all callback examples

According to the code, SerialTransfer requires the passed callback array to stay allocated for its whole lifetime.

  1. This is not documented.
  2. All the callback-related examples are actually accessing reusable stack memory.

Steps to reproduce: A modified uart_rx_with_callbacks.ino example is attached below - using LED blinking, as I have just one serial. I was able to reproduce it also by printing the memory addresses.

Expected behavior:

  1. This should be documented.
  2. Examples should have the callback config defined outside of any functions.
  3. I actually noticed that a solution is already part of the "polishing" effort, where a dynamic linked list is used instead. So not filing a PR for now.

Example of invalid memory access:

#include <Arduino.h>
#include "SerialTransfer.h"

SerialTransfer myTransfer;

// A callback passed to SerialTransfer
void hi() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}

// My very private function
void hey() {
  for (int i = 0; i < 10; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
    digitalWrite(LED_BUILTIN, LOW);
    delay(50);
  }
}

// Prevent compiler from optimizing unused stack variables.
// Serial1.println(foo) would work too if you had Serial1 :-)
volatile uint16_t variableInUse1 = 0;
volatile uint16_t variableInUse2 = 0;

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  functionPtr callbackArr[] = { hi };
  variableInUse1 = (uint16_t) &callbackArr[0];
  ///////////////////////////////////////////////////////////////// Config Parameters
  configST myConfig;
  myConfig.debug        = true;
  myConfig.callbacks    = callbackArr;
  myConfig.callbacksLen = sizeof(callbackArr) / sizeof(functionPtr);
  /////////////////////////////////////////////////////////////////
  myTransfer.begin(Serial, myConfig);

  // Dispatch a few messages with the setup() stack
  while (millis() < 10000LU) {
    myTransfer.tick(); // hi() is called
  }
}


void loop() {
  functionPtr myVeryPrivateArray[] = { hey };
  variableInUse2 = (uint16_t) &myVeryPrivateArray[0];

  // Dispatch messages within the loop() stack
  myTransfer.tick(); // oh my - hey() is called!
}

SerialTransfer for contemporary send and receive

Good morning, first of all congratulations for the excellent library, but I'm having a problem when I try to do tx and rx from two nodes simultaneously, the nodes locks without apparently send and receive nothing.

Many thanks.

Arturo

Library Compiling Issue

I can't seem to get this library to compile. I've written up one of the simplest examples I could think of.

I keep getting this error message. 'class SerialTransfer' has no member named 'txBuff'

Are txbuff and rxBuff deprecated because it looks like they are defined on lines 53 and 54 of Packet.h so I don't understand what the issue is.

Please see the attached example and let me know if there's something I can change to get it to compile.

I am using
Arduino IDE: 1.8.13
SerialTransfer Library: 3.1.1 (Installed through Arduino Library Manager)
Pop!_OS 20.10

Full Error Message:
/home/linuxworkstation/Desktop/serialLibCompileTest/serialLibCompileTest.ino: In function 'void loop()':
serialLibCompileTest:20:18: error: 'class SerialTransfer' has no member named 'txBuff'
myTransfer.txBuff[i] = myTransfer.rxBuff[i];
^
serialLibCompileTest:20:41: error: 'class SerialTransfer' has no member named 'rxBuff'
myTransfer.txBuff[i] = myTransfer.rxBuff[i];
^
exit status 1
'class SerialTransfer' has no member named 'txBuff'

example.zip

How do we specify which "node" an I2C packet gets sent to?

With serial there is only one other node - the one at the end of the serial link.

However with I2C working in a "multi master" environment, any node can send to any other node.

How does the I2CTransfer get told the address of the node to send a frame to?

Error compiling on SAMD21

Describe the bug
I get following errors when including the "SerialTransfer.h" header in PlatformIO for a SAMD21:

 #include "Wire.h"
          ^~~~~~~~
compilation terminated.
.pio\libdeps\interferometer\SerialTransfer\src\SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
.pio\libdeps\interferometer\SerialTransfer\src\SPITransfer.cpp:111:29: error: 'SPDR' was not declared in this scope
  volatile uint8_t recChar = SPDR;
                             ^~~~
.pio\libdeps\interferometer\SerialTransfer\src\SPITransfer.cpp:111:29: note: suggested alternative: 'SPI1'
  volatile uint8_t recChar = SPDR;
                             ^~~~
                             SPI1
*** [.pio\build\interferometer\libbc2\SerialTransfer\I2CTransfer.cpp.o] Error 1
*** [.pio\build\interferometer\libbc2\SerialTransfer\SPITransfer.cpp.o] Error 1

After deleting the SPI and I2C headers from the library the errors disappear.

Desktop (please complete the following information):

  • OS: Win10
  • PlatformIO with Arduino Framework and Atmel SAM Core

Issue with ESP8266

Hi guys,
I'm using the SerialTransfer lib in order to send data from an ESP8266 (NodeMCU Lua Amica Modul V2 ESP8266 ESP-12F) to an Arduino Mega2560. Both sketches, for ESP8266 and Arduino are written and uploaded with the Arduino IDE (version 1.8.13).
Up to version 2.1.2 the attached code for the ESP8266 module compiled, linked and worked fine. After updating the library to 3.0.3 (I tried also all the versions in between) the code doesn't compile anymore and exits with the error message:

D:\Dokumente\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
D:\Dokumente\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp:119:29: error: 'SPDR' was not declared in this scope
volatile uint8_t recChar = SPDR;

Is this issue known? Does the current version 3.0.0 and above not support the ESP8266 modules anymore?

By the way: version 3.0.3 works also with the Arduino.

Best regards
Fernass

WiFiClient_OpenWeatherMap.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.