0

My .ino looks roughly like this

#include "command.h"

Command command;
void setup() {
}

void loop() {
}

command.h

class Command
{
    public:
        Command();
};

command.cpp

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

Command::Command() {
  Serial.begin(9600);
}

void serialEvent() {
  while (Serial.available() > 0) {
    char inChar = (char)Serial.read();
    Serial.print(inChar);
  }
}

The serial events don't seem to be happening. It works normally if I move the code out of the class.

  • Does it work when you move serialEvent() back to the sketch? This might be a build/link issue. – Mikael Patel Dec 22 '15 at 13:02
4

When you put the Serial.begin in the constructor and declare the Command object at file scope, the Serial.begin will occur before setup(). Not recommended, perhaps not allowed.

If you do that, the compiler has to figure out that the Serial instance must be constructed before the Command instance is constructed. It can't always figure out the correct order.

In general, this is why you see many classes with a begin or init method. This allows the construction of file-scope instances to take place in any order, before setup. Then setup does the Command.begin(), which finally calls Serial.begin, long after Serial has been constructed.

Also, using SerialEvent is no better than doing the polling in loop(). If you're busy doing something else, SerialEvent does not get called. If you need to handle characters in the background, in the RX interrupt, you might want to take a look at a modified version for the Serial object(s) I posted, NeoHWSerial. You can attach a routine to be called whenever a character is received.

  • Yes by putting an init method in the Command class and calling it from setup() the problem was fixed. – P Hemans Dec 22 '15 at 23:00
  • @user316182, Yes, I am sure that SerialEvent is not called from the RX char interrupt. It is called from main, which just calls loop and then serialEventRun in the never-ending for loop. You may as well just call your serialEvent code from loop. Sadly enough, there was a time when SerialEvent was dispatched from the IRQ, but it was later moved to main. See this commit. :-( – slash-dev Jul 11 '16 at 0:47
0

@slash-dev "...Also, using SerialEvent is no better than doing the polling in loop()." Are you sure about that? SerialEvent (and especially the ones on Teensy3) use hardware interrupts which can be handled in the midst of other operations; even delay() does not block interrupts (http://playground.arduino.cc/Code/AvoidDelay). It's hard to imagine multiple serial streams running at 100 kbaud or better (test reported in PJRC forum) and handling each character in the main loop even if that was all your program did. And why would you want to? There are good reasons interrupts exist.
Update: I'm not allowed to "comment" without 50 reputation. Thanks for the commit link... I can't imagine why HardwareSerial would not use interrupts... that is the default on all other platforms we've used for years.

  • Uhh... did you notice you were pressing the "Add Another Answer" button? There is an "add a comment" button below my answer that you should have used. I have replied above, in a comment to my answer. – slash-dev Jul 11 '16 at 0:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.