Newbie question.... help passing (and store as member vars) serial to library

Hi… I’ve been pulling my hair out for a couple of days with this one…
I’ve extensively searched online, and also the arduino forum, but no one has posted a complete example with both the cpp & h files, so I only get half the story of one way to do this…

So… I have plenty of experience in programming in Python, Propeller SPIN / ASM & PIC ASM/Basic, so I have some experience… and I’ve ‘hacked’ other peoples sketches to do what I want them to do, but C pointers & references, and declaring/storing them are confusing the hell out of me…

SO… My aim is, I want to pass references to two Stream objects to the constructor of my library, and save them as member vars, so I can use the serial ports from within any method in my library class (sorry if I’m getting terminology wrong)

I’ve tried lots of stuff (using the * notation for pointers instead, directly calling Serial.begin, changing whether its Stream& USB or Stream &USB) … Nothings working

I’ve copied and pasted examples of the forum, as a get me started… still wont compile

CH376_Demo.ino

#include <CH376.h>
#include <SoftwareSerial.h>

SoftwareSerial USB(10,11);
CH376 FS(Serial, USB);

void setup() {
  // put your setup code here, to run once:

  FS.testMethod();
}

void loop() {
  // put your main code here, to run repeatedly:

}

CH376.h

#ifndef CH376_H
#define CH376_H

#include "Arduino.h"
class CH376
{
	public:
	  
	  /*         ****** Constructor method ******
	   * pass a reference to stream objects so either hardware
	   * or software serial can be used for either port, for flexibility...
	  */
	  CH376(Stream &usbSerPort, Stream &debugSerPort);
   
   	  
	  //Test method that uses the debug port
	  void testMethod();
	
	private:
	
		//Private references to stream (serial port) objects
		Stream& USB;
		Stream& DEGUG;
};

#endif

CH376.cpp

#include "Arduino.h"
#include "CH376.h"

Stream& USB;
Stream& DEGUG;

CH376::CH376(Stream &usbSerPort, Stream &debugSerPort) {
	
	//Save references
	USB = usbSerPort;
	DEBUG = debugSerPort;

	//Start CH376 port
	USB.begin(9600);
		
	//Start debug port
	DEBUG.begin(9600);



}

void CH376::testMethod(){


	bool alwaysTrue = true;

	/* Do loads of stuff in this method ...
	 * then when done, I need to send a debug message
	 * 
	 * Blah blah blah....
	 * 
	 * {{ some code }}
	 * {{ more code }}
	 * ......
	 */
	 
	 	 
	//I'm done.... send a debug or error message or whatever
	if (alwaysTrue){
		DEBUG.print("Command sent OK");
	} else {
		DEBUG.print("It went horribly wrong!!");
	}
}

CH376_Demo.ino (251 Bytes)

CH376.h (507 Bytes)

CH376.cpp (736 Bytes)

Could you post the compiler errors?

FYI your class will have access to the hardware Serial anyways.

Remember that the begin() method in Steam class is called in setup() so you may want to consider another member function for that (i.e. begin()).

Arduino: 1.6.9 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:4:9: error: 'USB' declared as reference but not initialized

Stream& USB;

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:5:9: error: 'DEGUG' declared as reference but not initialized

Stream& DEGUG;

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp: In constructor 'CH376::CH376(Stream&, Stream&)':

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:7:1: error: uninitialized reference member 'CH376::USB' [-fpermissive]

CH376::CH376(Stream &usbSerPort, Stream &debugSerPort) {

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:7:1: error: uninitialized reference member 'CH376::DEGUG' [-fpermissive]

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:11:2: error: 'DEBUG' was not declared in this scope

DEBUG = debugSerPort;

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:14:6: error: 'class Stream' has no member named 'begin'

USB.begin(9600);

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp: In member function 'void CH376::testMethod()':

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:41:3: error: 'DEBUG' was not declared in this scope

DEBUG.print("Command sent OK");

^

C:\Program Files (x86)\Arduino\libraries\CH376\CH376.cpp:43:3: error: 'DEBUG' was not declared in this scope

DEBUG.print("It went horribly wrong!!");

^

exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

... Its mostly complaining about my USB and DEBUG references to the ports not being in scope...
... which is fundamentally what I would like to know how to do...

I am trying to make USB & DEBUG member vars, so I can use the ports throughout the library

Lines 4 & 5 of CH376.cpp were my attempt to do this...

Stream& USB;
Stream& DEGUG;

... and with the

FYI your class will have access to the hardware Serial anyways.

...
... I tried the simple approach of Serial.begin, and Serial.print within the library... which didnt work, but did work as expected in a standalone sketch

  Stream& DEGUG;

Ups.

You have to initialize References differently:

class CH376 {
  public:
    CH376(Stream &usbSerPort, Stream &debugSerPort) : sUsb(usbSerPort), sDebug(debugSerPort) {}
    void testMethod() {
      sUsb.println(F("Usb: tested."));
      sDebug.println(F("Debug: tested."));
    }
  private:
    Stream& sUsb;
    Stream& sDebug;
};

CH376 test(Serial, Serial);

void setup() {
  Serial.begin(115200);
  test.testMethod();
}

void loop() {}
Usb: tested.
Debug: tested.

Firstly, the bit after the colon… how does that work?

Secondly…

OK… Maybe I’m being a bit daft here… but, your example is code is helpful, but its factored as a single file…

The thing I was eluding to in my original post about ‘getting half the story’ is that a lot of forum code posts seem to be factored as single files, whilst Arduino’s own how to write your own library guide, and generic C++ guides online seem to elude to .h and .cpp (the conflicting programming styles are confusing and really not helping newcomers to C)

I’m wanting it as ‘the traditional’ .h, .cpp, and .ino seperate files, as this is what the style guidelines I have seen online advise…

I’m up to this point… But it throws a CH376::CH376(Stream&, Stream&)’ previously defined comile time error

CH376_Demo.ino

#include <CH376.h>
#include <SoftwareSerial.h>

SoftwareSerial USB(10,11);
CH376 FS(Serial, USB);

void setup() {
  // put your setup code here, to run once:

  FS.testMethod();



}

void loop() {
  // put your main code here, to run repeatedly:

}

CH376.h

#ifndef CH376_H
#define CH376_H

#include "Arduino.h"
class CH376
{
	public:
	  
	  /*         ****** Constructor method ******
	   * pass a reference to stream objects so either hardware
	   * or software serial can be used for either port, for flexibility...
	  */
	  CH376(Stream &usbSerPort, Stream &debugSerPort) : sUsb(usbSerPort), sDebug(debugSerPort){};
   
   	  
	  //Test method that uses the debug port
	  void testMethod();
	
	private:
	
		//Private references to stream (serial port) objects
		Stream& sUsb;
		Stream& sDebug;
};

#endif

CH376.cpp

#include "Arduino.h"
#include "CH376.h"

CH376::CH376(Stream& sUsb, Stream& sDebug) {

	//Start CH376 port
	sUsb.begin(9600);
		
	//Start debug port
	sDebug.begin(9600);

}

void CH376::testMethod(){


	bool alwaysTrue = true;

	/* Do loads of stuff in this method ...
	 * then when done, I need to send a debug message
	 * 
	 * Blah blah blah....
	 * 
	 * {{ some code }}
	 * {{ more code }}
	 * ......
	 */
	 
	 	 
	//I'm done.... send a debug or error message or whatever
	if (alwaysTrue){
		sDebug.print("Command sent OK");
	} else {
		sDebug.print("It went horribly wrong!!");
	}
}

… I’m trying to get my head round C (actually, really the proper way of black magic that is pointers, references and declaring and using them properly)

I’ve got the rest of the library code about there as a standalone sketch based on a heavily ‘hacked’ version of Scott C’s code… Just trying to port it over to a library

I’ve tried various permutations of line 4 in my cpp file…
IE:-

CH376::CH376(Stream& sUsb, Stream& sDebug) {
.... or .....
CH376::CH376(sUsb, sDebug) {
.... or ....
CH376::CH376(Stream& , Stream& ) {
.... and ....
CH376::CH376(Stream &sUsb, Stream &sDebug) {
.... and ....
CH376::CH376() {

… A plain ‘laymans english’ explanation would help, just til everything clicks into place

Firstly, the bit after the colon… how does that work?

cpp initializer_list

If you prefer parts:

CH376.h

#ifndef _CH376_H
#define _CH376_H_
#include <Arduino.h>

class CH376 {
  public:
    CH376(Stream &usbSerPort, Stream &debugSerPort);
    void testMethod();
  private:
    Stream& sUsb;
    Stream& sDebug;
};

#endif

CH376.cpp

#include "CH376.h"

CH376::CH376(Stream &usbSerPort, Stream &debugSerPort) : 
  sUsb(usbSerPort), 
  sDebug(debugSerPort)
{
}

void CH376::testMethod() {
  sUsb.println(F("Usb: tested."));
  sDebug.println(F("Debug: tested."));
}

Sketch

#include "CH376.h"

CH376 test(Serial, Serial);

void setup() {
  Serial.begin(115200);
  test.testMethod();
}

void loop() {}

Output

Usb: tested.
Debug: tested.

Ok… thanks… That does what I’m after…

Just reading the initialiser list reference page

This may be interesting too cprogramming tutorial initialization-lists-c++.