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