CODE IS AI WRITTEN!
This MicroPython code creates an atomic clock decoder that can receive and interpret time signals from radio-controlled atomic clocks (like WWVB in North America or DCF77 in Europe). Here's what it does:
Signal Decoding: Uses interrupt-driven signal processing to decode the atomic clock's pulse patterns into binary data
Time Parsing: Extracts date and time information from the decoded signal
Timezone Support: Allows you to set your local timezone offset from UTC
Time Display: Provides functions to get and display the current time
To use it:
Connect an atomic clock receiver module to a GPIO pin on your MicroPython board (default is pin 4)
Initialize the decoder with your timezone offset
Run the main loop to start decoding signals
You can adjust the timezone at any time using the set_timezone() method.
Note that the exact decoding logic may need adjustment based on your specific atomic clock signal format (DCF77, WWVB, MSF, etc.), as each uses slightly different encoding schemes. The provided code is based on the DCF77 format but includes comments to help you adapt it to other formats.
Would you like me to explain any specific part of the code in more detail? N
yes please
I'll walk through the key components of the atomic clock decoder code in detail: Signal Decoding Process
The heart of the decoder is in the _edge_detected method, which is triggered by interrupts when signal transitions occur:
python
def _edge_detected(self, pin): """Interrupt handler for signal edges""" now = utime.ticks_ms() duration = utime.ticks_diff(now, self.last_edge) self.last_edge = now
# Typical pulse widths for atomic clock signals
if 80 <= duration <= 120:
# ~100ms pulse = 0 bit
self.bits.append(0)
elif 180 <= duration <= 220:
# ~200ms pulse = 1 bit
self.bits.append(1)
elif 1800 <= duration <= 2200:
# ~2000ms pulse = start of new minute
self._process_frame()
self.bits = []
self.current_second = 0
This code measures the duration between signal transitions to determine if it's:
A short pulse (~100ms) representing a '0' bit
A longer pulse (~200ms) representing a '1' bit
A very long pulse (~2000ms) indicating the start of a new minute frame
Time Data Extraction
Once a full minute's worth of data is collected (usually 59-60 bits), _process_frame() decodes it:
python
def _process_frame(self): """Process a complete frame of data""" if len(self.bits) < 59: print("Incomplete frame, discarding") return
try:
# Extract time data from bits (example for DCF77 format)
minute = self._bcd_to_dec(self.bits[21:28])
hour = self._bcd_to_dec(self.bits[29:35])
day = self._bcd_to_dec(self.bits[36:42])
weekday = self._bcd_to_dec(self.bits[42:45])
month = self._bcd_to_dec(self.bits[45:50])
year = 2000 + self._bcd_to_dec(self.bits[50:58])
This extracts specific bit ranges that encode different time elements. The bit positions shown here are for DCF77 (European signal), but would need adjustment for other signal formats like WWVB (North America). BCD Conversion
Time data in atomic clock signals is often encoded in Binary-Coded Decimal (BCD) format, which this helper method decodes:
python
def _bcd_to_dec(self, bits): """Convert BCD bits to decimal""" result = 0 factor = 1
for i in range(len(bits) - 1, -1, -1):
if i % 4 == 3:
factor = 1
if bits[i]:
result += factor
factor *= 2
if factor > 8:
factor = 10
This converts groups of 4 bits from binary to decimal digits, handling the BCD encoding where each decimal digit (0-9) is represented by 4 bits. Timezone Management
The timezone handling allows flexibility for users in different regions:
python
def set_timezone(self, offset): """Set the timezone offset in hours from UTC""" self.timezone_offset = offset
# Update current time with new timezone
dt = self.rtc.datetime()
hour = (dt[4] - self.timezone_offset + offset) % 24
self.rtc.datetime((dt[0], dt[1], dt[2], dt[3], hour, dt[5], dt[6], dt[7]))
This adjusts the displayed time by modifying the hour value while keeping internal time accurate. Main Loop
The run() method creates the continuous operational loop:
python
def run(self): """Main loop to update time and handle signal processing""" last_second = -1 while True: current_second = utime.time() % 60 if current_second != last_second: last_second = current_second if current_second % 10 == 0: # Display time every 10 seconds self.display_time() utime.sleep_ms(100)
This periodically displays the time while the signal processing happens in the background via interrupts. Adapting for Different Signal Formats
To adapt this code for different atomic clock signals:
For WWVB (US): You'd need to adjust the bit positions in _process_frame() since WWVB uses a different bit layout than DCF77
For JJY (Japan): The encoding is different, using multiple pulses per second
For MSF (UK): Similar to DCF77 but with different bit positions
The core interrupt-handling mechanism would remain similar, but the pulse duration thresholds and bit decoding logic would need adjustment based on the specific protocol.
Is there any specific part of the code you'd like me to explain in more detail? N
Can you adapt this For WWVB (US)?
I'll adapt the atomic clock decoder specifically for the WWVB signal format used in the United States.
The code has been specifically adapted for the WWVB signal format used in the United States. Here are the key changes: WWVB-Specific Adaptations:
Signal Decoding:
Changed the pulse width detection to match WWVB's unique format:
0.2s low + 0.8s high = binary '0'
0.5s low + 0.5s high = binary '1'
0.8s low + 0.2s high = position marker (not a data bit)
Data Format:
Updated the data extraction to match WWVB's bit layout:
Minutes: bits 1-8
Hours: bits 12-19
Day of Year: bits 22-39 (WWVB uses day-of-year rather than month/day)
Year: bits 45-52 (last two digits)
DST indicators: bits 55-56
Daylight Saving Time:
Added DST detection and handling according to WWVB's encoding:
Bits 55-56 indicate DST status
Automatically adjusts clock time when DST is in effect
US-Centric Features:
Default timezone is EST (-5)
Added get_timezones() method that returns common US timezones
Converts day-of-year to month/day for display
Enhanced Output:
Time display includes day of week and DST indicator
Added more detailed debug information
How to Use:
Connect a WWVB receiver module to a GPIO pin on your MicroPython board (default is pin 4)
Initialize with your timezone offset (defaults to EST):
python
clock = WWVBClockDecoder(signal_pin=4, timezone_offset=-5) # EST
Optionally change the timezone:
python
clock.set_timezone(-8) # Set to PST
Run the decoder:
python
clock.run()
The decoder will continuously monitor for WWVB signals, and once it receives a valid time frame, it will update the internal RTC and display the current time every 10 seconds.
This implementation handles the unique aspects of WWVB, including its BCD encoding, day-of-year format, and DST indicators, making it appropriate for use throughout the United States. Claude can make mistakes. Please double-check responses.