I suppose your question is not about the format (although you need to know if the listener expects like RMC, ZDA...) but more about the hardware side of things.
with NMEA-0183 the talker is an RS-422 style differential line driver, and the listener as an opto-isolated differential receiver.
The receiver side is trivial, which is why you have no problems finding tutos to cover reading TTL serial into a microcontroller.
The transmit side is harder, since building a proper talker means adding real line driver hardware.
The minimum hardware for a talker is one small differential line driver chip between the microcontroller UART TX pin and the two wires going out to the bus (and a few extra components likely a cap or something - I'm a software guy but I'm sure you can find that out). A MAX3488E or SN65HVD3082E would probably do the job and both are 3.3V RS-422 or RS-485 transceivers that would work directly off an ESP32 logic level.
The driver enable pin needs to be tied high permanently as you’re only ever transmitting and never listening back. The chip’s A and B output pins become the NMEA-0183 pair.
If this is for boating, a shared ground wire alongside the 2 wires is worth adding too, since I think to remember old marine listener hardware expects one even though the differential signal does not strictly need it.
(I’ve moved all my gears to NMEA-2000 so don't really remember all the details)
EDIT
I'm assuming that the existing GPS modules delivered a standard serial output, say at 9600 baud, to your clock and you are going to tap in there somehow with the ESP32.
Can you clarify if you are asking about the hardware circuit to send out a phrase which includes the time or if you are asking about formatting such a phrase ?
Note this is a 3V3 device (not 5V) and is one transceiver.
This can work on 5V
You might also consider:
Which gives you 4 line drivers in one package. The corresponding receivers are AM26LS32. I use these for something similar to what you are proposing: Inspired by the GPS sentence idea with $xxyyy as the start I use $xxx as the start for conveying the time, temperature and other measurement, and and TLP2768 opto isolators to receive the data.
Of course this is all pure, but nevertheless interesting, speculation at the moment, until the OP provides further details, but if the nixie clocks have a module such as this: GPS Time Receiver For Nixie Clock [GPS7] - £29.95 - PV Electronics and, for reasons which I hope will become clear, the OP wants to replace it with an ESP32 then, as far as I can see, it should be quite straightforward. A bit of level shifting, perhaps, and sending a timestamp message in the form of an NMEA sentence at regular intervals.
So to clear the situation up, I have several old Mr. Nixie clocks.
Till today I use just the internal clockwork to run them, but I would like to have them controlled by an external time signal.
They should work with an external GPS module like 6v6gt linked in his last post, since it has a headphone jack for this.
Since my clocks are not close to a window or so, I would prefer to use WiFi / NTP as a source.
Unfortunateley, the manual just says this (besides it needs NMEA0183):#
Radio Frequency Time or GPS Receiver
The clock can automatically synchronise time from DCF (Europe), MSF (UK) and WWVB (US).
The clock can also receive time from a GPS receiver that transmits information using NMEA-0183 protocol with $GPRMC
sentence; e.g. the wired BR-355 or the wireless GPS connection.
1. Set option 12 for: 1 = DCF, 2 = WWVB, 3 = MSF, 4 = GPS
• If using GPS, set the baud rate in option 13 (normally 4.8 kbps).
2. Set option 14 and 15 for the hours and minutes your time zone on standard time (no DST) is offset from the
synchronization source. This are usually only a whole hours:
• Germany is 1 hour plus offset (non DST) from UTC time transmitted by the GPS.
• UK is 1 hour minus offset from the time transmitted by the German DCF signal.
• France has no offset from the time transmitted by the German DCF signal.
3. Set option 16 to identify if your offset must be added or subtracted from the time source.
4. If you’re using WWVB source and you don’t need require automatic DST adjustment, set option 17 to “1”
5. Set option 23 to select between hourly seek and daily seek in DCF / WWVB / MSF modes. Daily seek is
recommended.
6. If you have selected daily seek, use option 24 to set the time of the daily seek.
7. Leave option 25 set to “1” to turn off the tubes during seek. This prevents interferences by the HV generator.
Set this option to “0” when using GPS source.
So my question was regarding general suggestions and examples how to go with it.
Since I am some kind with these signals (I worked as integrator for nautical Wempe network systems), I can summerise my PoV till now on this:
Yes, I need a RS422 signal as output.
I think this might be the easiest way for me:
The NMEA sentences rom post #4 looks exactly like what I would need.
So what I need to do is:
-Log into Wifi
-Grab NTP signal
-Parse it to NMEA sentences (I have no idea about that logic)
-Send it out via the module as RS422
then it's just a matter of getting the right time from NTP and building the sentence and send it out over Serial
Serial monitor will show
NTP to GPRMC demo
IP address obtained = 10.10.0.2
NTP synced
$GPRMC,170439.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*38
$GPRMC,170440.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*36
$GPRMC,170441.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*37
$GPRMC,170442.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*34
$GPRMC,170443.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*35
$GPRMC,170444.00,A,0000.0000,N,00000.0000,E,0.0,0.0,071126,,*32
...
click to see the code
#include <WiFi.h>
#include <esp_sntp.h>
const char *ssid = "Wokwi-GUEST";
const char *wifiPassword = "";
const char *ntpServer = "fr.pool.ntp.org"; // French one, use "pool.ntp.org" to be generic
bool ntpSyncDone = false;
void ntpSyncCallback(struct timeval *tv) {
ntpSyncDone = true;
Serial.println("NTP synced");
}
void wifiStationGotIp(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("IP address obtained = ");
Serial.println(WiFi.localIP());
}
void wifiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("Disconnected from network, attempting to reconnect");
WiFi.begin(ssid, wifiPassword);
}
// builds and sends a $GPRMC sentence from the current system time
void sendGprmc() {
time_t now = time(NULL);
struct tm *utcTime = gmtime(&now);
char sentence[96];
char body[80];
// position is not available from NTP, so a fixed null position is sent with a valid "A" status
// you can also hard code your actual location here instead of the null one, if you want the sentence to carry it
snprintf(body, sizeof(body),
"GPRMC,%02d%02d%02d.00,A,0000.0000,N,00000.0000,E,0.0,0.0,%02d%02d%02d,,",
utcTime->tm_hour, utcTime->tm_min, utcTime->tm_sec,
utcTime->tm_mday, utcTime->tm_mon + 1, utcTime->tm_year % 100);
uint8_t checksum = 0;
for (size_t i = 0; i < strlen(body); i++) {
checksum ^= body[i];
}
snprintf(sentence, sizeof(sentence), "$%s*%02X\r\n", body, checksum);
Serial.print(sentence);
}
void setup() {
Serial.begin(115200);
WiFi.onEvent(wifiStationGotIp, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.onEvent(wifiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
configTzTime("UTC0", ntpServer); // GPRMC time is UTC, no timezone offset
sntp_set_time_sync_notification_cb(ntpSyncCallback);
WiFi.begin(ssid, wifiPassword, 6); // get rid of the 6 if not on wokwi
Serial.println("NTP to GPRMC demo");
}
void loop() {
static unsigned long lastSend = 0;
if (ntpSyncDone && millis() - lastSend >= 1000) {
sendGprmc();
lastSend = millis();
}
}
I guess you would use the same jack socket if you use the DCF radio option and these modules sometimes output a very low voltage, say 1.5v, so it could well be that you need nothing special between the ESP32 and the jack socket, however, I'd start with a resistor of say 1k and a common ground.
Your serial output has to conform to whatever options you can set here:
If using GPS, set the baud rate in option 13 (normally 4.8 kbps)
Looking further, I found this for one model of the "Mr. Nixie" clock: https://www.manualslib.com/manual/1744380/Mr-Nixie-Sv410.html?page=10 . I'm not sure if this matches yours, though. The DCF/ GPS socket is on the left. There appears to be a solder jumper possibly for inverting the signal. The direct signal goes directly to a pin of a PIC microcontroller which is powered at 5v so here it looks like the ESP output would have to level shifted to 5v. Note that 5v appears also on that socket.
Or maybe also try to find some documentation which more closely matches your exact clock.
Incidentally, there are existing projects for generating a DCF77 time signal using an ESP, some of which can even generate the 77.5Khz radio signal. Googling for "dcf77 signal generation by esp" gets a number of hits. But I'm sure also that @J-M-L could also enhance his code to provide a DCF77 signal emulator to give you another option.
EDIT
Looking at the manual extract that the OP presented, the daylight saving time handling of the clock seems somewhat crude. There doesn't appear, for example, to be any way of adjusting the date and time of the DST switch/switch back. It may be better to do time zone conversion on the ESP32 and roll that into in the NMEA sentence . The clock would then be configured as if it were in a UTC timezone with a 0 dst offset.
Conclusion (with all the usual caveats) is that a simple (maybe not even level shifted) serial output from the ESP32 should be enough. Either a hardware Serial port or software serial should do.
I'm assuming that you want to use the existing jack socket and don't want to make invasive changes to the circuit board. I'd probably wire it like this and leave the polarity jumper connected between positions B and C. I'm also assuming that the optional module ASK-RXB2 is not installed.
This level shifts from 3v3 to the 5v used in the rest of the circuit. Of course, there are other ways of doing it but this should work. The connection ESP32_TX is from a second UART (or software serial pin) on the ESP32 and the primary UART should be reserved for debug output.
It looks like Daylight Saving Time (DST) change is not automatic and you must press a button to manually make the change. Is that so and do you want to keep it like this ?