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
- Committer:
- kenjiArai
- Date:
- 2016-11-23
- Revision:
- 13:1041596c416c
- Parent:
- 11:20e7a45f1448
- Child:
- 14:ba6ea409ab05
File content as of revision 13:1041596c416c:
/* * mbed Application program / Frequency Counter with GPS 1PPS Compensation * Only for ST Nucleo-F746ZG * * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL * http://www.page.sannet.ne.jp/kenjia/index.html * http://mbed.org/users/kenjiArai/ * Created: October 18th, 2014 * Revised: January 2nd, 2015 * Re-started: June 25th, 2016 ported from F411 to F746 * Revised: Novemeber 23rd, 2016 * * Base program: Frequency_counter_w_GPS_1PPS (only for Nucleo-F411RE board) * https://developer.mbed.org/users/kenjiArai/code/Frequency_Counter_w_GPS_1PPS/ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* -------------------------------------------------------------------------------- Frequency Counter Functions Mesurement frequency range: 10Hz to 100MHz (BNC Connector) Extended range: Up to 1GHz (1/10 prescaler) or more over (1/20) (SMA) Gate time: 1 sec to 4095sec (extend to more if RAM is avairable) Reciprocal measurement: 0.01Hz to 5KHz (extend more lower frequency change input I/F) Base Internal Clock: 50MHz VCTCXO (Connor-Winfield TB514-050.0M) 1 PPS: GPS receiver(u-blux7/NEO-7) with an external antenna (SMA) Temperature controlled Oven: 32 degree Celsius +/-0.2 for 50MHz VCTCXO & 3.3V regulater Hardware Configration frequency input: PC_6 & PA_3 50MHz base clock input: PA_5 GPS 1PPS input: PA_1 Connect (for 1sec gate): PA_7, PB_10 and PC_7 connected together IMPORTANT!!!! SB13 & SB181 must REMOVE from Nucleo-F746ZG board -------------------------------------------------------------------------------- */ #define USE_COM // use Communication with PC(UART) #define USE_DEBUG //#define HW_TEST_GO // activate Hardware test mode // Include -------------------------------------------------------------------- #include "mbed.h" #include "rtos.h" #include "GPSrcvr.h" #include "DRV8830.h" #include "ADT7410.h" #include "PID.h" #include "frq_cuntr_f746.h" #include "TextLCD.h" #include "QEI.h" #include "uif.h" // Definition ----------------------------------------------------------------- #ifdef USE_COM #define BAUD(x) pc.baud(x) #define GETC(x) pc.getc(x) #define PUTC(x) pc.putc(x) #define PRINTF(...) pc.printf(__VA_ARGS__) #define READABLE(x) pc.readable(x) #else #define BAUD(x) {;} #define GETC(x) {;} #define PUTC(x) {;} #define PRINTF(...) {;} #define READABLE(x) {;} #endif #ifdef USE_DEBUG #define U_DEBUGBAUD(x) pc.baud(x) #define U_DEBUG(...) pc.printf(__VA_ARGS__) #define DBG(c) pc.putc(c) #else #define U_DEBUGBAUD(x) {;} #define U_DEBUG(...) {;} #define DBG(c) {;} #endif #define CLEAR_PD_2_RX_LINE() {UART5->ICR = 0; UART5->CR1 = 0; UART5->CR1 = 5;} #define CLOCK_BASE (50.000000f) // MHz #define TRGT_TEMP (32.0f) // degC #define RECIPRO_OVRFLW 10000 // = 5KHz #define RECIPRO_TIMEOUT 1000000 // = 0.001Hz #define GSP_BUF_B (128 * 3) #define GPS_BUF_S (128 * 2) using namespace Frequency_counter; // Object --------------------------------------------------------------------- DigitalOut led_gate(LED1); DigitalOut in_frq_slct(PC_9); DigitalInOut prescaler10or20(PC_5); DigitalIn pa1(PA_1); Timer tmr0; Timer tmr1; Timer tmr2; Ticker enter_irq; //**** UART Serial pc(USBTX, USBRX); //**** Req. Counter FRQ_CUNTR fc(CLOCK_BASE); // External clock freq. //**** Peltier temperature control I2C i2cBus(PB_9,PB_8); // SDA, SCL DRV8830 heater(i2cBus, (uint8_t)DRV8830ADDR_00); // H brige PID pid(8.0f, 85.0f, 4.0f, 0.7f); // PID for oven ADT7410 t(i2cBus, ADT7410ADDR_NN); // inside oven temp. // RAM ------------------------------------------------------------------------ // all display data dispDef disp_data; // Freq. double new_frequency; double freq_recipro; uint32_t interval_recipro; uint8_t recipro_new_data_ready; uint8_t recipro_overflow; // ROM / Constant data -------------------------------------------------------- // Function prototypes -------------------------------------------------------- extern void dispay_LCD_and_UART(dispDef *dt); extern void select_input_div_1or10or20(uint8_t mode); //------------------------------------------------------------------------------ // Control Program //------------------------------------------------------------------------------ // Frequency measurement void measure_freq(void const *args) { while(true) { if (fc.status_freq_update() != 0) { new_frequency = fc.read_freq_data(); disp_data.m_frq = new_frequency; disp_data.m_frq_comp = fc.read_compensated_freq_data_w_gt(1); disp_data.m_frq_10 = fc.read_compensated_freq_data_w_gt(10); disp_data.m_frq_100 = fc.read_compensated_freq_data_w_gt(100); disp_data.m_frq_1000 = fc.read_compensated_freq_data_w_gt(1000); } if (fc.status_1pps() != 0) { disp_data.b_1pps_new = fc.read_newest_1pps(); disp_data.b_1pps_lng = fc.read_avarage_1pps(); } Thread::wait(100); // 0.1sec } } // Frequency measurement / Reciprocal measurement void measure_freq_recipro(void const *args) { int32_t run2stop; while(true) { tmr0.reset(); tmr0.start(); fc.recipro_start_measure(); while (fc.recipro_check_trigger() == 0){ Thread::wait(1); // 1mS run2stop = tmr0.read_ms(); if (run2stop >= RECIPRO_TIMEOUT){ break; } } if (run2stop >= RECIPRO_TIMEOUT){ freq_recipro = 0; } else { interval_recipro = fc.recipro_read_data(); if (interval_recipro >= RECIPRO_OVRFLW){ // Measure less than 5KHz frequency freq_recipro = CLOCK_BASE/(double)interval_recipro * 1000000; recipro_overflow = 0; } else { freq_recipro = 0; recipro_overflow = 1; } } recipro_new_data_ready = 1; disp_data.m_frq_recipro = freq_recipro; disp_data.recipro_of = recipro_overflow; run2stop = tmr0.read_ms(); if (run2stop > 1000){ Thread::wait(run2stop % 1000); // next interval } else { run2stop = 1000 - run2stop; /* Wait until it is time to check again. */ Thread::wait(run2stop); // 1sec interval } } } // Constant temperature oven control void temp_control(void const *args) { static double volt = 0.0; static double tmp = 0; static double pid_val = 0; static uint32_t error_count = 3600; static int32_t keep_1sec; t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT); pid.setInputLimits(0.0f, 5.0f); pid.setOutputLimits(0.0f, 5.0f); pid.setSetPoint(TRGT_TEMP/10.0f); while(true) { tmr2.reset(); tmr2.start(); tmp = t.read_temp(); disp_data.box_tmp = tmp; //PRINTF("Temp=%f degC\r\n", tmp); pid.setProcessValue(tmp / 10.0f); pid_val = pid.compute(); volt = pid_val - (TRGT_TEMP/10.0f); if (volt < -5.0f) { volt = -5.0f; } else if (volt > 5.0f) { volt = 5.0f; } if ((volt == -5.0f) || (volt == 5.0f)){ if (--error_count == 0){ pid.reset(); error_count = 3600; pid.setInputLimits(0.0f, 5.0f); pid.setOutputLimits(0.0f, 5.0f); pid.setSetPoint(TRGT_TEMP/10.0f); } } else { error_count = 3600; } heater.set_voltage(-volt); //PRINTF("Volt=%f V\r\n", volt); if (heater.status()) { heater.reset(); } if ((tmp > (TRGT_TEMP + 0.2f)) || (tmp < (TRGT_TEMP - 0.4f))){ disp_data.temp_is_okay = 0; } else { disp_data.temp_is_okay = 1; } #if defined(HW_TEST_GO) pc.printf("Volt=%+4.3f [V] , Oven Temp. %+6.3f [degC]", volt, tmp); pc.printf(", Diff=%3.1f-x= %+6.3f \r\n", TRGT_TEMP, TRGT_TEMP - tmp); #endif keep_1sec = 1000 - keep_1sec; Thread::wait(keep_1sec); // 1sec interval } } void display_data(void const *args) { int32_t tim_remain; while(true){ tmr1.reset(); tmr1.start(); disp_data.gps_1pps_ave = fc.read_num_in_buffer(); disp_data.ready_1pps = check_gps_3d(); // User_IF dispay_LCD_and_UART(&disp_data); // separate files uif.cpp & uif.h /* Wait */ tim_remain = 1000 - tmr1.read_ms(); Thread::wait(tim_remain); } } void receive_gps(void const *args) { gps_data_rcv(); // infinit loop -> never return // separate files GPSrcvr.cpp & GPSrcvr.h } #if !defined(HW_TEST_GO) // Normal control mode // Thread definition osThreadDef(measure_freq, osPriorityNormal,1024); osThreadDef(measure_freq_recipro, osPriorityNormal,1024); osThreadDef(temp_control, osPriorityNormal,2048); osThreadDef(receive_gps, osPriorityNormal,1024); osThreadDef(display_data, osPriorityNormal,2048); int main(){ disp_first_msg(); Thread::wait(1000); // 1sec disp_wait_gps(); osThreadCreate(osThread(receive_gps), NULL); PRINTF("\r\nStart GPS receiving!\r\n"); while (check_gps_is_okay() == false){;} // wait till "true" PRINTF("GPS data is valid!\r\n"); fc.debug_printf_internal_data(); osThreadCreate(osThread(measure_freq), NULL); Thread::wait(5); //wait osThreadCreate(osThread(temp_control), NULL); Thread::wait(8); //wait osThreadCreate(osThread(measure_freq_recipro), NULL); Thread::wait(3); //wait osThreadCreate(osThread(display_data), NULL); Thread::wait(10); //wait select_input_div_1or10or20(0); // BNC (none presclaer) while(true) { /* Wait until it is time to check again. */ Thread::wait(60000); // 1min. } } #else // Hardware Test mode #include "hw_tst.h" extern void hardware_test(void); int main(){ hardware_test(); } double read_temperature(uint8_t n) { if (n == 0){ t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT); return 0; } else if (n == 1){ return t.read_temp(); } return 0; } #endif // !defined(HW_TEST_GO)