Hello~
Here is my sketch, that can read 5x PWM duty cycle and FAN clock.
The PWM is 25KHz.
I currently have a problem for pwm duty cycle.
The sketch works fine if PWM duty cycle setting from16% to 100%.
However, if the duty cycle is less than 16% (1% -> 16%), the read value will be incorrect, maybe show 6%, 8%, 10% .......
Does anyone know why?
#include <Wire.h>
// 可將 Arduino\hardware\arduino\avr\libraries\Wire\utility\twi.h 改成400000L (400 KHz) 加快顯示速度
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// FAN pin 4 PWM input
#define PWM1 6
#define PWM2 5
#define PWM3 4
#define PWM4 3
#define PWM5 2
// FAN pin 3 clock input
#define CLK1 12
#define CLK2 11
#define CLK3 10
#define CLK4 9
#define CLK5 8
static double duty;
static double freq;
static double freq1;
static double FANspeed;
static long highTime = 0;
static long lowTime = 0;
static long tempPulse;
static long lastSeen;
float val;
float va0;
int sensorValue = 0;
#define READ_DELAY 3
void setup()
{
// TCCR2B = TCCR2B & B11111000 | B00000011; // // set timer 2 divisor to 32 for PWM frequency of 980.39 Hz
lcd.init(); // initialize the lcd
lcd.backlight();
delay(300);
lcd.noBacklight();
delay(300);
lcd.backlight();
delay(300);
lcd.noBacklight();
delay(300);
lcd.backlight();
delay(300);
lcd.noBacklight();
delay(300);
lcd.backlight();
delay(200);
// Print a message to the LCD.
lcd.setCursor(0, 0);
lcd.print(" MAJESTIC TEST JIG ");
lcd.setCursor(0, 2);
lcd.print(" FAN ROTATION TEST ");
lcd.setCursor(0, 3);
lcd.print(" Ver.:1.0");
delay(1000);
lcd.clear();
// PIN I/O DEFINE
pinMode(PWM1, INPUT_PULLUP);
pinMode(PWM2, INPUT_PULLUP);
pinMode(PWM3, INPUT_PULLUP);
pinMode(PWM4, INPUT_PULLUP);
pinMode(PWM5, INPUT_PULLUP);
digitalWrite(PWM1, HIGH);
digitalWrite(PWM2, HIGH);
digitalWrite(PWM3, HIGH);
digitalWrite(PWM4, HIGH);
digitalWrite(PWM5, HIGH);
/*
pinMode(CLK1, INPUT_PULLUP);
pinMode(CLK2, INPUT_PULLUP);
pinMode(CLK3, INPUT_PULLUP);
pinMode(CLK4, INPUT_PULLUP);
pinMode(CLK5, INPUT_PULLUP);
*/
pinMode(CLK1, INPUT);
pinMode(CLK2, INPUT);
pinMode(CLK3, INPUT);
pinMode(CLK4, INPUT);
pinMode(CLK5, INPUT);
digitalWrite(CLK1, HIGH);
digitalWrite(CLK2, HIGH);
digitalWrite(CLK3, HIGH);
digitalWrite(CLK4, HIGH);
digitalWrite(CLK5, HIGH);
Serial.begin(9600);
lcd.setCursor(0, 0);
lcd.print("DT_");
lcd.setCursor(0, 1);
lcd.print("FQ1_");
lcd.setCursor(10, 1);
lcd.print("FQ2_");
lcd.setCursor(0, 2);
lcd.print("FQ3_");
lcd.setCursor(10, 2);
lcd.print("FQ4_");
lcd.setCursor(0, 3);
lcd.print("FQ5_");
lcd.setCursor(10, 3);
lcd.print("PWM");
lcd.setCursor(17, 3);
lcd.print("KHz");
}
void loop()
{
//read FAN colck (ratation)
readPWM(PWM1);
// lcd.setCursor(0, 0);
// lcd.print("DT_");
lcd.setCursor(3, 0);
lcd.print(duty, 0);
lcd.setCursor(4, 0);
duty_detect();
lcd.setCursor(5, 0);
lcd.print(" ");
readPWM(PWM2);
lcd.setCursor(6, 0);
lcd.print(duty, 0);
lcd.setCursor(7, 0);
duty_detect();
lcd.setCursor(8, 0);
lcd.print(" ");
/////////////////////////////////////
lcd.setCursor(14, 3);
if (freq < 1)
{
lcd.print("0 ");
}
else
{
lcd.print(freq /1000, 0);
}
////////////////////////////////////////////
readPWM(PWM3);
lcd.setCursor(9, 0);
lcd.print(duty, 0);
lcd.setCursor(10, 0);
duty_detect();
lcd.setCursor(11, 0);
lcd.print(" ");
readPWM(PWM4);
lcd.setCursor(12, 0);
lcd.print(duty, 0);
lcd.setCursor(13, 0);
duty_detect();
lcd.setCursor(14, 0);
lcd.print(" ");
readPWM(PWM5);
lcd.setCursor(15, 0);
lcd.print(duty, 0);
lcd.setCursor(16, 0);
duty_detect();
lcd.setCursor(17, 0);
lcd.print(" ");
readPWM(CLK1);
// lcd.setCursor(0, 1);
// lcd.print("FQ1_");
lcd.setCursor(4, 1);
//lcd.print(freq*30, 0);
zero_freq_detect(); //(讀取頻率及輸出數值)
lcd.setCursor(8, 1);
blank_bit(); //(刪除最後兩個雜訊讀到的最後兩位數) , 最多僅能顯示 9999
// 如果轉速是千位數變成百位數,則清除最後邊殘留未清除的數字)
lcd.setCursor(7, 1);
if ((freq * 30) < 999)
{
lcd.print(" ");
}
readPWM(CLK2);
// lcd.setCursor(10, 1);
// lcd.print("FQ2_");
lcd.setCursor(14, 1);
// lcd.print(freq*30, 0);
zero_freq_detect();
lcd.setCursor(18, 1);
blank_bit();
// 如果轉速是千位數變成百位數,則清除最後邊殘留未清除的數字)
lcd.setCursor(17, 1);
if ((freq * 30) < 999)
{
lcd.print(" ");
}
readPWM(CLK3);
// lcd.setCursor(0, 2);
// lcd.print("FQ3_");
lcd.setCursor(4, 2);
// lcd.print(freq*30, 0);
zero_freq_detect();
lcd.setCursor(8, 2);
blank_bit();
// 如果轉速是千位數變成百位數,則清除最後邊殘留未清除的數字)
lcd.setCursor(7, 2);
if ((freq * 30) < 999)
{
lcd.print(" ");
}
readPWM(CLK4);
// lcd.setCursor(10, 2);
// lcd.print("FQ4_");
lcd.setCursor(14, 2);
// lcd.print(freq*30, 0);
zero_freq_detect();
lcd.setCursor(18, 2 );
blank_bit();
// 如果轉速是千位數變成百位數,則清除最後邊殘留未清除的數字)
lcd.setCursor(17, 2);
if ((freq * 30) < 999)
{
lcd.print(" ");
}
readPWM(CLK5);
// lcd.setCursor(0, 3);
// lcd.print("FQ5_");
lcd.setCursor(4, 3);
// lcd.print(freq*30, 0);
zero_freq_detect();
lcd.setCursor(8, 3);
blank_bit();
// 如果轉速是千位數變成百位數,則清除最後邊殘留未清除的數字)
lcd.setCursor(7, 3);
if ((freq * 30) < 999)
{
lcd.print(" ");
}
/*
//偵測PWM的頻率
// lcd.setCursor(17, 3);
// lcd.print("KHz");
readPWM(PWM2);
lcd.setCursor(14, 3);
if (freq <1)
{
lcd.print("0 ");
}
else
{
lcd.print(freq/1000, 0);
}
*/
}
// 偵測到 duty cycle <1 的話,就顯示 0)
void duty_detect()
{
if (duty < 1)
{
lcd.print("0");
}
}
// 將9999 , 後的數字強制清除,避免顯示亂碼)
void blank_bit()
{
lcd.print(" ");
}
//讀取風扇頻率(CLOCK), 如果 <1 的話,就顯示 0 (6個位元都清0) ,
void zero_freq_detect()
{
delay (10);
if (freq < 1)
{
lcd.print("0 ");
}
else
{
lcd.print(freq * 30, 0);
}
}
// ---------------------------------------------
//Takes in reading pins and outputs pwm frequency and duty cycle.
void readPWM(int readPin)
{
highTime = 0;
lowTime = 0;
lastSeen = millis();
while ((millis() - lastSeen) < READ_DELAY)
{
// tempPulse = pulseIn(readPin,HIGH,50000);
tempPulse = pulseIn(readPin, HIGH, 50000);
if (tempPulse > highTime) {
highTime = tempPulse;
}
}
lastSeen = millis();
while ((millis() - lastSeen) < READ_DELAY)
{
// tempPulse = pulseIn(readPin,LOW,50000);
tempPulse = pulseIn(readPin, LOW, 50000);
if (tempPulse > lowTime) {
lowTime = tempPulse;
}
}
freq1 = ((double) 1000000) / (double (lowTime + highTime));
if (freq1 == INFINITY) {
freq = 0;
duty = 0;
}
else {
freq = freq1;
duty = (100 * (highTime / (double (lowTime + highTime))));
}
//freq = ((double) 1000000)/(double (lowTime+highTime));
//duty = (100*(highTime/(double (lowTime+highTime))));
}
/*
void readPWM(int readPin)
{
highTime = pulseIn(readPin, HIGH, 50000);
lowTime = pulseIn(readPin, LOW, 50000);
freq1 = 1000000 / ( highTime + lowTime);
if (freq1 == INFINITY) {
freq = 0;
duty = 0;
}
else {
freq = freq1;
duty = (100 * (highTime / (double (lowTime + highTime))));
}
//freq = ((double) 1000000)/(double (lowTime+highTime));
//duty = (100*(highTime/(double (lowTime+highTime))));
}
*/