Great success with decoding the 9600bps serial data on the RO line. I've successfully identified the function of 17 of the 35 data fields. Many of them are probably just padding, too. Here's the breakdown, based on the message sent by the MCU and a small arduino sketch that modifies it.
- Messages begin with an LF (0x0A) and end with 0x8D.
- 34 data fields, such as time, date, temperature, etc and padding fields are separated by 0xAC. They are not indexed, so must all be sent in order in each message.
- Data are ASCII numbers, 0x30 - 0x39. Data contain a "don't care" bit, so sometimes are sent by the MCU as 0xB0 - 0xB9. No difference in functionality is observed. My code just uses ASCII.
- Data may have multiple digits (variable word length); leading zeroes are ignored.
- Some data fields, e.g. rainfall, are measured in hundredths, not base units. The decimal is inferred.
- Range of displayable values is determined by how the processor handles the data.
- Rainfall, for instance, is maxed at 65535 hundredths of an inch, indicating it's written directly to a uint16_t.
- Hours are transmitted in 24-hr format, but displayed in AM/PM format. If >12, subtract 12, set PM). As a result,
- Null bytes don't bother anything, so storing and sending strings/char*s are acceptable.
Here is a little arduino sketch that showcases the data format, and sends it out using SoftwareSerial.
#include <SoftwareSerial.h>
SoftwareSerial softSerial(9, 10); // RX, TX. Connect TX to Display's RO.
#define START "\x0A"
#define EOM "\x8D"
#define datalen 36
char* data[datalen] = {
START,
"12\xAC", //hours, 24-hr format. If >12, add 12. "111\xAC"=99.
"34\xAC", //Minutes, max 99.
"56\xAC", //First field (US month)
"78\xAC", //Second field (US day)
"01744\xAC", //ind temp, 1744=0F
"01744\xAC", //outside temp
"01744\xAC", //aux temp
"979\xAC", //unk
"4439\xAC", //humidity
"0\xAC", //unk
"07647\xAC", //barometer
"0\xAC", //unk
"65535\xAC", //daily rainfall
"00000\xAC", //monthly rainfall
"00000\xAC", //yearly rainfall
"000\xAC", //Wind speed in km/hr. (display only has 2 digits, but truncates >99)
"00\xAC", //Wind direction. 15 LEDs, indexed clockwise. W=12. Wraps around. ESE lights two LEDs - I think it's a bug in the factory ROM!
"0\xAC", //unk
"00\xAC", //Avg wind speed
"09\xAC", //Avg wind direction
"53\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"65000\xAC", //pressure rate, and associated rising/falling LEDs
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
"0\xAC", //unk
EOM
};
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
softSerial.begin(9600);
}
void loop() { // run over and over
for (int i = 0; i < datalen; i++) {
//Do not use serial debug messages in the same timing loop as the live data. It breaks timing.
Serial.print(i, DEC);
Serial.print(": ");
Serial.println(data[i]);
// 0xAC in extended ASCII is "¬". EOM looks like "�". Line feed will print an empty line.
}
digitalWrite(LED_BUILTIN, HIGH); //mimics MCU LED, but doesn't pulse RS485
for (int i = 0; i < datalen; i++) {
softSerial.print(data[i]);
}
digitalWrite(LED_BUILTIN, LOW);
delay(100); //This can possibly be lower, but cannot be zero
}
I've also characterized a couple of the calculated fields, but not all of them. Here's what I've got, where 'x' is the serial value:
- Temperatures (out, ind, aux)
- x = 1000 * (25*F + 368) / 211
- x = 1000 * (45*C + 1168) / 211
- Range -15 - 260 F
- Pressure
- x = (11471 * (inhg - 28)) / 3
- range is 28.00 - 31.44 inhg, which is sufficient for most of this planet.
- TBD
- Humidity
- Pressure rate
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.