2016年4月17日 星期日

使用Arduino 製作生產線counter


有時候管理者無法第一時間知道生產線的不良,這時候如果有一台警報器可以提醒管理者就很不錯了,依照慣例還是以Arduino來完成它,或許日後可以加上WIFI功能
這一些寫工作都是下班時間利用自己的時間逐步完成的。



#include // Main Loop 使用的函數
#include // IIC communication I2C使用的函數
#include // I2C LCD 使用的函數 使用LiquidCrystal目錄之下的LiquidCrystal_I2C.h
#include // SPI使用的函數【與涂書田馬達通信的函數】
#include   // EEPROM 
//#include
/*
//***********************************************************************************
//  程式設計:李進衛
//  Arduino UNO 
//  Compiler Arduino IDE
//  延續以前的程式架構採用main loop 架構
// main loop 5ms 
// 2014-06-29將microchip程式keyboard process base移植到arduino 系統
// 2014-06-29 移植check time process  to Arduino 
// 2014-06-29 compiler OK 需要再做hardware test 
// Pin 13 has a LED connected on most Arduino boards
// 因為LCD顯示速度比較慢如果還要讓文字有閃爍效果會造成MAIN LOOP的check time副程式超時時序產生錯誤,所以MAIN LOOP改為20MS【2016-03-23李進衛修改】
// 2016-03-23 新增加可以設定NG的數字使它更有彈性
//【按住P_clear按鍵--》開電--》當版本顯示完之後放開P_clear按鍵LCD顯示Set...閃爍狀態就可輸入set counter次數,設定完之後再按一次P_clear
// 確認就可以了】
//


//***********************************************************************************


*/

#define TBASE 20   // main loop time base for 20mS
// #define T100MS 20  // 
#define T20MS 20/TBASE  //4
#define T30MS 30/TBASE  //6
#define T100MS 100/TBASE
#define T150MS 150/TBASE
#define T200MS 200/TBASE
#define T250MS 250/TBASE
#define T300MS 300/TBASE  //60
//*******************2014-08-10 由PAD TEST V3 移植過來
#define P_counter 2
#define  P_clear 3
#define P_version 4
#define P_revers 5
#define P_relay 8
#define P_ss 10
#define P_LED 13
//#define swd 10
#define adcwait 20
#define ADC_margin 250  //ADC  margin
#define relayOn 1
#define relayOff 0
#define user_setcounter_address 0
#define user_counter_address 1 

const byte startport = 2; //設定起始pin為第2腳
const byte stopport = 13; //設定掃描線結束位置為13pin
int adcval = 0;
int padval = 0;
byte counter = 0; //counter NG
byte set_counter = 5;
byte keycount = 0;
byte usercounter = 0;
boolean f_keyon;
 boolean f_Warning = 0;
boolean f_setting = 0;
boolean f_user_set_counter = 0;
// boolean key4ok = 0;
// boolean key5ok = 0;
// boolean key6ok = 0;
// boolean key7ok = 0;
// boolean key8ok = 0;
// boolean key9ok = 0;
// boolean key10ok = 0;
// boolean key11ok = 0;
// boolean key12ok = 0;

boolean allok = 0;
byte keycode;
//*****************************************************
byte ledState;
boolean  Blink1HZ; //1HZ閃爍旗標
boolean Blink2HZ; //2HZ閃爍旗標
boolean TMAIN;
byte T_CNT1;
byte SQN = 0;
byte TB_100MS;
byte TB_250MS;
byte TB_500MS;
byte TB_1SEC;
byte TB_1MINS;
byte TB_1HOURS;
byte T_Blink_Count;
byte KEY_NEW = 0xff;   // = 0xFF;
byte KEY_OLD;   // = 0xFF;
byte KEY_CMD;   // = 0xFF;
byte KEY_CHT;         // = T20MS;
byte KEY_SQN  = 0;         // = 1;
boolean F_CMDON;
boolean F_KEYREP;
byte KEY_CHEN;
byte KEY_REP;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

void setup()
{
DDRD = 0x00;  //設定埠D為輸入模式
// pinMode(P_ss,OUTPUT);
pinMode(P_LED,OUTPUT); // LED output pin for output mode
pinMode(P_relay,OUTPUT); // control relay port
digitalWrite(P_LED,LOW); // LED OFF
T_CNT1 = 0;  // CLEAR T_CNT1
TMAIN = 0;
usercounter = EEPROM.read(user_setcounter_address);
if (usercounter ==0xA5)
{
set_counter = EEPROM.read(user_counter_address);
}
  //pinMode(LED, OUTPUT);
//*************************
    //****** LCD setting ********
//*************************
  lcd.begin(16,2);         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.backlight(); //點亮背光
  // Print a message to the LCD.
  lcd.setCursor(2, 0); //設定游標在第2列第0行
  lcd.print("YA Horng PE ");
  lcd.setCursor(2, 1);
  lcd.print("Lee Chin Wei");
//  Serial.println("Ya horng");
//*******************************************
//設定通信模式
//*******************************************
  Serial.begin(115200);  // 開啟UART 鮑率為 115200
 // SPI.begin();
 // SPI.setBitOrder(MSBFIRST); // MSB先送
 // SPI.setDataMode(SPI_MODE1); // setting SPI mode clock 由0--> 1 資料由負緣取樣 
 // SPI.setClockDivider(SPI_CLOCK_DIV64); // SPI clock
  
delay(2500);
lcd.clear();
   lcd.setCursor(2, 0);  //設定游標在第2列第0行
  lcd.print("Counter ");
  lcd.setCursor(2, 1);
  lcd.print(counter,DEC);

  // Disable Arduino's default millisecond counter (from now on, millis(), micros(),
  // delay() and delayMicroseconds() will not work)
disableMillis();
  // Prepare Timer1 to send notifications every 1000000us (1s)
  // On 16 MHz Arduino boards, this function has a resolution of 4us for intervals <= 260000,
  // and a resolution of 16us for other intervals
  // On 8 MHz Arduino boards, this function has a resolution of 8us for intervals <= 520000,
  // and a resolution of 32us for other intervals
//  startTimer1(1000000L);
startTimer1(20000);  // main loop setting for 20mS by Lee Chin Wei 2016-03-23 modify 
if (!digitalRead(P_clear))
{
delay(20);
if (!digitalRead(P_clear))
{
f_setting = 1;
while ( !digitalRead(P_clear));
delay(20);
}
}  
}


void read_key(void)
{
if (!digitalRead(P_counter))
{
KEY_NEW = 1;
// Serial.println("KEY_NEW=1");
    return;
if (!digitalRead(P_clear))
{
KEY_NEW = 2;
//      Serial.println("KEY_NEW=2");
          return;
}
KEY_NEW = 0xff;
 //Serial.println("KEY_NEW=0xff");
}

//************************************
//***** NG 按鍵處理
//************************************
void key1_pro(void)
{
  if (F_KEYREP ==1) // 已經執行過了就返回不再重複執行
return;
if (f_setting ==1)
{
EEPROM.write(user_setcounter_address,0xA5);
set_counter++;
} else{
counter++; 
}
  lcd.setCursor(2, 0);  //設定游標在第2列第0行
  lcd.print("Counter ");
  lcd.setCursor(2, 1);
  if (f_setting ==1)
  {
 lcd.print(set_counter,DEC);

  } else{
lcd.print(counter,DEC);
}
if ((counter >= set_counter ) &&(f_setting ==0))
{
  digitalWrite(P_LED,HIGH); // LED ON
      digitalWrite(P_relay,relayOn);
  lcd.setCursor(6, 1);
  lcd.print("Warning !!");
  f_Warning = 1;
}
}

//******************************************
//***** CLEAR counter
//******************************************
void key2_pro(void)
{
if (F_KEYREP ==1) 
return;
if ( f_setting ==1)
{
EEPROM.write(user_counter_address,set_counter);
f_setting = 0;
lcd.setCursor(10, 0);  //設定游標在第2列第0行
lcd.print("      ");
}
counter = 0;
lcd.clear();  
lcd.setCursor(2, 0);  //設定游標在第2列第0行
lcd.print("Counter ");
lcd.setCursor(2, 1);
lcd.print(counter,DEC); // 
digitalWrite(P_LED,LOW); // LED Off
digitalWrite(P_relay,relayOff); // Relay turn off
f_Warning = 0;   //clear Warning flag
}
//******************************************
//***** 顯示版本處理副程式
//******************************************
/*
void key3_pro(void)
{
if (F_KEYREP ==1)
return;
  check_version();

}  
*/
//******************************************
//***** 馬達正轉 反轉處理副程式
//******************************************
/*
void key4_pro(void)
{
if (F_KEYREP ==1)
return;
  if (f_rf == 0)
  {
    f_rf = 1;
  motor_reverse();
  }else{
    f_rf = 0;
    motor_forward();
  }
}

void key5_pro(void)
{
if (F_KEYREP ==1)
return;

}

*/


//******************************************************************************
        //;****************************
        //;*****  KEYON_PROCESS   *****
        //;****************************
        //;FOR CHECK KEY FUNCTION WHEN FIRST KEY PRESSED
        //;當KEY按住不放時,仍然只執行一次
void    KEYON_PROCESS()
{
        switch ( KEY_CMD )
        {
case 1 : key1_pro(); break;
case 2 : key2_pro(); break;
// case 3 : key3_pro(); break;
// case 4 : key4_pro(); break;
// case 5 : key5_pro(); break;
// case 6 : key6_pro(); break;
// case 7 : key7_pro(); break;
// case 8 : key8_pro(); break;
// case 9 : key9_pro(); break;
// case 10 : key10_pro(); break;
// case 11 : key11_pro(); break;
// case 12 : key12_pro(); break;
// case 13 : key13_pro(); break;
// case 14 : key14_pro(); break;
// case 15 : key15_pro(); break;
// case 16 : key16_pro(); break;
        }
}


        //;****************************
        //;*****  KEYOFF_PROCESS  *****
        //;****************************
        //;FOR CHECK KEY FUNCTION WHEN KEY RELEASED
void    KEYOFF_PROCESS()
{
        switch ( KEY_CMD )
        {
// case 1: key1_off_pro(); break;
// case 2: key2_off_pro(); break;
// case 3: key3_off_pro(); break;
// case 4: key4_off_pro(); break;
// case 5: key5_off_pro(); break;
// case 6: key6_off_pro(); break;
// case 7: key7_off_pro(); break;
// case 8: key8_off_pro(); break;
// case 9: key9_off_pro(); break;
// case 10: key10_off_pro(); break;
// case 11: key11_off_pro(); break;
// case 12: key12_off_pro(); break;
// case 13: key13_off_pro(); break;
// case 14: key14_off_pro(); break;
// case 15: key15_off_pro(); break;
// case 16: key16_off_pro(); break;
        }
}


void    KEYCHT_440()
{
        KEY_SQN = 1;
        KEYOFF_PROCESS();       // 按鍵放開的第一時間處理
}


void    initial_key()                   //.............. Step 0
{
        KEY_NEW = 0xFF;
        KEY_OLD = 0xFF;
        KEY_CMD = 0xFF;
        KEY_CHT = T20MS;
        KEY_SQN = 1;
}


void    new_old_check()                 //.............. Step 1
{
        if ( (KEY_NEW!=KEY_OLD)&&(KEY_NEW!=0XFF) )
        {
        KEY_OLD = KEY_NEW;
        KEY_CHT = T100MS;
        KEY_SQN = 2;
        }
        if ( (KEY_NEW!=KEY_OLD)&&(KEY_NEW==0XFF) )
        {
        KEY_SQN = 0;
        }
}


void    confirm_key()                   //.............. Step 2
{
        if ( KEY_NEW == KEY_OLD )
        {
 //               Serial.println("key confirm !!");
                KEY_CMD = KEY_NEW;
                F_CMDON = 1;            // 按鍵生效
                KEY_REP = T200MS;       // 原來的值 T700MS,T500MS
                KEY_CHT = T30MS;
                KEYON_PROCESS();        // 按鍵按下的第一時間處理
                KEY_SQN = 3;
        }
        else
        {
                if ( (KEY_NEW!=0xFF) || ((KEY_NEW==0xFF)&&(KEY_CHT==0)) )
                {
                KEY_OLD = KEY_NEW;
                KEY_SQN = 1;
                }
        }
}


void    hold_key()                      //.............. Step 3
{
        if ( KEY_NEW == KEY_OLD )       // === KEY REPEAT 
        {
                if (KEY_NEW==0)
                {
                        KEY_CHT = T20MS;
                        F_KEYREP = 0;           //
                        KEY_SQN = 4;            //2004.12.07 APPEND BY JEREMY(對應按鍵失效)
                }
                KEY_CHT = T30MS;
                if ( KEY_REP == 0 )
                {
                       KEY_REP  = T200MS;      // 200 ms time out
                       F_CMDON  = 1;           // 按鍵生效
                       F_KEYREP = 1;           // KEY REPEAT
  KEY_COD_PROCESS(); // 2016-03-21 by leecw Append for key on process
                }
        } else

                if ( (KEY_NEW==0xFF)&&(KEY_CHT==0) )
                {
                        KEY_OLD = KEY_NEW;
                        KEY_CHT = T20MS;
                        F_KEYREP = 0;           // CLEAR KEY REPEAT FLAG
                        KEY_SQN = 4;            //執行release_key的判斷
                }
//        else if ( KEY_NEW < KEY_OLD )                   // === 按住 X 鍵(KEY CODE較大的按鍵)再按 Y 鍵(KEY CODE較小的按鍵)
//        {
//                if ( (KEY_CHT == 0) && (KEY_NEW == 1) || (KEY_NEW == 2) )//KEY_CODE(BEND-)=1,KEY_CODE(BEND+)=2 
//                {
//                        F_KEYREP = 0;
//                        KEYCHT_440();   //須執行按鍵的動作
//                }
 //       }
//        else if ( KEY_NEW > KEY_OLD )                   // === KEY RELEASE或再按住 X 鍵(KEY CODE較大的按鍵)
//        {       
//                if ( (KEY_NEW==0xFF)&&(KEY_CHT==0) )
//                {
//                        KEY_OLD = KEY_NEW;
//                        KEY_CHT = T20MS;
//                        F_KEYREP = 0;           // CLEAR KEY REPEAT FLAG
//                        KEY_SQN = 4;            //執行release_key的判斷
//                }
//                else if ( KEY_NEW != 0xFF )
//                {
//                        if ( (KEY_CHEN==0)&&( (KEY_NEW==1)||(KEY_NEW==2) ) )    // 對應按住 BEND- 放開後迅速按 BEND+ 的處理
//                        {
//                                F_KEYREP = 0;           // CLEAR KEY REPEAT FLAG
//                                KEYCHT_440();           //
//                        }
//                }
//        }
}


void    release_key(void)                   //.............. Step 4
{        
        if ( KEY_NEW == KEY_OLD )
        {
                if ( KEY_CHT == 0 )
                KEYCHT_440();
        }
        else if ( (KEY_NEW!=KEY_OLD)&&(KEY_NEW!=KEY_CMD) )              // 對應在處理 KEY_CHT 的 timming 再按到 BEND +/-  
        {                                                               //
                if ( (KEY_CHEN==0)&&((KEY_NEW==1)||(KEY_NEW==2)) )      //
                {                                                       //
                KEYCHT_440();                                           //
                }                                                       //
                else                                                    //
                {                                                       //
                KEY_OLD = KEY_NEW;                                      //
                KEY_CHT = T30MS;                                        //
                }                                                       //
        }
        else if ( (KEY_NEW!=KEY_OLD)&&(KEY_NEW==KEY_CMD) )
        {
                KEY_OLD = KEY_NEW;
                KEY_SQN = 3;
        }
}




        //;***********************************
        //;*****  KEY CHATTER  &  CHECK  *****
        //;*****  HAVE  ANY  KEY  INPUT  *****
        //;***********************************
        //;IN     :KEY_NEW,KEY_SQN,KEY_CHT
        //;OUT    :KEY_OLD,KEY_CMD,F_KEYREP
        //;KEY_SQN =  0 --> INITIAL ALL REGISTER
        //;KEY_SQN =  1 --> CHECK KEY_NEW & KEY_OLD
        //;KEY_SQN =  2 --> KEY ON CHATTER CHECK
        //;KEY_SQN =  3 --> KEY REPEAT CHECK
        //;KEY_SQN =  4 --> KEY OFF CHATTER
        //;KEY_SQN = 32 --> 按住 X 按鍵再按 Y 鍵
        
void    KEY_CHT_PROCESS()
{
        switch ( KEY_SQN )
        {
        case  0:
                initial_key();          // *** 初始所使用的暫存器
                break;
        case  1:
                new_old_check();        // *** 檢查新碼和舊碼
                break;
        case  2:
                confirm_key();          // *** 承認按下的按鍵
                break;
        case  3:
                hold_key();             // *** 保持按鍵按下的處理
                break;
        case  4:
                release_key();          // *** 放開按鍵
                break;
        default:
                KEY_SQN = 0;
                break;
        }
}

void K_counter_add(void)
{
if (f_setting ==1)
{
set_counter++;
} else{
counter++;
}
  if ((counter >= set_counter ) &&(f_setting ==0))
  {
       digitalWrite(P_LED,HIGH);  // LED ON
      digitalWrite(P_relay,relayOn);
lcd.setCursor(6, 1);
lcd.print("Warning !!");
f_Warning = 1;
  }    
    lcd.setCursor(2, 0);  //設定游標在第2列第0行
  lcd.print("Counter ");
  lcd.setCursor(2, 1);
  if (f_setting ==1)
  {
 lcd.print(set_counter,DEC);

  } else{
lcd.print(counter,DEC);
}
  
  }

        //;*****************************************
        //;*****  KEY CODE PROCESS SUBROUTINE  *****
        //;*****************************************
        //;IN     :KEY_CMD
        //;OUT    :當KEY按住不放時,利用KEY_REP的設定,可重複執行KEY CODE動作
void    KEY_COD_PROCESS()
{
        if ( F_CMDON == 1 )
        {

        F_CMDON = 0;
                switch ( KEY_CMD )
                {
//                        case 0 : K_PITCH();     break;
                        case 1 :   K_counter_add(); break;  //K_PIT_M();     break;
//                        case 2 : K_PIT_P();     break;
//                        case 3 : K_STOP();      break;
//                        case 4 : K_SINGLE();    break;
//                        case 5 : K_TIME();      break;
//                        case 6 : K_PLYPAS();    break;
//                        case 7 : K_PTEN();      break;
//                        case 8 : K_CUE1();      break;
//                        case 9 : K_BSKIP();     break;
//                        case 10: K_FSKIP();     break;
//                        case 11: K_FBS();       break;
//                        case 12: K_FFS();       break;
//                        case 13: K_OPCL();      break;
//                        case 14: K_BPM();       break;
                }
        }
}


//******************************************************************************


void t100ms_process()
{
  if (TB_500MS ==0)
  {
    TB_500MS = 5;
    //0.5sec要處理的程式放這裡
 //     ledState ^= 1;
      Blink1HZ ^=1;  // Blink1HZ與1 互斥或  【反向的意思】
  } else {
           
           TB_500MS--;
            
  }
  
  
}

//***************************
//***** 系統時間
//***************************
void check_time()
{
  if (TB_100MS ==0)
  {
    TB_100MS = T100MS;
    t100ms_process();    
  } else {
    
            TB_100MS--;
          }
    
  if (TB_250MS ==0)
  {
      TB_250MS = T250MS;
      Blink2HZ ^=1;  // Blink2HZ與1 互斥或  【反向的意思】
      
    } else{
        TB_250MS--;
      }
  if (T_Blink_Count ==0)
  {
      T_Blink_Count = 50; //100;    
//      Blink1HZ ^=1; // Blink1HZ與1 互斥或  【反向的意思】
//      Blink2HZ ^=1; // Blink2HZ與1 互斥或  【反向的意思】
      
    } else{
        T_Blink_Count--;
        if (T_Blink_Count == 25)  //50) 
        {
//                      Blink2HZ ^=1;
       
        }
    
    }
      
  if (T_CNT1 !=0)
   T_CNT1--;
   
   if (KEY_CHT !=0)
   KEY_CHT--;
   
   if (KEY_REP !=0)
   KEY_REP--;
   


}

void display_process()
{

if (f_setting ==1)
{
              if (Blink1HZ == 1)
 {
 lcd.setCursor(10, 0);
              lcd.print("Set...");
 } else{
lcd.setCursor(10, 0);
lcd.print("      ");
 
 
}
}
    if (f_Warning ==1)
    {
    if ( Blink1HZ==1)
    {
    digitalWrite(P_LED,HIGH);
    digitalWrite(P_relay,relayOn);
    lcd.setCursor(6, 1);
    lcd.print("Warning !!");
    
    } else {
              digitalWrite(P_LED,LOW);
              digitalWrite(P_relay,relayOff);
              lcd.setCursor(6, 1);
              lcd.print("          ");
          
    }
    } 
}

//********************************************************************
//********************************************************************
//*****  Main Loop 
//*****  Program by Chin Wei Lee
//*****  Date : 2014-06 28
//********************************************************************
//********************************************************************

void loop()
{
  while (TMAIN){
check_time();   // 檢查系統時間【所有的時間處理】
read_key(); // 讀取按鍵
KEY_CHT_PROCESS(); //按鍵的反彈跳處理及按鍵的處理
        display_process();   // Warning 的處理
TMAIN = 0;
}

}

// Define the function which will handle the notifications
ISR(timer1Event)
{
  TMAIN = 1;
  // Reset Timer1 (resetTimer1 should be the first operation for better timer precision)
//    Serial.println("time interrupt 5ms");
  resetTimer1();
//  check_time();
  // For a smaller and faster code, the line above could safely be replaced with a call
  // to the function resetTimer1Unsafe() as, despite its name, it IS safe to call
  // that function in here (interrupts are disabled)
  
  // Make sure to do your work as fast as possible, since interrupts are automatically
  // disabled when this event happens (refer to interrupts() and noInterrupts() for
  // more information on that)
}



使用Arduino 製作速度警告器


#Arduino #frequency counter #Speed #33轉 #45轉
Arduino 的便利性使得大家都節省不少時間以及金錢,最近我們老大需要一台可以偵測速度變化的工具,只給我很短的時間,想來想去也只有Arduino 比較適合。
所以利用幾個網上的時間把它完成,因為上班時間實在是很忙沒有時間可以寫程式。
source code如下:


/* FreqMeasure - Example with LCD output
 * http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
 *
 * This example code is in the public domain.
李進衛 修改為我適用的程式程式最原始的出處如上 
Date:2016年3月29日05:40:06
下班時間撰寫的程式

 
 
 */
#include
#include // IIC communication I2C使用的函數
#include // I2C LCD 使用的函數 使用LiquidCrystal目錄之下的LiquidCrystal_I2C.h
//#include "eeprom_anything.h"
#define wait_stable 0
#define set_speed_flag 1 
#define read_speed_frequency 2  

//struct config_type
//{
// float fail_freq = 0.00;
//};

byte mode = 0;
byte sqn = 0;
 float readarray[12];
 float freq33min = 2.14;
 float freq33max = 2.26;
 float freq45min = 2.91;
 float freq45max = 3.09;
double sum=0;
double frequval = 0;
int count=0;
 #define P_buzzer 6
 float frequarray = 0.0;
 boolean f_stable = 0;
 boolean f_3345 = 1;
boolean f_warning = 0; 
//#include
byte ok33counter = 0;
byte ok45counter = 0;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

//LiquidCrystal lcd(5, 4, 3, 2, 1, 0);

void setup() {
  Serial.begin(57600);
  pinMode(P_buzzer,OUTPUT); // setting P_buzzer for output
  digitalWrite(P_buzzer,HIGH); // buzzer off
 // lcd.begin(8, 2);
 // lcd.print("Freq:");
   lcd.begin(16,2);         // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.backlight(); //點亮背光
  lcd.setCursor(0, 0); //設定游標在第2列第0行
  lcd.print("2016-04-08v02");
  lcd.setCursor(0, 1);
  lcd.print("LeeCW");
delay(1000);
lcd.clear();

  FreqMeasure.begin();
}



//*******************************
//空轉等待轉速穩定等8個信號
//*******************************
//
void speed_stable(void)
{
      lcd.setCursor(0,0);
      lcd.print("Waiting Stable!!");

for (int i = 0; i <8 div="" i="">
{
while(!FreqMeasure.available()); // 等待傳回可以讀計數數值
}


mode = set_speed_flag; // task to go set speed 
sqn = 0; //station = 0 

}




/*
***************************************************************
副程式名稱:speed3345read
傳回值: 沒有
設定值: f_3345 旗標
作用: 33轉,45轉的判斷
先讀進10筆資料--》判斷是33轉或者45轉
***************************************************************
*/

void speed3345read(void)
{
if (f_warning==0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("33/45 Decide!!");
}
for ( int ii=0; ii<12 div="" ii="">
{
while(!FreqMeasure.available()); // 等待傳回可以讀計數數值
frequval =  FreqMeasure.read();    // 讀取數值
    frequarray = FreqMeasure.countToFrequency(frequval); //將數值換算成頻率存到矩陣當中
readarray[ii] = frequarray;
Serial.println(readarray[ii]);
}
  for (int i=0;i<12 div="" i="">
  {
    frequarray = readarray[i];
if(frequarray >= freq33min)
{
if (frequarray <=freq33max)
{
ok33counter++;
// Serial.print("ok33counter:");
// Serial.print(i);
// Serial.print("-->");
// Serial.println(ok33counter);
}
}
/*    if ((frequarray>=freq33min)&&((frequarray freq33min))) // 測試陣列中的數量OK的是多少?
{
        ok33counter++;
Serial.print("ok33counter:");
Serial.print(i);
Serial.print("-->");
Serial.println(ok33counter);
} */
    
  }
  for (int i=0;i<12 div="" i="">
  {
    frequarray = readarray[i];
if (frequarray >= freq45min)
{
if (frequarray <= freq45max )
{
ok45counter++;
}
}
/*
    if ((frequarray>=freq45min)&&((frequarray freq45min))) // 測試陣列中的數量OK的是多少?
{
        ok45counter++;
// for debug Serial.print("ok45counter:");
// for debug Serial.print(i);
// for debug Serial.print("-->");
// for debug Serial.println(ok45counter);
} */
    
  }

if (ok33counter >ok45counter)
{
f_3345 = 1;
ok33counter = 0;
ok45counter = 0;
//                Serial.println("Speed is 33!!");
} else{
f_3345 = 0;
ok33counter = 0;
ok45counter = 0;
//                                Serial.println("Speed is 45!!");
}
ok33counter = 0;
ok45counter = 0;
mode = read_speed_frequency;
sqn = 0;
}


void read_freq_000(void)
{
// lcd.clear();
// lcd.setCursor(0,0);
// lcd.print("33/45 Test!!");
for ( int ii=0; ii<12 class="Apple-tab-span" ii="" span="" style="white-space: pre;">
//連續讀12筆資料
{
while(!FreqMeasure.available()); // 等待傳回可以讀計數數值
frequval =  FreqMeasure.read();    // 讀取數值
frequarray = FreqMeasure.countToFrequency(frequval); //將數值換算成頻率存到矩陣當中
readarray[ii] = frequarray;
lcd.setCursor(0, 1);
      lcd.print(frequarray);
      lcd.print("HZ");
 if (f_3345 ==1)
lcd.setCursor(7, 1);
lcd.print("SPEED 33");
}else {
lcd.setCursor(7, 1);
lcd.print("SPEED 45");
}
}
sqn = 1;


}

void read_freq_100(void)
{
                ok33counter = 0;
                ok45counter = 0;
if (f_3345==1) // 33 then 
{
for (int i=0;i<12 div="" i="">
{
frequarray = readarray[i];
// for debug                                                Serial.println(frequarray);

if (frequarray >= freq33min)
{
if (frequarray <= freq33max)
{
ok33counter++;
}
}
/* if ((frequarray >freq33min)&&((frequarray < freq33max)||(frequarray > freq33min))) // 測試陣列中的數量OK的是多少?
{
ok33counter++;
// for debug                                                Serial.print("OK counter is :");
// for debug                                                Serial.println(ok33counter);
} */
    
}  // 讀取陣列中的資料來判斷有超標的資料有幾筆?
if (ok33counter < 8)
{
digitalWrite(P_buzzer,LOW);
ok33counter = 0;
lcd.setCursor(0, 0);
lcd.print("33 Warning !!");
mode = set_speed_flag;
f_warning = 1;
}
ok33counter = 0;
} else 
{
for (int i=0;i<12 div="" i="">
{
frequarray = readarray[i];
if (frequarray >= freq45min)
{
if (frequarray <= freq45max )
{
ok45counter++;
}
}
// if ((frequarray >freq45min)&&((frequarray < freq45max)||(frequarray > freq45min))) // 測試陣列中的數量OK的是多少?
//if ((frequarray >freq33max)||(frequarray < freq33min)) // 測試陣列中的數量OK的是多少?
// {
// ok45counter++;
// }
    
} // 讀取陣列中的資料來判斷有超標的資料有幾筆?
if (ok45counter < 8)
{
digitalWrite(P_buzzer,LOW);
ok45counter = 0;
lcd.setCursor(0, 0);
lcd.print("45 Warning !!");
mode = set_speed_flag;
f_warning = 1;
}
ok45counter = 0;


}
sqn =0;

}
void read_freq(void)
{
// config_type config;
switch(sqn)
{
case 0: read_freq_000(); break;
case 1: read_freq_100(); break;
default : sqn = 0;
}
/*
for ( int ii=0; ii<12 class="Apple-tab-span" ii="" span="" style="white-space: pre;">
//連續讀12筆資料
{
while(!FreqMeasure.available()); // 等待傳回可以讀計數數值
frequval =  FreqMeasure.read();    // 讀取數值
frequarray = FreqMeasure.countToFrequency(frequval); //將數值換算成頻率存到矩陣當中
readarray[ii] = frequarray;
if (f_3345==1) // 33 then 
{
for (int i=0;i<12 div="" i="">
{
frequarray = readarray[i];
if ((frequarray >freq33max)||(frequarray < freq33min)) // 測試陣列中的數量OK的是多少?
{
ok33counter++;
}
    
}  // 讀取陣列中的資料來判斷有超標的資料有幾筆?
if (ok33counter >=3)
{
ok33counter = 0;
lcd.setCursor(0, 0);
lcd.print("33 Warning !!");
}
ok33counter = 0;
} else 
{
for (int i=0;i<12 div="" i="">
{
frequarray = readarray[i];
if ((frequarray >freq33max)||(frequarray < freq33min)) // 測試陣列中的數量OK的是多少?
{
ok45counter++;
}
    
} // 讀取陣列中的資料來判斷有超標的資料有幾筆?
if (ok45counter >=3)
{
ok45counter = 0;
lcd.setCursor(0, 0);
lcd.print("45 Warning !!");
}
ok45counter = 0;


}


  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 2) {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      lcd.setCursor(0, 1);
      lcd.print(frequency);
      lcd.print("HZ");
 //  Serial.println(frequency,DEC);
      sum = 0;
      count = 0;
    }
  } */





}

void loop() {




switch(mode)
{
case wait_stable: speed_stable(); break; //等待轉速穩定
case set_speed_flag : speed3345read(); break; //檢測轉速
case read_speed_frequency: read_freq(); break; //計算頻率
default : mode = 0;
}

/*
這是用來測試矩陣的讀寫判斷是否正常
2016-03-30
李進衛

*/
/*
//******************************************************************************************************
  for (int i=0;i<10 div="" i="">
  {
    frequarray = readarray[i];
    if ((frequarray freq33min)) // 測試陣列中的數量OK的是多少?
    {
            okcounter++;
      }
    
    }
//*******************************************************************************************************    
 */ 
 // speed3345read();
  
}


WEMOS D1 MINI ESP8266 製作 NTP + 網路斷線自動重置裝置

我的同事建議我將 NTP 加上網路斷線偵測可以重新reset的功能