Skip to content

Commit 9bd2010

Browse files
committed
Changed ScanPacket from struct to class
Expanded the ScanPacket struct into a class with a constructor, getter, and setter methods Changed ScanPacket to store angle as raw 16-bit fixed point value instead of float Added getter methods to ScanPacket class to get angle as degrees, millidegrees, or raw fixed point value Added constants defining bit flags for each of the error/sync bits in data blocks Moved the Sweep data member bIsScanning from public to private access and added a getter method for this value Removed const type qualifier on return type of _ascii_bytes_to_integer Updated README Updated keywords Minor formatting changes
1 parent 6caa8e5 commit 9bd2010

File tree

8 files changed

+252
-98
lines changed

8 files changed

+252
-98
lines changed

README.md

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Arduino Library for Scanse Sweep LiDAR
33

44
# Compatibility
55
### Arduino
6-
Currently the library has only been tested with an `Arduino Mega 2560`.
6+
Currently the library has only been tested with an `Arduino Mega 2560`, an `Arduino Mega ADK`, and an `Arduino Micro`.
77
### Sweep Firmware
88
| sweep firmware | compatibility |
99
| :------------: | :-----------: |
@@ -19,7 +19,7 @@ Copy the entire `Sweep/` folder to your `.../Arduino/libraries/` directory.
1919

2020
Checkout the provided `Examples/` directory for 2 full examples.
2121

22-
For best results, you should provide dedicated external 5V power to the Sweep rather than using power from the Arduino. Just be sure to connect the ground from the power source and the arduino. If you are just experimenting, you can run the sweep off the 5V power from the Arduino with the Arduino receiving power over USB. However this has only been tested with an external powered USB hub. It is possible that using a low power USB port (ex: laptop) to power the arduino + sweep will result in unexpected behavior.
22+
For best results, you should provide dedicated external 5V power to the Sweep rather than using power from the Arduino. Just be sure to connect the ground from the power source and the arduino. If you are just experimenting, you can run the sweep off the 5V power from the Arduino with the Arduino receiving power over USB. However, it is possible that using a low power USB port (ex: laptop) to power the arduino + sweep will result in unexpected behavior.
2323

2424
![Alt text](wiring_diagrams/MegaSerialPrinter.png?raw=true "Title")
2525

@@ -71,15 +71,16 @@ Data collection:
7171
bool bSuccess = device.startScanning();
7272
...
7373

74-
// Create a scan packet to populate with the sensor reading
75-
ScanPacket reading;
7674
// read 10 individual sensor readings
7775
for (int i = 0; i < 10; i++) {
78-
if(device.getReading(reading)) {
79-
bool bFirstOfNewScan = reading.bIsSync;
80-
float angle = reading.angle;
81-
uint16_t range = reading.distance;
82-
uint8_t confidence = reading.signalStrength;
76+
// Create a scan packet to populate with the sensor reading
77+
bool success = false;
78+
ScanPacket reading = device.getReading(success);
79+
if(success) {
80+
bool bFirstOfNewScan = reading.isSync();
81+
float angle = reading.getAngleDegrees();
82+
uint16_t range = reading.getDistance();
83+
uint8_t confidence = reading.getSignalStrength();
8384
...
8485

8586
// stop scanning
@@ -90,17 +91,19 @@ bool bSuccess = device.stopScanning();
9091
9192
# API
9293
94+
### Sweep
95+
9396
```c++
9497
Sweep(Stream &serial)
9598
```
9699

97100
Constructs a sweep device on the provided Stream object.
98101

99102
```c++
100-
bool bIsScanning
103+
bool isScanning()
101104
```
102105

103-
True if the device is currently scanning.
106+
Returns true if the device is currently scanning.
104107

105108
```c++
106109
bool startScanning()
@@ -118,22 +121,16 @@ bool stopScanning()
118121
Signals the sweep device to stop scanning. Will block for ~500ms to flush leftover data stream from the buffer and validate a second response from the sensor.
119122

120123
```c++
121-
bool getReading(ScanPacket &reading)
124+
ScanPacket getReading(bool &success)
122125
```
123126
124127
Reads a single sensor reading from the serial buffer. Must be called frequently enough to keep up with the data stream.
125128
126129
```c++
127-
struct ScanPacket
128-
{
129-
bool bIsSync; // 1 -> first reading of new scan, 0 otherwise
130-
float angle; // degrees
131-
uint16_t distance; // cm
132-
uint8_t signalStrength; // 0:255, higher is better
133-
}
130+
class ScanPacket
134131
```
135132

136-
Structure representing a single sensor reading (ranging). ie: a full 360deg scan would be composed of many such readings.
133+
Class representing a single sensor reading (ranging). ie: a full 360deg scan would be composed of many such readings.
137134

138135
```c++
139136
bool getMotorReady()
@@ -158,6 +155,7 @@ Returns the current motor speed setting in HZ
158155
bool setMotorSpeed(const uint8_t motorSpeedCode[2])
159156

160157
// Available Codes
158+
MOTOR_SPEED_CODE_0_HZ
161159
MOTOR_SPEED_CODE_1_HZ
162160
MOTOR_SPEED_CODE_2_HZ
163161
MOTOR_SPEED_CODE_3_HZ
@@ -198,5 +196,46 @@ void reset()
198196

199197
Resets the device. Attempting to communicate with the device while it is resetting will cause issues. While the device is booting the LED on the device will blink green. The device is capable of communication when the LED turns from green to blue, although the motor may still be adjusting until the blue LED stops blinking as well.
200198

199+
### ScanPacket
200+
201+
```c++
202+
ScanPacket(const bool bIsSync, const uint16_t rawAngle, const uint16_t distance, const uint8_t signalStrength)
203+
```
204+
205+
Constructs a ScanPacket object with the given parameters. The construction of the ScanPacket object for a reading is handled by the Sweep class's getReading() method; you should not need to use this constructor.
206+
207+
```c++
208+
bool isSync() const
209+
```
210+
211+
Returns true if this reading was the first reading of a new scan; otherwise, returns false.
201212

213+
```c++
214+
float getAngleDegrees() const
215+
```
216+
217+
Returns the angle of this reading as a float, in degrees.
218+
219+
```c++
220+
float getAngleMillidegrees() const
221+
```
222+
223+
Returns the angle of this reading as a float, in millidegrees.
224+
225+
```c++
226+
uint16_t getAngleRaw() const
227+
```
228+
229+
Returns the angle of this reading as the raw 16-bit fixed point value. The scaling factor of this value is 16; this means that the angle in degrees is obtained by dividing the raw value by 16.
230+
231+
```c++
232+
uint16_t getDistance() const
233+
```
234+
235+
Returns the distance of this reading, in centimeters.
236+
237+
```c++
238+
uint8_t getSignalStrength() const
239+
```
202240

241+
Returns the signal strength of this reading. A low value indicates low strength, and a high value indicates high strength.

Sweep/Examples/MegaDistanceBlink/MegaDistanceBlink.ino

100644100755
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ const uint8_t STATE_ERROR = 7;
6666

6767
// Create a Sweep device using Serial #1 (RX1 & TX1)
6868
Sweep device(Serial1);
69-
// Scan packet struct, used to store info for a single reading
70-
ScanPacket reading;
7169

7270
uint16_t closestDistanceInSpecifiedFOV = 4000; // the distance (in cm) of the closest object in the specified angular range
7371
uint16_t interval = 1000; // interval at which to blink onboard LED (milliseconds)
@@ -181,22 +179,24 @@ bool verifyCurrentDeviceSettings()
181179
bool gatherDistanceInfo()
182180
{
183181
// attempt to get the next scan packet
184-
// Note: getReading() will write values into the "reading" variable
185-
if (device.getReading(reading))
182+
// Note: getReading() will return a ScanPacket object
183+
bool success = false;
184+
ScanPacket reading = device.getReading(success);
185+
if (success)
186186
{
187187
// marks the end of the angular range, so report true
188-
if (reading.bIsSync)
188+
if (reading.isSync())
189189
return true;
190190

191191
// consider a Field of View in the angular range [360-FOV: 0]
192-
if (reading.angle > 360 - FOV)
192+
if (reading.getAngleDegrees() > 360 - FOV)
193193
{
194194
// only consider valid readings (sensor will report distance of 1 for failed readings)
195-
if (reading.distance > 1)
195+
if (reading.getDistance() > 1)
196196
{
197197
// check if this reading is closer than anything seen so far
198-
if (reading.distance < closestDistanceInSpecifiedFOV)
199-
closestDistanceInSpecifiedFOV = reading.distance;
198+
if (reading.getDistance() < closestDistanceInSpecifiedFOV)
199+
closestDistanceInSpecifiedFOV = reading.getDistance();
200200
}
201201
}
202202
}
@@ -244,4 +244,4 @@ void reset()
244244
ledState = LOW;
245245
digitalWrite(LED_BUILTIN, ledState); // turn the LED off by making the voltage LOW
246246
device.reset();
247-
}
247+
}

Sweep/Examples/MegaSerialPrinter/MegaSerialPrinter.ino

100644100755
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131

3232
// Create a Sweep device using Serial #1 (RX1 & TX1)
3333
Sweep device(Serial1);
34-
// Scan packet struct, used to store info for a single reading
35-
ScanPacket reading;
3634

3735
// keeps track of how many scans have been collected
3836
uint8_t scanCount = 0;
@@ -193,21 +191,23 @@ void gatherSensorReading()
193191
{
194192
// attempt to get the next scan packet
195193
// Note: getReading() will write values into the "reading" variable
196-
if (device.getReading(reading))
194+
bool success = false;
195+
ScanPacket reading = device.getReading(success);
196+
if (success)
197197
{
198198
// check if this reading was the very first reading of a new 360 degree scan
199-
if (reading.bIsSync)
199+
if (reading.isSync())
200200
scanCount++;
201201

202202
// don't collect more than 3 scans
203203
if (scanCount > 3)
204204
return;
205205

206206
// store the info for this sample
207-
syncValues[sampleCount] = reading.bIsSync;
208-
angles[sampleCount] = reading.angle;
209-
distances[sampleCount] = reading.distance;
210-
signalStrengths[sampleCount] = reading.signalStrength;
207+
syncValues[sampleCount] = reading.isSync();
208+
angles[sampleCount] = reading.getAngleDegrees();
209+
distances[sampleCount] = reading.getDistance();
210+
signalStrengths[sampleCount] = reading.getSignalStrength();
211211

212212
// increment sample count
213213
sampleCount++;
@@ -259,4 +259,4 @@ void reset()
259259
userInput = "";
260260
Serial.println("\n\nWhenever you are ready, type \"start\" to to begin the sequence...");
261261
currentState = 0;
262-
}
262+
}

Sweep/ScanPacket.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "ScanPacket.h"
2+
3+
ScanPacket::ScanPacket(const bool bIsSync, const uint16_t rawAngle,
4+
const uint16_t distance, const uint8_t signalStrength):
5+
_bIsSync(bIsSync), _rawAngle(rawAngle), _distance(distance),
6+
_signalStrength(signalStrength) {}
7+
8+
bool ScanPacket::isSync() const
9+
{
10+
return _bIsSync;
11+
}
12+
13+
float ScanPacket::getAngleDegrees() const
14+
{
15+
return _rawAngle / SCALING_FACTOR;
16+
}
17+
18+
float ScanPacket::getAngleMillidegrees() const
19+
{
20+
return (_rawAngle / SCALING_FACTOR) * MILLIDEGREE_FACTOR;
21+
}
22+
23+
uint16_t ScanPacket::getAngleRaw() const
24+
{
25+
return _rawAngle;
26+
}
27+
28+
uint16_t ScanPacket::getDistance() const
29+
{
30+
return _distance;
31+
}
32+
33+
uint8_t ScanPacket::getSignalStrength() const
34+
{
35+
return _signalStrength;
36+
}

Sweep/ScanPacket.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef _SCANPACKET_H
2+
#define _SCANPACKET_H
3+
4+
#include <stdint.h>
5+
6+
/**
7+
* Class representing the data block returned from the Sweep.
8+
*/
9+
class ScanPacket
10+
{
11+
public:
12+
// Constructor
13+
ScanPacket(const bool bIsSync, const uint16_t rawAngle,
14+
const uint16_t distance, const uint8_t signalStrength);
15+
16+
// Returns true if this reading is the first of a new scan
17+
bool isSync() const;
18+
19+
// Returns the angle in degrees as a float
20+
float getAngleDegrees() const;
21+
22+
// Returns the angle in millidegrees as a float
23+
float getAngleMillidegrees() const;
24+
25+
// Returns the angle as a raw fixed point value
26+
uint16_t getAngleRaw() const;
27+
28+
// Returns the range measurement
29+
uint16_t getDistance() const;
30+
31+
// Returns the signal strength
32+
uint8_t getSignalStrength() const;
33+
34+
private:
35+
// Scaling factor of raw angle
36+
static constexpr float SCALING_FACTOR = 16.0;
37+
// Millidegrees conversion factor
38+
static constexpr float MILLIDEGREE_FACTOR = 1000;
39+
40+
bool _bIsSync; // 1 -> first reading of new scan, 0 otherwise
41+
uint16_t _rawAngle; // fixed point value: (degrees * 16)
42+
uint16_t _distance; // cm
43+
uint8_t _signalStrength; // 0:255, higher is better
44+
};
45+
46+
#endif

Sweep/Sweep.cpp

100644100755
Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
#include "Sweep.h"
22

3-
Sweep::Sweep(Stream &serial) : _serial(serial)
4-
{
5-
bIsScanning = false;
6-
}
3+
Sweep::Sweep(Stream &serial) : _serial(serial), bIsScanning(false) {}
4+
75
Sweep::~Sweep()
86
{
97
_serial.flush();
108
}
119

10+
bool Sweep::isScanning()
11+
{
12+
return bIsScanning;
13+
}
14+
1215
bool Sweep::startScanning()
1316
{
1417
if (bIsScanning)
@@ -50,23 +53,37 @@ bool Sweep::stopScanning()
5053
return false;
5154
}
5255

53-
bool Sweep::getReading(ScanPacket &reading)
56+
ScanPacket Sweep::getReading(bool &success)
5457
{
58+
success = false;
5559
if (!bIsScanning)
56-
return false;
60+
{
61+
return ScanPacket(false, 0, 0, 0);
62+
}
5763

58-
// wait for the receipt (possible timeout)
64+
// wait for the receipt (possible timeout)
5965
if (_readResponseScanPacket())
6066
{
6167
// TODO: validate receipt
62-
reading.bIsSync = _responseScanPacket[0] % 2 == 1;
63-
// convert the angle into a float in degrees
64-
reading.angle = angle_raw_to_deg((_responseScanPacket[2] << 8) + (_responseScanPacket[1]));
65-
reading.distance = (_responseScanPacket[4] << 8) + (_responseScanPacket[3]);
66-
reading.signalStrength = _responseScanPacket[5];
67-
return true;
68+
int i = 0;
69+
70+
bool bIsSync = _responseScanPacket[i++] & _SYNC_MASK;
71+
72+
uint16_t angle_lsb = _responseScanPacket[i++];
73+
uint16_t angle_msb = _responseScanPacket[i++] << 8;
74+
uint16_t angle = angle_lsb + angle_msb;
75+
76+
uint16_t distance_lsb = _responseScanPacket[i++];
77+
uint16_t distance_msb = _responseScanPacket[i++] << 8;
78+
uint16_t distance = distance_lsb + distance_msb;
79+
80+
uint8_t signalStrength = _responseScanPacket[i++];
81+
82+
success = true;
83+
return ScanPacket(bIsSync, angle, distance, signalStrength);
6884
}
69-
return false;
85+
86+
return ScanPacket(false, 0, 0, 0);
7087
}
7188

7289
bool Sweep::getMotorReady()

0 commit comments

Comments
 (0)