※本文將透過ESP32上的藍芽4.2,以BLE MESH架構的資訊收發方式進行資料傳輸,本範例使用之感測器為MPU6050(三軸陀螺儀+三軸加速計感測模組),將接收到的感測器數值作為資料並以MESH架構進行接收與傳輸。

Arduino IDE

首先,要在Arduino IDE上使用ESP32 需先進行開發版的安裝,此部分本文不詳細說明。
詳情請於網路上收尋關鍵字 「Arduino ESP32 開發環境安裝」 即可找到教學。

MESH簡易介紹

MESH是建立在Wi-Fi協議之上的網路協議。MESH允許散佈在較大物理區域(室內和室外)中的眾多設備(稱為節點)在單個WLAN(無線區域網路)下互連。

同時MESH具有自我組織和自我修復的功能,這意味著該網路可以自動構建和維護。

傳統的Wi-Fi網絡架構

在傳統的Wi-Fi網路體系結構中,單個節點(訪問點–通常為路由器)連接到所有其他節點(站)。每個節點都可以使用訪問點相互通信。但是,這僅限於接入點的Wi-Fi覆蓋範圍。每個站點必須在範圍內才能直接連接到接入點。ESP-MESH不會發生這種情況。

傳統Wi-Fi網絡ESP32 ESP8266

ESP-MESH網絡架構

使用ESP-MESH,節點無需連接到中央節點。節點負責彼此中繼傳輸。這允許多個設備分佈在較大的物理區域上。節點可以自組織並彼此動態對話,以確保數據包到達其最終節點目的地。如果從網絡中刪除了任何節點,則它可以自我組織以確保數據包到達其目的地。

ESP-MESH網絡ESP32 ESP8266i

painlessMesh程式庫

painlessMesh庫使我們能夠用一個簡單的程式庫,於ESP32上建立一個MESH傳輸架構的網路。

painlessMesh函式庫所建立的是真正的自組織網路,這意味著不需要中央控制器或路由器。任何由1個或多個節點組成的系統都將自組織為功能齊全的網格。

安裝painlessMesh庫

您可以通過Arduino程式庫管理器安裝painlessMesh。點擊草稿碼>匯入程式庫>管理程式庫。即可開啟程式庫管理器。

於程式庫管理器搜尋欄位搜尋「 painlessmesh 」並安裝該庫。本文正在使用1.4.7版。

該庫還需要其他一些額外程式庫支援。應該會彈出一個新窗口,要求您安裝所有缺少的額外程式庫。
請選擇「全部安裝」。

如果未顯示此窗口或不確定是否已安裝所有額外程式庫,則需要安裝以下3項額外程式庫:

WiFi MESH基本示例(廣播消息)

接著開始使用WiFi MESH,我們首先嘗試該庫的基本範例。本範例創建一個網狀網絡,其中所有板均向所有其他板廣播消息。

我們用四個ESP32對這個範例進行實驗。您可以依自身情況增減ESP32數量。
(該範例對ESP32與ESP8266皆可兼容。)

ESP-MESH painlessMesh基本示例ESP32 ESP8266

程式碼– painlessMesh庫基本示例

將以下程式碼複製到您的Arduino IDE 即可進行上傳並察看結果。(或者點擊檔案>範例>Painless Mesh>basic

#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  String msg = "Hi from node1";
  msg += mesh.getNodeId();
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

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

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

在上傳代碼之前,您可以設定 MESH_PREFIX (就像WiFi名稱一樣)和 MESH_PASSWORD (WiFi密碼)。

然後,我們建議您為每個ESP32更改以下欄位,以輕鬆識別發送消息的節點。
例如,對於節點1,更改消息,如下所示:

String msg = "Hi from node 1 ";

程式碼如何運作

首先載入painlessMesh程式庫。

#include "painlessMesh.h"

MESH資訊

然後,添加網格詳細資料。這MESH_PREFIX指網路的名稱。您可以將其更改為任何您喜歡的。

#define MESH_PREFIX "whateverYouLike"

這 MESH_PASSWORD,顧名思義就是網路密碼。您可以將其更改為任何您喜歡的。

#define MESH_PASSWORD "somethingSneaky"

網格中的所有節點應使用相同的 MESH_PREFIX 和 MESH_PASSWORD。

這 MESH_PORT指您要在其上運行網狀服務器的TCP端口。默認值為5555。

#define MESH_PORT 5555

排程器

建議避免使用 delay()在網狀網路代碼中。為了維護網路,需要在後台執行一些任務。使用delay() 會阻止這些任務的發生,並可能導致網路失去穩定性或崩潰。

相反,建議使用 TaskScheduler 運行您在painlessMesh本身中使用的任務。

以下行創建了一個新的 排程器 叫 userScheduler。

Scheduler userScheduler; // to control your personal task

painlessMesh

建立一個 painlessMesh 對象稱為 mesh 來處理網狀網路。

painlessMesh  mesh;

建立任務

建立一個名為 taskSendMessage 負責處理 sendMessage() 只要程序正在執行,便每秒執行一次。

Task taskSendMessage(TASK_SECOND * 1 , TASK_FOREVER, &sendMessage);

發送訊息到網路

這 sendMessage()功能將訊息發送到訊息網路中的所有節點(廣播)。

void sendMessage() {
  String msg = "Hi from node 1";
  msg += mesh.getNodeId();
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
}

該訊息包含【Hi from node 1 】,以及該ESP32的晶片ID。

String msg = "Hi from node 1";
msg += mesh.getNodeId();

要廣播訊息,只需使用 sendBroadcast() 上的方法,以網路為對象並將訊息作為參數傳遞(msg)發送。

mesh.sendBroadcast(msg);

每次發送新訊息時,代碼都會更改訊息之間的間隔(一到五秒)。

taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));

網路回調函數

接下來,建立多個回調函數,當特定事件在網路上發生時將被啟用。

這 receiveCallback() 函式負責顯示訊息發件人(from)和訊息的內容(msg.c_str())。

void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

這 newConnectionCallback()每當有新節點加入網路時,該函數就會執行。目前設定此功能僅顯示新節點的晶片ID。您可以修改功能來執行任何其他任務。

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

這 changedConnectionCallback() 每當網路上的連接發生改變時(節點的加入或離開時),該函數就會執行。

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

這 nodeTimeAdjustedCallback()當網路不同步時,該功能會執行,以便所有節點都同步。並顯示偏移量。

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

setup()中程式碼

在setup()裡面初始化序列埠監控器。

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

選擇所需的調試訊息類型:

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

用前面定義的WiFi資訊初始化網路。

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);

將所有回調函數分配給它們相應的事件。

mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

最後,增加 taskSendMessage 功能 userScheduler。調度程序負責在正確的時間處理和運行任務。

userScheduler.addTask(taskSendMessage);

最後,啟用 taskSendMessage,以便程序開始將訊息發送到網路。

taskSendMessage.enable();

要保持網路運行,請增加 mesh.update()到 loop()中。

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

執行結果

將上述的程式碼上傳到所有ESP32上。不要忘記修改訊息以輕鬆識別發送的節點。

將ESP32連接到電腦後,打開每個ESP32的序列埠監控視窗。

您應該看到所有ESP32都收到彼此的訊息。例如,這些是節點1收到的訊息。它從節點2、3和4接收訊息。

ESP-MESH基本示例4板Arduino串行監視器

當網路上發生改變時,您還應該看到其他訊息:節點離開或加入網路時。

ESP MESH基本示例串行監視器更改的連接

使用ESP-MESH交換感測器讀數

在下一個範例中,我們將在4個板之間交換感測器讀數(您可以使用不同數量的板)。每個板都接收其他板的讀數。

ESP-MESH交流BME280傳感器讀數ESP32 ESP8266

例如,我們將交換來自感測器:MPU6050的讀數,不過您也可以使用任何其他感測器。

所需零件

這是此範例所需的零件:

  • 4個ESP32板
  • 4個MPU6050
  • 跳線(杜邦線)

Arduino_JSON程式庫

在此範例中,我們將以JSON格式交換感測器讀數。為了使處理JSON變量更容易,我們將使用Arduino_JSON程式庫。

您可以在Arduino IDE庫管理器中安裝該庫。只需轉到 草稿碼  > 匯入函式庫  > 管理程式庫, 然後按以下方式搜索庫名稱:

電路圖

如下圖所示,將MPU6050感測器連接到ESP32默認的I2C引腳。

程式碼– ESP-MESH廣播感測器讀數

將以下程式碼上傳到您的每個ESP32上,並修改nodeNumber欄位的變數。該程式碼讀取當前X軸、Y軸、Z軸讀數,並將其廣播到網狀網路上的所有ESP32。讀數以JSON字符串的形式發送,其中還包含用於標示發送訊息之ESP32的節點號。

#include "painlessMesh.h"
#include <Wire.h>
#include <MPU6050.h>
#include <Arduino_JSON.h>

#define   MESH_PREFIX     "whateverYouLike" //name for your MESH
#define   MESH_PASSWORD   "somethingSneaky" //password for your MESH
#define   MESH_PORT       5555  //default port

//Number for this node
int nodeNumber = 1;

//MPU6050 Pin/SDA-21,SCL-22
MPU6050 mpu;


//String to send to other nodes with sensor readings
String readings;

Scheduler userScheduler; // to control your personal task

painlessMesh  mesh;

// User stub
String getReadings(); // Prototype so PlatformIO doesn't complain
void sendMessage();

Task taskSendMessage( TASK_SECOND * 0.5 , TASK_FOREVER, &sendMessage );

String getReadings () {
  JSONVar jsonReadings;
  Vector normAccel = mpu.readNormalizeAccel();
  Vector normGyro = mpu.readNormalizeGyro();
  jsonReadings["node"] = nodeNumber;
  
  jsonReadings["Accel_X"] = String(normAccel.XAxis);
  jsonReadings["Accel_Y"] = String(normAccel.YAxis);
  jsonReadings["Accel_Z"] = String(normAccel.ZAxis);
  
  jsonReadings["Gyro_X"] = String(normGyro.XAxis);
  jsonReadings["Gyro_Y"] = String(normGyro.YAxis);
  jsonReadings["Gyro_Z"] = String(normGyro.ZAxis);
  
  readings = JSON.stringify(jsonReadings);
  return readings;
}

void sendMessage() {
  String msg = getReadings();
  
  mesh.sendBroadcast( msg );
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
  //Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
  Serial.println();
  Serial.println("----------------------------------");
  Serial.printf("Received from %u ", from);
  Serial.println();
  Serial.printf("msg=%s\n",msg.c_str());
  JSONVar myObject = JSON.parse(msg.c_str());
  int node = myObject["node"];
  //三軸加速度(Accel)
  double X = myObject["Accel_X"];
  double Y = myObject["Accel_Y"];
  double Z = myObject["Accel_Z"];
  //三軸陀螺儀(Gyro)
  double GX = myObject["Gyro_X"];
  double GY = myObject["Gyro_Y"];
  double GZ = myObject["Gyro_Z"];
  
  Serial.println("**********************************");
  //三軸加速度(Accel)
  Vector normAccel = mpu.readNormalizeAccel();
  Serial.print(" Accel_X:");
  Serial.print(normAccel.XAxis);
  Serial.print(" Accel_Y:");
  Serial.print(normAccel.YAxis);
  Serial.print(" Accel_Z:");
  Serial.println(normAccel.ZAxis);
  //三軸陀螺儀(Gyro)
  Vector normGyro = mpu.readNormalizeGyro();
  Serial.print(" Gyro_X:");
  Serial.print(normGyro.XAxis);
  Serial.print(" Gyro_Y:");
  Serial.print(normGyro.YAxis);
  Serial.print(" Gyro_Z:");
  Serial.println(normGyro.ZAxis);
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("-->New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

/*******MPU6050三軸加速度(Accel)主程式******/
void MPU_Accel_set(){
  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
  {
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }
  
  switch(mpu.getRange()){
    case MPU6050_RANGE_2G:             
      Serial.println("+/- 2 g"); 
      break;
  }
}

/*******MPU6050三軸陀螺儀(Gyro)主程式******/
void MPU_Gyro_set(){
  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)){
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }
  // Set threshold sensivty. Default 3.
  mpu.setThreshold(3);
   
  switch(mpu.getScale()){   
    case MPU6050_SCALE_250DPS:         
    Serial.println("250 dps"); 
    break;
  } 
}

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

void setup() {
  Serial.begin(115200);
  MPU_Accel_set();
  MPU_Gyro_set();
  
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.update();
  
}

程式碼如何運作

繼續閱讀本節以了解代碼如何運行。

程式庫

首先載入所需的庫: Wire 和 MPU6050用於感測器的連接;painlessMesh處理網狀網路和 Arduino_JSON 輕鬆建立和處理JSON字符串。

#include "painlessMesh.h"
#include <Wire.h>
#include <MPU6050.h>
#include <Arduino_JSON.h>

網路資訊

在以下各行中插入網格詳細信息。

#define   MESH_PREFIX     "whateverYouLike" //name for your MESH
#define   MESH_PASSWORD   "somethingSneaky" //password for your MESH
#define   MESH_PORT       5555  //default port

這 MESH_PREFIX指網路的名稱。您可以將其更改為任何您喜歡的。
這MESH_PASSWORD,就是網路密碼。您可以將其更改為任何您喜歡的。
網路中的所有節點應使用相同的MESH_PREFIX 和 MESH_PASSWORD。
這 MESH_PORT指您要在其上運行網狀服務器的TCP端口。默認值為5555。

MPU6050

建立一個 MPU6050 對象稱為 mpu 在默認的ESP32 I2C引腳上。

//MPU6050 Pin/SDA-21,SCL-22
MPU6050 mpu;

在裡面 nodeNumber變量為您的ESP32個別節點編號。每個板的編號必須不同。

//Number for this node
int nodeNumber = 1;

這 readings 變量將用於保存要發送到其他ESP32的讀數。

String readings;

排程器

以下行創建了一個新的 排程器 叫 userScheduler。

Scheduler userScheduler; // to control your personal task

painlessMesh

建立一個 painlessMesh 對象稱為 mesh 來處理網狀網路。

painlessMesh  mesh;

建立任務(tasks)

建立一個名為 taskSendMessage 負責發送 sendMessage() 只要程序正在執行,便每0.5秒鐘執行一次。
假如今天從Node2、3接收到資料,則Node1序列埠視窗顯示接收到之資料數共為4筆,(Node2、3各兩筆資料)。

Task taskSendMessage(TASK_SECOND * 0.5 , TASK_FOREVER, &sendMessage);

getReadings()

這 getReadings() 函數從MPU6050感測器讀取當前X軸、Y軸、Z軸讀數,並連接所有訊息,包括稱為JSON變量的節點號 jsonReadings。

JSONVar jsonReadings;
  Vector normAccel = mpu.readNormalizeAccel();
  Vector normGyro = mpu.readNormalizeGyro();
  jsonReadings["node"] = nodeNumber;
  //三軸加速度(Accel)
  jsonReadings["Accel_X"] = String(normAccel.XAxis);
  jsonReadings["Accel_Y"] = String(normAccel.YAxis);
  jsonReadings["Accel_Z"] = String(normAccel.ZAxis);
  //三軸陀螺儀(Gyro)
  jsonReadings["Gyro_X"] = String(normGyro.XAxis);
  jsonReadings["Gyro_Y"] = String(normGyro.YAxis);
  jsonReadings["Gyro_Z"] = String(normGyro.ZAxis);

這 jsonReadings 將該變量轉換為JSON字符串 stringify()並保存在 readings 變量。

readings = JSON.stringify(jsonReadings);

然後該變量由函數回傳。

return readings;

發送消息到網路

這 sendMessage() 函數發送帶有讀數和節點號的JSON字符串(getReadings())到網路中的所有節點(廣播)。

void sendMessage () {
  String msg = getReadings();
  mesh.sendBroadcast(msg);
}

網路回傳函數

接下來,創建多個回傳函數,這些事件將在網格上發生某些事件時被執行。

這 receiveCallback() 函數顯示訊息發件人(from)和訊息的內容(msg.c_str())。

void receivedCallback( uint32_t from, String &msg ) {
  Serial.println();
  Serial.println("----------------------------------");
  Serial.printf("Received from %u ", from);
  Serial.println();
  Serial.printf("msg=%s\n",msg.c_str());

該消息採用JSON格式,因此,我們可以按以下方式訪問變量:

  JSONVar myObject = JSON.parse(msg.c_str());
  int node = myObject["node"];
  //三軸加速度(Accel)
  double X = myObject["Accel_X"];
  double Y = myObject["Accel_Y"];
  double Z = myObject["Accel_Z"];
  //三軸陀螺儀(Gyro)
  double GX = myObject["Gyro_X"];
  double GY = myObject["Gyro_Y"];
  double GZ = myObject["Gyro_Z"];

最後,在串行監視器上打印所有信息。

  Serial.println("**********************************");
  //三軸加速度(Accel)
  Vector normAccel = mpu.readNormalizeAccel();
  Serial.print(" Accel_X:");
  Serial.print(normAccel.XAxis);
  Serial.print(" Accel_Y:");
  Serial.print(normAccel.YAxis);
  Serial.print(" Accel_Z:");
  Serial.println(normAccel.ZAxis);
  //三軸陀螺儀(Gyro)
  Vector normGyro = mpu.readNormalizeGyro();
  Serial.print(" Gyro_X:");
  Serial.print(normGyro.XAxis);
  Serial.print(" Gyro_Y:");
  Serial.print(normGyro.YAxis);
  Serial.print(" Gyro_Z:");
  Serial.println(normGyro.ZAxis);

這 newConnectionCallback()每當有新節點加入網路時,該函數就會執行。此功能僅顯示新節點的晶片ID。您可以修改功能以執行任何其他任務。

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

這 changedConnectionCallback() 每當網路上的連接發生改變時(節點的加入或離開時),該函數就會執行。

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

這 nodeTimeAdjustedCallback()當網路調整時間時,該功能會執行,以便所有節點都同步。並顯示偏移量。

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

初始化MPU6050感測器

這 void MPU_Accel_set( ) 、 void MPU_Gyro_set( ) 功能為初始化MPU6050感測器。

/*******MPU6050三軸加速度(Accel)主程式******/
void MPU_Accel_set(){
  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
  {
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }
  
  switch(mpu.getRange()){
    case MPU6050_RANGE_2G:             
      Serial.println("+/- 2 g"); 
      break;
  }
}

/*******MPU6050三軸陀螺儀(Gyro)主程式******/
void MPU_Gyro_set(){
  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)){
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }
  // Set threshold sensivty. Default 3.
  mpu.setThreshold(3);
   
  switch(mpu.getScale()){   
    case MPU6050_SCALE_250DPS:         
    Serial.println("250 dps"); 
    break;
  } 
}

setup()

在 setup()裡面初始化序列埠監控器。

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

啟用 MPU_Accel_set( ) 、 MPU_Gyro_set( ) 初始化MPU6050感測器。

  MPU_Accel_set();
  MPU_Gyro_set();

選擇所需的調試訊息類型:

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

用前面定義的WiFi資訊初始化網路。

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);

將所有回調函數分配給它們相應的事件。

mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

最後,增加 taskSendMessage 功能 userScheduler。調度程序負責在正確的時間處理和運行任務。

userScheduler.addTask(taskSendMessage);

最後,啟用 taskSendMessage,以便程序開始將訊息發送到網路。

taskSendMessage.enable();

要保持網路運行,請增加 mesh.update()到 loop()中。

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

執行結果

將代碼上傳到所有ESP32(每個ESP32具有不同的節點號)後,您應該看到每個ESP32都在接收其他ESP32的訊息。

以下截圖顯示了節點1收到的消息。它接收來自節點2的感測器讀數,並顯示自身感測器讀數。

以下截圖顯示了節點2收到的消息。它接收來自節點1的感測器讀數,並顯示自身感測器讀數。

完成

以上即為本範例所有教學內容。

發表於

透過 LED 燈的明亮,通常是入門 Arduino 的第一步,只要在指定腳位輸入 High、Low的訊號,就可以很簡單地看到成果。因此,控制LED自然也成為從ROS出發來控制Arduino板的第一步.

1.連線準備

使用裝備:

  • ASUS筆電win10 VM ubuntu
  • Arduino

2.測試架構: 

3.上傳程式

程式碼如下:

#include <ros.h>
#include <std_msgs/Empty.h>

ros::NodeHandle nh; //
  
void messageCb( const std_msgs::Empty& toggle_msg){
    digitalWrite(13, HIGH-digitalRead(13));
    delay(3000);  
    digitalWrite(13, HIGH-digitalRead(13));
}
  
ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );
  
void setup()
{
    pinMode(13, OUTPUT);
    nh.initNode();
    nh.subscribe(sub);
}
  
void loop()
{
    nh.spinOnce();
    delay(1);
}

程式鍵入後,上傳.

如跳錯誤訊息:

證明USB權限沒開.到命令字元鍵入 :

sudo chmod 666 /dev/ttyUSB0

/dev/ttyUSB0 是 接收USB資料位置,可到 arduino -> Tools -> Port 查詢

4.ROS架設初始化,命令字元鍵入:

roscore

5.ROS運行Arduino,命令字元鍵入:

rosrun rosserial_python serial_node.py /dev/ttyUSB0 _baud:=57600

如有報錯,有可能是USB權限沒開.上面有寫.

6.傳送訊息給arduino,命令字元鍵入:

rostopic pub toggle_led std_msgs/Empty --once

結果arduino的pin13腳位,閃3秒關閉

7.程式範列講解:

#include <ros.h>
#include <std_msgs/Empty.h>

ros.h 標頭檔包含了標準 ROS 類別,每支 ROS 程式都要 include 此標頭檔. 接著也需載入定義 message 的標頭檔,在此為 std_msgs/Empty.h,空的message.

ros::NodeHandle nh; //創建一個ros的節點

在系統內部,NodeHandle 維護著一個引用計數,且只有當第一個物件被宣告時才會通報 ROS Master 註冊一個新的節點。同樣地,當所有的 NodeHandles 都被關閉後,節點才會被取消註冊。

void messageCb( const std_msgs::Empty& toggle_msg){
    digitalWrite(13, HIGH-digitalRead(13)); 
    delay(3000);  //停(3000為3秒)
    digitalWrite(13, HIGH-digitalRead(13)); 
}

回調函式是節點訂閱消息(message)的基礎機制,當有消息到達時,會自動以消息的指標作為參數,再呼叫回調函式,完成對消息內容的處理。以上程式用來接收 Publisher 發布的 Empty 消息,讓 Arduino 板子的第13支腳位的 LED 閃爍 

HIGH-digitalRead(13)->13腳位如果是HIGH得LOW,如果是low就得HIGH

ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );   

ros::訂閱者 <訊息rostopic pub /ardrone/takeoff std_msgs/Empty> 子(“name”,位置物件) . 訂閱節點首先須聲明訂閱的消息話題 (message topic),這些資訊會紀錄在 ROS Master中.Master會注意系統中是否存在發布該話題的節點,若存在,則會建立兩個節點的連接.

void setup()
{
    pinMode(13, OUTPUT);//設pin13為輸出
    nh.initNode();//初始化
    nh.subscribe(sub);//添加子節點
}
void loop()
{
    nh.spinOnce();//執行一次
    delay(1);//停1毫秒
}

結束~~~~

樹梅派可支持多個攝像頭同時輸出,我們只要修改mjpg-streamer的啟動腳本就可以辦到

  • 首先進行遠程桌面
  • 打開命令終端
  • 安裝mjpg-streamer軟體
  • git clone http://github.com/jacksonliam/mjpg-streamer.git
  • 安裝所需套件
  • sudo apt-get install subversion
  • sudo apt-get install libjpeg8-dev
  • sudo apt-get install imagemagick
  • sudo apt-get install libv4l-dev
  • sudo apt-get install cmake
  • sudo apt-get install git
  • 有問題全部按y
  • 下載完後打開資料夾
  • cd mjpg-streamer/mjpg-streamer-experimental
  • 把剛載的東西放進去
  • make
  • make all
  • sudo make install
  • 再來把攝影機連接樹莓派 的USB孔
  • 在用lsusb檢查連線狀態]
  • 確定連線後在資料夾下打上指令來啟動攝影機
  • ./mjpg_streamer -i”./input_uvc.so” -o”./output_http.so -w ./www”
  • 完成啟動後就可以在網頁上打上
  • http://192.168.0.135:8080/
  • 就有影像啦

目錄

  1. 簡介
  2. 代碼編寫
  3. 開船小遊戲
  4. 我是小小音樂家

1.簡介 

  Scratch是2007年美國麻省理工學院(MIT)媒體實驗室終身幼兒園團隊的一個計畫,主要是協助兒童學習創意思考、協同合作及系統性思考,所發展的一套開源的程式設計自由軟體,當然也適用於各年齡層的人使用。Scratch將一般專業的程式設計指令轉化為簡單的積木方塊,只要將這些指令積木拖曳組合,就能簡單的完成程式設計。我們可以使用Scratch來創作互動式故事、遊戲、動畫和音樂等作品,並且可以透過註冊官網(http://scratch.mit.edu)將自己的作品上傳,與全世界分享創意及觀摩優秀作品。

2.代碼編寫

1.開啟 Scratch

2.打開軟體可以設置成中文(步驟:1左上方地球2.more…3.找到正體中文)

我們通過Scratch軟體,去控制LED燈,這表示著我們主要工作是用這個軟體去控制樹莓派的GPIO,以及利用它去通過GPIO接收傳感器發來的訊號並對信號進行處裡。

打開 1.編輯2.Start GPIO server

準備好之後,就可以開始了,先看一個實例

當旗子被點擊到時,gpioserver及打開GPIOSERVER,然後使用config10out設定引腳10(BCM編碼方式)為out輸出模式。循環裡面使用gpio10high設定10引腳為高電流,gpio10low設定10引腳為低電流。這個程序就是讓10號腳位,也就是PWR.A35電源板上的LED0每隔一秒閃爍一次。

這是樹梅派GPIO圖

PWR.A35電源板

第二個例子(開船小遊戲)

有一天,船長開著小船在大海裡航行,突然風雲變色颳起了陣陣海風,船長眼看事情不妙需要緊急靠岸,遠方有一座小島但路上有許多浮木擋著去路,路況極為險惡需要各位小幫手帶領船長和船員們安全上岸。

首先我們要準備素材

  1. 有很多浮木和一個小島的舞台
  2. 一艘小船(背景為馬賽克)的腳色

控制船

  • 案一下船的圖案
  • 向船形素材添加程式,讓他可以從左下開始,然後跟隨鼠標指針。

撞船了!

現在,船形素材可以簡單地穿過木製障礙物航行!您現在要解決此問題。

您的船形素材需要兩種樣式:一種是普通的船,另一種是用於當船撞船時使用的。複製船型素材的樣式,並命名一個服裝為“普通船”,另一個命名為“撞船”。

單擊你的“撞船”素材,然後使用工具框選素材的各個部分,然後移動並旋轉它們,以使船看起來像已撞成碎片。

現在,將代碼添加到船上,使其在碰到任何棕色木製障礙物時會崩潰並破裂。您還應該添加代碼,以確保船形精靈始終從看起來“正常”開始。

再次測試您的代碼。如果您現在嘗試將船隻駛過木製障礙物,則船隻應墜毀,然後移回其起始位置。

贏了!

現在,在您的船型素材的代碼中增加另一個語句,讓玩家在使船到達黃色小島時獲勝。

當船到達島上時,小船要說“ YEAH!”,然後結束。

不要忘記以上是放在forever迴圈中

挑戰:音效

你可以添加在船隻墜毀或到達島嶼時播放的音效嗎?

選擇要添加聲音的素材。單擊聲音選項卡,然後單擊選擇聲音

聲音是按類別組織分的,你可以將鼠標停在圖標上可以聽到聲音。

選擇合適的聲音。

然後,您應該看到你的素材有你選擇的聲音。

添加計時器

現在,您將在遊戲中添加一個計時器,以便玩家必須盡快到達該島。

單擊“代碼”選項卡中的“ vanable”,然後單擊“make a vanable ”。

輸入speed。您可以選擇變量對所有子畫面可用,還是僅對該子畫面可用。按確定

創建vanable後,它會顯示在舞台上,或者您可以在“腳本”選項卡中取消選中該變量以將其隱藏。

現在,將代碼塊添加到{舞台}上,以便計時器開始計數,直到船到達島上為止。

測試你的遊戲,看看您能多快將船駛向島上!

障礙物和助推器

現在遊戲遠太容易了,所以你會添加一些東西,使遊戲更加有趣。

首先,您將添加一些助推器以加快速度。

現在,將更多代碼塊添加到船的forever循環中,以便船素材在觸摸白色箭頭時會加速。

測試你的遊戲,看看你的新助推器箭頭是否能使船加速。

接下來要做出一道旋轉門。

添加一個看起來像這樣的新素材,並將其命名為“ gate”:

確保旋轉門的顏色與木制障礙物的顏色相同。

盡量把它畫在最中間

向gate設定代碼讓他永久旋轉

現在,您應該有一個一直旋轉的門。

挑戰:改善遊戲

  • 你可以在遊戲中添加更多障礙嗎?例如,您可以在背景中添加綠色史萊姆並更改代碼,當玩家讓他們接觸時,史萊姆會減慢船速。
  • 或者是你可以添加移動障礙物,例如原木或鯊魚!
  • 您可以將您的遊戲變成兩個玩家之間的競賽嗎?第二名玩家將需要使用上下左右來控制自己的船。
  • 你是否可以通過添加不同的背景來創建更多關卡,然後可以允許玩家在關卡之間進行選擇?

第三個例子(我是小小音樂家)

素材

開始編碼之前,您需要在編碼中添加一個“樂器”。在Scratch中,這些“樂器”被稱為素材。

打開一個新的Scratch項目。

在線:在rpf.io/scratch-new上打開一個新的在線Scratch項目。

如果您需要下載並安裝Scratch離線編輯器,可以在rpf.io/scratchoff中找到它。

看起來像這樣:

您可以看到的貓精靈是Scratch吉祥物。這個遊戲不需要此吉祥物 ,因此可以通過右鍵單擊它,然後單擊叉叉來關掉它它。

接下來,點擊“素材庫”以打開所有Scratch素材的列表。

向下滾動,直到看到鼓素材。按鼓將其添加到你的項目中。

點擊並將鼓拖動到舞台底部。

在頂部的文本框中輸入名稱,為程序命名。

然後點擊“ Untitled”,然後點擊 “Save now”以保存您的項目。

舞台

在右邊的區域,是一個空白的舞台,他將會變成表演區!

此刻,舞台是白色的,看起來很無聊!通過 點擊選擇背景為其添加背景

點擊頂部列表中的“ 室內 ”。然後單擊劇院背景。

現在,您的階段應類似於以下內容:

製作鼓

現在,您將代碼添加到您的鼓中,以便在單擊該鼓時發出聲音。

您可以在“腳本”選項卡中找到代碼塊,並且它們都是彩色的!

首先添加音樂擴展名,以便您可以演奏樂器。

單擊左下角的添加擴展名按鈕。

點擊音樂擴展名將它添加。

點擊鼓嘗試新樂器!

挑戰:改變鼓聲

您可以更改單擊時鼓發出的聲音嗎?

按下空格鍵,還能使鼓發出聲音嗎?您將需要使用以下代碼event塊:

如果要復製現有代碼,請右鍵單擊它,然後單擊複製

做一個歌手

現在,您將為歌手添加歌手!

在舞台上添加歌手Sprite。

從庫中添加一個Scratch Sprite

在使歌手唱歌之前,您需要向歌手Sprite添加聲音。確保已選擇歌手素材,然後單擊“聲音”選項卡,然後單擊“ 選擇聲音”

點擊語音列表頂部,然後選擇一種聲音添加到您的精靈。

要使用聲音,請將以下代碼塊添加到歌手精靈中:

在舞台上單擊您的歌手,看看會發生什麼。她會唱歌嗎?

戲服

現在,您將使歌手看起來像她在唱歌!

您可以通過創建新服裝來更改歌手精靈​​在被點擊時的外觀。單擊“服裝”選項卡,您將看到歌手服裝。

右鍵單擊服裝,然後單擊重複以創建服裝的副本。

點擊新的服裝(稱為“ Singer2”),然後選擇線條工具並繪製線條,以使您的歌手看起來像在發出聲音。

這些服裝的名稱目前還不太有用。在服裝的文本框中輸入名稱,將其名稱更改為“不唱歌”和“唱歌”。

現在您為歌手準備了兩種不同的服裝,您可以選擇顯示哪種服裝!將這兩個代碼塊添加到歌手精靈中。

該部分中提供了用於更改服裝的代碼塊。

在舞台上點擊您的歌手。她看起來像在唱歌嗎?

現在,使您的鼓看起來像被敲打一樣!

記住要測試您的新代碼是否有效!

挑戰:增加您的樂隊

利用您在該項目中學到的知識,打造自己的樂隊!您可以創建自己喜歡的任何樂器-查看可用的樂器精靈和聲音以獲取一些想法。

不過,您的樂器不一定要現實。例如,您可以用鬆餅製成一架鋼琴!

您可以使用庫中更多的素材,也可以繪製自己的素材!

如果您有麥克風,則可以錄製自己的聲音,甚至可以使用網絡攝像頭來敲擊樂器!

目錄

  1. 實驗概述
  2. 實驗原理
  3. 代碼編寫
  4. 硬體連接及運行效果

1.實驗概述

使用樹莓派上的pythonm語言,編寫出一個小程式,來控制繼電器的吸合,經由這個實驗,可以學到最基本的1/0口控制,python控制樹莓派IO工作原理,繼電器的工作原理。

2.實驗原理

繼電器(relay) 是一種電子控制器件,它具有控制系統和被控制系統,通常應用於自動控制電路中,是用較小的電流去控制較大電流的一種「自動開關」,在電路中起著自動調節、安全保護、轉換電路等作用,當我們開始用樹梅派控制繼電器,就可以非常簡單的做出利用網頁控制的智慧插座或自動開關。

3.代碼編寫

  • 定義繼電器的腳位(sign=11)
  • 將GPIO設定為輸出模式,和起始電流(HIGH)或( LOW)
  • 代碼為:GPIO.setup(Sing,GPIO.OUT,initial=GPIO.LOW)
  • 使用GPIO.output()函數,把Sing腳位電流拉高
  • 代碼為: GPIO.output(Sing,True)
  • 接下來用延遲函數延遲1秒
  • 使用GPIO.output()函數,把Sing腳位電流拉低
  • 代碼為: GPIO.output(Sing, False)
  • 然後再延遲1秒,重複3~6的過程,我們就可以看到繼電器每隔一秒鐘被通斷一次。

import time

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

Sing =11

GPIO.setwarnings(False)

GPIO.setup(Sing,GPIO.OUT,initial=GPIO.LOW)

def do_action():

    GPIO.output(Sing,True)

    time.sleep(1)

    GPIO.output(Sing,False)

    time.sleep(1)

for i in range(1,5):

    do_action()

4.硬體連接及運行效果

  1. 硬體連接如下圖所示
  1. 啟動樹莓派並上傳運行

目錄

  1. 實驗概述
  2. 實驗原理
  3. 代碼編寫
  4. 硬體連接及運行效果

1.實驗概述

使用樹莓派上的pythonm語言,編寫出一個小程式,讓蜂鳴器發出聲音,經由這個實驗,可以學到最基本的1/0口控制,python控制樹莓派IO工作原理,蜂鳴器工作原理。

2.實驗原理

蜂鳴器是一個可以產生聲音信號的裝置,使用直流電供電,接通訊號源之後,音訊信號電流通過電磁線圈,使電磁線圈產生磁場,造成 振動膜片週期性地振動發聲。蜂鳴器的典型應用包括警笛、報警裝置、火災警報器、防空警報器、防盜器、定時器,等一些需要發聲的東西。

3.代碼編寫

  • 定義蜂鳴器的腳位(sign=11)
  • 將GPIO設定為輸出模式,和起始電流(HIGH)或( LOW)
  • 代碼為:GPIO.setup(Sing,GPIO.OUT,initial=GPIO.LOW)
  • 使用GPIO.output()函數,把Sing腳位電流拉高
  • 代碼為: GPIO.output(Sing,True)
  • 接下來用延遲函數延遲1秒
  • 使用GPIO.output()函數,把Sing腳位電流拉低
  • 代碼為: GPIO.output(Sing, False)
  • 然後再延遲1秒,重複3~6的過程,我們就可以看到蜂鳴器响一秒停一秒。

import time

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

Sing =11

GPIO.setwarnings(False)

GPIO.setup(Sing,GPIO.OUT,initial=GPIO.LOW)

def do_action():

    GPIO.output(Sing,True)

    time.sleep(1)

    GPIO.output(Sing,False)

    time.sleep(1)

for i in range(1,5):

    do_action()

4.硬體連接及運行效果

  1. 硬體連接如下圖所示
  1. 啟動樹莓派並上傳運行

目錄

  1. 實驗概述
  2. 實驗原理
  3. 代碼編寫

1.實驗概述

使用樹莓派上的pythonm語言,編寫出一個小程式,控制PWR.A53板上的三個LED燈閃爍,經由這個實驗,可以學到最基本的1/0口控制,延時函數,python控制樹莓派IO工作原理等。

2.實驗原理

LED燈是一種基本的發光器,給它輸入5V電壓時,它就會亮,給它0V時它就熄滅,這次實驗,利用PWR.A53板上的LED燈LED0、LED1、LED2三個燈,這三個燈分別接到10、9、25三個IO管腳(BCM模式),只要在程式裡改變那些腳位輸出電流,就可以讓LED燈閃爍的效果。下方圖示為腳位分布圖

3.代碼編寫

  • 設定LED的腳位(LED0=10)
  • 將GPIO設定為輸出模式,和起始電流(HIGH)或( LOW)
  • 代碼為: GPIO.steup(LED0, GPIO.OUT,initia= GPIO.HIGH )
  • 使用GPIO.output()函數,把LED0這個腳位電流拉低
  • 代碼為: GPIO.output(LED0,False)

程式如下

import time

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

LED0=10

LED1=9

LED2=25

GPIO.setwarnings(False)

GPIO.setup(LED0,GPIO.OUT,initial=GPIO.HIGH)##led

GPIO.setup(LED1,GPIO.OUT,initial=GPIO.HIGH)##led

GPIO.setup(LED2,GPIO.OUT,initial=GPIO.HIGH)##led

def init_light():

        GPIO.output(LED0,False)

        GPIO.output(LED1,False)

        GPIO.output(LED2,False)

        time.sleep(0.5)

        GPIO.output(LED0,True)

        GPIO.output(LED1,False)

        GPIO.output(LED2,False)

        time.sleep(0.5)

        GPIO.output(LED0,False)

        GPIO.output(LED1,True)

        GPIO.output(LED2,False)

        time.sleep(0.5)

        GPIO.output(LED0,False)

        GPIO.output(LED1,False)

        GPIO.output(LED2,True)

        time.sleep(0.5)

        GPIO.output(LED0,False)

        GPIO.output(LED1,False)

        GPIO.output(LED2,False)

        time.sleep(0.5)

        GPIO.output(LED0,False)

        GPIO.output(LED1,False)

        GPIO.output(LED2,False)

for i in range(1,5):

        init_light()

目錄

  1. 實驗概述
  2. 設備連接
  3. 樹莓派IO介紹
  4. 代碼編寫(notepad++)
  5. 代碼上傳及運行

1.實驗概述

Raspberry官方提供的raspbian系統,已經有python庫。可以直接使用python2.7來編成,來控制樹莓派的引角。

PWR.A35系列電源驅動板,將樹梅派40PIN插針的IO口全部引出。根據功能劃分了引腳。電源板上自帶3顆LED燈,由IO口的低電流驅動,我們以此當範例來講解python編成的基本操作。

2.設備連接

  1. 樹梅派主板和PWR.A35電源板扣在一起
  2. 源連接PWR.A35主板的電源
  3. 使用VNC遠端桌面

3.樹莓派IO介紹

樹莓派python庫對引腳有兩種定義方式,一種是以40根插針順序定義的IO(.BOARD模式),另一種是以主芯片內部腳位序號來定義的IO(.BCM模式)。我們是使用第二種腳位,因為這樣能夠更貼近芯片和硬件原本的設計,不會把3V3的引腳當作IO1來使用。下圖為樹梅派主板IO口及PWR.A35主板上的IO分布圖。

電源板上有三個LED燈,對應IO口,原理圖和實際位置如下圖所示。由原理圖可知,LED為上位模式,IO口輸出0時,LED亮,IO口輸出1時,LED滅,我們用python來實現控制三個LED閃爍.。

4.代碼編寫(Notepad++)

樹梅派系統,控制程序是基於python編寫的。Python是一種腳本語言,編程容易。但是唯一的問題就是需要注意格式,差排記得是按Tab鍵,不是空白鍵喔。

  • 安裝Notepad++(在Google就找的到) 點選下載
  • 開啟Notepad++,新建文件為LED.py,設置格式為UNLX格式(步驟:  編輯 ~ 換行格式 ~ 轉換為UNLX格式)

輸入如下帶碼並保存(記得後面要.py):

  • import time
  • import RPi.GPIO as GPIO
  • GPIO.setmode(GPIO.BCM)
  • LED0=10
  • LED1=9
  • LED2=25
  • GPIO.setwarnings(False)
  • GPIO.setup(LED0,GPIO.OUT,initial=GPIO.HIGH)##led
  • GPIO.setup(LED1,GPIO.OUT,initial=GPIO.HIGH)##led
  • GPIO.setup(LED2,GPIO.OUT,initial=GPIO.HIGH)##led
  • def init_light():
  •         GPIO.output(LED0,False)
  •         GPIO.output(LED1,False)
  •         GPIO.output(LED2,False)
  •         time.sleep(0.5)
  •         GPIO.output(LED0,True)
  •         GPIO.output(LED1,False)
  •         GPIO.output(LED2,False)
  •         time.sleep(0.5)
  •         GPIO.output(LED0,False)
  •         GPIO.output(LED1,True)
  •         GPIO.output(LED2,False)
  •         time.sleep(0.5)
  •         GPIO.output(LED0,False)
  •         GPIO.output(LED1,False)
  •         GPIO.output(LED2,True)
  •         time.sleep(0.5)
  •         GPIO.output(LED0,False)
  •         GPIO.output(LED1,False)
  •         GPIO.output(LED2,False)
  •         time.sleep(0.5)
  •         GPIO.output(LED0,False)
  •         GPIO.output(LED1,False)
  •         GPIO.output(LED2,False)
  • for i in range(1,5):
  •         init_light()
  • 代碼上傳及運行(WINSCP)
  • 打開WINSCP
  • 打上你要上傳的IP位置(每人都不一樣)
  • 用戶名:pi

密碼:raspberry(可保存連結下次就不用打)

  • 點擊登入,,並把編輯好的程序拖入work文件夾(如果沒有可以自己創建)
  • 在遠程桌面打開命令終端(或者可以使用ssh)輸入
  • cd work (進入work這個資料夾)
  • ls (查看資料夾裡有甚麼)
  • python popo_1.py (用python開啟popo_1.py這個資料)

這樣就可以看到妳寫的燈號閃爍了(如果都寫對的話)

6.如果有錯誤電腦無法識別,系統會告知你哪一行錯了,在檢查格式有沒有打錯,有沒有打錯字,等等…(這是個很漫長的過程,很心累但撐過就是你的,加油!!)

目錄

  1. 設備連接
  2. 設置臨時Client模式
  3. 設置永久Client模式

1.設備連接

  1. 樹莓派主板和PWA.A35電源主板扣在一起
  2. 電池接PWA.A35電源主板的電源口
  3. 把滑鼠鍵盤接到樹莓派的USB口
  4. HDMI線一端接螢幕,一端接在樹莓派上(也可使用遠端桌面)
  5. 打開電源板開關,等待系統啟動完成

2.設置臨時Client模式

1)首先來到樹梅派桌面,點擊左上Wifi圖示(因為我是插有線網路所以是兩個箭頭),再彈出的列表選擇要連的Wifi,打密碼即可連線

2)在瀏覽器可以測是網路是否連通,點選左上小地球圖示。

3)恢復默認AP,點擊Wifi圖示下面的Turn Off WiFi即可

3.設置永久Client模式

1)前已經安裝的套件都先更新到最新。

  • wget -q https://git.io/voEUQ -O /tmp/raspap && bash /tmp/raspap

過程中會詢問一些設定事項,依照個人需求選擇(大多選擇Y),重開機之後即可完成

完成後的預設 AP 資訊如下:

  • 樹莓派無線網卡 IP (管理介面網址):10.3.141.1
    • 使用者名稱:admin
    • 使用者密碼:secret
  • DHCP 範圍:10.3.141.50 到 10.3.141.255
  • WiFi 名稱 (SSID):raspi-webgui
  • WiFi 密碼:ChangeMe

3)到點腦右下角找到Wifi符號,打開後會看到剛設定Wifiau名稱raspi-webgui,連線密碼是ChangeMe(注意大小寫),選擇連線。

4)連線之後開啟Google Chrome,在搜索欄打上管理介面網址:10.3.141.1

進入之前需要打(這是預設的)

  • 使用者名稱:admin
    • 使用者密碼:secret

5)進入之後可以在這改HDCP

在這改使用者名稱,新的密碼

設定完記得按Save setting

最後Reboot就完成了

目錄

  • Linux常用命令
  • nano編輯器及其配置

一、Linux常用命令

Linux下的命令有幾千條,但真的實際在開發中用到的就只有那些。

  1. 查詢目錄的內容

Ls[選項][文件或目錄]

選項:

  • -a所有文件
  • -l查看詳情
  • -d查看目錄屬性
  • -h顯示文件大小

2.切換目錄

  •   cd目錄

  簡化操作:

  • cd~進入當前用戶目錄
  • cd-上次目錄
  • cd ..進入上一級目錄
  • pwd查看當前目錄所在位置

3.查看SD卡剩餘空間

  • df-h

4.查看ip地址

  • Ifconfig

5.壓縮: tar -zcvf filrname.tar.gz dirname

解壓:tar –zxvf filename.tar.gz

6. Linux系統常用apt(Advanced package Tool)高級軟件工具來安裝軟件

  • Sudo apt-get  install  xxx   安裝軟件
  • Sudo apt-get  update      更新軟件列表
  • Sudo apt-get  upgrade     更新以安裝軟件
  • Sudo apt-get  remove  xxx  刪除軟件

具體有關Linux命令的教學網址(https://man.linuxde.net/)

二、使用nano編輯器及其配置

linux下有很多文字編輯器,其中系統都會自帶nano這個最基本的編輯器。

直接在命令列中輸入( nano  [文件名稱] )即可開啟檔案或新建檔案。

  • 移動光標:使用方向鍵移動
  • 選擇文件:按住滑鼠左鍵拖動
  • 複製、剪貼合黏貼
  • 複製一整行:Alt+6
  • 剪貼一整行Ctrl+K
  • 黏貼: Ctrl+U

光顯控制

如果需要複製/剪貼多行或者一行中的一部份,先將光標移動到需要複製/剪貼的文件的開頭。按Ctrl+6(或者Alt+A)做標記,然後移動光標到 待複製/剪貼的文本末尾。這時選定的文本會反白,用Alt+6來複製,Ctrl+K來剪貼。若要在選擇文本過程中要取消,只需要在按一次Ctrl+6。

搜索

Ctrl+ W,然後輸入你要搜尋的關鍵字,按Enter確定。這將會定位到第一個匹配的文本,接著可以用Alt+ W來定位到下一個匹配的文本。

翻頁

  • Ctrl+Y到上一頁
  • Ctrl+X到下一頁

保存

  • 使用Ctrl+O來保存所右的修改

退出

按Ctrl+X.

如果你修改文件,它會詢問你是否需要保存修改。Y確認保存,N不保存,按Ctrl+C取消返回。如果輸入Y,下一步會問你想保存的文件名稱,如果不用修改直接按Enter就行:若想要保存成其他名子(也就是另存為)輸入新名子按Enter確定。這時候也可以用Ctrl+C來取消返回。

目錄

  • 使用WinSCP戶傳文件

使用WinSCP戶傳文件

有時候我們需要在windows和樹莓派兩個不同系統之間傳輸文件,因為兩邊系統不一樣,無法互傳,就需要用到ssh服務來跨系統傳輸。

  1. https://winscp.net/download/WinSCP-5.15.9-Setup.exe下載WinSCP
  1. 下載完之後點擊進入WinSCP
  • 檔案協定 : SCP
  • 主機名稱輸入你的IP位置。(如192.168.0.116)
  • 使用者名稱 : pi
  • 密碼 : raspberry
  • 按是

4)在這個介面就可以在兩個不同系統之間拖動文件了

注意 : 有時拖移文件遇到文件傳輸失敗,一般是樹莓派這邊權限不夠,我們只要給予最高權限。Chmod 777樹莓派目錄名。

注意 : 在通過SSH上傳文件時出現: Encountedred 1 error during the transfer 錯誤一方面是我們登陸樹莓派時,權限問題將我們要拖拉的文件的權限給chmod 777 filename.令一方面是windows這邊文件是有權限的,一般只要把它移到桌面就可以傳輸,同時windows這邊文件的路徑和文件名稱不能帶()。不然它會出現傳輸錯誤。

目錄

  1. 操作說明
  2. SSH遠程登
  3. 修改pi帳號密碼和開啟Root帳號
  4. 遠程桌面登
  5. 遠程桌面登入 (有線)

1.操作說明

這個方法適合用筆電或是沒有顯示器的人使用,可以不用micro HDMI線、螢幕、外接鍵盤和滑鼠,只需要用網路線和一台ap就可以借由筆電的螢幕鍵盤和滑鼠來操作。

2.SSH遠程登

SSH:(我們目前開發中一般以這種方式登入)

當我們需要進行遠程開發(通過網路線或WIFI連接),可以借助Linux系統特有的一種服務SSH來完成。系統以集成Wifi AP功能,開機後自動開啟Wifi熱點(在沒有連接其他無線的情況下)往口設置為靜態ip,容易訪問。

  1. SSH運行程序

1)   首先把SD卡插上電腦,在boot卡裡新增一個文字檔,把檔名改成ssh,(這樣做可以強制開啟ssh) 。到chrome線上應用程式商店找到Secure Shell Extension並加到chrome。

2)鍵安裝完成後,可以直接在瀏覽器的網址列直接打上ssh, 接下來再按下Tab鍵就會自動進入ssh插件模式, 然後就可以打上 (使用者)@ ( IP位址 ),

[email protected]

初次登入的話,一開始會先建立金鑰的認證, 請輸入yes來同意認證。

登入密碼:raspberry

(因為密碼是預設的關係,打字是不會顯現出來的,打完直接按Enter就可以成功登入)

成功登入後就會如下圖, 會進到一個Raspberry Pi中的shell中,然後可以開始使用了。

3.修改pi帳號密碼和開啟Root帳號

1)再命令行下執行sudo passwd root。

2)執行命令後系統會提示輸入兩次root密碼,輸入你想設置的密碼。

3)然後再執行Sudo passwd  –unloock root。

4.遠程桌面登入

當PC和樹莓派在同一個區域網時,就可以遠控制樹莓派

  • 首先要用ssh連接樹莓派,把更新資料庫,執行
  • sudo apt-get update
  • 再升級sudo apt-get upgrade(這需要一段時間)

   輸入y

  • 安裝VNC的librar,執行sudo apt-get install tightvnc

和sudo apt-get install tightvncserver(安裝需要一點時間)

  • 載完之後,設定密碼,執行vncpasswd

打兩次你要設定的密碼

6)設定完之後,執行vncserver

就會產生另一個螢幕叫座raspberry:1就可以用電腦連接。

7)在你的電腦chrome搜尋RealVNC,選擇你的作業系統點選下載

8)載好之後開啟RealVNC,點選左上角File,底下的New connection建立新連線

9)進入之後再server ip輸入你的ip加上:1 , (ex.192.168.0.116:1) (:1 就是你剛剛新建的螢幕)

10)按OK之後就會出現虛擬螢幕

11)點擊你創建的螢幕,會出現警告欄,按繼續。

11)打上你剛設定的密碼按ok。

12)遠端桌面就完成了。

使用完之後記得在伺服器終端打上vncserver -kill :1

出現killing xtingtvnc process 代表已關閉1號伺服器

當然也可以設成開機啟動在 Linux 系統上如果想要在開機時自動執行,只要將要執行的指令寫在對應的系統設定檔中,就可以輕鬆達到這個效果,我們的作法就是把指定加在 /etc/rc.local 這個指令稿中,只要放在這裡的指令,在每次 Linux 開機時就會自動被執行。

  • sudo nano /etc/rc.local
  • 在exit 0的上一行,寫入vncserver
  • ctrl+x離開在按y存檔
  • sudo reboot重新啟動就完成了

5.遠程桌面登入 (有線)

當PC和樹莓派在同一個區域網時,就可以控制樹莓派,除了可以透過剛剛上面說的ssh外,也可以使用固定ip的方法,用有線的方式連接樹莓派。注意:固定ip和ap模式是無法並存的,在有線連接的狀態下,是無法下載RaspAP的喔

  • 首先要用ssh連接樹莓派,執行
  • sudo nano /etc/network/interfaces
  • 如果有浮動ip記得先刪除,沒有的話直接把這些打上去
  • auto eth0
  • iface eth0 inet static
  • address 192.168.100.200
  • netmask 255.255.255.0
  • 按Ctrl+O和Entre儲存檔案
  • 在按 Ctrl+X離開編輯器
  • 接著在命令列打上sudo reboot
  • 重新啟動後將樹莓派插上網路線並連接到電腦 。(電腦沒有網路孔可使用轉接頭)
  • 現在我們要把電腦也設定成固定ip,讓他們在同一個網域
  • 在桌面的右下方又件點選網路,開啟網路和網際網路設定
  • 在視窗裡點選變更介面卡選項
  • 到乙太網路右鍵選擇內容
  • 快速點擊(網際網路通訊協定第4版)兩下
  • 設定電腦ip
  • IP位址:192.168.100.100
  • 子網路遮罩:255.255.255.0
  • 其他都空白,然後按確定
  • 這時就可以用192.168.100.200登入ssh開啟vnc
  • vncserver
  • 他會開啟一個叫做192.168.100.200:1的螢幕。
  • 在上面的空白欄位上打上192.168.100.200:1
  • 然後Enter
  • 點選Continue
  • 打密碼:raspberry
  • 然後按OK
  • 就成功以有線的方法,連線了~
  • 下載後打開balenaEtcher,點擊(select image)。
  • 選擇剛下載的Raspbian映像檔(記得要先解壓縮)。
  • 選擇你的SD卡,然後Flash。
  • 就會開始下載了,載完關閉即可。
  • 把你的SD卡插到樹梅派的插槽就可以啟動了。

SD卡擴容

因為我們是使用 img 檔燒錄 SD 卡的作業系統,所以系統內定只有用到 2GB空間。

如果想從 2GB 擴展到整個 SD 的空間的話,請依以下步驟設定。

  • 進入設定係統,在命令列下面輸入sudo raspi-config。
  • 選擇 Advanced Options 然後Enter。
  • 選擇第一項Expand Filesystems Ensures that all of the SD card storage is available
  • 按Enter。
  • 它告訴我們已經磁區已經擴展完成,下一次開機就會是擴展後的結果。