-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
153 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,42 @@ | ||
# arduino_pps_gprmc_time_sync | ||
Use Arduino Uno to simulate a GPS module, sending PPS pulse and GPRMC to Lidar | ||
|
||
Use Arduino Uno to simulate a GPS module, sending PPS pulse and GPRMC message to Lidar. | ||
|
||
## Verified Platform | ||
- Arduino Uno | ||
- Velodyne Lidar VLP-16 | ||
- ROS 2 Foxy with VLP-16 driver https://github.com/ros-drivers | ||
|
||
## Wiring Connection | ||
|
||
| VLP-16 | Arduino | | ||
| ---- | ---- | | ||
| Ground | GND | | ||
| GPS PULSE | Pin#8 | | ||
| GPS RECEIVE | Pin#11 | | ||
|
||
## VLP-16 Configuraition | ||
|
||
Make sure the parameter `gps_time` in yaml file is set to **true** to enable time sync. | ||
|
||
![](resource/vlp16_gps_time.png) | ||
|
||
## Test Result | ||
|
||
- VLP-16 web interface | ||
|
||
It is successfully synchronized if you see the coordinates of **GPS Position** and locked **PPS** status. | ||
|
||
![](resource/vlp16_pps_locked.jpg) | ||
|
||
- VLP-16 ROS 2 timestamp | ||
|
||
If the `gps_time` parameter is set, then you will see the time jump after time synchronized. | ||
|
||
![](resource/vlp16_time_sync_stamp.jpg) | ||
|
||
- GPRMC debug message | ||
|
||
You can enable the debug messages in Arduino code to monitor the GPRMC. | ||
|
||
![](resource/arduino_serial_monitor.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#include <SoftwareSerial.h> | ||
|
||
const byte pps_pin = 8; | ||
const byte msg_pin = 9; | ||
const byte rx_pin = 10; | ||
const byte tx_pin = 11; | ||
const bool inverse_logic = true; | ||
SoftwareSerial gprmc_conn(rx_pin, tx_pin, inverse_logic); | ||
|
||
const unsigned int trigger_freq = 1; | ||
const unsigned long dt = 1000000 / trigger_freq; // => dt = 1 sec | ||
const unsigned long dt_pps_pull_low = dt + 100000; // => dt + 100ms | ||
const unsigned long dt_sent_gprmc = dt_pps_pull_low + 250000; // => dt_pps_pull_low + 100ms | ||
unsigned long timestamp; | ||
unsigned long trigger_start_time; | ||
unsigned long ts_pps_high; | ||
unsigned long ts_pps_low; | ||
unsigned long ts_msg_high; | ||
unsigned long ts_msg_low; | ||
unsigned long i; | ||
|
||
// Start timestamp: HH:MM:SS | ||
int hh = 00; | ||
int mm = 01; | ||
int ss = 02; | ||
// GPS coordinates from Taipei | ||
char pos_latitude[] = "25.04776"; | ||
char pos_longitude[] = "121.53185"; | ||
|
||
void setup() { | ||
pinMode(rx_pin, INPUT); | ||
pinMode(tx_pin, OUTPUT); | ||
pinMode(pps_pin, OUTPUT); // PPS | ||
pinMode(msg_pin, OUTPUT); // Indicator of msg_sent | ||
Serial.begin(9600); | ||
gprmc_conn.begin(9600); | ||
// gprmc_conn.println("Hello World!"); | ||
trigger_start_time = micros(); | ||
} | ||
|
||
void loop() { | ||
char buffer[128]; | ||
byte CRC = 0; | ||
|
||
timestamp = micros() - trigger_start_time; | ||
if (timestamp >= dt*i + dt_sent_gprmc) | ||
{ | ||
digitalWrite(msg_pin, HIGH); | ||
i += 1; | ||
if (ss == 59) | ||
{ | ||
ss = 0; | ||
if (mm == 59) | ||
{ | ||
mm = 0; | ||
hh += 1; | ||
} | ||
else mm += 1; | ||
} | ||
else ss += 1; | ||
|
||
ts_msg_high = micros(); | ||
|
||
// Prepare GPRMC msg | ||
sprintf(buffer, "GPRMC,%02d%02d%02d,A,%s,N,%s,E,022.4,084.4,070423,,A", hh, mm, ss, pos_latitude, pos_longitude); | ||
for (byte x = 0; x < strlen(buffer); x++) { | ||
// XOR every character in between '$' and '*' | ||
CRC = CRC ^ buffer[x]; | ||
} | ||
|
||
// Send GPRMC msg | ||
gprmc_conn.print("$"); | ||
gprmc_conn.print(buffer); | ||
gprmc_conn.print("*"); | ||
gprmc_conn.print(CRC, HEX); | ||
gprmc_conn.println(); | ||
|
||
digitalWrite(msg_pin, LOW); | ||
ts_msg_low = micros(); | ||
|
||
#if 0 | ||
// Print Debug Messages | ||
Serial.print("PPS at: "); | ||
Serial.print(ts_pps_high); | ||
Serial.print(" PPS low after: "); | ||
Serial.print(ts_pps_low-ts_pps_high); | ||
Serial.print(" MSG high after: "); | ||
Serial.print(ts_msg_high-ts_pps_high); | ||
Serial.print(" MSG low after: "); | ||
Serial.print(ts_msg_low-ts_pps_high); | ||
Serial.print(" $"); | ||
Serial.print(buffer); | ||
Serial.print("*"); | ||
Serial.print(CRC, HEX); | ||
Serial.println(); | ||
#endif | ||
|
||
} | ||
else if (timestamp >= dt*i + dt_pps_pull_low) | ||
{ | ||
// Pull pps to low | ||
digitalWrite(pps_pin, LOW); | ||
ts_pps_low = micros(); | ||
} | ||
else if (timestamp >= dt*i) | ||
{ | ||
// Pull pps to high | ||
digitalWrite(pps_pin, HIGH); | ||
ts_pps_high = micros(); | ||
} | ||
|
||
} |