2024/11/04(月)Arduino mega : frequency counter/duty cycle meter を改良する
Added feature: analog input, able to preset threshold level.
(and we fixed a bug at the auto range feature.)
Sketch:
//Arduino frequency counter/duty cycle meter (analog input) //www.electronicsblog.net/ #include <LiquidCrystal.h> #include <TimerThree.h> #include <TimerFour.h> //LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // cycle meter input is pin 21 #define Button A1 // 52 #define ClkOut A7 // clock generator output #define ClkLed 16 // to check generated clock #define CmpSig A2 // analog comparator input #define CmpOut 21 // analog comparator output #define CmpLed 17 // to check signal detected int divider[6] ={ 0,1,8,64,256,1024}; volatile int prescaler=5; int b=0; int screen =0; volatile double count =0; volatile double middle =0; double usage =0; bool x = false; ISR(TIMER1_OVF_vect) { if (prescaler<4) { prescaler++; } } void interrupt() { if (!x) { count=TCNT1; TCNT1=0x000; TCCR1B=prescaler; attachInterrupt(2, interrupt, FALLING); } else { middle=TCNT1; attachInterrupt(2, interrupt, RISING); } x=!x; } void timerClock() { // clock generator interrupt handler static int tcnt = 0; bool out = (tcnt % 4 == 0); ++tcnt; digitalWrite(ClkOut, out); digitalWrite(ClkLed, out); // high = led lit } void setup_clock_gen() { pinMode(ClkOut, OUTPUT); pinMode(ClkLed, OUTPUT); Timer3.initialize(120000); // in micro second Timer3.attachInterrupt(timerClock); } volatile int volt = 0; void timerAnalog() { // analog read interrupt handler const int vth1 = 400; const int vth0 = 320; static int out = 0; int val = analogRead(CmpSig); if (val > vth1) { out = 1; } if (val < vth0) { out = 0; } volt = val; digitalWrite(CmpOut, out); digitalWrite(CmpLed, out); // high = led lit } void setup() { lcd.begin(16, 2); pinMode(Button, INPUT); digitalWrite(Button, HIGH); //pull up resistor pinMode(CmpSig, INPUT); pinMode(CmpOut, OUTPUT); pinMode(CmpLed, OUTPUT); TIMSK1=0x01; // enabled global and timer overflow interrupt; TCCR1A = 0x00; // normal operation page 148 (mode0); attachInterrupt(2, interrupt, RISING); //setup_clock_gen(); analogReference(DEFAULT); ADCSRA = ADCSRA & 0xf8; // 分周比を決めるビット(ADPS2:0)を000へ ADCSRA = ADCSRA | 0x04; // 分周比を決めるビットに分周比16(100)をセット Timer4.initialize(100); // in micro second Timer4.attachInterrupt(timerAnalog); } void loop() { usage=count/65536*100; /// screen modes switch (screen) { case 0: lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); lcd.print("Freq "); lcd.print(16000000.0/divider[prescaler]/count); lcd.print(" Hz"); lcd.setCursor(0, 1); lcd.print("Duty "); lcd.print(middle/count*100); lcd.print(" % "); lcd.print(" "); break; case 1: lcd.setCursor(0, 0); lcd.print("Period: "); lcd.print(volt); lcd.setCursor(0, 1); lcd.print(0.0000625*divider[prescaler]*count); lcd.print(" ms "); break; case 2: lcd.setCursor(0, 0); lcd.print("H "); lcd.print(0.0000625*divider[prescaler]*middle); lcd.print(" ms "); lcd.setCursor(0, 1); lcd.print("L "); lcd.print(0.0000625*divider[prescaler]*(count-middle)); lcd.print(" ms "); break; case 3: lcd.setCursor(0, 0); lcd.print("Prescaler /"); lcd.print(divider[prescaler]); lcd.setCursor(0, 1); lcd.print("Count.use "); //usage=count/65536*100; lcd.print(usage); lcd.print("% "); break; } delay(250); if (prescaler>1) { if (usage<0.15) { prescaler--; delay(200); } } ///button ///////// if (!digitalRead(Button)&&!b) { screen++; if (screen==4) { screen=0 ; } lcd.clear(); b=3; } if (!b==0) b--; }