2016年4月17日 星期日

使用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();
  
}


2016年3月24日 星期四

鄉下的野菜

每一個星期總是回家看看爸爸和媽媽,在住家附近總是看到許許多多的野菜
這一棵花很眼熟,出現在我們的千元紙鈔上它叫雞角刺

這一棵叫做野人參


不知名的香草

2016年3月12日 星期六

眼鏡型放大鏡

2016-03-12 上網購買了一支眼鏡型放大鏡很炫,只對於需要從事精密工作的人很好用
戴起來一點像外星人!!

自製AA電池行動電源

#AA電池 #AA  #行動電源  # AA行動電源 #AA電池行動電源  #40元行動電源 #50元行動電源
有一天我突發奇想為何不製作一個可以使用最普遍的AA電池製作一個手機平板都可以使用的行動電源,既然有了想法就要實現它。
所需要的零件
1. DCto DC 在露天網站購買的,20元。
2. AA電池盒在49五金行買的,20元。

DC to DC 升壓型的

電池是在49五金行買的20元
焊接之後就可以使用了




使用HTC手機測試是OK的可以使用


再來使用平板電腦測試也是可以使用


大功告成!!


春卷

#春卷 #吃春卷 
2016-03-06
真是【青操】!!



這是我的最愛


每年這個時候岳母都會吃春卷,今年當然沒有例外。


豬肝菠菜湯

#豬肝 #粉肝  #菠菜  #菠菜豬肝湯
這是傳說中的#粉肝


菠菜這是岳父大人自己種的有機菠菜
好久沒有自己煮菜了,今天心血來潮煮了一鍋菠菜豬肝湯。。。。

2015年8月29日 星期六

如何使用Arduino 替代 NI USB-6501 DAQ

#Arduino
#DAQ
#Labview
#Arduino UNO
#NI USB-6501

如何使用Arduino 替代 NI USB-6501 DAQ
所需的硬體以及軟體如下:
Arduino UNO
USB to TTL
Arduino IDE
USB to TTL驅動程式
LABVIEW
2011年版本。

這一個Project 最主要的目的是要使用Arduino取代NI USB6501 的DAQ
使用Arduino的方案可以節省許多成本。
Labview主程式碼如下圖:

步驟:
1.      建立Arduino的串列埠使他可以透過RS232通信界面藉由USB to TTL跟LABVIEW溝通。
所需的設定如下:
在這個專案中我設定的鮑率是每秒115200 bits
2.      撰寫 與LABVIEW通信的函數
Labview是一種資料流概念的程式語言所以一定要記得下列步驟:
打開-->讀/寫-->關閉
將料寫入RS232送到Arduino
關閉RS232 COM  port

Receive_data :接受來自於LABVIEW的通信命令。
Test_do_data : 處理命令的工作。
/*
Program by Lee Chin Wei
Date : 2015-06-29
這是使用Labview 控制Arduino 來取代NI 的DAQ
Port D 為輸出數位IO
prot C 為類比輸入IO
通信格式:
0x55,0xAA,0xXX,0xXX

*/
#include
//#include // IIC communication 
//#include // LCD 

//#define A0_Command  0x10   //A0采集命令字
//#define A1_Command  0x11   //A1采集命令字
//#define D0_Command  0x20   //D0采集命令字
//#define D1_Command  0x21   //D1采集命令字
#define portb_output 0x0b
#define portc_input 0x0c
#define portd_output 0xd

byte comdata[4]={0};      //定义数组数据,存放串口接收数据

int AD_Value=0;          //AD转换后的数字量
float float_AD_Value;    //数字量换算成浮点电压量
int D_Value=0;           //数字量测量的数据
byte PB_data = 0;
byte PD_data = 0;
byte PC_data = 0;
byte PCACK = 0;
byte comport = 0;
byte pdata = 0;
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address定義LCD的腳位

void receive_data(void);      //接收串列資料
void test_do_data(void);         //測試串列資料是否正確並更新資料

void setup()
{
//  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("Reset!! ");
//  lcd.setCursor(2, 1);
//  lcd.print(" ");  // show the Jig version
//delay(2000);    //延遲2秒
//lcd.clear();

  Serial.begin (115200); //(9600);    
//  pinMode(2, INPUT);
//  pinMode(3, INPUT);
  DDRB = 0b00111111;
  DDRC = 0x00;
  DDRD = 0b11111100;

 // DDRD = 0xFF; //setting for output
 // PORTD = 0xFF;  // PORTD OUTPUT 0XFF HIGHT
}
void loop()
{


//          digitalWrite (8,HIGH);

  if  (Serial.available() > 0 )   //不斷的檢查串列埠是否有資料

   {
//        PCACK = Serial.read();
//        if (PCACK == 0x12)
//        {
// lcd.setCursor(2, 0); //設定游標在第2列第0行
// lcd.print(PCACK);

// Serial.println(0x34);
 //         digitalWrite (8,LOW);
         receive_data();            //接收串列的資料
        test_do_data();               //測試資料是否正確並更新
//        }
   }
}

void receive_data(void)    
{
   int i ;
   for(i=0;i < 4;i++)
   {
 //     while (Serial.available() == 0);
      comdata[i] =Serial.read(); //將RS232資料讀進buffer 共4bytes
      //延遲一下,讓串列暫存器準備下一個位元,如果不延遲可能會導致資料遺失。
       delay(2);
   }
         comport = comdata[2];
         pdata = comdata[3];
// lcd.setCursor(5, 1); //設定游標在第2列第0行
// lcd.print(comport);
// lcd.setCursor(7, 1); //設定游標在第2列第0行
// lcd.print(pdata);
 
}

void test_do_data(void)
{
if ((comdata[0] == 0x55)&&(comdata[1] ==0xAA))
{
//      digitalWrite(8,HIGH);
     switch (comport)
     {
         case portb_output :                         // portb for output
              { PB_data = pdata;
               PORTB = PB_data;                      //
//  lcd.setCursor(0, 1); //設定游標在第2列第0行
//  lcd.print(1);
//               Serial.println(0x34);
               break;
              }
       case portc_input :
             {  PC_data = pdata;
               PORTC = PC_data;  //comdata[3];
 // lcd.setCursor(1, 1); //設定游標在第2列第0行
 // lcd.print(2);
//               Serial.println(0x34);
               break; }
       case portd_output :
             {  PD_data = pdata;
               PORTD = PD_data;
  //             digitalWrite (8,LOW);
  //             Serial.println(0x34);
  //lcd.setCursor(2, 1); //設定游標在第2列第0行
  //lcd.print(3);
             
               break; }
        defualt :
        {
//  lcd.setCursor(3, 1); //設定游標在第2列第0行
//  lcd.print("Defual");
//               Serial.println(0x34);
         break;}
       }
}  //if comdata == 0x55&& 0xAA
}



如何使用終端機軟體收集來自於Arduino的資料

  將治具使用Micro USB cable 連上電腦 開啟終端機軟體 選擇 Serial🡪按下OK File🡪Log…  設定log file要存放位置,建議檔案名稱直接取名為*.CSV 例如:20231224.csv 按下治具Reset按鍵開始收集資料