Skyward boardcore
Loading...
Searching...
No Matches
VN100Serial.cpp
Go to the documentation of this file.
1/* Copyright (c) 2021 Skyward Experimental Rocketry
2 * Author: Matteo Pignataro, Fabrizio Monti
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "VN100Serial.h"
24
26
27namespace Boardcore
28{
29
31 std::chrono::milliseconds timeout)
32 : VNCommonSerial(usart, baud, "vn100-serial", crc, timeout)
33{
34}
35
37{
38 SensorErrors backup = lastError;
39
40 // If already initialized
41 if (isInit)
42 {
44 LOG_WARN(logger, "Sensor vn100 already initialized");
45 return true;
46 }
47
48 // Allocate the pre loaded strings based on the user selected crc
49 switch (this->crc)
50 {
52 askSampleCommand = "$VNBOM,1*45\n";
53 break;
55 askSampleCommand = "$VNBOM,1*749D\n";
56 break;
58 askSampleCommand = "$VNBOM,1*XX\n";
59 break;
60 }
61
62 // Set the error to init fail and if the init process goes without problem
63 // i restore it to the last error
65
67
68 if (!setCrc(false))
69 {
70 LOG_ERR(logger, "Unable to set the vn100 user selected CRC");
71 return false;
72 }
73
74 if (!disableAsyncMessages(false))
75 {
76 LOG_ERR(logger, "Unable to disable async messages from vn100");
77 return false;
78 }
79
81 {
82 LOG_ERR(logger, "Unable to config the user vn100 serial port");
83 return false;
84 }
85
86 if (!verifyModelNumber("VN-100"))
87 {
88 LOG_ERR(logger, "Error, model number not corresponding");
90 return false;
91 }
92
93 if (!setBinaryOutput())
94 {
95 LOG_ERR(logger, "Unable to set binary output register");
96 return false;
97 }
98
99 // I need to repeat this in case of a non default
100 // serial port communication at the beginning
101 if (!setCrc(true))
102 {
103 LOG_ERR(logger, "Unable to set the vn100 user selected CRC");
104 return false;
105 }
106
107 if (!disableAsyncMessages(true))
108 {
109 LOG_ERR(logger, "Unable to disable async messages from vn100");
110 return false;
111 }
112
113 // Set the isInit flag true
114 isInit = true;
115
116 // All good i restore the actual last error
117 lastError = backup;
118
119 return true;
120}
121
122bool VN100Serial::selfTest() { return true; }
123
125{
126 VN100SerialData data;
127 BinaryData binData;
128
129 const uint64_t timestamp = TimestampTimer::getTimestamp();
130
131 bool sampleOutcome =
132 false; // True if a valid sample was retrieved from the sensor
133
134 sampleOutcome = getBinaryOutput<BinaryData>(binData, askSampleCommand);
135 if (!sampleOutcome)
137
138 // With binary output the checksum is always calculated with checksum16
139 bool validChecksum =
140 (crc == CRCOptions::CRC_NO) ||
141 (calculateChecksum16(reinterpret_cast<uint8_t*>(&binData),
142 sizeof(binData)) == 0);
143
144 if (sampleOutcome && !validChecksum)
146
147 // Verify if the sample is valid
148 sampleOutcome = sampleOutcome && validChecksum;
149
150 if (sampleOutcome)
151 {
152 buildBinaryData(binData, data, timestamp);
153 return data;
154 }
155 else
156 {
157 // Last error is already set
158 return lastSample;
159 }
160}
161
162void VN100Serial::buildBinaryData(const BinaryData& binData,
163 VN100SerialData& data,
164 const uint64_t sampleTimestamp)
165{
166 // Acceleration data
167 data.accelerationTimestamp = sampleTimestamp;
168 data.accelerationX = binData.accelerationX;
169 data.accelerationY = binData.accelerationY;
170 data.accelerationZ = binData.accelerationZ;
171
172 // Angular speed data
173 data.angularSpeedTimestamp = sampleTimestamp;
174 data.angularSpeedX = binData.angularX;
175 data.angularSpeedY = binData.angularY;
176 data.angularSpeedZ = binData.angularZ;
177
178 // Magnetometer data
179 data.magneticFieldTimestamp = sampleTimestamp;
180 data.magneticFieldX = binData.magneticFieldX;
181 data.magneticFieldY = binData.magneticFieldY;
182 data.magneticFieldZ = binData.magneticFieldZ;
183
184 // Quaternion data
185 data.quaternionTimestamp = sampleTimestamp;
186 data.quaternionX = binData.quaternionX;
187 data.quaternionY = binData.quaternionY;
188 data.quaternionZ = binData.quaternionZ;
189 data.quaternionW = binData.quaternionW;
190
191 // Temperature data
192 data.temperatureTimestamp = sampleTimestamp;
193 data.temperature = binData.temperature;
194
195 // Pressure data
196 data.pressureTimestamp = sampleTimestamp;
197 data.pressure = binData.pressure;
198}
199
200bool VN100Serial::setBinaryOutput()
201{
212 const char* setBinarySampleCommand = "";
213 switch (this->crc)
214 {
216 setBinarySampleCommand = "$VNWRG,75,0,16,01,0530*44\n";
217 break;
219 setBinarySampleCommand = "$VNWRG,75,0,16,01,0530*9CFA\n";
220 break;
222 setBinarySampleCommand = "$VNWRG,75,0,16,01,0530*XX\n";
223 break;
224 }
225
227
228 if (!sendStringCommand(setBinarySampleCommand))
229 {
231 "sendStringCommand() failed, cannot set binary output");
232 return false;
233 }
234
236 {
238 "recvStringCommand() failed, cannot set binary output");
239 return false;
240 }
241
242 if (checkErrorVN(recvString.data()) != 0)
243 {
244 LOG_WARN(logger, "Error while setting binary output: {}",
245 recvString.data());
246 return false;
247 }
248
249 return true;
250}
251
252} // namespace Boardcore
#define LOG_WARN(logger,...)
#define LOG_ERR(logger,...)
SensorErrors lastError
Definition Sensor.h:54
Driver for STM32F4 low level USART/UART peripheral.
Definition USART.h:170
void clearQueue()
Clears the rxQueue.
Definition USART.cpp:616
bool init() override
Initialize the sensor.
bool selfTest() override
Check if the sensor is working.
VN100Serial(USART &usart, int baudrate, CRCOptions crc, std::chrono::milliseconds timeout)
Constructor.
VN100SerialData sampleImpl() override
Sample action implementation.
uint8_t checkErrorVN(const char *message)
Check if the message received from the sensor contains an error.
uint16_t calculateChecksum16(const uint8_t *message, int length)
Calculate the 16bit array on the given array.
bool setCrc(bool waitResponse=true)
Sets the user selected crc method.
static const uint8_t recvStringMaxDimension
Maximum size of the receiving string.
bool verifyModelNumber(const char *expectedModelNumber)
Verify the model number of the sensor.
bool disableAsyncMessages(bool waitResponse)
Disables the async messages that the sensor is default configured to send at 40Hz on startup.
std::array< char, recvStringMaxDimension > recvString
Buffer used to store the string received from the sensor.
bool recvStringCommand(char *command, int maxLength)
Receives a command from the sensor but swaps the first with a \0 to close the message.
bool configUserSerialPort()
Configures the user defined serial communication.
void configDefaultSerialPort()
Configures the default serial communication.
bool sendStringCommand(std::string command)
Sends the command to the sensor with the correct checksum added so '*' symbol is not needed at the en...
USART & usart
Serial interface that is needed to communicate with the sensor via ASCII codes.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
SensorErrors
Generic error codes that a sensor can generate.
Definition SensorData.h:38
@ INVALID_WHOAMI
Definition SensorData.h:40