Translate

2018年12月19日 星期三

工科技藝競賽-數位電子與全國技藝競賽-工業電子ARM開發環境

使用MCU:STM32L052R8

使用軟體為STM32CubeMX,用於快速初始化晶片與建立範例專案

使用軟體為Keil uVision5,用於編寫程式、除錯與燒錄

使用燒錄器為ST-LINK/V2

先下載MDK for STM32F0,STM32G0與STM32L0

(ARM與STMicroelectronics合作,用戶可免費使用STM32F0,STM32G0和STM32L0全功能的Keil MDK版本。)

一、先至http://www2.keil.com/stmicroelectronics-stm32/mdk下載MDK-ARM版本5.26並啟用(上述網址有啟用說明)

二、下載STM32CubeMX與ST-Link utility download link

三、開啟STM32CubeMX下載STM32L0Cube Library或直接下載完在匯進去。


 Help-Manage embedded software packages


選擇STM32L0點選最新的版本就會自動下載安裝

點選From Local...可以載入之前下載的lib



 

2018年12月4日 星期二

國產溫度控制器(配合電鍋變身舒肥機)解析-Vulcan、JetSOVI、EZPLUG

之前有想過自已用Arduino做舒肥機,所以找了很多的資料,有看到三台國產的舒肥機,看了這三台的介紹順便用外行人的眼光在解析一下供有興趣的人參考。
Vulcan 價格:3899
官網:http://store.kitchbot.com/ FB:https://www.facebook.com/KitchBot.Taiwan/
嘖嘖群眾集資:https://www.zeczec.com/projects/vulcan

JetSOVI  價格:2200
部落格:https://www.jet3c.com/
FB:https://www.facebook.com/Jet3C/

EZPLUG 價格:2280
官網:https://ezplugcooking.com/
FB:https://www.facebook.com/EZplug-Sous-Vide-Plug-%E6%99%BA%E6%85%A7%E8%88%92%E8%82%A5%E6%8F%92%E9%A0%AD-137254786874557/
嘖嘖群眾集資:https://www.zeczec.com/projects/ezplug

解析:
誕生時間:Vulcan最早,接下來是JetSOVI、EZPLUG最後

商品體積:JetSOVI > Vulcan > EZPLUG
JetSOVI:體積最大,最重。
Vulcan:體積適中。
EZPLUG:體積最小好攜帶。

外觀:Vulcan > EZPLUG >JetSOVI
Vulcan、EZPLUG:有開版
JetSOVI:3D列印

APP操作:Vulcan > JetSOVI >EZPLUG
Vulcan:可以更新食譜
JetSOVI: EZPLUG:功能最簡單

直接操作:JetSOVI > Vulcan > EZPLUG
Vulcan:三顆觸控按鍵
JetSOVI:觸控面板
EZPLUG:什麼都沒有

額外功能:Vulcan > JetSOVI=EZPLUG
Vulcan:可以控制烤箱

支援電壓:Vulcan = JetSOVI>EZPLUG
Vulcan、JetSOVI:110~220V
EZPLUG:110V

可控制功率:JetSOVI > Vulcan = EZPLUG
JetSOVI:約1650W (25A SSR)
Vulcan:網路查不到資料
EZPLUG:使用繼電器HF3FA(250V 10A)

硬體規格:
Vulcan:群登科技AI7697H(ARM Cortex M4 197MHZ、352KB SRAM、4MB Flash、Wifi、BLE)
JetSOVI :Arduino nano(Atmel ATmega328P 16MHZ 、2KB SRAM、32KB Flash)外加ESP8611(WIFI)、3.2吋解控螢幕
EZPLUG:查無資料

2018年12月3日 星期一

2018年11月28日 星期三

透過Execl VBA將資料寫進google sheet(import or send data from Excel to Google sheet)

參考:透過Excel將資料寫進google sheet(import or send data from Excel to Google sheet)

詳細的使用方法上述參考網址都有,就不在敘述。

使用上的問題,當有修正Google Apps Script的程式時除了要重新發佈->部置為網路應用程式外專案版本也要變動。不然會一直是修正前的程式碼在執行。

可以將Google的試算表傳給任何人,當Excel上傳資料後,Google試算表約1~3秒就會更新。適合即時回報統計數值。

1、VBA副程式

Public Sub sendData2GoogleSheet()
    On Error GoTo handleerr
    num1 = Sheet1.Range("E2") '將excel的E2的欄位資料丟進num1的變數中
    num2 = Sheet1.Range("F2") '將excel的F2的欄位資料丟進num2的變數中
    num3 = Sheet1.Range("G2") '將excel的G2的欄位資料丟進num3的變數中
    num4 = Sheet1.Range("H2") '將excel的H2的欄位資料丟進num4的變數中
    num5 = Sheet1.Range("I2") '將excel的I2的欄位資料丟進num5的變數中
    num6 = Sheet1.Range("J2") '將excel的J2的欄位資料丟進num6的變數中
    num7 = Sheet1.Range("K2") '將excel的K2的欄位資料丟進num7的變數中
    num8 = Sheet1.Range("L2") '將excel的L2的欄位資料丟進num8的變數中
   '將資料寫進googlesheet
    Set WinHttp = CreateObject("WinHttp.WinHttpRequest.5.1")
    postData = "method=write&snum1=" & num1 & "&snum2=" & num2 & "&snum3=" & num3 & "&snum4=" & num4 & "&snum5=" & num5 & "&snum6=" & num6 & "&snum7=" & num7 & "&snum8=" & num8  '&與變數之間要空一格
    WinHttp.Open "POST", "這裡請填上你發佈的網路應用程式的網址", False
    WinHttp.setRequestHeader "authority", "script.google.com"
    WinHttp.setRequestHeader "User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    WinHttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
    WinHttp.send postData
    MsgBox "傳送成功"
    Exit Sub
handleerr:
    MsgBox "傳送失敗"
 
End Sub

2、Google Apps Script

var sheet1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1"); 
 
function doPost(e) {
  var para = e.parameter, method = para.method; 
  if (method == "write") {
    write_data(para);
  }
}
function write_data(para) {
  var num1 = para.snum1,num2 = para.snum2,num3 = para.snum3,num4 = para.snum4,num5 = para.snum5,num6 = para.snum6,num7 = para.snum7,num8 = para.snum8; 
  var date = new Date();
  var now = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
  sheet1.getRange(4,2).setValue(num1);
  sheet1.getRange(5,2).setValue(num2);
  sheet1.getRange(6,2).setValue(num3);
  sheet1.getRange(7,2).setValue(num4);
  sheet1.getRange(8,2).setValue(num5);
  sheet1.getRange(9,2).setValue(num7);
  sheet1.getRange(10,2).setValue(num8);
  sheet1.getRange(3,2).setValue(num6);
  sheet1.getRange(1,2).setValue(now);
}

2018年10月3日 星期三

Excel VBA選擇COM Port讀取Arduino資料

請先學習Excel VBA 尋找可用的RS232 port利用Excel VBA利用串列埠RS232讀取Arduino資料

新增一個NETComm1、TextBox1、CommandButton1、CommandButton2、ComboBox1、Label1

備註:TextBox1屬性MultiLine請設為True



表單畫面如下:

程式碼:

Private Sub CommandButton1_Click()
    On Error Resume Next
    NETComm1.SThreshold = 1
    NETComm1.RThreshold = 1
    NETComm1.CommPort = ComboBox1.Text
    If NETComm1.PortOpen = False Then  'if the serial port is closed
        NETComm1.PortOpen = True       'open the serial port
        CommandButton1.Enabled = False
    End If
    If Err Then MsgBox Error$, 48
End Sub

Private Sub CommandButton2_Click()
    'Close serial port on exit
    On Error Resume Next    'Error handler
    
    If NETComm1.PortOpen = True Then    'check if the serial port is open
        NETComm1.PortOpen = False       'close the serial port
    End If
    If Err Then MsgBox Error$, 48     'Display error in message box
    End
End Sub


Private Sub NETComm1_OnComm()
    Static Buffer As String
    Dim CRLFPos As Integer
    Buffer = Buffer & NETComm1.InputData 'or whatever name you use for the instance of NETComm
    
    CRLFPos = InStr(Buffer, vbCr)
    If CRLFPos > 0 Then
        Dim MyData As String
        d = Now()
        MyData = d & Mid(Buffer, 1, CRLFPos - 1) & vbCrLf
        TextBox1.Text = TextBox1.Text & MyData
        Buffer = ""
    End If
End Sub

Private Sub UserForm_Initialize()
    Dim i As Byte
    For i = 1 To 9
        If IsComPortAvailable(i) = True Then
            ComboBox1.AddItem i
        End If
    Next
End Sub

Private Sub UserForm_Terminate()
    'Close serial port on exit
    On Error Resume Next    'Error handler
    
    If NETComm1.PortOpen = True Then    'check if the serial port is open
        NETComm1.PortOpen = False       'close the serial port
    End If
    If Err Then MsgBox Error$, 48     'Display error in message box
    
End Sub
Function IsComPortAvailable(ByVal portNum As Integer) As Boolean
    Dim fnum As Integer
    On Error Resume Next
    fnum = FreeFile
    Open "COM" & CStr(portNum) For Binary Shared As #fnum
    If Err = 0 Then
        Close #fnum
        IsComPortAvailable = True
    End If
End Function



(Arduino程式碼在「利用Excel VBA利用串列埠RS232讀取Arduino資料」)文章內 

請選擇本身電腦Arduino com port

執行畫面:



Excel VBA 尋找可用的RS232 port

參考:VB如何得知可用的RS232 Port?

VBA 新增表單並新增一個CommandButtor1、ComboBox1

程式碼如下:

 
Private Sub CommandButton1_Click()
    End
End Sub

Private Sub UserForm_Initialize()
    Dim i As Byte
    For i = 1 To 9
        If IsComPortAvailable(i) = True Then
            ComboBox1.AddItem i
        End If
    Next
End Sub
Function IsComPortAvailable(ByVal portNum As Integer) As Boolean
    Dim fnum As Integer
    On Error Resume Next
    fnum = FreeFile
    Open "COM" & CStr(portNum) For Binary Shared As #fnum
    If Err = 0 Then
        Close #fnum
        IsComPortAvailable = True
    End If
End Function

執行畫面:



2018年10月2日 星期二

Excel在工作表新增 VBA控制項

Excel 2007-開發人員-設計模式是反灰無法使用



步驟一:Excel 2007-開發人員-Visual Basic 出現Microsoft Visual Basic-Book1縮小後就可以看到Excel 2007-開發人員-設計模式可以使用

Excel 2007-開發人員-插入-表單控制項

選擇表單控制項-按鍵

在工作表單空白處畫出一個按鍵-指定巨集-新增

巨集存放在Book1

模組自動會新增一個Module1

在程式碼新增

 
Sub 按鈕1_Click()
   MsgBox "第一個範例"
End Sub




回到工作表按下「按鈕一」跑出警告畫面


2018年10月1日 星期一

Excel VBA開啟檔案後自動執行表單

當已經設計好VBA表單,希望打開Excel檔就執行可以在VBAProject-Microsoft Excel物件-ThisWorkbook的程式碼中新增下列程式碼





Private Sub Workbook_Open()
    UserForm1.Show '表單名稱.show
End Sub

利用Excel VBA利用串列埠RS232讀取Arduino資料

使用:NetCommOCX

我的電腦係win7 32位元 請至   Updated installer for Windows 7


依NETCommOCX Information Page介紹安裝以系統管理員身分執行Setup.exe








Excel 2007 -->開發人員-->Visual Basic-->






新增一個NETComm1、TextBox1、CommandButton1、CommandButton2

NETComm1的commport記得要填上arduino使用的COM

將下列程式碼複制到VBA程式碼

Private Sub CommandButton1_Click()
    On Error Resume Next
    NETComm1.SThreshold = 1
    NETComm1.RThreshold = 1
    NETComm1.CommPort = 4
    If NETComm1.PortOpen = False Then  'if the serial port is closed
        NETComm1.PortOpen = True       'open the serial port
    End If
    If Err Then MsgBox Error$, 48
End Sub

Private Sub CommandButton2_Click()
    'Close serial port on exit
    On Error Resume Next    'Error handler
    
    If NETComm1.PortOpen = True Then    'check if the serial port is open
        NETComm1.PortOpen = False       'close the serial port
    End If
    If Err Then MsgBox Error$, 48     'Display error in message box
    End
End Sub

Private Sub NETComm1_OnComm()
    Dim d As Date
    Static Buffer As String
    Dim CRLFPos As Integer
    Buffer = Buffer & NETComm1.InputData 'or whatever name you use for the instance of NETComm
    
    CRLFPos = InStr(Buffer, vbCr)
    If CRLFPos > 0 Then
        Dim MyData As String
        d = Now()
        MyData = d & Mid(Buffer, 1, CRLFPos - 1) & vbCrLf
        TextBox1.Text = TextBox1.Text & MyData
        Buffer = ""
    End If
End Sub
Private Sub UserForm_Terminate()
    'Close serial port on exit
    On Error Resume Next    'Error handler
    
    If NETComm1.PortOpen = True Then    'check if the serial port is open
        NETComm1.PortOpen = False       'close the serial port
    End If
    If Err Then MsgBox Error$, 48     'Display error in message box
    
End Sub

Arduino接線圖


Arduino端程式碼

#include <DHT.h>
#define DHTPIN 2    // 設定DHT的接腳
#define DHTTYPE DHT11   // DHT 11 定義DHT的類型為DHT11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(9600);
  //Serial.println("DHT11 test!");
  dht.begin(); //啟動DHT
}
 
void loop() {
  // 每次偵測間隔2秒
  char ch=13;
  delay(2000);
  
  //讀取濕度
  float h = dht.readHumidity();
  //讀取攝氏溫度
  float t = dht.readTemperature();
  //讀取華氏溫度
  float f = dht.readTemperature(true);
 
  //檢查是不是有讀到資料
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor! \n");
    return;
  }
  Serial.print("Humidity:");
  Serial.print(h,1); //顯示到小數點後一位
  Serial.print("%/");
  Serial.print("Temperature:");
  Serial.print(t,1);//顯示到小數點後一位
  Serial.print("C");
  Serial.print(ch);

}

Arduino透過串列埠傳送溫溼度數值給電腦的Excel VBA


2018年9月17日 星期一

荖葉月平均售價

數值係本身出售給盤商的月收入除於月產量(大、小支),非每市都有交易。以上數值僅供考慮種植的農民參酌用。(農糧署統計99年彰化縣荖葉年產量 14524公斤/公頃=24206台斤/公頃=2420台斤/分。

民國99年農糧署調查特用作物生產成本

彰化縣荖葉年產量 14524公斤/公頃=24206台斤/公頃=2420台斤/分

生產成本1531460元/公頃=153146元/分

荖葉每台斤生產成本153146/2420=63.28元/台斤

106年平均售價171.8元/台斤。

107年平均售價125.9元/台斤。





2018年7月23日 星期一

Arduino UNO R3 自製Library RS232通訊

參考:葉難Arduino撰寫自已的程式庫如何編寫ARDUINO LIBRARY

將自已寫的Arduino UNO R3 使用自建C函式庫改寫成Library

UART相關設定參考:http://coopermaa2nd.blogspot.com/2011/07/5-usart.html 在arduino\libraries資料夾下新增一個自已的函式庫資料夾RS232


USART 暫存器

UCSR0A 這個暫存器中,比較重要的是 RXC0, TXC0, UDRE0 這三個旗號:

bit7:RXC0: USART Receive Complete,當 receiver buffer 中有未讀取的資料時,這個旗號會豎起來,當資料被讀走時,旗號會清除。

bit6:TXC0: USART Transmit Complete,當 Shift Register 的資料被傳送出去,而且 transmit buffer (UDR0) 中也沒有資料時,這個旗號會豎起來。

bit5:UDRE0: USART Data Register Empty,當 transmit buffer (UDR0) 準備好放下一個要傳送的資料時,這個旗號會豎起來。





while(!(UCSR0A & 0b00100000)){ }//等待bit5變成1,否則一直等待。等待RS232空閒。
void RS232::put_string(char *string) {
   while(*string) { 
            while(!(UCSR0A & 0b00100000)) { } 
            UDR0=*string++; 
   }
 }
while(!(UCSR0A & 0b10000000)){}//等待bit7變成1,否則一直等待。一直等待RS232傳送資料過來。
char RS232::get_char() {
   char recchar;
   while(!(UCSR0A & 0b10000000)){}
   recchar=UDR0;
   put_char(recchar);
   return recchar; 
}


新增一個RS232.h內容如下:

#ifndef RS232_H
#define RS232_H
#include <avr/interrupt.h> 
class RS232 {
public:
 RS232();
 ~RS232();
 void begin(unsigned long baud);
 void put_char(char str);
 void put_string(char *string);
 char get_char(void); 

};
#endif
新增一個RS232.cpp內容如下:
#include <RS232.h>
RS232::RS232(){ 
}
RS232::~RS232(){ 
}
void RS232::begin(unsigned long baud){
    unsigned int baud_setting=(F_CPU/16/baud)-1;
    UBRR0H=(unsigned char)(baud_setting>>8);
    UBRR0L=(unsigned char)baud_setting;
    UCSR0B=0B00011000;//啟用transmitter和receiver,並且不使用中斷。RXEN0=1,TXEN0=1,RXCIE0=0,TXCIE0=0。
    UCSR0C=0B00000110;//設定frame format為N,8,1
}
void RS232::put_string(char *string)
{
    while(*string)
    {
        while(!(UCSR0A & 0b00100000))
        {  }
        UDR0=*string++;
    }
}
void RS232::put_char(char str)
{
       while(!(UCSR0A & 0b00100000))
       {  }
       UDR0=str;
}
char RS232::get_char()
{
 char recchar;
 while(!(UCSR0A & 0b10000000)){}
 recchar=UDR0;
 put_char(recchar);
 return recchar;
}


新增一個檔案keywords.txt內容如下:
RS232 KEYWORD1
begin KEYWORD2
put_char KEYWORD2
put_string KEYWORD2
get_char KEYWORD2
新增一個資料檔案example\rs232_lib.ino內容如下:
#include <RS232.h>
RS232 RS232;
void setup(){
  RS232.begin(9600);
}
void loop(){
  char char_reg;
  char_reg=RS232.get_char();
  RS232.put_char('Z');
  RS232.put_string("Hello World");
}

2018年7月19日 星期四

Arduino UNO R3藍牙實驗 App Inventor2 透過藍牙傳送訊號給 Arduino

參考:[雙A計劃] Part0:App Inventor 透過藍牙傳送訊號給 Arduino

材料清單:
1、Android手機
2、Arduino UNO R3
3、藍芽模組(BT06),請仿照電路圖接線(藍芽RX接Arduino D5、藍芽TX接Arduino D4、藍芽VCC接Arduino 5V、藍芽GND接Arduino GND)




'
接完線依照文章內容打上程式,編輯後上傳到板子上。




#include <SoftwareSerial.h>
#include <Wire.h>  //引用二個函式庫SoftwareSerial及Wire SoftwareSerial 
SoftwareSerial I2CBT(4,5); //定義PIN4及PIN5分別為Arduino RX及TX腳位接藍芽的TX腳位與RX腳位 
void setup() { 
  Serial.begin(9600); //Arduino起始鮑率9600 
  I2CBT.begin(9600); //藍牙鮑率9600
  //(注意!此鮑率每個藍牙晶片不一定相同,請先確認完再填寫進去) 
} 

void loop() { 
  byte cmmd[20]; 
  int insize; 
  while(1){ 
  if ((insize=(I2CBT.available()))>0)
  {  //判斷有沒有訊息接收 
    Serial.print("input size = "); 
    Serial.println(insize);  //顯示接收多少訊息 
    for (int i=0; i<insize; i++) {
      Serial.print(cmmd[i]=char(I2CBT.read()));//將接收的訊息顯示出來
      Serial.println(" ");  
    }//if
  } //for 
  }//while
}






2018年7月18日 星期三

Arduino 藍芽BT06(相容HC06)測試AT指令,行結尾使用NL&CR

BT06從淘寶買來的相容HT06

參考資料:http://coopermaa2nd.blogspot.com/search?q=bluetooth

參考[雙A計劃] Part1:App Inventor 經由藍牙控制 Arduino LED 亮滅做實驗這個實驗電路也很簡單四條線,一開始接完燒錄完程式,手機按BT List沒有反應。最後發現原來手機要開啟藍芽功能,先去連線Arduino的藍芽輸入PIN碼才能使用。

後來參考HC-05與HC-06藍牙模組補充說明(三):使用Arduino設定AT命令去使用裡面的接線,去測試一下我的藍牙模組有沒有反應,一開始輸入AT也是沒有反應,
後來去修改通訊速率一個一個試都沒有反應。有看到HC-06要使用沒有行結尾、HC-05要使用\n\r行結尾。最後設定使用\n\r輸入AT有反應了。

雖然BT-06相容HC-06但行結尾是相容HC-05。

參考[雙A計畫]藍牙模組(HC05、HC06)常見的指令使用教學裡的電路圖接線,用arduino IDE的序列埠監控視窗,行結尾使用NL&CR 。
AT:用於確認通訊。
AT+VERSION:查看韌體版本
AT+NAMEOOOO:設定模組的識別名稱。

AT+PINOOOO:更改配對密碼。假如你不想讓其他人輕易地連接到你的藍牙裝置,可以透過這個AT命令修改配對密碼。



2018年7月9日 星期一

Arduino UNO R3 4×4鍵盤模組實驗

參考:https://swf.com.tw/?p=917

利用Time 1中斷,每0.1秒去掃描看沒有按鍵被按。
Time中斷可參考http://tomyam-yang.blogspot.com/2017/06/arduino-timer-as-counter.html

提升電阻參考https://www.arduino.cc/en/Tutorial/DigitalPins

volatile char key_pad;因為key_pad變數使用在中斷內如果不使用volatile去定義,有可能這一次編譯可以正常執行,下一次編譯卻有問題,詳細說明可參考http://newscienceview.blogspot.com/2013/09/c-volatile.html

將多維陣列keymap[][]傳入副函式scan_key的方法如下:
key_pad=scan_key(KEY_COLS,KEY_ROWS,(char *)keymap,colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,*keymap,colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,keymap[0],colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,&keymap[0][0],colPins,rowPins);

陣列的參數傳遞可以參考C陣列[C++]如何將多維陣列傳入副函式二維陣列與雙重指標之間的關係


char scan_key(byte,byte,char *,byte *,byte *);
#define KEY_ROWS 4 // 按鍵模組的列數
#define KEY_COLS 4 // 按鍵模組的行數
const byte colPins[KEY_COLS] = {9, 8, 7, 6};     // 設定「行」腳位
const byte rowPins[KEY_ROWS] = {13, 12, 11, 10}; // 設定「列」腳位
const char keymap[KEY_ROWS][KEY_COLS] = {
  {'A', '7', '8', '9'},
  {'B', '4', '5', '6'},
  {'C', '1', '2', '3'},
  {'D', 'E', 'F', '0'}
};
volatile char key_pad;
void setup() {
 byte i;
//設定中斷1參數:
  TCCR1A=0x00;
  TCCR1B=0b00000101;//設定除頻1024 15625HZ 
  TCNT1=-1562;      //約0.1秒掃描一次
  TIMSK1 |=0x01;    //啟動Timer中斷

  key_pad=0;
  for ( i = 0; i <= 3; i++) {
    pinMode(rowPins[i], INPUT);
    pinMode(colPins[i], OUTPUT);
    digitalWrite(colPins[i], HIGH);
    digitalWrite(rowPins[i], HIGH);//啟動上拉電阻
  }
  Serial.begin(9600);
}

void loop() {
  while(key_pad)
  {
    Serial.println(key_pad);
    key_pad=0;
  }
}
ISR(TIMER1_OVF_vect)
{
  TIMSK1 &=0xfe;
  key_pad=scan_key(KEY_COLS,KEY_ROWS,(char *)keymap,colPins,rowPins);
  TCNT1=-1562;
  TIMSK1 |=0x01;
 }
 
char scan_key(byte col,byte row,char *key_map,byte *col_pin,byte *row_pin)
{
  unsigned long time_;
  byte i,j;
  byte scanVal;   // 暫存掃描到的按鍵值low or high
  time_=millis();
  for (i = 0; i < row; i++) { //按著不放的情況下不用理它
    scanVal=digitalRead(*(row_pin+i));
    if (scanVal == LOW)
    {
      return 0;   
    }
  }
  for (i = 0; i < row; i++) {
    for (j = 0; j < col; j++) {
      digitalWrite(*(col_pin+j),LOW);
      scanVal=digitalRead(*(row_pin+i));
      if (scanVal == LOW) {    // 如果輸入值是「低電位」…      
        for(;;)
        {
          if((millis()-time_)>1000)
          {
            return 0;
          }
          delay(100);
          scanVal=digitalRead(*(row_pin+i));
          if (scanVal == LOW)
          {
            return *(key_map+i*row+j);
          }
        }
      }
      digitalWrite(*(col_pin+j),HIGH);    
    }
  }
  return 0;
 }

2018年7月5日 星期四

Arduino UNO R3 使用自建C函式庫

參考資料:https://arduino.stackexchange.com/questions/946/how-to-call-c-functions-from-arduino-sketch

UART的使用可以參考http://tomyam-yang.blogspot.com/2017/06/arduino-timer-as-counter.html


要在arduino主程式使用c函式庫,需要把函式庫放在arduino/libraries資料夾下。


並在主程式使用extern "C"{} include 函式


我在libraries底下建一個資料夾放我的.c與.h檔,分別是io.h、iom328p.h、serial.c、serial.h


io.h與iom328p.h是內建的,是定義arduino uno r3的參數,但當你使用自建c函式庫驗證會找不到,所以就把它放進來同一個資料夾內。


底下的程式是自建uart程式,bitrate:9600。

主要副程式

void uart9600_setup(); //初始設定

void serial_put(char *string); //輸出字串

char serial_get(void);//取的字元

void serial_putchar(char string);//輸出字元

主程式:


extern "C"{
#include <serial.h>
}
char rechchar;
char message[]="Hello World";
void setup() {
  // put your setup code here, to run once:
  uart9600_setup();
  serial_put(message);
}

void loop() {
    rechchar=serial_get();
}
serial.c

#include <iom328p.h>
#include <io.h>
void serial_put(char *string)
{
   while(*string)
   {
      while(!(UCSR0A & 0b00100000))
      {  }
      UDR0=*string++;
   }
}
void serial_putchar(char string)
{

      while(!(UCSR0A & 0b00100000))
      {  }
      UDR0=string;
}
char serial_get()
{
  char recchar;
  while(!(UCSR0A & 0b10000000))
  {

  }
  recchar=UDR0;
  //UDR0=*recchar;
  serial_putchar(recchar);
  return recchar;
}
void uart9600_setup()
{
   //unsigned int baud_setting=103;
   UBRR0H=(unsigned char)0;
   UBRR0L=(unsigned char)103;
   UCSR0B=0B00011000;//啟動接收中斷、啟動傳送接收
   UCSR0C=0B00000110;
}
ISR(USART_RX_vect)
{
  char ReceivedChar;
  ReceivedChar=UDR0;
  UDR0=ReceivedChar;
}
serial.h


void uart9600_setup();

void serial_put(char *string);

char serial_get(void);

void serial_putchar(char string);


















2018年7月4日 星期三

Arduino UNO LCD 2004A I2C

參考資料:https://makerpro.cc/2017/02/how-arduino-use-i2c-to-control-lcd-module/

這個看起來很簡單只需接四條線,也有範例程式,但花了我快一個星期才試好。最後發現是LCD出廠把光源調到最亮,字才會跑不出來。最後也是去購買的拍賣看到留言才知道問題。
參考資料用的I2C位址係0x27,因我使用的LCD I2C晶片不一樣所以不同。
可以參考https://docs.labs.mediatek.com/resource/linkit7697-arduino/en/tutorial/driving-1602-lcd-with-pcf8574-pcf8574a

PCF8574A這個IC的位址0X3f
PCF8574這個IC的位址0X27
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR    0x3f  // 定義I2C使用PCF8574A這個IC的位址
// 其實位址可以利用A0,A1或A2改變
// 定義LiquidCrystal函式庫裡LCD各個腳位
#define BACKLIGHT_PIN 3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,BACKLIGHT_PIN, POSITIVE);
void setup() {
  lcd.begin(20,4);        // 4行,每行20個字
  lcd.setBacklight(HIGH); // 開啟LCD背光,要關閉就用LOW
  lcd.setCursor ( 0, 0 );            // 到第一行第一個字
  lcd.print("hello, world!");
}
 int n = 1; // 顯示LCD刷新次數
 void loop() {
  lcd.noCursor();
  lcd.setCursor (16,3);         // 到第四行的第16個字元
  lcd.print(n++,DEC);           // 更新次數
                                // 覆蓋前一個數字
  delay(500);                   // 等待半秒鐘後更新
  lcd.cursor();
  delay(500);
}

2018年1月15日 星期一

105-106年荖葉進口量與平均價格






從圖所示,進口量其實跟平均價格趨勢一致。價格好進口量就多,價格差進口量就少。

當國內價格高出一定值時,進口就大量進來國內,進口量與產地價格就會趨近。

所以是國內價格影響進口量還是進口量影響國內價格。國內價格低的時候是國內價格影響進口量的成份大,反之國內價格高時是進口量影響國內價格的成份大。