2024/11/04(月)Arduino mega : frequency counter/duty cycle meter を改良する

Original: https://www.electronicsblog.net/arduino-frequency-counterduty-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--;

}