Smartcar Shield
SRF08.cpp
Go to the documentation of this file.
1 #include "SRF08.hpp"
2 #include "../../../../utilities/Utilities.hpp"
3 
4 namespace
5 {
6 // For documentation on addressing, please refer to:
7 // http://www.robot-electronics.co.uk/htm/srf08tech.html
8 const uint8_t kFirstAddress = 112;
9 const uint8_t kLastAddress = 127;
10 const uint8_t kRangingCommandRegister = 0x00;
11 const uint8_t kRangingInCm = 0x51;
12 } // namespace
13 
14 using namespace smartcarlib::constants::srf08;
16 using namespace smartcarlib::utils;
17 
18 SRF08::SRF08(Runtime& runtime, uint8_t address)
19  : mAddress{ address }
20  , mRuntime(runtime)
21  , mPingDelay{ kDefaultPingDelay }
22  , mAttached{ false }
23 {
24 }
25 
26 void SRF08::attach()
27 {
28  if (!mAttached)
29  {
30  mRuntime.i2cInit();
31  mAttached = true;
32  }
33 }
34 
35 unsigned int SRF08::getDistance()
36 {
37  attach();
38 
39  static const uint8_t kFirstEchoHighByte = 0x02;
40  static const uint8_t kNumberOfBytesToRequest = 2;
41 
42  measureDistance();
43 
44  mRuntime.i2cBeginTransmission(mAddress);
45  mRuntime.i2cWrite(kFirstEchoHighByte);
46  mRuntime.i2cEndTransmission();
47 
48  mRuntime.i2cRequestFrom(mAddress, kNumberOfBytesToRequest);
49  if (mRuntime.i2cAvailable() == 0)
50  {
51  return static_cast<unsigned int>(-1); // Return a large error-like value
52  }
53  auto high = mRuntime.i2cRead();
54  auto low = mRuntime.i2cRead();
55 
56  static constexpr auto kBitsInByte = 8;
57 
58  return static_cast<uint16_t>((high << kBitsInByte) + low);
59 }
60 
61 unsigned int SRF08::getMedianDistance(uint8_t iterations)
62 {
63  if (iterations == 0 || iterations > kMaxMedianMeasurements)
64  {
65  return static_cast<unsigned int>(-1); // Return a large number to indicate error
66  }
67 
68  unsigned int measurements[kMaxMedianMeasurements];
69  for (auto i = 0; i < iterations; i++)
70  {
71  measurements[i] = getDistance();
72  mRuntime.delayMillis(mPingDelay);
73  }
74 
75  return getMedian(measurements, iterations);
76 }
77 
78 void SRF08::setGain(uint8_t gainValue)
79 {
80  attach();
81 
82  static const uint8_t kGainRegister = 0x01;
83  static const uint8_t kMinGain = 0;
84  static const uint8_t kMaxGain = 31;
85 
86  mRuntime.i2cBeginTransmission(mAddress);
87  mRuntime.i2cWrite(kGainRegister);
88  mRuntime.i2cWrite(getConstrain(gainValue, kMinGain, kMaxGain));
89  mRuntime.i2cEndTransmission();
90 }
91 
92 void SRF08::setRange(uint8_t range)
93 {
94  attach();
95 
96  static const uint8_t kRangeRegister = 0x02;
97 
98  mRuntime.i2cBeginTransmission(mAddress);
99  mRuntime.i2cWrite(kRangeRegister);
100  // Max_Range = (range * 3.4) + 3.4 in centimeters
101  mRuntime.i2cWrite(range);
102  mRuntime.i2cEndTransmission();
103 }
104 
105 unsigned long SRF08::setPingDelay(unsigned long milliseconds)
106 {
107  mPingDelay = milliseconds;
108  return mPingDelay;
109 }
110 
112 {
113  attach();
114 
115  static const uint8_t kLightSensorByte = 0x01;
116  static const uint8_t kNumberOfBytesToRequest = 1;
117 
118  // Start a ranging
119  measureDistance();
120 
121  // Get only the light reading byte
122  mRuntime.i2cBeginTransmission(mAddress);
123  mRuntime.i2cWrite(kLightSensorByte);
124  mRuntime.i2cEndTransmission();
125  mRuntime.i2cRequestFrom(mAddress, kNumberOfBytesToRequest);
126  mRuntime.delayMillis(mPingDelay);
127 
128  return mRuntime.i2cAvailable() != 0 ? static_cast<uint8_t>(mRuntime.i2cRead())
129  : static_cast<uint8_t>(-1);
130 }
131 
132 uint8_t SRF08::changeAddress(uint8_t newAddress)
133 {
134  attach();
135 
136  static const uint8_t kFirstInChangeAddressSequence = 0xA0;
137  static const uint8_t kSecondInChangeAddressSequence = 0xAA;
138  static const uint8_t kThirdInChangeAddressSequence = 0xA5;
139 
140  newAddress = getConstrain(newAddress, kFirstAddress, kLastAddress);
141 
142  mRuntime.i2cBeginTransmission(mAddress);
143  mRuntime.i2cWrite(kRangingCommandRegister);
144  mRuntime.i2cWrite(kFirstInChangeAddressSequence);
145  mRuntime.i2cEndTransmission();
146 
147  mRuntime.i2cBeginTransmission(mAddress);
148  mRuntime.i2cWrite(kRangingCommandRegister);
149  mRuntime.i2cWrite(kSecondInChangeAddressSequence);
150  mRuntime.i2cEndTransmission();
151 
152  mRuntime.i2cBeginTransmission(mAddress);
153  mRuntime.i2cWrite(kRangingCommandRegister);
154  mRuntime.i2cWrite(kThirdInChangeAddressSequence);
155  mRuntime.i2cEndTransmission();
156 
157  mRuntime.i2cBeginTransmission(mAddress);
158  mRuntime.i2cWrite(kRangingCommandRegister);
159  mRuntime.i2cWrite(static_cast<uint8_t>(newAddress << 0x01));
160  mRuntime.i2cEndTransmission();
161 
162  mAddress = newAddress;
163 
164  return mAddress;
165 }
166 
167 void SRF08::measureDistance()
168 {
169  mRuntime.i2cBeginTransmission(mAddress);
170  mRuntime.i2cWrite(kRangingCommandRegister);
171  mRuntime.i2cWrite(kRangingInCm);
172  mRuntime.i2cEndTransmission();
173  mRuntime.delayMillis(mPingDelay);
174 }
SRF08::changeAddress
uint8_t changeAddress(uint8_t newAddress)
Changes the address of the specific SRF08 sensor.
Definition: SRF08.cpp:132
Runtime::i2cEndTransmission
virtual uint8_t i2cEndTransmission()=0
Ends a transmission to an I2C device equivalent of Wire.endTransmission in Arduino.
Runtime::i2cInit
virtual void i2cInit()=0
Initialize I2C bus as master, equivalent of Wire.begin in Arduino.
SRF08::setGain
void setGain(uint8_t gain)
Combined with the range setting affects how much time each measurement will last as well as the maxim...
Definition: SRF08.cpp:78
Runtime::delayMillis
virtual void delayMillis(unsigned long milliseconds)=0
Block the execution for the specified number of milliseconds, equivalent of delay in Arduino.
Runtime
Definition: Runtime.hpp:35
smartcarlib::utils::getMedian
AnyNumber getMedian(AnyNumber unsortedNumbers[], const unsigned int &arraySize)
Gets the median value out of the supplied number array.
Definition: Utilities.hpp:66
Runtime::i2cBeginTransmission
virtual void i2cBeginTransmission(uint8_t address)=0
Initiate a transmission to the specified I2C slave device, equivalent of Wire.beginTransmission in Ar...
Runtime::i2cRead
virtual int i2cRead()=0
Reads a byte from I2C bus, equivalent of Wire.read in Arduino.
SRF08.hpp
Runtime::i2cRequestFrom
virtual uint8_t i2cRequestFrom(uint8_t address, uint8_t numberOfBytes)=0
Request a number of bytes from the specified I2C slave, equivalent of Wire.requestFrom in Arduino.
SRF08::getMedianDistance
unsigned int getMedianDistance(uint8_t iterations=smartcarlib::constants::srf08::kDefaultIterations) override
Gets the median distance from the specified number of measurements.
Definition: SRF08.cpp:61
smartcarlib::utils
Definition: Utilities.hpp:9
SRF08::getLightReading
uint8_t getLightReading()
Conducts a measurement from the on-board light sensor.
Definition: SRF08.cpp:111
SRF08::getDistance
unsigned int getDistance() override
Gets the distance measured by the sensor in centimeters.
Definition: SRF08.cpp:35
smartcarlib::constants::srf08
Definition: SRF08.hpp:18
Runtime::i2cAvailable
virtual int i2cAvailable()=0
Gets the number of bytes available to be retrieved, equivalent of Wire.availableO in Arduino.
smartcarlib::constants::srf08::kDefaultPingDelay
const uint8_t kDefaultPingDelay
Definition: SRF08.hpp:21
smartcarlib::constants::distanceSensor
Definition: DistanceSensor.hpp:13
SRF08::setPingDelay
unsigned long setPingDelay(unsigned long milliseconds=smartcarlib::constants::srf08::kDefaultPingDelay)
Delay between ranging measurements.
Definition: SRF08.cpp:105
smartcarlib::utils::getConstrain
constexpr AnyNumber getConstrain(AnyNumber number, AnyNumber min, AnyNumber max)
Limit the number between a range.
Definition: Utilities.hpp:46
SRF08::SRF08
SRF08(Runtime &runtime, uint8_t address)
Constructs an SRF08 sensor that communicates over I2C.
Definition: SRF08.cpp:18
smartcarlib::constants::distanceSensor::kMaxMedianMeasurements
const int kMaxMedianMeasurements
Definition: DistanceSensor.hpp:15
Runtime::i2cWrite
virtual size_t i2cWrite(uint8_t value)=0
Send the specified byte via i2c, equivalent of Wire.write in Arduino.
SRF08::setRange
void setRange(uint8_t range)
Combined with the gain setting affects how much time each measurement will last as well as the maximu...
Definition: SRF08.cpp:92