2018年8月23日 星期四

arduino+DS3231時鐘+0.96OLED or I2C_LCD模組


參考文章
【自造學堂】如何用Arduino x RTC完成LCD時間顯示?
*0*RTC(即時時鐘)模組*0* 如何更新 DS3231 RTC 模組的時間與大型數字時鐘製作

需要安裝資料庫
for DS3231
(下載後解壓縮安裝)  DS3231_TEST

for 0.96OLED
(資料庫搜尋安裝)      Adafruit_GFX
(資料庫搜尋安裝)      Adafruit_SSD1306

for I2C LCD
(資料庫搜尋安裝)      LiquidCrystal_I2C

額外經驗
如何把1變成01(補0)
C語言Printf 自動補0
Topic: Leading zeros for seconds coding

之後要研究的
按鈕改時間設定
https://github.com/tehniq3/oled_096_128x64_i2c_RTC_animated-clock
http://ruten-proteus.blogspot.com/2017/08/ds3231-rtc-iiclcd-clock.html



程式碼-DS3231時鐘+0.96OLED
#include <DS3231.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//時鐘設定
DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
byte year, month, date, DoW, hour, minute, second;

//OLED設定
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//螢幕設定,定義顯示高度跟寬度
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

char buffer [16];
char time [16];

void setup() {
  // Start the I2C interface
  Wire.begin();
  //第一次使用要設定以下時間,之後就可以不用設定了
  //Clock.setSecond(00);//Set the second
  //Clock.setMinute(25);//Set the minute
  //Clock.setHour(16); //Set the hour
  //Clock.setDoW(4); //Set the day of the week
  //Clock.setDate(23); //Set the date of the month
  //Clock.setMonth(8); //Set the month of the year
  //Clock.setYear(17); //Set the year (Last two digits of the year)
  // Start the serial interface
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.clearDisplay();
}

void loop() {
  int sec,minute,hour,date,month,year,temperature;
  sec=Clock.getSecond();
  minute=Clock.getMinute();
  hour=Clock.getHour(h12, PM);
  date=Clock.getDate();
  month=Clock.getMonth(Century);
  year=Clock.getYear();

  temperature=Clock.getTemperature();

  sprintf(time,"20%02u-%02u-%02u",year,month,date); //設定印出01,02,而非1,2
  sprintf(buffer,"%02u:%02u:%02u",hour,minute,sec); //設定印出01,02,而非1,2

  Serial.print("20");
  Serial.print(year,DEC);
  Serial.print(time);
  Serial.print(' ');
  Serial.print(buffer);
  Serial.print('\n');
  Serial.print("Temperature=");
  Serial.print(temperature);
  Serial.print('\n');

  //英文字符显示
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.setTextSize(1);             //设置字体大小
  display.print(time);
  display.setCursor(86,0);
  display.print(temperature);
  display.println("oC");
  display.setTextSize(2);             //设置字体大小
  display.print(buffer);
  delay(1000);
  display.display(); 
  display.clearDisplay();
}


程式碼-DS3231時鐘+I2C_LCD
#include <DS3231.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
byte year, month, date, DoW, hour, minute, second;

//LED_Fundino紅色板子用
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//LED_MH黑色板子用
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

//建立O型
byte OC[8] = {
  B01100,
  B10010,
  B01100,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

//設定暫存
char buffer [16];
char time [16];

void setup() {
// Start the I2C interface
  Wire.begin();
  //第一次使用要設定以下時間,之後就可以不用設定了
  //Clock.setSecond(00);//Set the second
  //Clock.setMinute(25);//Set the minute
  //Clock.setHour(16); //Set the hour
  //Clock.setDoW(4); //Set the day of the week
  //Clock.setDate(23); //Set the date of the month
  //Clock.setMonth(8); //Set the month of the year
  //Clock.setYear(17); //Set the year (Last two digits of the year)
  // Start the serial interface
  Serial.begin(115200);

  // 初始化 LCD,一行 16 的字元,共 2 行,預設開啟背光
  lcd.begin(16, 2);

  //建立OC型
  lcd.createChar (1, OC);  // load OC to memory 1

  // 閃爍2次
  for(int i = 0; i < 1; i++) {
    lcd.backlight(); // 開啟背光
    delay(50);
    lcd.noBacklight(); // 關閉背光
    delay(50);
  }
  lcd.backlight();

  // 輸出初始化文字
  lcd.setCursor(0, 0); // 設定游標位置在第一行行首
  lcd.print("DCJH-Maker");
  delay(500);
  lcd.setCursor(0, 1); // 設定游標位置在第二行行首
  lcd.print("Hello,MAKER!");
  delay(1000);
  lcd.clear();
}

void loop() {
  int second,minute,hour,date,month,year,temperature;
  second=Clock.getSecond();
  minute=Clock.getMinute();
  hour=Clock.getHour(h12, PM);
  date=Clock.getDate();
  month=Clock.getMonth(Century);
  year=Clock.getYear();

  temperature=Clock.getTemperature();

  sprintf(time,"20%02u-%02u-%02u",year,month,date); //設定印出01,02,而非1,2
  sprintf(buffer,"%02u:%02u:%02u",hour,minute,second); //設定印出01,02,而非1,2

  Serial.print(time);
  Serial.print(' ');
  Serial.print(buffer);
  Serial.print('\n');
  Serial.print("Temperature=");
  Serial.print(temperature);
  Serial.print('\n');

  lcd.setCursor(0, 0); // 設定游標位置在第一行行首
  lcd.print(time);
  lcd.setCursor(12, 0);
  lcd.print(temperature);
  lcd.print(char(1));
  lcd.print("C");
  lcd.setCursor(0, 1); // 設定游標位置在第二行行首
  lcd.print(buffer);

  delay(1000);
}

2018年6月19日 星期二

arduino_nano+心跳模組+0.96吋oled顯示+nRF24L01無線收發器

前面幾個步驟完成後,終於可以朝生物實驗器材需求最後一關邁進了,那就是-無線通訊,如果學生可以做實驗的同時,老師電腦就收到數據,這樣就可以同步分析數據結果了,而nRF24L01這個無線收發器可以支援1對6,最大功率時距離70m內好像不成問題,未來實驗就可以同時接收6組的數據了,感覺十分方便
你需要一台發送訊號,另一台接收訊號才行,如上圖




程式寫完就可以同步收發心跳模組的訊息,並呈現在電腦上,如上圖


參考文章
nRF24L01無線收發器模組與Arduino通訊實驗(二):一對一通訊
*2*nRF24L01+*2* SHT31 單點無線溫溼度傳輸
Arduino 無線傳輸模組 NRF24L01 測試


裡面遇到一個難關是:接收端表現出來的心跳錶數值都是亂碼,所以我想說數值不行傳輸,那就把數值轉成文字後再傳送應該就沒問題了,查了一下文章發現這個,
在Arduino下將數字(int)轉字元(char)的方法
裡面的這行加入後
itoa (myBPM, BPM, 10);      //將myBPM數字轉成BPM文字
果然就可以正確表示出數據了,能接受數據的瞬間真的很開心!


以下是這個模組要做的事情

1.安裝liberary
SPI
RF24

2.將接收與發送
--------------以下是發送端程式碼部分,發送端本身就接心跳錶跟螢幕--------------
#include <SPI.h>
#include <Wire.h>
#include "RF24.h"
#define USE_ARDUINO_INTERRUPTS true    // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h>     // Includes the PulseSensorPlayground Library. 
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//設定nRF24L01發射訊號
RF24 rf24(7, 8); // CE腳, CSN腳
const byte addr[] = "1Node";
const char msg[] = "Heart Beat";
int myBPM;

//LED設定
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//螢幕設定,定義顯示高度跟寬度
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16


//  Variables
const int PulseWire = 0;       // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int LED13 = 13;          // The on-board Arduino LED, close to PIN 13.
int Threshold = 550;           // Determine which Signal to "count as a beat" and which to ignore.
                               // Use the "Gettting Started Project" to fine-tune Threshold Value beyond default setting.
                               // Otherwise leave the default "550" value.
int z,a;

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

PulseSensorPlayground pulseSensor;  // Creates an instance of the PulseSensorPlayground object called "pulseSensor"

void setup() {
  Serial.begin(9600);

  //設定nRF24L01發射訊號
  rf24.begin();
  rf24.setChannel(83);       // 設定頻道編號
  rf24.openWritingPipe(addr); // 設定通道位址
  rf24.setPALevel(RF24_PA_MIN);   // 設定廣播功率
  rf24.setDataRate(RF24_250KBPS); // 設定傳輸速率
  rf24.stopListening();       // 停止偵聽;設定成發射模式


  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  // init done

  // Configure the PulseSensor object, by assigning our variables to it.
  pulseSensor.analogInput(PulseWire); 
  pulseSensor.blinkOnPulse(LED13);       //auto-magically blink Arduino's LED with heartbeat.
  pulseSensor.setThreshold(Threshold); 

  // Double-check the "pulseSensor" object was created and "began" seeing a signal.
   if (pulseSensor.begin()) {
    Serial.println("We created a pulseSensor Object !");  //This prints one time at Arduino power-up,  or on Arduino reset.
  }
 
  display.clearDisplay();
}

void loop() {
  int myBPM = pulseSensor.getBeatsPerMinute();  // Calls function on our pulseSensor object that returns BPM as an "int".
                                          // "myBPM" hold this BPM value now.

  //英文字符显示
  display.setTextSize(1);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.println("DCJH laboratory");   //输出字符并换行
 
  display.setTextSize(2);             //设置字体大小
  display.print("HB ");          //输出文字
  display.print(myBPM);
  display.print(" ");          //输出文字
  display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色
  display.setCursor(72,8);
  display.print("/min");          //输出文字
  display.display(); 
  display.clearDisplay();

  char BPM[4] ;
  itoa (myBPM, BPM, 10);      //將myBPM數字轉成BPM文字

  //設定nRF24L01發射訊號
  rf24.write(&msg, sizeof(msg));  // 傳送資料
  rf24.write(&BPM, sizeof(BPM));  // 傳送資料
}

--------------以下是接收端程式碼部分,接收端接電腦,輸入後電腦可以開啟"序列埠監控視窗"等訊號傳過來--------------

#include <SPI.h>
#include "RF24.h"

RF24 rf24(7, 8); // CE腳, CSN腳

const byte addr[] = "1Node";
const byte pipe = 1;  // 指定通道編號

int myBPM;

void setup() {
  Serial.begin(9600);
  rf24.begin();
  rf24.setChannel(83);  // 設定頻道編號
  rf24.setPALevel(RF24_PA_MIN);
  rf24.setDataRate(RF24_250KBPS);
  rf24.openReadingPipe(pipe, addr);  // 開啟通道和位址
  rf24.startListening();  // 開始監聽無線廣播
  Serial.println("nRF24L01 ready!");
}

void loop() {
  if (rf24.available(&pipe)) {
    char msg[32] = "";
    char BPM[32] = "";
    rf24.read(&msg, sizeof(msg));
    rf24.read(&BPM, sizeof(BPM));
    Serial.println(msg); // 顯示訊息內容
    Serial.println(BPM); // 顯示訊息內容
    delay(500);
  }
}


-------------------以下是露天網購材料與價錢-------------
NRF24L01+ 升級版改進型 無線模組台產SI24R1 2.4G無線收發(W005) 28元
https://goods.ruten.com.tw/item/show?21545029419316

arduino_nano+0.96OLED顯示

完成品如右側顯示,左側是arduino uno,整體而言加了擴充版還是比原來uno小,未來覺得可以推廣nano+擴充版就好。
這次主要想讓整個儀器比較小一點,所以使用arduino_nano這個比較小的板子,配上擴充版,其實整體而言好像比uno更便宜而且好用,唯一要擔心的可能是容量問題(如果是ATMEGA328P的flash應該都是32kb所以一樣大沒問題),還有他要多安裝一個軟體,Arduino UNO 相容版(CH341) Windows 驅動程式(點此下載)

nano的說明可以參考這篇文章
小狐狸事務所-Arduino Nano 開機測試

接下來0.96吋的oled顯示,我一樣丟"arduino 0.96 led"進去餵狗,找到這些文章
Arduino通過I2C(SSD1306)驅動0.96寸12864OLED
阿玉maker研究區-09-OLED顯示器

然後本來想顯示中文,可是目前失敗中,未來可參考這些文章持續改進
Arduino Uno 驱动OLED进阶 显示中英文字
Step By Step系列 - 番外篇 OLED圖片取檔方法, 使用LCD Assistant
運用SSD1306 OLED模組顯示圖像
使用 LCD Assistant轉換字體
发一个 绘图 Adafruit GFX图形库(這個感覺很厲害,所以備份了文章內容,以後應該用的到)


總之最後就可以顯示我要的訊息了 



以下是我修改的有關0.96吋oled的顯示部分

需要準備的東西
1.安裝一個軟體,Arduino UNO 相容版(CH341) Windows 驅動程式(點此下載)

2.安裝新的Library程式庫
Adafruit_SSD1306
Adafruit-GFX-Library

3.把下面的程式碼倒進去就可以了
--------------以下是程式碼部分--------------
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//OLED設定
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//螢幕設定,定義顯示高度跟寬度
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup() {
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  // init done

  display.clearDisplay();
}

void loop() {
    //英文字符显示
  display.setTextSize(1);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.println("test");   //输出字符并换行
 
  display.setTextSize(2);             //设置字体大小
  display.print("Hello_world");          //输出文字
  display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色
  display.setCursor(72,8);
  display.print("test");          //输出文字
  display.display(); 
  display.clearDisplay();
}


-------------------以下是露天網購材料與價錢,非廣告,僅供參考-------------
XTWduino nano V3.0 ATMEGA328P 改進板  90元
http://goods.ruten.com.tw/item/show?21519333276248

Arduino NANO UNO 多用 擴展板 48元
http://goods.ruten.com.tw/item/show?21550342023467

0.96寸 黃藍雙色 I2C IIC通信 12864 OLED液晶屏模塊 130元 (別家有120元的)
http://goods.ruten.com.tw/item/show?21715781107651

2018年5月29日 星期二

arduino心跳模組專案


暨上次挑戰完雙溫濕度計感測模組以後,最近終於下定決心要去做心跳模組了。
雖然之前上雙溫濕度計感測模組覺得沒有很成功,因為學生在裝設arduino就要花太多時間了,何況是需要串聯、插麵包板時候。
已經覺得降低很多難度與門檻了,看來還是遠遠不夠,造成計畫持續延宕。
而且每讓教學現場下降一門檻,我自己的時間成本就會拉好高好高,不斷的反思這樣是否可以真的實現在教室內呢?還是只能在延伸課程中?

之前在教師研習時也覺得arduino光是插線就是一件很困難的事情,老師覺得困難,學生操作時當然也是一樣的。

最近因為計畫死線關係,重還是必須完成arduino設計,讓下一年的課程可能可以用到這個工具,這次寫完這個專案其實滿有成就感的。

目標是做一個可以顯示心跳數值跟圖像化表現專案
心跳越快下面的心臟數量越多,閃爍速度也越快。
然後超過心跳120,會有火的圖形出現,140兩個火,160三個火,表示達到燃脂運動區間

先說說這次拼湊了那些元件與概念
1.PulseSensor基本介紹
https://pulsesensor.com/pages/code-and-guide

1.LCD畫圖方式,心型,跳動的心型
https://www.youtube.com/watch?v=jaD0dJtovwc
謝KK偷插電資訊課的畫圖程式
http://163.22.72.1/html5/colour_by_numbers/html5_colour_by_numbers/colour_by_numbers.html

2.迴圈與判斷式if,else if
http://ming-shian.blogspot.tw/2013/09/arduino.html
http://www.86duino.com/?p=593&lang=TW

3.燃脂心跳區間
http://www.dreye-health.com/SingularController?service=goCheck&path=feat


認真參考過但是後來發現自己等級還不夠的資料

1.Arduino Based Heartbeat Monitor
http://www.circuitstoday.com/pulse-sensor-arduino
https://circuitdigest.com/microcontroller-projects/heartbeat-monitor-project-using-arduino

2.arduino數學函數
http://yhhuang1966.blogspot.tw/2015/09/arduino_23.html

3.millis()時間函數
http://coopermaa2nd.blogspot.tw/2011/04/millis-button.html
http://coopermaa2nd.blogspot.tw/2011/04/millis.html
http://yhhuang1966.blogspot.tw/2015/09/arduino_9.html
http://rainage.blogspot.tw/2016/02/arduino.html

需要準備的東西
1.下載程式庫pulsesensor playground
2.開啟範例pulsesensor playground → Getting_BPM_to_Monitor
3.把我的檔案倒進去就可以了
--------------以下是程式碼部分--------------

/*  Getting_BPM_to_Monitor prints the BPM to the Serial Monitor, using the least lines of code and PulseSensor Library.
 *  Tutorial Webpage: https://pulsesensor.com/pages/getting-advanced
 *
--------Use This Sketch To------------------------------------------
1) Displays user's live and changing BPM, Beats Per Minute, in Arduino's native Serial Monitor.
2) Print: "♥  A HeartBeat Happened !" when a beat is detected, live.
2) Learn about using a PulseSensor Library "Object".
4) Blinks LED on PIN 13 with user's Heartbeat.
--------------------------------------------------------------------*/

#define USE_ARDUINO_INTERRUPTS true    // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h>     // Includes the PulseSensorPlayground Library. 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// 設定 LCD I2C 位址
// Set the pins on the I2C chip used for LCD connections:
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol

//LED_Fundino紅色板子用
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//LED_MH黑色板子用
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);


//  Variables
const int PulseWire = 0;       // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int LED13 = 13;          // The on-board Arduino LED, close to PIN 13.
int Threshold = 550;           // Determine which Signal to "count as a beat" and which to ignore.
                               // Use the "Gettting Started Project" to fine-tune Threshold Value beyond default setting.
                               // Otherwise leave the default "550" value.
int z,a;

PulseSensorPlayground pulseSensor;  // Creates an instance of the PulseSensorPlayground object called "pulseSensor"

//建立心型
byte heart_h[8] = {
  B00000,
  B00000,
  B01010,
  B10101,
  B10001,
  B01010,
  B00100,
  B00000
};
byte heart_f[8] = {
  B00000,
  B00000,
  B01010,
  B11111,
  B11111,
  B01110,
  B00100,
  B00000
};
//建立火型
byte fire[8] = {
  B00100,
  B10100,
  B10100,
  B11100,
  B10101,
  B10011,
  B11001,
  B01110
};
void setup() { 

  Serial.begin(9600);          // For Serial Monitor

  // Configure the PulseSensor object, by assigning our variables to it.
  pulseSensor.analogInput(PulseWire); 
  pulseSensor.blinkOnPulse(LED13);       //auto-magically blink Arduino's LED with heartbeat.
  pulseSensor.setThreshold(Threshold); 

  // Double-check the "pulseSensor" object was created and "began" seeing a signal.
   if (pulseSensor.begin()) {
    Serial.println("We created a pulseSensor Object !");  //This prints one time at Arduino power-up,  or on Arduino reset.
  }
  // 初始化 LCD,一行 16 的字元,共 2 行,預設開啟背光
  lcd.begin(16, 2);

  //建立心型
  lcd.createChar (1, heart_h);  // load heart_h to memory 1
  lcd.createChar (2, heart_f);  // load heart_f to memory 2
  lcd.createChar (3, fire);    // load fire to memory 3
 
  pinMode(LED13,OUTPUT);    // pin that will blink to your heartbeat!

  // 閃爍兩次
  for (int i = 0; i < 1; i++) {
    lcd.backlight(); // 開啟背光
    delay(250);
    lcd.noBacklight(); // 關閉背光
    delay(250);
  }
  lcd.backlight();

  // 輸出初始化文字
  lcd.setCursor(0, 0); // 設定游標位置在第一行行首
  lcd.print("Hello, Maker!");
  delay(500);
  lcd.setCursor(0, 1); // 設定游標位置在第二行行首
  lcd.print("heartbeat");
  delay(1000);
  lcd.clear(); //顯示清除
}



void loop() {

 int myBPM = pulseSensor.getBeatsPerMinute();  // Calls function on our pulseSensor object that returns BPM as an "int".
                                          // "myBPM" hold this BPM value now.
 lcd.setCursor(0, 0); // 設定游標位置在第一行行首
 lcd.print("HeartBeat=");

 if (pulseSensor.sawStartOfBeat()) {            // Constantly test to see if "a beat happened".
  Serial.println("♥  A HeartBeat Happened ! "); // If test is "true", print a message "a heartbeat happened".
  Serial.print("BPM: ");                        // Print phrase "BPM: "
  Serial.println(myBPM);                        // Print the value inside of myBPM.
  lcd.print(" ");
  lcd.print(myBPM);
  lcd.print("      ");

  //心型跳動
  for(z=1;z<=2;z=z+1){
    lcd.setCursor(0,1);  // 設定游標位置在第二行行首

    if(myBPM<80){       //判別心跳介於哪個區間,if,else if判斷式
      lcd.print(char(z));
      lcd.print("                ");
      delay(20000/myBPM);  //不知道為什麼這樣跟心跳頻率滿接近的,是try error得到的結果
    }
    else if(myBPM>=80 && myBPM<100){
      lcd.print(char(z)); 
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print("              ");
      delay(20000/myBPM);
    }
    else if(myBPM>=100 && myBPM<120){
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print("                ");
      delay(20000/myBPM);
    }
    else if(myBPM>=120 && myBPM<140){
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print("        ");
      lcd.print(char(3));
      delay(20000/myBPM);
    }
    else if(myBPM>=140 && myBPM<160){
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print("     ");
      lcd.print(char(3));
      lcd.print(char(3));
      delay(20000/myBPM);
    }
    else if(myBPM>=160){
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print(char(z));
      lcd.print("   ");
      lcd.print(char(3));
      lcd.print(char(3));
      lcd.print(char(3));
      delay(20000/myBPM);
    }
  }
 }
 else{
  lcd.print(" ");
  lcd.print(myBPM);
  lcd.print(" ");
  }
}






-------------------以下是露天網購材料與價錢-------------
單顆18650升壓5V充電裝置,共127元
18650電池,68元
http://goods.ruten.com.tw/item/show?21516007891673
電池盒,8元
http://goods.ruten.com.tw/item/show?21514873619557
充電保護裝置,30元
http://goods.ruten.com.tw/item/show?21529155040880
升壓模組,18元
http://goods.ruten.com.tw/item/show?21513816706112
開關,3元
http://goods.ruten.com.tw/item/show?21645325862802

Arduino IIC I2C 5V LCD,165元
http://goods.ruten.com.tw/item/show?21550344478159#qa&p=1

Arduino Pulse Sensor 脈搏 心率 感測器模組,190元
http://goods.ruten.com.tw/item/show?21530165613441

Arduino UNO,170元
http://goods.ruten.com.tw/item/show?21513818850541

以上價錢不含運也不含稅,本人也沒有收廣告費XD,請自己找更便宜或是喜歡的方式購買
基本上淘寶價錢會更低大概一半,東西也很輕,可以考慮一下

2018年1月5日 星期五

moodle_at_xmapp_windows更新與搬家紀錄

windows系統下moodle搬家要用到的相關資料
由於檔案很大,所以很難搬,PHP也更新成新版了,舊的方法資料夾檔案硬搬會失敗

第一個是想把外掛都搬過去,所以先重新命名xampp/apps/htdocs資料夾變成htdocs_1
複製了原來moodle的xampp/apps/htdocs資料夾去相同位置,打開新moodle就開始下載更新,然後就完成了(可喜可賀...)

接著就進行緩慢的搬家過程,搬家時由於匯入檔案只要超過某個大小,就會匯不進去,查了資料發現是這些問題
Moodle作業上傳檔案大小設定
PHP, MySQL參數設定參考網頁

改完就可以上傳很大很大的檔案,也變得比較快了(似乎彷彿...)

課程備份的方式是在課程頁面/系統管理/課程管理/備份 把檔案下載下來再打包就OK了

不過要把所有課程掛回去好像是非常非常緩慢的過程,畢竟有些檔案有點大(200mb以上,9mb的大概要搬20分鐘....),可能是部分有放影片檔,把影片檔刪掉應該就沒問題了。

-----------------------------
php.ini
要修改的包括以下幾項
max_execution_time
max_input_time
memory_limit
post_max_size
upload_max_filesize
default_socket_timeout
mysql.connect_timeout

2017年12月13日 星期三

arduino溫濕度計輸出LCD(四) 雙偵測器顯示

一個DHT11可以,那是否可以設定兩個以上的溫濕度計呢?
看到有人問這個問題,不過我google不到成品,那就自己設計看看
反正應該不難,就是給他貼兩倍就對了
在#define這邊增加一個 DHT2PIN 4 ,設定是pin4,所以第一個DHT插pin2,第二個插pin4
增加DHT dht2(DHT2PIN, DHTTYPE); 其實我也不知道這個在幹嘛,不過總覺得要增加

這部分增加一組可以存數據的h2、t2、f2(其實f是華氏溫度根本也沒用到其實可以刪...)
  //第二個sensor
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht2.readHumidity();
  // Read temperature as Celsius (the default)
  float t2 = dht2.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f2 = dht2.readTemperature(true);

這一段我看不懂也不知道怎麼改,於是我沒複製兩份
  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

然後覺得跑出來的數字有小數點,但是這個DHT11根本無法測量小數點差異,於是加了int()將讀到的數字取整數(這個部分如果沒問小P老師我找半天找不到...)

  lcd.print(int(h));  //int(h)取h的整數
  lcd.print("% ");

以下是修改後的程式碼,應該可以順利運作才是,而且拔除其中一個還能顯示!error!,完成這個雙溫濕度計偵測器的方案。不過DHT11感覺在濕度不是很精準,我買了很多個每個插上去數值都不太一樣,可能還是需要校正或是注意一下。
成品長這樣




// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"

#define DHTPIN 2     // what digital pin we're connected to
#define DHT2PIN 4    // what digital2 pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// 設定 LCD I2C 位址
//LED_Fundino紅色板子用
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//LED_MH黑色板子用
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

DHT dht(DHTPIN, DHTTYPE);
DHT dht2(DHT2PIN, DHTTYPE);

void setup() {
  // 初始化 LCD,一行 16 的字元,共 2 行,預設開啟背光
  lcd.begin(16, 2);
  //
  Serial.begin(9600);
  dht.begin();
  // 閃爍兩次
  for (int i = 0; i < 1; i++) {
    lcd.backlight(); // 開啟背光
    delay(250);
    lcd.noBacklight(); // 關閉背光
    delay(250);
  }
  lcd.backlight();

  // 輸出初始化文字
  lcd.setCursor(0, 0); // 設定游標位置在第一行行首
  lcd.print("Hello, Maker!");
  delay(500);
  lcd.setCursor(0, 1); // 設定游標位置在第二行行首
  lcd.print("thermometer*2");
  delay(1000);
  lcd.clear(); //顯示清除
}
void loop() {
  // Wait a few seconds between measurements.
  delay(100);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  //第二個sensor
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht2.readHumidity();
  // Read temperature as Celsius (the default)
  float t2 = dht2.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f2 = dht2.readTemperature(true);

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  lcd.setCursor(0, 0); // 設定游標位置在第一行行首
  lcd.print("sensor1 sensor2");
  lcd.setCursor(0, 1); // 設定游標位置在第二行行首
   
  // 如果拔除sensor1出現error
  if (isnan(h) || isnan(t) || isnan(f)) {
    lcd.print("!error!");
    return;
  }
  lcd.print(int(h));  //int(h)取h的整數
  lcd.print("% ");
  lcd.print(int(t));
  lcd.print("C ");
  
  // 如果拔除sensor2出現error
  if (isnan(h2) || isnan(t2) || isnan(f2)) {
    lcd.print("!error!");
    return;
  }
  lcd.print(int(h2));
  lcd.print("% ");
  lcd.print(int(t2));
  lcd.print("C");
}