Using SoftwareSerial inside a library - Arduino 1.02

Hello,

Just after a bit of help please.
Attempting to write a library.

The Library is going to use the SoftwareSerial library that comes with the Arduino IDE.
The Sketch itself doesnt need access to the Software Serial port, just the library.

Ive tried a few things, but so far I get:
error: 'SoftwareSerial' does not name a type

in the library.h file I have the #include <SoftwareSerial.h>
in the library.cpp file I have tried a few things, but same result. SoftwareSerial mySerial(2, 3). And then it uses mySerial.write() etc throughout.
And in the sketch I have nothing, as the sketch I dont need to reference it.

I tried the SoftwareSerial mySerial; in the header file, and then myLibrary::mySerial(2,3) in the cpp file... but whatever combination I use I seem to get the same result.
Also SoftwareSerial mySerial = SoftwareSerial(2,3);

If a better code example is required, I can whip one up, but if someone could help me understand what needs to go where, so the library can use the Software Serial, that would be apprecaited.
I clearly dont know what I am doing.

So far I have been following http://arduino.cc/en/Hacking/LibraryTutorial but I havent found anything from searching that has helped yet.

I did find this, however obviously havent understood correctly as I am still having problems, http://arduino.cc/forum/index.php/topic,114761.0.html

Any help would be appreciated

Regards
J

WanaGo:
And in the sketch I have nothing, as the sketch I dont need to reference it.

I did find this, however obviously havent understood correctly as I am still having problems, http://arduino.cc/forum/index.php/topic,114761.0.html

That thread (correctly) says you need to #include the header in the main sketch as well. So you have

lib1.h

#include <lib2.h>
// stuff

sketch.ino

#include <lib1.h>
#include <lib2.h>
// stuff

Ok, I have added that to the main sketch too - thought I had tried that.
Now get:

error: a call to a constructor cannot appear in a constant-expression
error: ISO C++ forbids initialization of member 'mySerial'
error: making 'mySerial' static
error: invalid in-class initialization of static data member of non-integral type 'SoftwareSerial'

All pointing to the same line of code in the .h file

private:
SoftwareSerial mySerial = SoftwareSerial(2, 3);

In that post it suggested I cant do SoftwareSerial mySerial = SoftwareSerial(2, 3); there, and that I just do SoftwareSerial mySerial; ?
And then have to call mySerial(2,3); somewhere else?

Will keep trying, but I must just be stupid.

All pointing to the same line of code in the .h file

private:
SoftwareSerial mySerial = SoftwareSerial(2, 3);

Sure, because that line of code is wrong. You can not assign a value to a variable in a header file. You can only declare variables in the header file.

You have to value the variable in the source file. Standard C++ stuff.

I had a similar problem a while back but with the serial port. PaulS helped me out.

Have a look at this:

http://arduino.cc/forum/index.php/topic,40435.0.html

I haven't tried it but the same principles should apply to the software serial.

Thanks guys, still cant get it working.

Here is a better layout of what I have currently, if you can point out what I have done wrong I would appreciate it.
I have little knowledge at all of C++.

So as mentioned above, I am just trying to get my library to be able to use the Software Serial, my sketch does not need access to it. But if it has to, then that is fine...

Library.h File

#ifndef Library_h
#define Library_h
 
#include "Arduino.h" // for Arduino 1.0

#include <SoftwareSerial.h> //Software Serial Library

class Library
{
	public:
		//Bunch of stuff here
	
	private:
		SoftwareSerial mySerial;
}

Library.cpp File

#include "Library.h"
#include "Arduino.h" // for Arduino 1.0

mySerial = SoftwareSerial(2, 3); //Tried various combinations, in and out of the constructor, but similar results.

Library::Library()  
{
	mySerial.begin(9600);
}

My Sketch

#include <SoftwareSerial.h>
#include <Library.h>

Library Library;

void Setup()
{
	
}

void loop()
{
}

The above might not be the best combination I have tried, but is one of them.
Really not sure what I am doing, so help would be apprecaited.

Thanks
J

You need to construct the SoftwareSerial instance at the same time you construct the class:

Library::Library() , mySerial(2,3)

Sorry so that goes in the cpp file?

So the h file and the sketch looks ok...?

But the cpp file needs to be this?:

#include "Library.h"
#include "Arduino.h" // for Arduino 1.0

Library::Library()  
{
	 mySerial(2,3);
	 mySerial.begin(9600);
}

not sure sure what Library::Library() , mySerial(2,3) means... is that a single line I put in place of the Library::Library() ?

Im getting a truck load of errors...

error: ISO C++ forbids declaration of 'Library' with no type
error: no 'int Library::Library()' member function declared in class 'Library'
etc

Sorry can you spell it out for me...
Thanks

made a typo which didnt help, in the Library::Library() line.

Errors I get now are:

Library.cpp: In constructor 'Library::Library()':
Library.cpp:13: error: no matching function for call to 'SoftwareSerial::SoftwareSerial()'
SoftwareSerial.h:83: note: candidates are: SoftwareSerial::SoftwareSerial(uint8_t, uint8_t, bool)
SoftwareSerial.h:48: note: SoftwareSerial::SoftwareSerial(const SoftwareSerial&)
Library.cpp:15: error: no match for call to '(SoftwareSerial) (int, int)'

Line 13 is:

Library::Library() //Line 13
{
	mySerial(2, 3);
	mySerial.begin(9600);
}

PaulS:
You need to construct the SoftwareSerial instance at the same time you construct the class:

Library::Library() , mySerial(2,3)

Probably a typo, sholuld be (in the cpp file):

Library::Library() : mySerial(2,3) {
    // code
}

Yep thats seems to be better, thanks.

I get past this bit now, got more errors related my other code now I think.

Thanks

If Class has member objects, its constructor takes this general form:

Class::Class() : obj1(...), obj2(...), ... {
// Class instance construction code
}

I know this is an old post, hopefully it pops up somewhere. I'm trying to implement the same concept but I don't understand what I'm doing wrong.

I want to run an instance of softwareserial in the library files, the error I'm running into though is

ISO C++ forbids declaration of 'SoftwareSerial' with no type

The line it refers to is

private:
SoftwareSerial *SSerial;

in my header file.

I attempted the change mentioned by PaulS where I instantiate the softwareserial when I create the constructor

Library::Library(): SSerial(4,5)
{

}

I've looked at examples and tried to match them, my first attempt everything worked properly except when I was trying to retrieve data using SSerial.available() and SSerial.read()

My code works fine without the software serial on the standard TX/RX pins, so what I'm trying to narrow down is what exactly do I need to place into my .h and .cpp files to have the software serial functioning properly.

My code works fine without the software serial on the standard TX/RX pins

Please explain this. You can NOT do software serial on the hardware serial pins.

http://snippets-r-us.com might be able to help you with the snippets. Here, we need to see ALL of your code.

PaulS:

My code works fine without the software serial on the standard TX/RX pins

Please explain this. You can NOT do software serial on the hardware serial pins.

http://snippets-r-us.com might be able to help you with the snippets. Here, we need to see ALL of your code.

What I mean by this is without implementing any type of softwareserial the code executes successfully, my problem is I have plans for the Pin 1 and Pin 0 so I have to move my device from pins 1/0 which is why I'm trying to implement the software serial to move them to pins 4,5. The snippets link isn't working for me, perhaps you know another link?

The snippets link isn't working for me, perhaps you know another link?

That was a clue-by-4. You were supposed to whack yourself with it, and post ALL of your code.

This is all code from a repository I was using for the camera I'm working with, the only changes from the original code is I made the changes so that it would work in Arduino 1.0+. This is my last attempt to make the changes to use software serial, I tried to imitate some of the changes from someones project called "MeetAndroid" if I can dig up that link I'll link that as well.
I don't know if you'd like to see the sketch as well but as of right now I had a boat load of errors and I managed to work through them and I'm down to this last one which I've been looking and I can't seem to fix it properly.

In file included from sketch_apr02a.ino:2:
C:\...\arduino-1.0.4\libraries\CameraC329/CameraC329.h:117: error: ISO C++ forbids declaration of 'SoftwareSerial' with no type
C:\...\arduino-1.0.4\libraries\CameraC329/CameraC329.h:117: error: expected ';' before '*' token

CameraC329.CPP

#include "CameraC329.h"
#include <SoftwareSerial.h>
#
//-----------------------------------------------------------------------------
//
// Constants
//
//-----------------------------------------------------------------------------

static const byte CMD_PREFIX = 0xFF;
static const byte CMD_INITIAL = 0x01;
static const byte CMD_GETPICTURE = 0x04;
static const byte CMD_SNAPSHOT = 0x05;
static const byte CMD_RESET = 0x08;
static const byte CMD_POWEROFF = 0x09;
static const byte CMD_DATA = 0x0A;
static const byte CMD_SYNC = 0x0D;
static const byte CMD_ACK = 0x0E;
static const byte CMD_NAK = 0x0F;
static const byte CMD_QUALITY = 0x10;
static const byte ZERO = 0x00;

/**
 * Constructor
 */
SoftwareSerial* camSerial;
CameraC329::CameraC329(uint16_t baudrate, uint8_t rxpin, uint8_t txpin)
{
    camSerial = new SoftwareSerial(rxpin, txpin);
    camSerial->begin(baudrate);
		
}


/**
 * Synchronize with the camera. Synchronization will be attempted up to
 * MAX_SYNC_ATTEMPTS. You must synchronize with the camera before you can
 * call other methods.
 *
 * @return True if successful, false otherwise.
 */
bool CameraC329::sync()
{
  uint8_t syncAttempts = 0;
  bool success = false;

  setOutputCommand(CMD_SYNC, ZERO, ZERO, ZERO, ZERO);

  while (syncAttempts < MAX_SYNC_ATTEMPTS)
  {
    sendCommand();

    // Wait for ACK response
    success = waitForACK(RESPONSE_DELAY, CMD_SYNC);

    // Make sure it is an ACK
    if (success)
    {
      // Now wait for SYNC from camera
      success = waitForResponse(RESPONSE_DELAY);
      if (success && inputCommand[3] == CMD_SYNC)
      {
        // All is good, flush the buffer
        camSerial.flush();

        // Send ACK
        setOutputCommand(CMD_ACK, CMD_SYNC, ZERO, ZERO, ZERO);
        sendCommand();

        return true;
      }
    }

    syncAttempts++;
  }

  return false;
}

/**
 * Sets the camera's initial baud rate, color type, and image sizes. Call this
 * method after synchronization to set up appropriate parameters before
 * taking a snapshot.
 *
 * @param baudRate The baud rate to use for future camera communication
 * @param colorType The color type
 * @param previewResolution The preview resolution
 * @param jpegResolution The JPEG resolution
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::initialize(BaudRate baudRate, ColorType colorType, 
    PreviewResolution previewResolution, JPEGResolution jpegResolution)
{
  setOutputCommand(CMD_INITIAL, baudRate, colorType, previewResolution,
    jpegResolution);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_INITIAL))
    return true;

  return false;
}

/**
 * Set the quality level for compressed (JPEG) images.
 *
 * @param qualityLevel The desired quality level. Should be a value from the
 * QualityLevel enumeration.
 */
bool CameraC329::setQuality(QualityLevel qualityLevel)
{
  setOutputCommand(CMD_QUALITY, qualityLevel, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_QUALITY))
    return true;

  return false;
}

/**
 * Takes a snapshot with the camera and stores it in the camera's internal
 * data buffer. Once a snapshot has been taken, use getPicture to retrieve
 * the photo data.
 *
 * @param pictureType The picture type to take. Should be a value from the
 * PictureType enumeration.
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::takeSnapshot(PictureType pictureType)
{
  setOutputCommand(CMD_SNAPSHOT, pictureType, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_SNAPSHOT))
    return true;

  return false;
}

bool CameraC329::getPicture(PictureType pictureType, void (*callback)(uint32_t pictureSize, uint16_t packetSize, uint32_t packetStartPosition, byte* packet))
{
  uint32_t pictureSize = 0;

  setOutputCommand(CMD_GETPICTURE, pictureType, ZERO, ZERO, ZERO);
  sendCommand();

  if (!waitForACK(RESPONSE_DELAY, CMD_GETPICTURE))
    return false;

  if (!(waitForResponse(RESPONSE_DELAY) && inputCommand[3] == CMD_DATA))
    return false;

  pictureSize = inputCommand[7] << 8;
  pictureSize |= inputCommand[6] << 8;
  pictureSize |= inputCommand[5];

  uint32_t bytePosition = 0;
  uint8_t package[DEFAULT_PACKAGE_SIZE];

  while (bytePosition < pictureSize)
  {
    if (!waitForResponse(RESPONSE_DELAY, package, DEFAULT_PACKAGE_SIZE))
      return false;

    callback(pictureSize, min(DEFAULT_PACKAGE_SIZE, pictureSize - bytePosition), bytePosition, package);
    bytePosition += DEFAULT_PACKAGE_SIZE;
  }

  return true;
}

/**
 * Resets the camera.
 *
 * @param resetType The type of reset to perform (ether a "soft" reset which
 * resets only the camera's internal state machine) or a "hard" reset.
 *
 * @return True if successful, false otherwise.
 */
bool CameraC329::reset(ResetType resetType)
{
  setOutputCommand(CMD_RESET, resetType, ZERO, ZERO, 0xFF);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_RESET))
    return true;

  return false;
}

/**
 * Power off the camera. The camera will be unusable after calling this method
 * until a successful re-synchronization.
 *
 * @return True if successful, false otherwise
 */
bool CameraC329::powerOff()
{
  setOutputCommand(CMD_POWEROFF, ZERO, ZERO, ZERO, ZERO);
  sendCommand();

  if (waitForACK(RESPONSE_DELAY, CMD_POWEROFF))
    return true;

  return false;
}

/**
 * @private
 *
 * Sends the command that is in the outputCommand buffer. Command bytes are
 * sent in big endian order.
 */
void CameraC329::sendCommand()
{
  uint8_t i;

  // Big endian
  for (i = 0; i < CMD_SIZE; i++)
  { 
    camSerial.write((byte)outputCommand[i]);
  }
}

bool CameraC329::waitForACK(uint32_t timeout, uint8_t cmd)
{
  bool success = waitForResponse(timeout);

  if (success && inputCommand[3] == CMD_ACK && inputCommand[4] == cmd)
    return true;

  return false;
}

/**
 * @private
 *
 * Waits for a response up to timeout, and stores the response in the
 * inputCommand array.
 *
 * @return True if response is received before the timeout, false otherwise.
 */
bool CameraC329::waitForResponse(uint32_t timeout)
{
  return waitForResponse(timeout, inputCommand, CMD_SIZE);
}

/**
 * @private
 *
 * Waits for a response up to timeout, and stores the response in the buffer
 * array provided.
 *
 * @param timeout The timeout
 * @param buffer The buffer within which to store the response
 * @param bufferLength The length of the provided buffer
 *
 * @return True if response is received before timeout, false otherwise
 */
bool CameraC329::waitForResponse(uint32_t timeout, byte buffer[], uint16_t bufferLength)
{
  uint8_t byteCount = 0;
  unsigned long time = millis();

  while (millis() - time <= timeout)
  {
    while (camSerial.available() > 0)
    {
      buffer[byteCount] = camSerial.read();
      byteCount++;

      if (byteCount == bufferLength)
        return true;
    }
  }

  if (byteCount > 0)
    return true;

  return false;
}

/**
 * @private
 *
 * Utility method for populating the output command buffer.
 */
void CameraC329::setOutputCommand(const byte command, byte param1, byte param2, byte param3, byte param4)
{
  outputCommand[0] = CMD_PREFIX;
  outputCommand[1] = CMD_PREFIX;
  outputCommand[2] = CMD_PREFIX;
  outputCommand[3] = command;
  outputCommand[4] = param1;
  outputCommand[5] = param2;
  outputCommand[6] = param3;
  outputCommand[7] = param4;
}

This is everything, sorry for the double post. Oh and the only difference between my attempt at this and the original user as far as software goes is I'm using 1.04

CameraC329.H
#ifndef CAMERAC329_H_
#define CAMERAC329_H_

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

// The byte size of UART commands
#define CMD_SIZE 8

// Number of sync attempts to try before giving up
#define MAX_SYNC_ATTEMPTS 60

// How long to wait for serial communication responses
#define RESPONSE_DELAY 100

// Size (in bytes) to split up picture data into packages for processing
#define DEFAULT_PACKAGE_SIZE 64 

class CameraC329 
{
  public:
    enum BaudRate
    {
      BAUD7200 = 0x08,
      BAUD14400 = 0x07,
      BAUD28800 = 0x06,
      BAUD57600 = 0x05,
      BAUD115200 = 0x04,
      BAUD230400 = 0x03,
      BAUD460800 = 0x02,
      BAUD921600 = 0x01
    };

    enum ColorType
    {
      CT_Y4 = 0x02,
      CT_Y8 = 0x03,
      CT_RGB12 = 0x05,
      CT_RGB16 = 0x06,
      CT_RGB24 = 0x08,
      CT_YUV16 = 0x09,
      CT_JPEG = 0x07
    };

    enum PreviewResolution
    {
      PR_80x60 = 0x01,
      PR_88x72 = 0x02,
      PR_160x120 = 0x03,
      PR_176x144 = 0x04,
      PR_320x240 = 0x05,
      PR_352x288 = 0x06,
      PR_640x480 = 0x07,
      PR_80x64 = 0x08,
      PR_128x96 = 0x09,
      PR_128x128 = 0x0A,
      PR_160x128 = 0x0B
    };

    enum JPEGResolution
    {
      JR_80x60 = 0x01,
      JR_88x72 = 0x02,
      JR_160x120 = 0x03,
      JR_176x144 = 0x04,
      JR_320x240 = 0x05,
      JR_352x288 = 0x06,
      JR_640x480 = 0x07,
      JR_80x64 = 0x08,
      JR_128x96 = 0x09,
      JR_128x128 = 0x0A,
      JR_160x128 = 0x0B
    };

    enum PictureType
    {
      PT_SNAPSHOT = 0x01,
      PT_PREVIEW = 0x02,
      PT_SERIAL_FLASH = 0x03,
      PT_JPEG_PREVIEW = 0x05,
      PT_PLAYBACK = 0x06
    };

    enum DataType
    {
      DT_REGISTER = 0x00,
      DT_SNAPSHOT = 0x01,
      DT_PREVIEW = 0x02,
      DT_JPEG_PREVIEW = 0x04,
      DT_PLAYBACK = 0x05
    };

    enum ResetType
    {
      RT_ALL = 0x00,
      RT_STATE = 0x01
    };

    enum QualityLevel
    {
      QL_BEST = 0x00,
      QL_BETTER = 0x01,
      QL_NORMAL = 0x02
    };

    CameraC329(uint16_t baudrate, uint8_t rxpin, uint8_t txpin);
    bool sync();
    bool initialize(BaudRate, ColorType, PreviewResolution, JPEGResolution);
    bool setQuality(QualityLevel);
    bool takeSnapshot(PictureType);
    bool getPicture(PictureType, void (*)(uint32_t, uint16_t, uint32_t, byte*));
    bool reset(ResetType);
    bool powerOff();
	

  private:
	SoftwareSerial *camSerial;
    byte outputCommand[CMD_SIZE];
    byte inputCommand[CMD_SIZE];
    void sendCommand();
    bool waitForACK(uint32_t, uint8_t);
    bool waitForResponse(uint32_t);
    bool waitForResponse(uint32_t, byte[], uint16_t);
    void setOutputCommand(const byte, byte, byte, byte, byte);
};

#endif // CAMERAC329_H_

In CameraC329.h, you have:

	SoftwareSerial *camSerial;

without providing the compiler a clue as to what a SoftwareSerial is. How much clearer can the message be?

Ok sorry I'm still a novice at this. However I did include the SoftwareSerial.h before and it gave me the same error message. I'm not sure if thats what you're referring to though.