返回部落格
精選文章

嵌入式系統與 IoT 開發:打造智慧連接的未來

探索嵌入式系統在 IoT 生態系統中的關鍵作用,從硬體選型到軟體架構的全方位指南。

BASHCAT 技術團隊
8 分鐘閱讀
#嵌入式系統#IoT#ESP32#Arduino

嵌入式系統與物聯網的完美結合

在數位化轉型的浪潮中,嵌入式系統與物聯網(IoT)技術的結合正在重新定義我們與周圍世界的互動方式。從智慧家居到工業 4.0,這些技術正在創造一個更加智能、互聯的未來。

嵌入式系統基礎

硬體平台選擇

選擇合適的硬體平台是成功專案的第一步:

ESP32 系列

ESP32 是我們最推薦的 IoT 開發平台之一:

#include "WiFi.h"
#include "PubSubClient.h"

const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
const char* mqtt_server = "your_mqtt_broker";

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");
}

Arduino 系列

對於入門級專案,Arduino 提供了友善的開發環境:

#include <SoftwareSerial.h>
#include <ArduinoJson.h>

SoftwareSerial bluetooth(2, 3);

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

  // 初始化感測器
  pinMode(A0, INPUT);  // 溫度感測器
  pinMode(13, OUTPUT); // LED指示燈
}

void loop() {
  int temperature = analogRead(A0);
  float celsius = (temperature * 5.0 / 1024.0 - 0.5) * 100;

  // 建立JSON格式數據
  StaticJsonDocument<200> doc;
  doc["temperature"] = celsius;
  doc["timestamp"] = millis();

  String output;
  serializeJson(doc, output);
  bluetooth.println(output);

  delay(1000);
}

感測器整合

數位感測器

DHT22 溫濕度感測器是常用的數位感測器:

#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

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

void loop() {
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.print("%  Temperature: ");
  Serial.print(temperature);
  Serial.println("°C");

  delay(2000);
}

類比感測器

光敏電阻的使用範例:

const int photocellPin = A0;
const int ledPin = 9;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int photocellReading = analogRead(photocellPin);

  // 將感測器值映射到LED亮度
  int ledBrightness = map(photocellReading, 0, 1023, 255, 0);
  analogWrite(ledPin, ledBrightness);

  Serial.print("Analog reading = ");
  Serial.print(photocellReading);
  Serial.print(" - LED brightness = ");
  Serial.println(ledBrightness);

  delay(100);
}

IoT 架構設計

通訊協定選擇

MQTT 協定

MQTT 是 IoT 應用中最常用的輕量級訊息協定:

import paho.mqtt.client as mqtt
import json
import time

def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    client.subscribe("sensors/temperature")

def on_message(client, userdata, msg):
    try:
        data = json.loads(msg.payload.decode())
        temperature = data['temperature']
        timestamp = data['timestamp']

        print(f"Received: {temperature}°C at {timestamp}")

        # 處理數據邏輯
        if temperature > 30:
            client.publish("alerts/high_temperature",
                          json.dumps({"alert": "High temperature detected"}))

    except Exception as e:
        print(f"Error processing message: {e}")

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)
client.loop_forever()

HTTP REST API

對於需要請求-回應模式的應用:

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

void sendSensorData(float temperature, float humidity) {
  if(WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin("http://your-api-server.com/api/sensors");
    http.addHeader("Content-Type", "application/json");

    StaticJsonDocument<200> doc;
    doc["device_id"] = "ESP32_001";
    doc["temperature"] = temperature;
    doc["humidity"] = humidity;
    doc["timestamp"] = millis();

    String jsonString;
    serializeJson(doc, jsonString);

    int httpResponseCode = http.POST(jsonString);

    if(httpResponseCode > 0) {
      String response = http.getString();
      Serial.println(response);
    }

    http.end();
  }
}

數據處理與分析

邊緣計算

在設備端進行初步數據處理:

#include <math.h>

class SensorFilter {
private:
  float readings[10];
  int index;
  bool filled;

public:
  SensorFilter() : index(0), filled(false) {}

  float addReading(float value) {
    readings[index] = value;
    index = (index + 1) % 10;
    if (index == 0) filled = true;

    return getAverage();
  }

  float getAverage() {
    float sum = 0;
    int count = filled ? 10 : index;

    for (int i = 0; i < count; i++) {
      sum += readings[i];
    }

    return sum / count;
  }

  bool isAnomalous(float value) {
    float avg = getAverage();
    float variance = 0;
    int count = filled ? 10 : index;

    for (int i = 0; i < count; i++) {
      variance += pow(readings[i] - avg, 2);
    }

    float stdDev = sqrt(variance / count);
    return abs(value - avg) > (2 * stdDev);
  }
};

SensorFilter tempFilter;

void loop() {
  float rawTemp = readTemperature();
  float filteredTemp = tempFilter.addReading(rawTemp);

  if (tempFilter.isAnomalous(rawTemp)) {
    Serial.println("Anomalous reading detected!");
    // 觸發警報或額外處理
  }

  // 只發送過濾後的數據
  sendSensorData(filteredTemp);
  delay(1000);
}

電源管理

低功耗設計

對於電池供電的 IoT 設備,功耗控制至關重要:

#include "esp_sleep.h"

#define uS_TO_S_FACTOR 1000000  // 微秒到秒的轉換因子
#define TIME_TO_SLEEP  30       // 睡眠時間(秒)

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

  // 讀取感測器數據
  float temperature = readTemperature();
  float humidity = readHumidity();

  // 發送數據
  sendDataToServer(temperature, humidity);

  // 配置喚醒源
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  Serial.println("Going to sleep now");
  Serial.flush();

  // 進入深度睡眠
  esp_deep_sleep_start();
}

void loop() {
  // 這裡不會執行,因為設備會在setup後進入睡眠
}

電池監控

#define BATTERY_PIN A0
#define VOLTAGE_DIVIDER_RATIO 2.0

float getBatteryVoltage() {
  int rawValue = analogRead(BATTERY_PIN);
  float voltage = (rawValue / 1024.0) * 3.3 * VOLTAGE_DIVIDER_RATIO;
  return voltage;
}

int getBatteryPercentage() {
  float voltage = getBatteryVoltage();

  // 假設鋰電池電壓範圍 3.0V - 4.2V
  if (voltage >= 4.2) return 100;
  if (voltage <= 3.0) return 0;

  return (int)((voltage - 3.0) / 1.2 * 100);
}

void checkBatteryStatus() {
  int batteryLevel = getBatteryPercentage();

  if (batteryLevel < 20) {
    // 發送低電量警告
    sendLowBatteryAlert();

    // 啟動節能模式
    enablePowerSaveMode();
  }
}

安全性考量

數據加密

#include "mbedtls/aes.h"

void encryptData(uint8_t* input, uint8_t* output, uint8_t* key) {
  mbedtls_aes_context aes;
  mbedtls_aes_init(&aes);
  mbedtls_aes_setkey_enc(&aes, key, 256);
  mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, input, output);
  mbedtls_aes_free(&aes);
}

void secureDataTransmission(String data) {
  uint8_t key[32] = {/* your encryption key */};
  uint8_t input[16];
  uint8_t encrypted[16];

  // 準備數據進行加密
  data.getBytes(input, 16);

  // 加密數據
  encryptData(input, encrypted, key);

  // 發送加密數據
  sendEncryptedData(encrypted, 16);
}

設備認證

#include <WiFiClientSecure.h>

WiFiClientSecure client;

void setupSecureConnection() {
  // 載入CA憑證
  client.setCACert(ca_cert);

  // 載入客戶端憑證和私鑰
  client.setCertificate(client_cert);
  client.setPrivateKey(client_key);
}

bool authenticateDevice() {
  if (client.connect("secure.server.com", 443)) {
    String authRequest = "GET /api/authenticate HTTP/1.1\r\n";
    authRequest += "Host: secure.server.com\r\n";
    authRequest += "Device-ID: " + String(ESP.getEfuseMac()) + "\r\n";
    authRequest += "Connection: close\r\n\r\n";

    client.print(authRequest);

    // 讀取回應
    String response = client.readString();
    return response.indexOf("200 OK") != -1;
  }

  return false;
}

實際專案範例

智慧農業監控系統

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

#define SOIL_MOISTURE_PIN A0
#define DHT_PIN 2
#define PUMP_PIN 8

DHT dht(DHT_PIN, DHT22);
WiFiClient espClient;
PubSubClient mqtt(espClient);

struct SensorData {
  float temperature;
  float humidity;
  int soilMoisture;
  bool pumpStatus;
  float batteryLevel;
};

void setup() {
  Serial.begin(115200);
  dht.begin();
  pinMode(PUMP_PIN, OUTPUT);

  connectWiFi();
  mqtt.setServer("mqtt.broker.com", 1883);
  mqtt.setCallback(mqttCallback);
}

void loop() {
  SensorData data = readSensors();

  // 自動灌溉邏輯
  if (data.soilMoisture < 30 && !data.pumpStatus) {
    activatePump();
    data.pumpStatus = true;
  } else if (data.soilMoisture > 70 && data.pumpStatus) {
    deactivatePump();
    data.pumpStatus = false;
  }

  // 發送數據到雲端
  publishSensorData(data);

  // 檢查電池狀態
  if (data.batteryLevel < 20) {
    enterPowerSaveMode();
  }

  delay(30000); // 30秒間隔
}

SensorData readSensors() {
  SensorData data;
  data.temperature = dht.readTemperature();
  data.humidity = dht.readHumidity();
  data.soilMoisture = map(analogRead(SOIL_MOISTURE_PIN), 0, 1023, 0, 100);
  data.pumpStatus = digitalRead(PUMP_PIN);
  data.batteryLevel = getBatteryLevel();
  return data;
}

故障診斷與維護

遠端診斷

void performDiagnostics() {
  DiagnosticReport report;

  // 檢查WiFi連接
  report.wifiStatus = WiFi.status() == WL_CONNECTED;
  report.signalStrength = WiFi.RSSI();

  // 檢查感測器狀態
  report.sensorStatus = testSensors();

  // 檢查記憶體使用
  report.freeHeap = ESP.getFreeHeap();
  report.heapFragmentation = ESP.getHeapFragmentation();

  // 檢查電源狀態
  report.batteryVoltage = getBatteryVoltage();

  // 發送診斷報告
  sendDiagnosticReport(report);
}

遠端更新

#include <HTTPUpdate.h>

void checkForUpdates() {
  String currentVersion = "1.0.0";
  String updateURL = "http://update.server.com/firmware.bin";

  HTTPClient http;
  http.begin(updateURL + "?version=" + currentVersion);

  int httpCode = http.GET();
  if (httpCode == 200) {
    Serial.println("Update available, starting download...");

    t_httpUpdate_return ret = httpUpdate.update(updateURL);

    switch (ret) {
      case HTTP_UPDATE_FAILED:
        Serial.printf("Update failed. Error: %s\n",
                     httpUpdate.getLastErrorString().c_str());
        break;
      case HTTP_UPDATE_NO_UPDATES:
        Serial.println("No updates available");
        break;
      case HTTP_UPDATE_OK:
        Serial.println("Update successful, rebooting...");
        ESP.restart();
        break;
    }
  }

  http.end();
}

未來趨勢

Edge AI 整合

#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"

// AI模型在邊緣設備上的推理
class EdgeAI {
private:
  tflite::MicroInterpreter* interpreter;

public:
  bool initModel(const unsigned char* model_data) {
    static tflite::MicroErrorReporter micro_error_reporter;
    static tflite::AllOpsResolver resolver;

    // 設置模型
    model = tflite::GetModel(model_data);

    // 建立解釋器
    static uint8_t tensor_arena[10000];
    interpreter = new tflite::MicroInterpreter(
        model, resolver, tensor_arena, 10000, &micro_error_reporter);

    return interpreter->AllocateTensors() == kTfLiteOk;
  }

  float predict(float* input_data) {
    // 設置輸入數據
    TfLiteTensor* input = interpreter->input(0);
    for (int i = 0; i < input->bytes / sizeof(float); i++) {
      input->data.f[i] = input_data[i];
    }

    // 執行推理
    if (interpreter->Invoke() != kTfLiteOk) {
      return -1;
    }

    // 獲取預測結果
    TfLiteTensor* output = interpreter->output(0);
    return output->data.f[0];
  }
};

總結

嵌入式系統與 IoT 技術的結合為我們打開了無限可能的大門。從智慧家居到工業自動化,這些技術正在重塑我們的世界。成功的 IoT 專案需要:

  1. 合適的硬體平台選擇
  2. 可靠的通訊架構
  3. 有效的電源管理
  4. 強健的安全機制
  5. 智能的數據處理

在 BASHCAT,我們擁有豐富的嵌入式系統和 IoT 開發經驗,能夠為客戶提供從概念到產品的完整解決方案。如果您有相關的專案需求,歡迎與我們聯繫。

延伸閱讀

探索更多相關的技術洞察與開發經驗分享

更多 embedded 文章

即將推出更多相關技術分享

查看全部文章