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