Go Down

Topic: [solved]creating a library dependent library (Read 800 times) previous topic - next topic

Imahilus

Apr 08, 2010, 01:34 pm Last Edit: Apr 08, 2010, 10:08 pm by Imahilus Reason: 1
Hello,

I am trying to create a library to interface with my URM37 ultrasonic range finder sensor.
I've had success communicating with this sensor over serial (success with the NewSoftSerial library, aswell as through the hardware serial).
And since I have it working from a sketch, I want to turn it into a library to keep my sketch clean.
Now this is where I've ran into a snag, since I want to make use of the NewSoftSerial library from within the one I am creating.

I get the following errors (basically, it sees all methods of the NewSoftSerial class as undefined references):
Code: [Select]
/tmp/build5679186724173996948.tmp/RangeFinder/RangerFinder.cpp.o: In function `RangeFinder::Begin(unsigned char, unsigned char, int, long)':

/home/imahilus/Arduino-0018/libraries/RangeFinder/RangerFinder.cpp:22: undefined reference to `NewSoftSerial::available()'

/home/imahilus/Arduino-0018/libraries/RangeFinder/RangerFinder.cpp:25: undefined reference to `NewSoftSerial::read()'

/home/imahilus/Arduino-0018/libraries/RangeFinder/RangerFinder.cpp:19: undefined reference to `operator new(unsigned int)'

/home/imahilus/Arduino-0018/libraries/RangeFinder/RangerFinder.cpp:19: undefined reference to `NewSoftSerial::NewSoftSerial(unsigned char, unsigned char, bool)'

/home/imahilus/Arduino-0018/libraries/RangeFinder/RangerFinder.cpp:20: undefined reference to `NewSoftSerial::begin(long)'


It is a shame there aren't any references as to library development that use other libraries (as is so often done in the coding industry).
I know the problem lies in the NewSoftSerial object, since I wrote another library that is completely unrelated to this one, that doesn't use an object from another library, that compiled and works just fine.

I've tried various things, but without effect..
A little help would be appreciated =)

The header file:
Code: [Select]
#ifndef rangefinder_h
#define rangefinder_h

#include "../NewSoftSerial/NewSoftSerial.h"
#include "WProgram.h"



/**
* The RangeFinder class is a completely transparant class that relies on the NewSoftSerial library.
* The measurements occur through serial communications, which can be set to any combination of digital I/O pins.
* While the NewSoftSerial library operates in a non-blocking fashion, to keep the use of this class simple,
* the measurements that are performed work in a blocking fashion (but allow for interrupts to happen normally during this blocking period).
* The Range Finder operates its own orientational servo, making it possible for it to control in which direction it performs its measurements.
**/
class RangeFinder
{
   public:
       RangeFinder();
       void Begin(uint8_t rx, uint8_t tx, int resetpin, long baudrate); //initialise the range finder on the provided pins as a NewSoftSerial device with the specified baudrate. The resetpin is needed to ensure a properly working sensor.
       void SetServoPosition(uint8_t rotation);                         //the rotation, in degrees, to which to set the servo. the servo has a range of 0~46, the physical range this represents should be 0~270 but might be smaller. The new rotation is applied with the next call to DistanceMeasurement.
       int  DistanceMeasurement();                                      //perform a distance measurement, this yields a result generally between 10~300 (cm's).
       int  TemperatureMeasurement();                                   //perform a temperature measurement. The value returned should be in degrees celsius with a resolution of .1, however, the value returned appears to be wrong?
   private:
       uint8_t        _servoPosition;
       int            _resetPin;
       NewSoftSerial* _serial;
};

#endif



The source file:
Code: [Select]
#include "../NewSoftSerial/NewSoftSerial.h"
#include "RangeFinder.h"



RangeFinder::RangeFinder()
{
}



/**
* Initialise the NewSoftSerial object and the Range Finder itself so it can be used.
**/
void RangeFinder::Begin(uint8_t rx, uint8_t tx, int resetpin, long baudrate)
{
   _resetPin = resetpin;
   pinMode(_resetPin, OUTPUT);
   _serial = new NewSoftSerial(rx, tx);
   _serial->begin(baudrate);
   
   digitalWrite(_resetPin, LOW); //resets while pin is low
   delay(500);                   //is apparently enough
   digitalWrite(_resetPin, HIGH);
}



/**
* Set the servo to a new rotation. The change is applied the next time DistanceMeasurement is called.
**/
void RangeFinder::SetServoPosition(uint8_t rotation)
{
   _servoPosition = rotation;
}



/**
* Send the 4 bytes of the Distance Measurement command to the Range Finder, subsequently wait for the reply and read it.
* The first byte returned is the command code, the fourth is a checksum byte (and as such these two bytes can be ignored).
**/
int RangeFinder::DistanceMeasurement()
{
   //send the command
   _serial->print(0x22,              BYTE);
   _serial->print(_servoPosition,    BYTE);
   _serial->print(0x00,              BYTE);
   _serial->print(34+_servoPosition, BYTE);
   while(_serial->available() < 4);
   
   //read the response
   _serial->read();
   delayMicroseconds(1);
   int distance = _serial->read();
   delayMicroseconds(1);
   distance = distance << 8;
   uint8_t byte2 = _serial->read();
   delayMicroseconds(1);
   distance += byte2;
   _serial->read();
   delayMicroseconds(1);

   //return the value
   return distance;
}



/**
* Send the 4 bytes of the Temperature Measurement command to the Range Finder, subsequently wait for the reply and read it.
* The first byte returned is the command code, the fourth is a checksum byte (and as such these two bytes can be ignored).
* The first 4 bits of the first data byte (the high byte) indicate whether the measurement is above 0C (by being all 0's), or below 0C (by being all 1's).
* The value returned from this measurement doesn't appear to be correct?
**/
int RangeFinder::TemperatureMeasurement()
{
   //send the command
   _serial->print(0x11, BYTE);
   _serial->print(0x00, BYTE);
   _serial->print(0x00, BYTE);
   _serial->print(0x11, BYTE);
   while(_serial->available() < 4);

   //read the response
   _serial->read();
   delayMicroseconds(1);
   uint8_t highbyte = _serial->read();
   delayMicroseconds(1);
   uint8_t lowbyte = _serial->read();
   delayMicroseconds(1);

   //process the response
   int temperature = 0;
   if((highbyte == 255)&&(lowbyte == 255))
   {
       temperature = 32767;
   }
   else
   if(highbyte > 127)
   {
       highbyte = highbyte & 0x0F;
       temperature = -(highbyte << 8)-lowbyte;
   }
   else
   {
       highbyte = highbyte & 0x0F;
       temperature = (highbyte << 8)+lowbyte;
   }
   _serial->read();
   delayMicroseconds(1);
   return temperature;
}


PS: I have verified that the path to the NewSoftSerial library and that the caps of the filenames are correct.
And thank you for any assistance =)

wayoda


Imahilus

Must've missed that one  :-[

Thank you for the glance!

Go Up