Skip to content

Commit 46b20be

Browse files
committed
First commit
1 parent b4ce410 commit 46b20be

File tree

6 files changed

+153
-1
lines changed

6 files changed

+153
-1
lines changed

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,42 @@
11
# arduino_pps_gprmc_time_sync
2-
Use Arduino Uno to simulate a GPS module, sending PPS pulse and GPRMC to Lidar
2+
3+
Use Arduino Uno to simulate a GPS module, sending PPS pulse and GPRMC message to Lidar.
4+
5+
## Verified Platform
6+
- Arduino Uno
7+
- Velodyne Lidar VLP-16
8+
- ROS 2 Foxy with VLP-16 driver https://github.com/ros-drivers
9+
10+
## Wiring Connection
11+
12+
| VLP-16 | Arduino |
13+
| ---- | ---- |
14+
| Ground | GND |
15+
| GPS PULSE | Pin#8 |
16+
| GPS RECEIVE | Pin#11 |
17+
18+
## VLP-16 Configuraition
19+
20+
Make sure the parameter `gps_time` in yaml file is set to **true** to enable time sync.
21+
22+
![](resource/vlp16_gps_time.png)
23+
24+
## Test Result
25+
26+
- VLP-16 web interface
27+
28+
It is successfully synchronized if you see the coordinates of **GPS Position** and locked **PPS** status.
29+
30+
![](resource/vlp16_pps_locked.jpg)
31+
32+
- VLP-16 ROS 2 timestamp
33+
34+
If the `gps_time` parameter is set, then you will see the time jump after time synchronized.
35+
36+
![](resource/vlp16_time_sync_stamp.jpg)
37+
38+
- GPRMC debug message
39+
40+
You can enable the debug messages in Arduino code to monitor the GPRMC.
41+
42+
![](resource/arduino_serial_monitor.png)

resource/arduino_serial_monitor.png

124 KB
Loading

resource/vlp16_gps_time.png

39.3 KB
Loading

resource/vlp16_pps_locked.jpg

87.5 KB
Loading

resource/vlp16_time_sync_stamp.jpg

101 KB
Loading
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#include <SoftwareSerial.h>
2+
3+
const byte pps_pin = 8;
4+
const byte msg_pin = 9;
5+
const byte rx_pin = 10;
6+
const byte tx_pin = 11;
7+
const bool inverse_logic = true;
8+
SoftwareSerial gprmc_conn(rx_pin, tx_pin, inverse_logic);
9+
10+
const unsigned int trigger_freq = 1;
11+
const unsigned long dt = 1000000 / trigger_freq; // => dt = 1 sec
12+
const unsigned long dt_pps_pull_low = dt + 100000; // => dt + 100ms
13+
const unsigned long dt_sent_gprmc = dt_pps_pull_low + 250000; // => dt_pps_pull_low + 100ms
14+
unsigned long timestamp;
15+
unsigned long trigger_start_time;
16+
unsigned long ts_pps_high;
17+
unsigned long ts_pps_low;
18+
unsigned long ts_msg_high;
19+
unsigned long ts_msg_low;
20+
unsigned long i;
21+
22+
// Start timestamp: HH:MM:SS
23+
int hh = 00;
24+
int mm = 01;
25+
int ss = 02;
26+
// GPS coordinates from Taipei
27+
char pos_latitude[] = "25.04776";
28+
char pos_longitude[] = "121.53185";
29+
30+
void setup() {
31+
pinMode(rx_pin, INPUT);
32+
pinMode(tx_pin, OUTPUT);
33+
pinMode(pps_pin, OUTPUT); // PPS
34+
pinMode(msg_pin, OUTPUT); // Indicator of msg_sent
35+
Serial.begin(9600);
36+
gprmc_conn.begin(9600);
37+
// gprmc_conn.println("Hello World!");
38+
trigger_start_time = micros();
39+
}
40+
41+
void loop() {
42+
char buffer[128];
43+
byte CRC = 0;
44+
45+
timestamp = micros() - trigger_start_time;
46+
if (timestamp >= dt*i + dt_sent_gprmc)
47+
{
48+
digitalWrite(msg_pin, HIGH);
49+
i += 1;
50+
if (ss == 59)
51+
{
52+
ss = 0;
53+
if (mm == 59)
54+
{
55+
mm = 0;
56+
hh += 1;
57+
}
58+
else mm += 1;
59+
}
60+
else ss += 1;
61+
62+
ts_msg_high = micros();
63+
64+
// Prepare GPRMC msg
65+
sprintf(buffer, "GPRMC,%02d%02d%02d,A,%s,N,%s,E,022.4,084.4,070423,,A", hh, mm, ss, pos_latitude, pos_longitude);
66+
for (byte x = 0; x < strlen(buffer); x++) {
67+
// XOR every character in between '$' and '*'
68+
CRC = CRC ^ buffer[x];
69+
}
70+
71+
// Send GPRMC msg
72+
gprmc_conn.print("$");
73+
gprmc_conn.print(buffer);
74+
gprmc_conn.print("*");
75+
gprmc_conn.print(CRC, HEX);
76+
gprmc_conn.println();
77+
78+
digitalWrite(msg_pin, LOW);
79+
ts_msg_low = micros();
80+
81+
#if 0
82+
// Print Debug Messages
83+
Serial.print("PPS at: ");
84+
Serial.print(ts_pps_high);
85+
Serial.print(" PPS low after: ");
86+
Serial.print(ts_pps_low-ts_pps_high);
87+
Serial.print(" MSG high after: ");
88+
Serial.print(ts_msg_high-ts_pps_high);
89+
Serial.print(" MSG low after: ");
90+
Serial.print(ts_msg_low-ts_pps_high);
91+
Serial.print(" $");
92+
Serial.print(buffer);
93+
Serial.print("*");
94+
Serial.print(CRC, HEX);
95+
Serial.println();
96+
#endif
97+
98+
}
99+
else if (timestamp >= dt*i + dt_pps_pull_low)
100+
{
101+
// Pull pps to low
102+
digitalWrite(pps_pin, LOW);
103+
ts_pps_low = micros();
104+
}
105+
else if (timestamp >= dt*i)
106+
{
107+
// Pull pps to high
108+
digitalWrite(pps_pin, HIGH);
109+
ts_pps_high = micros();
110+
}
111+
112+
}

0 commit comments

Comments
 (0)