Very simple but enough accuracy "Frequency Counter". Using GPS 1PPS signal for 1sec gate. CPU is F746, F446 and F411.
Dependencies: fc_GPS1PPS_f746_f4xx iSerial mbed
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
Concept block are follows.
F746
/media/uploads/kenjiArai/block_diagram_fc_f746_wo_oven.pdf
F411&F446
/media/uploads/kenjiArai/block_diagram_fc_f411_wo_oven.pdf
Hardware Circuit(common F746,F446 and F411)
/media/uploads/kenjiArai/fc_f746ng_circuit.pdf
main.cpp
- Committer:
- kenjiArai
- Date:
- 2016-11-16
- Revision:
- 0:da29cdc50643
File content as of revision 0:da29cdc50643:
/* * mbed Application program / Frequency Counter using GPS 1PPS gate puls * Only for ST DISCO-F746NG and Nucleo-F411RE + F446RE * * 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 * Re-started: October 5th, 2016 Change board -> DISCO-F746NG * Re-started: October 10th, 2016 back to F411 * Revised: Nobember 15th, 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. */ #define USE_COM // use Communication with PC(UART) #define USE_DEBUG // Include -------------------------------------------------------------------- #include "mbed.h" #include "GPSrcvr.h" #include "fc_GPS1PPS.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 #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) #define RECIPRO_LMT 4500 #define RECIPRO_10KHZ 5000 #elif defined(TARGET_STM32F746NG) #define RECIPRO_LMT 9000 #define RECIPRO_10KHZ 10000 #else #error "Target is only Nucleo-F411RE + F446RE or DISCO-F746NG!!!" #endif #define GSP_BUF_B (128 * 3) #define GPS_BUF_S (128 * 2) enum input_select { BNC_NORMAL = 1, RECIPRO_AC, RECIPRO_DC, SMA_10, SMA_20 }; using namespace Frequency_counter; // Object --------------------------------------------------------------------- #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) DigitalOut input_frq_select(PA_4); DigitalInOut prescaler10or20(PA_7); DigitalOut recipro_select(PB_6); #elif defined(TARGET_STM32F746NG) DigitalOut input_frq_select(PF_9); DigitalInOut prescaler10or20(PB_15); DigitalOut recipro_select(PA_8); #endif DigitalOut led1(LED1); Serial pc(USBTX, USBRX); Timer tmr; //**** Req. Counter FRQ_CUNTR fc; // RAM ------------------------------------------------------------------------ // Freq. double new_frequency; double f_10sec; double f_100sec; double f_1000sec; double freq_recipro; // Operation mode uint8_t input_mode; // ROM / Constant data -------------------------------------------------------- // 12345678901234567890 static char *const msg_msg0 = "Frequency Counter by JH1PJL K.Arai"; #if defined(TARGET_NUCLEO_F411RE) static char *const msg_msg1 = "on Nucleo-F411RE System"; #elif defined(TARGET_NUCLEO_F446RE) static char *const msg_msg1 = "on Nucleo-F446RE System"; #elif defined(TARGET_STM32F746NG) static char *const msg_msg1 = "on DISCO-F746NG System"; #endif static char *const msg_msg2 = " "__DATE__" "; static char *const msg_mode1 = " BNC none-prescaler "; static char *const msg_mode2 = " BNC recipro(BNC none-prescaler) "; static char *const msg_mode3 = " BNC recipro(dedicated BNC input)"; static char *const msg_mode4 = " SMA prescaler 1/10 "; static char *const msg_mode5 = " SMA prescaler 1/20 "; // Function prototypes -------------------------------------------------------- void gps_data_rcv(void); //------------------------------------------------------------------------------ // Control Program //------------------------------------------------------------------------------ void freq_measurement(uint8_t mode) { uint16_t n = 0; char buf[48]; time_t seconds; double scale; if (mode == SMA_20){ scale = 20.0f; } else if(mode == SMA_10){ scale = 10.0f; } else { scale = 1.0f; } while(true){ tmr.reset(); tmr.start(); if (fc.status_freq_update() != 0) { new_frequency = fc.read_freq_data() * scale; f_10sec = fc.read_freq_w_gate_time(10) * scale; f_100sec = fc.read_freq_w_gate_time(100) * scale; f_1000sec = fc.read_freq_w_gate_time(1000) * scale; PRINTF("%8d, Freq: %9.0f,", ++n, new_frequency); PRINTF(" F10s: %10.1f, F100s: %11.2f,", f_10sec, f_100sec); PRINTF(" F1000s: %12.3f,", f_1000sec); } else { PRINTF("%8d, No data,,,,", ++n); } if (mode == SMA_20){ PRINTF(" Div: 1/20,"); } else if(mode == SMA_10){ PRINTF(" Div: 1/10,"); } else { PRINTF(" Div: 1/1 ,"); } seconds = time(NULL) + 32400; // Adjust UTC to JST strftime(buf, 40, " %I:%M:%S %p JST (%m/%d)", localtime(&seconds)); PRINTF("%s\r\n", buf); wait_ms(1000 - tmr.read_ms()); // 1sec interval } } void recipro() { uint16_t n = 0; char buf[48]; time_t seconds; double freq_recipro; uint32_t interval_recipro; uint32_t base_clk; int32_t run2stop; while(true){ fc.recipro_start_measure(); PRINTF("Start measurement\r"); while (fc.recipro_check_trigger() == 0){ run2stop = tmr.read_ms(); if (run2stop >= 100000){ // 100sec 0.001Hz break; } } if (run2stop >= 1000000){ // 100sec 0.001Hz freq_recipro = 0; } else { interval_recipro = fc.recipro_read_data(); base_clk = fc.recipro_base_clk_data(1); if (interval_recipro >= 9000){// Measure less than 10KHz frequency freq_recipro = (double)base_clk / (double)interval_recipro; PRINTF("%8d, Freq: %11.5f [Hz] , ", n++, freq_recipro); PRINTF("Raw: %11u [cnt] , ", interval_recipro); PRINTF("Base: %11u [Hz], ", base_clk); seconds = time(NULL) + 32400; // Adjust UTC to JST strftime(buf, 40, " %I:%M:%S %p JST (%m/%d)", localtime(&seconds)); PRINTF("%s\r\n", buf); run2stop = tmr.read_ms(); if (run2stop < 1000){ run2stop = 1000 - run2stop; wait_ms(run2stop); // 1sec interval } } else { freq_recipro = 0; } } } } int main() { PRINTF("\r\n%s%s\r\n", msg_msg0, msg_msg2); PRINTF("%s\r\n", msg_msg1); PRINTF("Wait GPS 1PPS signal\r\n"); gps_data_rcv(); PRINTF("\r\nPlease select measurement mode.\r\n"); PRINTF("%s-> 1\r\n", msg_mode1); PRINTF("%s-> 2\r\n", msg_mode2); PRINTF("%s-> 3\r\n", msg_mode3); PRINTF("%s-> 4\r\n", msg_mode4); PRINTF("%s-> 5\r\n", msg_mode5); PRINTF("Enter 1 to 5 (other input then 1)\r\n"); // Select operation mode char c = GETC() - '0'; if ((c > 5) || (c <= 0)){ c = 1;} input_mode = c; PRINTF("If you want to change the input signal,"); PRINTF(" please restart the system (Enter Alt+B from your PC)\r\n"); PRINTF("\r\nStart measuring\r\nMeasureing mode = "); switch(input_mode){ case RECIPRO_AC: PRINTF("%s\r\n", msg_mode2); input_frq_select = 1; prescaler10or20.output(); prescaler10or20 = 0; recipro_select = 0; recipro(); break; case RECIPRO_DC: PRINTF("%s\r\n", msg_mode3); input_frq_select = 1; prescaler10or20.output(); prescaler10or20 = 0; recipro_select = 1; recipro(); break; case SMA_10: PRINTF("%s\r\n", msg_mode4); input_frq_select = 0; prescaler10or20.output(); prescaler10or20 = 0; recipro_select = 0; freq_measurement(input_mode); break; case SMA_20: PRINTF("%s\r\n", msg_mode5); input_frq_select = 0; prescaler10or20.input(); recipro_select = 0; freq_measurement(input_mode); break; case BNC_NORMAL: default: input_mode = BNC_NORMAL; PRINTF("%s\r\n", msg_mode1); input_frq_select = 1; prescaler10or20.output(); prescaler10or20 = 0; recipro_select = 0; freq_measurement(input_mode); break; } while(true){;} // Just in case }