0

I am working on an Arduino project, that would use HardwareSerial object reference stored in a class and call methods on it. However, there is problem with writing output using the reference.

Minimal use case to demonstrate behavior is in following files:

main.ino

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

TestClass testClassInstance(Serial);

void setup() {

}

void loop() {
    testClassInstance.print("Hi There\r\n");
    delay(1000);
}

testclass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <Arduino.h>

class TestClass {
public:
    TestClass(HardwareSerial &serial);
    void print(const char * text);

private:
    HardwareSerial _serial;
};

#endif

testclass.cpp

#include "testclass.h"

TestClass::TestClass(HardwareSerial &serial) : _serial(serial) {
    _serial.begin(9600);
    _serial.print("Initializing\r\n");
}

void TestClass::print(const char *text) {
    _serial.print(text);
}

After reset, there are only two characters sent: "In"

In the example above, initialization is done before setup() method and Serial's state is probably reset before calling it. Having changed that to dynamic allocation in setup method did not change this behavior as well.

modification of main.ino

TestClass *testClassInstance;

void setup() {
  testClassInstance = new TestClass(Serial);
}

There might be problem with passing the reference to Serial, but in that case I would expect to not have any output at all.

Any help is greatly appreciated.

2 Answers 2

2

You can't do complex tasks (or anything that relies on the Arduino API in any form) in your constructor. Simply because that all gets called before the Arduino API initializes, and in so doing the serial port gets disabled.

Instead you should do your complex operations and API-based operations in .begin(), which is why 99.99% of all libraries (including HardwareSerial) have a .begin() method.

2
  • This looks reasonable. Does begin() method exist in main file next to setup() and loop() functions? Or does it have to exist on my wrapper class and be manually called in setup()? Additionally, is there some manual that specifies how Arduino API is initialized and what happens then, so I could RTFM? :)
    – Aries
    Commented Jul 19, 2017 at 22:20
  • .begin() is a function you must write in your class. The user then calls it from setup(). No, I am not aware of any generic documentation - simply because it is different for every core. Just assume that nothing bar setting some variables / flags can be done in the constructor - that's the safest way.
    – Majenko
    Commented Jul 19, 2017 at 22:43
0

I have debugged deeper and the problem was somehow passing HardwareSerial to constructor as parameter with HardwareSerial &serial.

When changing it to pointer HardwareSerial *serial and using access via pointer-type variable, everything works.

Many thanks for suggestions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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