Frequency counter using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.
Dependencies: QEI DRV8830 PID ADT7410 TextLCD Frq_cuntr_Nucleo-F746ZG RingBuffer
Fork of Frequency_Counter_w_GPS_1PPS by
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
main.cpp@11:20e7a45f1448, 2015-01-02 (annotated)
- Committer:
- kenjiArai
- Date:
- Fri Jan 02 10:40:50 2015 +0000
- Revision:
- 11:20e7a45f1448
- Parent:
- 9:e98e94ba17f9
- Child:
- 13:1041596c416c
Change serial communication using iSerial. Bug fix for temperature control.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 5:af9fa3d0731c | 1 | /* |
kenjiArai | 8:7b033903c8fb | 2 | * mbed Application program / Frequency Counter with GPS 1PPS Compensation |
kenjiArai | 5:af9fa3d0731c | 3 | * |
kenjiArai | 5:af9fa3d0731c | 4 | * Copyright (c) 2014 Kenji Arai / JH1PJL |
kenjiArai | 5:af9fa3d0731c | 5 | * http://www.page.sannet.ne.jp/kenjia/index.html |
kenjiArai | 5:af9fa3d0731c | 6 | * http://mbed.org/users/kenjiArai/ |
kenjiArai | 5:af9fa3d0731c | 7 | * Created: October 18th, 2014 |
kenjiArai | 11:20e7a45f1448 | 8 | * Revised: January 2nd, 2015 |
kenjiArai | 5:af9fa3d0731c | 9 | * |
kenjiArai | 5:af9fa3d0731c | 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
kenjiArai | 5:af9fa3d0731c | 11 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE |
kenjiArai | 5:af9fa3d0731c | 12 | * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
kenjiArai | 5:af9fa3d0731c | 13 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
kenjiArai | 5:af9fa3d0731c | 14 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
kenjiArai | 5:af9fa3d0731c | 15 | */ |
mio | 0:c988614df67a | 16 | |
kenjiArai | 6:44c2bcbdd77b | 17 | #define USE_COM // use Communication with PC(UART) |
kenjiArai | 9:e98e94ba17f9 | 18 | #define SET_RTC |
kenjiArai | 9:e98e94ba17f9 | 19 | //#define USE_DEBUG |
kenjiArai | 6:44c2bcbdd77b | 20 | |
kenjiArai | 5:af9fa3d0731c | 21 | // Include --------------------------------------------------------------------------------------- |
mio | 0:c988614df67a | 22 | #include "mbed.h" |
kenjiArai | 9:e98e94ba17f9 | 23 | #include "rtos.h" |
kenjiArai | 9:e98e94ba17f9 | 24 | #include "TextLCD.h" |
kenjiArai | 9:e98e94ba17f9 | 25 | #include "DRV8830.h" |
kenjiArai | 9:e98e94ba17f9 | 26 | #include "ADT7410.h" |
kenjiArai | 9:e98e94ba17f9 | 27 | #include "PID.h" |
kenjiArai | 8:7b033903c8fb | 28 | #include "frq_cuntr_full.h" |
kenjiArai | 9:e98e94ba17f9 | 29 | #include "CheckRTC.h" |
kenjiArai | 11:20e7a45f1448 | 30 | #include "iSerial.h" |
kenjiArai | 9:e98e94ba17f9 | 31 | #include "gps.h" |
kenjiArai | 8:7b033903c8fb | 32 | |
kenjiArai | 8:7b033903c8fb | 33 | using namespace Frequency_counter; |
mio | 0:c988614df67a | 34 | |
kenjiArai | 5:af9fa3d0731c | 35 | // Definition ------------------------------------------------------------------------------------ |
kenjiArai | 5:af9fa3d0731c | 36 | #ifdef USE_COM |
kenjiArai | 5:af9fa3d0731c | 37 | #define BAUD(x) pc.baud(x) |
kenjiArai | 5:af9fa3d0731c | 38 | #define GETC(x) pc.getc(x) |
kenjiArai | 5:af9fa3d0731c | 39 | #define PUTC(x) pc.putc(x) |
kenjiArai | 5:af9fa3d0731c | 40 | #define PRINTF(...) pc.printf(__VA_ARGS__) |
kenjiArai | 5:af9fa3d0731c | 41 | #define READABLE(x) pc.readable(x) |
kenjiArai | 5:af9fa3d0731c | 42 | #else |
kenjiArai | 5:af9fa3d0731c | 43 | #define BAUD(x) {;} |
kenjiArai | 5:af9fa3d0731c | 44 | #define GETC(x) {;} |
kenjiArai | 5:af9fa3d0731c | 45 | #define PUTC(x) {;} |
kenjiArai | 5:af9fa3d0731c | 46 | #define PRINTF(...) {;} |
kenjiArai | 5:af9fa3d0731c | 47 | #define READABLE(x) {;} |
kenjiArai | 5:af9fa3d0731c | 48 | #endif |
mio | 1:2a347c40b1da | 49 | |
kenjiArai | 9:e98e94ba17f9 | 50 | #ifdef USE_DEBUG |
kenjiArai | 9:e98e94ba17f9 | 51 | #define DEBUGBAUD(x) pc.baud(x) |
kenjiArai | 9:e98e94ba17f9 | 52 | #define DEBUG(...) pc.printf(__VA_ARGS__) |
kenjiArai | 9:e98e94ba17f9 | 53 | #else |
kenjiArai | 9:e98e94ba17f9 | 54 | #define DEBUGBAUD(x) {;} |
kenjiArai | 9:e98e94ba17f9 | 55 | #define DEBUG(...) {;} |
kenjiArai | 9:e98e94ba17f9 | 56 | #endif |
kenjiArai | 9:e98e94ba17f9 | 57 | |
kenjiArai | 9:e98e94ba17f9 | 58 | #define CLOCK_BASE (24.999982f) |
kenjiArai | 9:e98e94ba17f9 | 59 | |
kenjiArai | 9:e98e94ba17f9 | 60 | #define GSP_BUF_B (128 * 3) |
kenjiArai | 9:e98e94ba17f9 | 61 | #define GPS_BUF_S (128 * 2) |
kenjiArai | 9:e98e94ba17f9 | 62 | |
kenjiArai | 5:af9fa3d0731c | 63 | // Object ---------------------------------------------------------------------------------------- |
kenjiArai | 9:e98e94ba17f9 | 64 | DigitalOut led_gate(LED1); |
kenjiArai | 11:20e7a45f1448 | 65 | //Serial pc(USBTX, USBRX); |
kenjiArai | 11:20e7a45f1448 | 66 | iSerial pc(USBTX, USBRX, 1024, 32); |
kenjiArai | 11:20e7a45f1448 | 67 | //Serial gps(NC, PA_10); // GPS RX |
kenjiArai | 11:20e7a45f1448 | 68 | iSerial gps(PA_9, PA_10, 32, 1024); // GPS RX |
kenjiArai | 8:7b033903c8fb | 69 | I2C i2cBus(PB_9,PB_8); // SDA, SCL |
kenjiArai | 9:e98e94ba17f9 | 70 | DRV8830 heater(i2cBus, (uint8_t)DRV8830ADDR_00); |
kenjiArai | 9:e98e94ba17f9 | 71 | ADT7410 t(i2cBus, ADT7410ADDR_NN); |
kenjiArai | 9:e98e94ba17f9 | 72 | TextLCD lcd(PB_0, PA_4, PC_0, PC_1, PC_2, PC_3, TextLCD::LCD20x4); // rs, e, d4-d7 |
kenjiArai | 9:e98e94ba17f9 | 73 | PID pid(14.0f, 50.0f, 1.5f, 1.0f); |
kenjiArai | 9:e98e94ba17f9 | 74 | // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit) |
kenjiArai | 9:e98e94ba17f9 | 75 | // PA_0,PA_1 & PB_10 use for Timer2(32bit) |
kenjiArai | 9:e98e94ba17f9 | 76 | // PA_8 & PC_7 use for MCO (Test purpose) |
kenjiArai | 9:e98e94ba17f9 | 77 | FRQ_CUNTR fc(PC_6, 1.0, CLOCK_BASE); // Input port, gate time[sec] and External clock freq. |
kenjiArai | 6:44c2bcbdd77b | 78 | |
kenjiArai | 5:af9fa3d0731c | 79 | // RAM ------------------------------------------------------------------------------------------- |
kenjiArai | 9:e98e94ba17f9 | 80 | // Freq. |
kenjiArai | 9:e98e94ba17f9 | 81 | uint32_t counter_1pps; |
kenjiArai | 9:e98e94ba17f9 | 82 | double new_frequency; |
kenjiArai | 9:e98e94ba17f9 | 83 | double base_clock_1pps; |
kenjiArai | 9:e98e94ba17f9 | 84 | // Temp Control |
kenjiArai | 9:e98e94ba17f9 | 85 | float volt = 0.0; |
kenjiArai | 9:e98e94ba17f9 | 86 | float tmp = 0; |
kenjiArai | 9:e98e94ba17f9 | 87 | float pid_val = 0; |
kenjiArai | 9:e98e94ba17f9 | 88 | uint32_t n = 0; |
kenjiArai | 9:e98e94ba17f9 | 89 | // GPS |
kenjiArai | 9:e98e94ba17f9 | 90 | uint32_t gps_status; |
kenjiArai | 9:e98e94ba17f9 | 91 | uint8_t gps_rmc_ready; |
kenjiArai | 9:e98e94ba17f9 | 92 | char GPS_Buffer[GSP_BUF_B]; //GPS data buffer |
kenjiArai | 9:e98e94ba17f9 | 93 | char MsgBuf_RMC[GPS_BUF_S]; |
kenjiArai | 9:e98e94ba17f9 | 94 | char MsgBuf_GGA[GPS_BUF_S]; |
kenjiArai | 9:e98e94ba17f9 | 95 | // Time |
kenjiArai | 9:e98e94ba17f9 | 96 | time_t seconds; |
kenjiArai | 9:e98e94ba17f9 | 97 | time_t seconds_jst; |
kenjiArai | 9:e98e94ba17f9 | 98 | struct tm t_gps; |
kenjiArai | 9:e98e94ba17f9 | 99 | // rtos |
kenjiArai | 9:e98e94ba17f9 | 100 | Queue<uint32_t, 2> queue0; |
kenjiArai | 6:44c2bcbdd77b | 101 | |
kenjiArai | 5:af9fa3d0731c | 102 | // ROM / Constant data --------------------------------------------------------------------------- |
kenjiArai | 9:e98e94ba17f9 | 103 | // 12345678901234567890 |
kenjiArai | 9:e98e94ba17f9 | 104 | static char *const msg_clear = " "; |
kenjiArai | 9:e98e94ba17f9 | 105 | static char *const msg_msg0 = "Frequency Counter "; |
kenjiArai | 9:e98e94ba17f9 | 106 | static char *const msg_msg1 = " mbed Nucleo F411RE"; |
kenjiArai | 9:e98e94ba17f9 | 107 | static char *const msg_msg2 = " by JH1PJL K.Arai"; |
kenjiArai | 9:e98e94ba17f9 | 108 | static char *const msg_msg3 = " "__DATE__" "; |
mio | 1:2a347c40b1da | 109 | |
kenjiArai | 5:af9fa3d0731c | 110 | // Function prototypes --------------------------------------------------------------------------- |
kenjiArai | 9:e98e94ba17f9 | 111 | uint32_t check_gps_ready(void); |
kenjiArai | 9:e98e94ba17f9 | 112 | void get_time_and_date(struct tm *pt); |
kenjiArai | 9:e98e94ba17f9 | 113 | void getline_gps(void); |
kenjiArai | 5:af9fa3d0731c | 114 | |
kenjiArai | 5:af9fa3d0731c | 115 | //------------------------------------------------------------------------------------------------- |
kenjiArai | 5:af9fa3d0731c | 116 | // Control Program |
kenjiArai | 5:af9fa3d0731c | 117 | //------------------------------------------------------------------------------------------------- |
kenjiArai | 9:e98e94ba17f9 | 118 | void measure_freq(void const *args) |
kenjiArai | 9:e98e94ba17f9 | 119 | { |
kenjiArai | 9:e98e94ba17f9 | 120 | while(true) { |
kenjiArai | 9:e98e94ba17f9 | 121 | if (fc.status_freq_update() != 0) { |
kenjiArai | 9:e98e94ba17f9 | 122 | new_frequency = fc.read_freq_data(); |
kenjiArai | 9:e98e94ba17f9 | 123 | queue0.put((uint32_t*)1); |
kenjiArai | 9:e98e94ba17f9 | 124 | } |
kenjiArai | 9:e98e94ba17f9 | 125 | if (fc.status_1pps() != 0) { |
kenjiArai | 9:e98e94ba17f9 | 126 | counter_1pps = fc.read_avarage_1pps(); |
kenjiArai | 9:e98e94ba17f9 | 127 | } |
kenjiArai | 9:e98e94ba17f9 | 128 | Thread::wait(100); |
kenjiArai | 9:e98e94ba17f9 | 129 | } |
kenjiArai | 9:e98e94ba17f9 | 130 | } |
kenjiArai | 9:e98e94ba17f9 | 131 | |
kenjiArai | 9:e98e94ba17f9 | 132 | void temp_control(void const *args) |
kenjiArai | 9:e98e94ba17f9 | 133 | { |
kenjiArai | 11:20e7a45f1448 | 134 | uint32_t error_count = 50; |
kenjiArai | 11:20e7a45f1448 | 135 | |
kenjiArai | 9:e98e94ba17f9 | 136 | t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT); |
kenjiArai | 9:e98e94ba17f9 | 137 | pid.setInputLimits(0.0, 4.5); |
kenjiArai | 9:e98e94ba17f9 | 138 | pid.setOutputLimits(0.0, 5.0); |
kenjiArai | 9:e98e94ba17f9 | 139 | pid.setSetPoint(2.5); |
kenjiArai | 9:e98e94ba17f9 | 140 | while(true) { |
kenjiArai | 9:e98e94ba17f9 | 141 | tmp = t.read_temp(); |
kenjiArai | 9:e98e94ba17f9 | 142 | pid.setProcessValue(tmp / 10); |
kenjiArai | 9:e98e94ba17f9 | 143 | pid_val = pid.compute(); |
kenjiArai | 9:e98e94ba17f9 | 144 | volt = pid_val - 2.5f; |
kenjiArai | 9:e98e94ba17f9 | 145 | if (volt < -0.8f) { |
kenjiArai | 9:e98e94ba17f9 | 146 | volt = -0.8f; |
kenjiArai | 9:e98e94ba17f9 | 147 | } else if (volt > 0.8f) { |
kenjiArai | 9:e98e94ba17f9 | 148 | volt = 0.8f; |
kenjiArai | 9:e98e94ba17f9 | 149 | } |
kenjiArai | 11:20e7a45f1448 | 150 | if ((volt == -0.800f) || (volt == 0.800f)){ |
kenjiArai | 11:20e7a45f1448 | 151 | if (--error_count == 0){ |
kenjiArai | 11:20e7a45f1448 | 152 | pid.reset(); |
kenjiArai | 11:20e7a45f1448 | 153 | error_count = 50; |
kenjiArai | 11:20e7a45f1448 | 154 | } |
kenjiArai | 11:20e7a45f1448 | 155 | } else { |
kenjiArai | 11:20e7a45f1448 | 156 | error_count = 50; |
kenjiArai | 11:20e7a45f1448 | 157 | } |
kenjiArai | 9:e98e94ba17f9 | 158 | heater.set_voltage(volt); |
kenjiArai | 9:e98e94ba17f9 | 159 | if (heater.status()) { |
kenjiArai | 9:e98e94ba17f9 | 160 | heater.reset(); |
kenjiArai | 9:e98e94ba17f9 | 161 | } |
kenjiArai | 9:e98e94ba17f9 | 162 | /* Wait until it is time to check again. */ |
kenjiArai | 9:e98e94ba17f9 | 163 | Thread::wait(1000); |
kenjiArai | 9:e98e94ba17f9 | 164 | } |
kenjiArai | 9:e98e94ba17f9 | 165 | } |
kenjiArai | 9:e98e94ba17f9 | 166 | |
kenjiArai | 9:e98e94ba17f9 | 167 | // Get GAA data |
kenjiArai | 9:e98e94ba17f9 | 168 | void gps_data_rcv(void const *args) |
kenjiArai | 5:af9fa3d0731c | 169 | { |
kenjiArai | 9:e98e94ba17f9 | 170 | int8_t i; |
kenjiArai | 9:e98e94ba17f9 | 171 | time_t old_ave_sec[2]; |
kenjiArai | 9:e98e94ba17f9 | 172 | uint32_t diff; |
kenjiArai | 9:e98e94ba17f9 | 173 | |
kenjiArai | 9:e98e94ba17f9 | 174 | gps.baud(9600); |
kenjiArai | 9:e98e94ba17f9 | 175 | seconds = time(NULL); |
kenjiArai | 9:e98e94ba17f9 | 176 | DEBUG("\r\nCurrent Time: %s\r\n", ctime(&seconds)); |
kenjiArai | 9:e98e94ba17f9 | 177 | old_ave_sec[0] = 0; |
kenjiArai | 9:e98e94ba17f9 | 178 | old_ave_sec[1] = 0; |
kenjiArai | 9:e98e94ba17f9 | 179 | while(true) { |
kenjiArai | 9:e98e94ba17f9 | 180 | getline_gps(); // Get GPS data from UART |
kenjiArai | 9:e98e94ba17f9 | 181 | if (strncmp(GPS_Buffer, "$GPRMC",6) == 0) { |
kenjiArai | 9:e98e94ba17f9 | 182 | for (i=0; GPS_Buffer[i] != 0; i++) {// Copy msg to RMC buffer |
kenjiArai | 9:e98e94ba17f9 | 183 | MsgBuf_RMC[i] = GPS_Buffer[i]; |
kenjiArai | 9:e98e94ba17f9 | 184 | } |
kenjiArai | 9:e98e94ba17f9 | 185 | MsgBuf_RMC[i+1] = 0; |
kenjiArai | 9:e98e94ba17f9 | 186 | DEBUG("GET RMC\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 187 | if (gps_status > 3) { |
kenjiArai | 9:e98e94ba17f9 | 188 | get_time_and_date(&t_gps); |
kenjiArai | 9:e98e94ba17f9 | 189 | seconds = mktime(&t_gps); |
kenjiArai | 9:e98e94ba17f9 | 190 | if (old_ave_sec[0] == 0){ |
kenjiArai | 9:e98e94ba17f9 | 191 | old_ave_sec[0] = seconds; |
kenjiArai | 9:e98e94ba17f9 | 192 | } else if (old_ave_sec[1] == 0){ |
kenjiArai | 9:e98e94ba17f9 | 193 | old_ave_sec[1] = seconds; |
kenjiArai | 9:e98e94ba17f9 | 194 | } else { |
kenjiArai | 9:e98e94ba17f9 | 195 | if (old_ave_sec[0] >= old_ave_sec[1]){ |
kenjiArai | 9:e98e94ba17f9 | 196 | diff = old_ave_sec[0] - old_ave_sec[1]; |
kenjiArai | 9:e98e94ba17f9 | 197 | } else { |
kenjiArai | 9:e98e94ba17f9 | 198 | diff = old_ave_sec[1] - old_ave_sec[0]; |
kenjiArai | 9:e98e94ba17f9 | 199 | } |
kenjiArai | 9:e98e94ba17f9 | 200 | if (diff > 100 ){ |
kenjiArai | 9:e98e94ba17f9 | 201 | old_ave_sec[0] = seconds; |
kenjiArai | 9:e98e94ba17f9 | 202 | old_ave_sec[1] = 0; |
kenjiArai | 9:e98e94ba17f9 | 203 | } else { |
kenjiArai | 9:e98e94ba17f9 | 204 | if (old_ave_sec[0] > old_ave_sec[1]){ |
kenjiArai | 9:e98e94ba17f9 | 205 | diff = seconds - old_ave_sec[0]; |
kenjiArai | 9:e98e94ba17f9 | 206 | if (diff < 100){ |
kenjiArai | 9:e98e94ba17f9 | 207 | old_ave_sec[1] = seconds; |
kenjiArai | 9:e98e94ba17f9 | 208 | } |
kenjiArai | 9:e98e94ba17f9 | 209 | } else { |
kenjiArai | 9:e98e94ba17f9 | 210 | diff = seconds - old_ave_sec[1]; |
kenjiArai | 9:e98e94ba17f9 | 211 | if (diff < 100){ |
kenjiArai | 9:e98e94ba17f9 | 212 | old_ave_sec[0] = seconds; |
kenjiArai | 9:e98e94ba17f9 | 213 | } |
kenjiArai | 9:e98e94ba17f9 | 214 | } |
kenjiArai | 9:e98e94ba17f9 | 215 | set_time(seconds); |
kenjiArai | 9:e98e94ba17f9 | 216 | DEBUG("SET RTC\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 217 | } |
kenjiArai | 9:e98e94ba17f9 | 218 | } |
kenjiArai | 9:e98e94ba17f9 | 219 | } |
kenjiArai | 9:e98e94ba17f9 | 220 | } else if (strncmp(GPS_Buffer, "$GPGGA",6) == 0) { |
kenjiArai | 9:e98e94ba17f9 | 221 | for (i=0; GPS_Buffer[i] != 0; i++) {// Copy msg to GGA buffer |
kenjiArai | 9:e98e94ba17f9 | 222 | MsgBuf_GGA[i] = GPS_Buffer[i]; |
kenjiArai | 9:e98e94ba17f9 | 223 | } |
kenjiArai | 9:e98e94ba17f9 | 224 | MsgBuf_GGA[i+1] = 0; |
kenjiArai | 9:e98e94ba17f9 | 225 | DEBUG("GET GGA\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 226 | gps_status = check_gps_ready(); |
kenjiArai | 9:e98e94ba17f9 | 227 | } |
kenjiArai | 9:e98e94ba17f9 | 228 | } |
kenjiArai | 9:e98e94ba17f9 | 229 | } |
kenjiArai | 9:e98e94ba17f9 | 230 | |
kenjiArai | 9:e98e94ba17f9 | 231 | void display_data(void const *args) |
kenjiArai | 9:e98e94ba17f9 | 232 | { |
kenjiArai | 9:e98e94ba17f9 | 233 | char buf[40]; |
kenjiArai | 8:7b033903c8fb | 234 | |
kenjiArai | 8:7b033903c8fb | 235 | BAUD(9600); |
kenjiArai | 9:e98e94ba17f9 | 236 | DEBUGBAUD(9600); |
kenjiArai | 6:44c2bcbdd77b | 237 | PRINTF("\r\nFrequency Counter by JH1PJL created on "__DATE__"\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 238 | // Initial screen |
kenjiArai | 9:e98e94ba17f9 | 239 | lcd.locate(0, 0); |
kenjiArai | 9:e98e94ba17f9 | 240 | lcd.printf(msg_msg0); |
kenjiArai | 9:e98e94ba17f9 | 241 | lcd.printf(msg_msg1); |
kenjiArai | 9:e98e94ba17f9 | 242 | lcd.printf(msg_msg2); |
kenjiArai | 9:e98e94ba17f9 | 243 | lcd.printf(msg_msg3); |
kenjiArai | 9:e98e94ba17f9 | 244 | Thread::wait(3000); |
kenjiArai | 9:e98e94ba17f9 | 245 | lcd.locate(0, 0); |
kenjiArai | 9:e98e94ba17f9 | 246 | lcd.printf(msg_clear); |
kenjiArai | 9:e98e94ba17f9 | 247 | lcd.printf(msg_clear); |
kenjiArai | 9:e98e94ba17f9 | 248 | lcd.printf(msg_clear); |
kenjiArai | 9:e98e94ba17f9 | 249 | lcd.printf(msg_clear); |
kenjiArai | 5:af9fa3d0731c | 250 | while(true) { |
kenjiArai | 9:e98e94ba17f9 | 251 | osEvent evt = queue0.get(); |
kenjiArai | 9:e98e94ba17f9 | 252 | PRINTF("FRQ= %11.1f Hz, ", new_frequency); |
kenjiArai | 9:e98e94ba17f9 | 253 | PRINTF("1PPS= %9d , %9d (new), ",counter_1pps, fc.read_newest_1pps()); |
kenjiArai | 9:e98e94ba17f9 | 254 | PRINTF("%+6.3f dC, ", tmp); |
kenjiArai | 9:e98e94ba17f9 | 255 | PRINTF("PID= %+6.3f , ", volt); |
kenjiArai | 9:e98e94ba17f9 | 256 | // PRINTF("t= %5d S, ", n++); |
kenjiArai | 9:e98e94ba17f9 | 257 | seconds = time(NULL); |
kenjiArai | 9:e98e94ba17f9 | 258 | seconds_jst = seconds + 32400; // +9 hours ->JST |
kenjiArai | 9:e98e94ba17f9 | 259 | // December 31,'14, 13:12:11 |
kenjiArai | 9:e98e94ba17f9 | 260 | // strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds)); |
kenjiArai | 9:e98e94ba17f9 | 261 | // 31 Dec 2014 13:12:11 |
kenjiArai | 9:e98e94ba17f9 | 262 | // strftime(buf,40, "%x %X ", localtime(&seconds)); |
kenjiArai | 9:e98e94ba17f9 | 263 | // 1:12:11 PM (2014/12/31) |
kenjiArai | 11:20e7a45f1448 | 264 | strftime(buf,40, "%I:%M:%S %p %m/%d", localtime(&seconds_jst)); |
kenjiArai | 9:e98e94ba17f9 | 265 | PRINTF("%s, ", buf); |
kenjiArai | 9:e98e94ba17f9 | 266 | if (fc.status_gps()) { |
kenjiArai | 9:e98e94ba17f9 | 267 | PRINTF("RDY"); |
kenjiArai | 9:e98e94ba17f9 | 268 | } else { |
kenjiArai | 9:e98e94ba17f9 | 269 | PRINTF("NO "); |
kenjiArai | 9:e98e94ba17f9 | 270 | } |
kenjiArai | 9:e98e94ba17f9 | 271 | PRINTF("\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 272 | lcd.locate(0, 0); |
kenjiArai | 9:e98e94ba17f9 | 273 | lcd.printf("Freq= %11.2f Hz", new_frequency); |
kenjiArai | 9:e98e94ba17f9 | 274 | lcd.locate(0, 1); |
kenjiArai | 9:e98e94ba17f9 | 275 | lcd.printf("1PPS=%9d Hz", counter_1pps); |
kenjiArai | 9:e98e94ba17f9 | 276 | lcd.locate(0, 2); |
kenjiArai | 9:e98e94ba17f9 | 277 | strftime(buf,40, " %I:%M:%S %p (%m/%d)", localtime(&seconds_jst)); |
kenjiArai | 9:e98e94ba17f9 | 278 | lcd.printf("%s, ", buf); |
kenjiArai | 9:e98e94ba17f9 | 279 | lcd.locate(0, 3); |
kenjiArai | 9:e98e94ba17f9 | 280 | lcd.printf("t= %+4.1f%cC", tmp, 0xdf); |
kenjiArai | 9:e98e94ba17f9 | 281 | if (fc.status_gps()) { |
kenjiArai | 9:e98e94ba17f9 | 282 | lcd.printf(" GPS RDY"); |
kenjiArai | 9:e98e94ba17f9 | 283 | } else { |
kenjiArai | 9:e98e94ba17f9 | 284 | lcd.printf(" NO GPS "); |
kenjiArai | 5:af9fa3d0731c | 285 | } |
kenjiArai | 9:e98e94ba17f9 | 286 | base_clock_1pps = (double)counter_1pps / 1000000; |
kenjiArai | 9:e98e94ba17f9 | 287 | double diff = base_clock_1pps - CLOCK_BASE; |
kenjiArai | 9:e98e94ba17f9 | 288 | if (diff < 0) { |
kenjiArai | 9:e98e94ba17f9 | 289 | diff *= -1; |
kenjiArai | 9:e98e94ba17f9 | 290 | } |
kenjiArai | 9:e98e94ba17f9 | 291 | if (diff < 0.00001) { // less than 10Hz |
kenjiArai | 9:e98e94ba17f9 | 292 | fc.set_external_clock(base_clock_1pps); |
kenjiArai | 5:af9fa3d0731c | 293 | } |
kenjiArai | 9:e98e94ba17f9 | 294 | /* Wait until it is time to check again. */ |
kenjiArai | 9:e98e94ba17f9 | 295 | Thread::wait(100); |
kenjiArai | 9:e98e94ba17f9 | 296 | } |
kenjiArai | 9:e98e94ba17f9 | 297 | } |
kenjiArai | 9:e98e94ba17f9 | 298 | |
kenjiArai | 9:e98e94ba17f9 | 299 | // Thread definition |
kenjiArai | 9:e98e94ba17f9 | 300 | osThreadDef(measure_freq, osPriorityNormal,1024); |
kenjiArai | 9:e98e94ba17f9 | 301 | osThreadDef(temp_control, osPriorityNormal,1024); |
kenjiArai | 11:20e7a45f1448 | 302 | osThreadDef(display_data, osPriorityNormal,1536); |
kenjiArai | 11:20e7a45f1448 | 303 | osThreadDef(gps_data_rcv, osPriorityNormal,1536); |
kenjiArai | 9:e98e94ba17f9 | 304 | |
kenjiArai | 9:e98e94ba17f9 | 305 | int main() |
kenjiArai | 9:e98e94ba17f9 | 306 | { |
kenjiArai | 9:e98e94ba17f9 | 307 | // PA8 & PC9 uses for MCO_1 & MCO_2 -> Clock output for checking |
kenjiArai | 9:e98e94ba17f9 | 308 | fc.port_mco1_mco2_set(4); // Clk/4 ->1/1(100MHz) cannot measure!! |
kenjiArai | 9:e98e94ba17f9 | 309 | osThreadCreate(osThread(measure_freq), NULL); |
kenjiArai | 9:e98e94ba17f9 | 310 | Thread::wait(5); //wait |
kenjiArai | 9:e98e94ba17f9 | 311 | osThreadCreate(osThread(temp_control), NULL); |
kenjiArai | 9:e98e94ba17f9 | 312 | Thread::wait(8); //wait |
kenjiArai | 9:e98e94ba17f9 | 313 | osThreadCreate(osThread(display_data), NULL); |
kenjiArai | 9:e98e94ba17f9 | 314 | Thread::wait(10); //wait |
kenjiArai | 9:e98e94ba17f9 | 315 | if (CheckRTC() == OK) { // If RTC is NG, no need to start GPS RX function |
kenjiArai | 9:e98e94ba17f9 | 316 | DEBUG("\r\nGPS task starts\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 317 | osThreadCreate(osThread(gps_data_rcv), NULL); |
kenjiArai | 9:e98e94ba17f9 | 318 | } |
kenjiArai | 9:e98e94ba17f9 | 319 | while(true) { |
kenjiArai | 9:e98e94ba17f9 | 320 | /* Wait until it is time to check again. */ |
kenjiArai | 9:e98e94ba17f9 | 321 | Thread::wait(5000); |
mio | 1:2a347c40b1da | 322 | } |
mio | 1:2a347c40b1da | 323 | } |
kenjiArai | 9:e98e94ba17f9 | 324 | |
kenjiArai | 9:e98e94ba17f9 | 325 | /////////////////////////////////////////////////////////////////////////////// |
kenjiArai | 9:e98e94ba17f9 | 326 | // GPS data Analysis |
kenjiArai | 9:e98e94ba17f9 | 327 | // |
kenjiArai | 9:e98e94ba17f9 | 328 | // PA6C GPS Module |
kenjiArai | 9:e98e94ba17f9 | 329 | // http://www.gtop-tech.com/en/product/MT3339_GPS_Module_03.html |
kenjiArai | 9:e98e94ba17f9 | 330 | // Update time: 1 second (1PPS: ±10ns RMS) |
kenjiArai | 9:e98e94ba17f9 | 331 | // MediaTek MT3339 Chipset, L1 Frequency, C/A code, 66 Channels |
kenjiArai | 9:e98e94ba17f9 | 332 | // NMEA 0183 |
kenjiArai | 9:e98e94ba17f9 | 333 | // |
kenjiArai | 9:e98e94ba17f9 | 334 | // current setting: GGA, VTG, GGA, RMC |
kenjiArai | 9:e98e94ba17f9 | 335 | // |
kenjiArai | 9:e98e94ba17f9 | 336 | /////////////////////////////////////////////////////////////////////////////// |
kenjiArai | 9:e98e94ba17f9 | 337 | // Get line of data from GPS |
kenjiArai | 9:e98e94ba17f9 | 338 | void getline_gps(void) |
kenjiArai | 9:e98e94ba17f9 | 339 | { |
kenjiArai | 9:e98e94ba17f9 | 340 | while (gps.getc() != '$') { |
kenjiArai | 9:e98e94ba17f9 | 341 | //DEBUG("GETC but not $\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 342 | Thread::yield(); |
kenjiArai | 9:e98e94ba17f9 | 343 | } |
kenjiArai | 9:e98e94ba17f9 | 344 | GPS_Buffer[0] = '$'; |
kenjiArai | 9:e98e94ba17f9 | 345 | for (int8_t i = 1; i < GSP_BUF_B; i++) { |
kenjiArai | 9:e98e94ba17f9 | 346 | GPS_Buffer[i] = gps.getc(); |
kenjiArai | 9:e98e94ba17f9 | 347 | if (GPS_Buffer[i] == '\r' || GPS_Buffer[i] == '\n') { |
kenjiArai | 9:e98e94ba17f9 | 348 | GPS_Buffer[i] = '\r'; |
kenjiArai | 9:e98e94ba17f9 | 349 | GPS_Buffer[i+1] = '\n'; |
kenjiArai | 9:e98e94ba17f9 | 350 | GPS_Buffer[i+2] = 0; |
kenjiArai | 9:e98e94ba17f9 | 351 | GPS_Buffer[i+3] = 0; |
kenjiArai | 9:e98e94ba17f9 | 352 | //DEBUG("Get one GPS data\r\n"); |
kenjiArai | 9:e98e94ba17f9 | 353 | return; |
kenjiArai | 9:e98e94ba17f9 | 354 | } |
kenjiArai | 9:e98e94ba17f9 | 355 | } |
kenjiArai | 9:e98e94ba17f9 | 356 | } |
kenjiArai | 9:e98e94ba17f9 | 357 | |
kenjiArai | 9:e98e94ba17f9 | 358 | // ASCII to hex |
kenjiArai | 9:e98e94ba17f9 | 359 | uint8_t hex(char c) |
kenjiArai | 9:e98e94ba17f9 | 360 | { |
kenjiArai | 9:e98e94ba17f9 | 361 | if(c<= '/') return( ERR ); |
kenjiArai | 9:e98e94ba17f9 | 362 | if(((c -= '0')<= 9 || 10 <= ( c -= 'A' - '0' - 10)) && c <= 15) { |
kenjiArai | 9:e98e94ba17f9 | 363 | return((uint8_t)c); |
kenjiArai | 9:e98e94ba17f9 | 364 | } |
kenjiArai | 9:e98e94ba17f9 | 365 | return(ERR); |
kenjiArai | 9:e98e94ba17f9 | 366 | } |
kenjiArai | 9:e98e94ba17f9 | 367 | |
kenjiArai | 9:e98e94ba17f9 | 368 | // Search next ',' (comma) |
kenjiArai | 9:e98e94ba17f9 | 369 | char *next_comma( char *p ) |
kenjiArai | 9:e98e94ba17f9 | 370 | { |
kenjiArai | 9:e98e94ba17f9 | 371 | while (1) { |
kenjiArai | 9:e98e94ba17f9 | 372 | if ( *p== ',' ) { |
kenjiArai | 9:e98e94ba17f9 | 373 | return ++p; |
kenjiArai | 9:e98e94ba17f9 | 374 | } else if ( *p == 0 ) { |
kenjiArai | 9:e98e94ba17f9 | 375 | return (char*)-1; |
kenjiArai | 9:e98e94ba17f9 | 376 | } else { |
kenjiArai | 9:e98e94ba17f9 | 377 | p++; |
kenjiArai | 9:e98e94ba17f9 | 378 | } |
kenjiArai | 9:e98e94ba17f9 | 379 | } |
kenjiArai | 9:e98e94ba17f9 | 380 | } |
kenjiArai | 9:e98e94ba17f9 | 381 | |
kenjiArai | 9:e98e94ba17f9 | 382 | // 2 digits ASCII char to one byte hex |
kenjiArai | 9:e98e94ba17f9 | 383 | unsigned char change_acii_hex( char*p ) |
kenjiArai | 9:e98e94ba17f9 | 384 | { |
kenjiArai | 9:e98e94ba17f9 | 385 | unsigned char c; |
kenjiArai | 9:e98e94ba17f9 | 386 | |
kenjiArai | 9:e98e94ba17f9 | 387 | c = hex(*p++); /* No concern ERR condition! */ |
kenjiArai | 9:e98e94ba17f9 | 388 | c = (c * 10) + hex(*p++); |
kenjiArai | 9:e98e94ba17f9 | 389 | return c; |
kenjiArai | 9:e98e94ba17f9 | 390 | } |
kenjiArai | 9:e98e94ba17f9 | 391 | |
kenjiArai | 9:e98e94ba17f9 | 392 | // Skip number of comma |
kenjiArai | 9:e98e94ba17f9 | 393 | char *num_of_comma( char *p, int8_t n ) |
kenjiArai | 9:e98e94ba17f9 | 394 | { |
kenjiArai | 9:e98e94ba17f9 | 395 | for (; n> 0; n--) { |
kenjiArai | 9:e98e94ba17f9 | 396 | if ( (p = next_comma(p)) == (char*) -1 ) { |
kenjiArai | 9:e98e94ba17f9 | 397 | return (char*)-1; |
kenjiArai | 9:e98e94ba17f9 | 398 | } |
kenjiArai | 9:e98e94ba17f9 | 399 | } |
kenjiArai | 9:e98e94ba17f9 | 400 | return p; |
kenjiArai | 9:e98e94ba17f9 | 401 | } |
kenjiArai | 9:e98e94ba17f9 | 402 | |
kenjiArai | 9:e98e94ba17f9 | 403 | // Get GPS status and number of satelites |
kenjiArai | 9:e98e94ba17f9 | 404 | uint32_t check_gps_ready(void) |
kenjiArai | 9:e98e94ba17f9 | 405 | { |
kenjiArai | 9:e98e94ba17f9 | 406 | char *p; |
kenjiArai | 9:e98e94ba17f9 | 407 | uint32_t x; |
kenjiArai | 9:e98e94ba17f9 | 408 | uint8_t d; |
kenjiArai | 9:e98e94ba17f9 | 409 | |
kenjiArai | 9:e98e94ba17f9 | 410 | // pick-up time |
kenjiArai | 9:e98e94ba17f9 | 411 | p = MsgBuf_GGA; |
kenjiArai | 9:e98e94ba17f9 | 412 | p = num_of_comma(p,6); // skip ',' |
kenjiArai | 9:e98e94ba17f9 | 413 | // reach to "Position Fix Indicator" |
kenjiArai | 9:e98e94ba17f9 | 414 | if (*p == '0') { |
kenjiArai | 9:e98e94ba17f9 | 415 | x = 0; |
kenjiArai | 9:e98e94ba17f9 | 416 | } else if (*p == '1') { |
kenjiArai | 9:e98e94ba17f9 | 417 | x = 0x10; |
kenjiArai | 9:e98e94ba17f9 | 418 | } else if (*p == '2') { |
kenjiArai | 9:e98e94ba17f9 | 419 | x = 0x20; |
kenjiArai | 9:e98e94ba17f9 | 420 | } else { |
kenjiArai | 9:e98e94ba17f9 | 421 | x= 0; |
kenjiArai | 9:e98e94ba17f9 | 422 | } |
kenjiArai | 9:e98e94ba17f9 | 423 | ++p; |
kenjiArai | 9:e98e94ba17f9 | 424 | if (*p == ',') { |
kenjiArai | 9:e98e94ba17f9 | 425 | ++p; |
kenjiArai | 9:e98e94ba17f9 | 426 | d = hex(*p++); |
kenjiArai | 9:e98e94ba17f9 | 427 | if (d != ERR) { |
kenjiArai | 9:e98e94ba17f9 | 428 | x += (uint32_t)d; |
kenjiArai | 9:e98e94ba17f9 | 429 | if (*p != ',') { |
kenjiArai | 9:e98e94ba17f9 | 430 | x = 0; |
kenjiArai | 9:e98e94ba17f9 | 431 | } |
kenjiArai | 9:e98e94ba17f9 | 432 | } else { |
kenjiArai | 9:e98e94ba17f9 | 433 | x = 0; |
kenjiArai | 9:e98e94ba17f9 | 434 | } |
kenjiArai | 9:e98e94ba17f9 | 435 | } else { |
kenjiArai | 9:e98e94ba17f9 | 436 | x = 0; |
kenjiArai | 9:e98e94ba17f9 | 437 | } |
kenjiArai | 9:e98e94ba17f9 | 438 | return x; |
kenjiArai | 9:e98e94ba17f9 | 439 | } |
kenjiArai | 9:e98e94ba17f9 | 440 | |
kenjiArai | 9:e98e94ba17f9 | 441 | // Get time(UTC) from GPS data |
kenjiArai | 9:e98e94ba17f9 | 442 | void get_time_and_date(struct tm *pt) |
kenjiArai | 9:e98e94ba17f9 | 443 | { |
kenjiArai | 9:e98e94ba17f9 | 444 | char *p; |
kenjiArai | 9:e98e94ba17f9 | 445 | |
kenjiArai | 9:e98e94ba17f9 | 446 | p = MsgBuf_RMC; |
kenjiArai | 9:e98e94ba17f9 | 447 | p = num_of_comma(p,1); /* skip one ',' */ |
kenjiArai | 9:e98e94ba17f9 | 448 | pt->tm_hour = change_acii_hex(p); |
kenjiArai | 9:e98e94ba17f9 | 449 | p += 2; |
kenjiArai | 9:e98e94ba17f9 | 450 | pt->tm_min = change_acii_hex(p); |
kenjiArai | 9:e98e94ba17f9 | 451 | p += 2; |
kenjiArai | 9:e98e94ba17f9 | 452 | pt->tm_sec = change_acii_hex(p); |
kenjiArai | 9:e98e94ba17f9 | 453 | p = MsgBuf_RMC; |
kenjiArai | 9:e98e94ba17f9 | 454 | p = num_of_comma(p,9); /* skip one ',' */ |
kenjiArai | 9:e98e94ba17f9 | 455 | pt->tm_mday = change_acii_hex(p); |
kenjiArai | 9:e98e94ba17f9 | 456 | p += 2; |
kenjiArai | 9:e98e94ba17f9 | 457 | pt->tm_mon = change_acii_hex(p) - 1; |
kenjiArai | 9:e98e94ba17f9 | 458 | p += 2; |
kenjiArai | 9:e98e94ba17f9 | 459 | pt->tm_year = change_acii_hex(p) + 100; |
kenjiArai | 9:e98e94ba17f9 | 460 | } |