Arduino <-> Core: SoftwareSerial and Serial1

@techbutler, I have a logic analyzer (DSLogic) so I will flash your code on a Core and test the Serial2 output to make sure that works. I’ll do the same with an arduino. Hopefully tonight and I get to it. :smile:

Here’s my modified SerialCommand.h just so we’re doing apples to apples :slight_smile:

Thanks again.


#ifndef SerialCommand_h
#define SerialCommand_h

#if defined (SPARK)
#include "application.h"
#else
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#endif    //Spark

// If you want to use SerialCommand with the hardware serial port only, and want to disable
// SoftwareSerial support, and thus don't have to use "#include <SoftwareSerial.h>" in your
// sketches, then uncomment this define for SERIALCOMMAND_HARDWAREONLY, and comment out the
// corresponding #undef line.
//
// You don't have to use SoftwareSerial features if this is not defined, you can still only use
// the Hardware serial port, just that this way lets you get out of having to include
// the SoftwareSerial.h header.

//#if defined (SPARK)
#define SERIALCOMMAND_HARDWAREONLY 1
#define commandSerial    Serial3        // Select serial port where commands are received
//#define commandSerial    Serial1        // For Arduino, select based on available ports
//#define commandSerial    Serial2
#define debugSerial        Serial        // Select serial port for debug messages
//#define debugSerial    Serial1
//#define debugSerial    Serial2
#else
#define SERIALCOMMAND_HARDWAREONLY 1
//#undef SERIALCOMMAND_HARDWAREONLY
#define commandSerial    Serial3        // Command and serial ports same for Software Serial
#define debugSerial        Serial
//#endif    //Spark

#ifdef SERIALCOMMAND_HARDWAREONLY
#warning "Warning: Building SerialCommand without SoftwareSerial Support"
#endif

#ifndef SERIALCOMMAND_HARDWAREONLY
#include <SoftwareSerial.h>
#endif

#if !defined (SPARK)
#include <string.h>
#endif

#define SERIALCOMMANDBUFFER 16
#define MAXSERIALCOMMANDS    10
#define MAXDELIMETER 2

#define SERIALCOMMANDDEBUG 1
//#undef SERIALCOMMANDDEBUG      // Comment this out to run the library in debug mode (verbose messages)

class SerialCommand
{
    public:
        SerialCommand();      // Constructor
        #ifndef SERIALCOMMAND_HARDWAREONLY
        SerialCommand(SoftwareSerial &SoftSer);  // Constructor for using SoftwareSerial objects
        #endif

        void clearBuffer();   // Sets the command buffer to all '\0' (nulls)
        char *next();         // returns pointer to next token found in command buffer (for getting arguments to commands)
        void readSerial();    // Main entry point.
        void addCommand(const char *, void(*)());   // Add commands to processing dictionary
        void addDefaultHandler(void (*function)());    // A handler to call when no valid command received.

    private:
        char inChar;          // A character read from the serial stream
        char buffer[SERIALCOMMANDBUFFER];   // Buffer of stored characters while waiting for terminator character
        int  bufPos;                        // Current position in the buffer
        char delim[MAXDELIMETER];           // null-terminated list of character to be used as delimeters for tokenizing (default " ")
        char term;                          // Character that signals end of command (default '\r')
        char *token;                        // Returned token from the command buffer as returned by strtok_r
        char *last;                         // State variable used by strtok_r during processing
        typedef struct _callback {
            char command[SERIALCOMMANDBUFFER];
            void (*function)();
        } SerialCommandCallback;            // Data structure to hold Command/Handler function key-value pairs
        int numCommand;
        SerialCommandCallback CommandList[MAXSERIALCOMMANDS];   // Actual definition for command/handler array
        void (*defaultHandler)();           // Pointer to the default handler function
        int usingSoftwareSerial;            // Used as boolean to see if we're using SoftwareSerial object or not
        #ifndef SERIALCOMMAND_HARDWAREONLY
        SoftwareSerial *SoftSerial;         // Pointer to a user-created SoftwareSerial object
        #endif
};

#endif //SerialCommand_h

@techbutler, there is NO Serial3 on the Core, only Serial, Serial1 and Serial2!!! For the Arduino, there is only a Serial3 on the larger boards like the Mega and (I think) the Due.

I know, I have the library running on a Mega.

1 Like

@techbutler, I have tested the Core to Arduino code using a Spark.function() to start with and it works fine. I had to turn off the debug messages in the library however so nothing is returned to the Core from the Arduino. Have yo disabled the debug printing?

I had gotten it to work with Spark.function back in the beginning as well, but that’s not how I’m building my test env. No change when disabling debug messages.

Just to recap what I’m after in Test and what I have discovered over the past day or so…

Two Cores are set up to toggle LEDs via buttons using Publish/Subscribe. A Mega is attached to one of the Cores via Serial3 <—> Serial1. The CommandSerial library is on the Mega.

I used my XMiniLab to confirm that “ON” and “OFF” were being sent over Serial1 at the appropriate button push.

I then decided to dumb everything down and just load up the sample SerialEvent example sketch on the Mega. This worked as advertised. “ON” and “OFF” showed up in the Mega Serial Monitor with each button push of the Core.

So, then I modified that code to include digitalWrite(LED,HIGH) if inputString=="ON"
This did not work.

I tried using strcmp and that didn’t work either.
I tried if (inputString.substring(0) == "ON") No go

Then I decide to use if(inputString.startsWith("ON")) and that worked. The Mega LEDs went on and off as expected.

So, to make this very long story short it seems there are hidden gems in these strings (\n? \r?) that are messing with the strcmp statement in the SerialCommand.cpp

if (strncmp(token,CommandList[i].command,SERIALCOMMANDBUFFER) == 0)

My hypothesis may be way off base. I just know what is working for me in this current environment.

And for posterity, the modified SerialEvent code:


#define arduinoLED 13   // Arduino LED on board

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

void setup() {
  
  pinMode(arduinoLED,OUTPUT);      // Configure the onboard LED for output
  digitalWrite(arduinoLED,LOW);    // default to LED off

  Serial.begin(9600);
  Serial3.begin(9600);
  
  inputString.reserve(64);
}

void loop() {
  serialEvent();
  
    // print the string when a newline arrives:
  if (stringComplete) {
    
    if(inputString.startsWith("ON"))  { 
      digitalWrite(arduinoLED, HIGH);
      // clear the string:
      inputString = "";
      stringComplete = false;
    }
    else  {
      if(inputString.startsWith("OFF"))  { 
        digitalWrite(arduinoLED, LOW);
        // clear the string:
        inputString = "";
        stringComplete = false;
      }
    }
  }
}


void serialEvent() {
  while (Serial3.available() > 0) {
    // get the new byte:
    char inChar = (char)Serial3.read(); 
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
}

1 Like

Bonjour,
Je vois des sujets mais aucune réponse sur la possibilité de réaliser une vraie Interruption sur l’UART
comme le fait SerialEvent => Arduino

J’ai vue ceci:

 <
dans #include "spark_wiring_usartserial.h" du Spark core
// Serial1 interrupt handler
// Serial1 uses standard Sparkcore pins PA2/TX(TX), PA3/RX(RX)
/*******************************************************************************
* Function Name  : Wiring_USART2_Interrupt_Handler (Declared as weak in stm32_it.cpp)
* Description    : This function handles USART2 global interrupt request.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Wiring_USART2_Interrupt_Handler(void)
{
  USART_Interrupt_Handler(&USART_MAP[USART_TX_RX]);
}`>


Comment utiliser cette fonction ?
Merci D'avance

Das Einlesen der seriell übertragenen Daten erfolgt im Hintergrund über einen echten Interrupt.

Andererseits ist SerialEvent() auch auf der Arduinio-Seite kein echter Interrupt-Handler

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read(); 
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
}

.

1 Like

Hi techbutler!

I’ve modify SerialCommand.h with your code,
But my Arduino IDE compile error:
Please help me!!

"CDT16_ControlBoard2:42: error: ‘SerialCommand’ does not name a type
CDT16_ControlBoard2.ino: In function ‘void setup()’:
CDT16_ControlBoard2:102: error: ‘sCmd’ was not declared in this scope
CDT16_ControlBoard2.ino: In function ‘void loop()’:
CDT16_ControlBoard2:120: error: ‘sCmd’ was not declared in this scope
CDT16_ControlBoard2.ino: In function ‘void cdtnum1()’:
CDT16_ControlBoard2:435: error: ‘sCmd’ was not declared in this scope
’SerialCommand’ does not name a type

Although this is not an Arduino forum, if you post your code you might be helped anyhow.

The error messages suggest that you are missing some #include statements and/or object instatiations.

1 Like