Leonardo Serial / Serial1 / SerialEvent

Hi,

I'm trying understand Serial for the Leonardo. I currently understand that Serial is the USB connection and Serial1 is pins 0 and 1.

Is there a SerialEvent1 as well as SerialEvent?

Also serial1.begin as well as serial.begin?

Thanks for your help.

headingwest: Is there a SerialEvent1 as well as SerialEvent?

There should be.

headingwest: Also serial1.begin as well as serial.begin?

Yes

hhmmm, I'm finding that on the Leonardo the Serial1 event fires, but not the Serial event.

I'm assuming that the serial event should fire when I type into the serial monitor and press enter?

Here is my test code:

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

void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString); 
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}

void serialEvent() {    
    Serial1.println('Test');    
}

hhmmm, I'm finding that on the Leonardo the Serial1 event fires, but not the Serial event.

Do you really need the serialEvent() or serialEvent1() methods? There is nothing that happens when those methods are called that can not just as easily be done in loop().

void loop()
{
   if(Serial.available() > 0)
   {
      // Deal with serial data
   }
   if(Serial1.available() > 0)
   {
      // Deal with serial data
   }

   // Do whatever else needs to be done
}

The methods are NOT interrupt handlers. They are convenience methods that do no more than what is shown above.

Listen to Paul, don't bother to use serialEvent().

Of course in your code, I'm not sure how you can tell it isn't working. You wouldn't "see" anything anyway.

The variable stringComplete is never set true.

Also:

Serial1.println('Test');

Should be:

Serial1.println("Test");

What do you have connected to Serial1 to let you know what is being "printed" when the serialEvent is firing?

OK, I'll take your advice not to use the SerialEvent functions. I guess I'm coming from an event driven background so need to change my perspective. I'll put it all into the loop.

So also - double quotes around strings - will do.

The serial1 is going out to an HC-05 bluetooth module which is tested over many frustrating hours and working. This does fire serial1 events when my Android passes bluetooth serial data. It's only the Arduino serial monitor not firing the serial event.

I'm guessing the serial monitor serialEvent() is not implemented? But the pin 0,1 serialEvent1() is implemented.

I think the fundamental advice to process in the loop is really valuable - thanks again.

headingwest:
I’m guessing the serial monitor serialEvent() is not implemented? But the pin 0,1 serialEvent1() is implemented.

You are assuming too much. As I said, in the code you are posting, you wouldn’t know if serialEvent() fired or not. In addition to the other problems I stated, you never even enabled Serial1.

Also, while you are breaking bad habits, don’t use String. Use character arrays instead.

Will do. I’ll test the LED on the serial event to clarify when I get back to my Arduino.

For other noobs the char arrays info is here: http://arduino.cc/en/Reference/String

To clarify from my latest test.

Typing into the Serial Monitor window does not fire the serialEvent() using the Leonardo. From what I can determine you can't use the serialEvent() on the Leonardo through USB serial, but you can use the serialEvent1() through serial on pins 0 and 1.

My test code switches on the LED, pauses 5 seconds, switches off the LED, then waits for a serial event to switch the LED back on...which never happens. Here is my code:

int led = 13;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  pinMode(led, OUTPUT);  
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(5000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
}

void loop() {
  delay (100);
}


void serialEvent() {
  digitalWrite(led, HIGH);  
}

You aren’t the only one who noticed.

One thing that has surprised me as I've entered the Arduino world is the small gaps in documentation - given the massive popularity of the Arduino environment.

For example the serialEvent() documentation doesn't mention that the Leonardo also has a serialEvent1(). It's also a shame that the current bugs aren't shown on the documentation page.

Let's hope the popularity continues to rise and bring in the extra resources to do these things.

Hi there!

I tried a few different things to fix that issue but I can only share information and a dirty hack:

If you have a look at (hardware/arduino/avr/cores/arduino/) main.cpp (and HardwareSerial.cpp) you can see that serialEvent() is no ISR. The truth is, that internally the serial.available() is called after every loop (and delays for example - see also http://arduino.cc/en/Tutorial/SerialEvent) and if there is data the serialEvent is called. So the simple and clean solution is to do your own check at the end of the loop()-function.
Another (dirty but comfortable) way is to replace content of main.cpp by the following code:

#include <Arduino.h>

int main(void)
{
	init();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
			
		#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
	  void serialEvent() __attribute__((weak));
	  if (Serial.available()) serialEvent();
	  #endif
	}
        
	return 0;
}

You can also modify Serial_::begin - function in CDC.cpp and insert the wait-loop for Leonardo-Serial:

void Serial_::begin(uint16_t baud_count)
{
	while (!Serial) { };
}

I also found it helpful to change the delay in Serial_::operator bool() in CDC.cpp from 10 to 1000ms. The chance to see the serial prints done in the init()-part of my sketches is much better now.

I’m using arduino nightly-build from June 2013.