Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ss:laboratoare:03 [2026/03/16 19:03]
ciprian.popescu0411
ss:laboratoare:03 [2026/03/16 19:36] (current)
ciprian.popescu0411
Line 7: Line 7:
   - Înțelegerea arhitecturii unui sistem IoT bazat pe MQTT (Publisher/​Subscriber).   - Înțelegerea arhitecturii unui sistem IoT bazat pe MQTT (Publisher/​Subscriber).
   - Configurarea mediului de dezvoltare (PlatformIO,​ Mosquitto, Python).   - Configurarea mediului de dezvoltare (PlatformIO,​ Mosquitto, Python).
-  - Utilizarea ESP32-CAM pentru captură foto și transmisie ​WiFi.+  - Utilizarea ESP32-CAM pentru captură foto și transmisie ​Wi-Fi.
   - Controlul dispozitivului de la distanță prin comenzi MQTT.   - Controlul dispozitivului de la distanță prin comenzi MQTT.
  
Line 15: Line 15:
  
   - **ESP32-CAM (Publisher/​Subscriber)**:​   - **ESP32-CAM (Publisher/​Subscriber)**:​
-    * Se conectează la rețeaua ​WiFi.+    * Se conectează la rețeaua ​Wi-Fi.
     * Publică imagini (JPEG) pe topicul ''​ssproject/​images''​.     * Publică imagini (JPEG) pe topicul ''​ssproject/​images''​.
     * Ascultă comenzi pe topicul ''​ssproject/​commands''​.     * Ascultă comenzi pe topicul ''​ssproject/​commands''​.
Line 118: Line 118:
 === 3.4 Definirea pinilor GPIO pentru cameră === === 3.4 Definirea pinilor GPIO pentru cameră ===
  
-Creați fișierul ''​camera/​include/​camera_pins.hpp''​ cu definițiile pinilor GPIO pentru modelul AI-Thinker:+Creați fișierul ''​camera/​include/​camera_pins.h''​ cu definițiile pinilor GPIO pentru modelul AI-Thinker:
  
-<file c camera_pins.hpp>+<file c camera_pins.h>
 #if defined(CAMERA_MODEL_AI_THINKER) #if defined(CAMERA_MODEL_AI_THINKER)
 #define PWDN_GPIO_NUM ​    32 #define PWDN_GPIO_NUM ​    32
Line 152: Line 152:
 camera/ camera/
 ├── include/ ├── include/
-│   ​└── camera_pins.hpp     # Definițiile pinilor GPIO+│   ​└── camera_pins.h       # Definițiile pinilor GPIO
 ├── src/ ├── src/
 │   ​└── main.cpp ​           # Codul principal (de mai jos) │   ​└── main.cpp ​           # Codul principal (de mai jos)
Line 173: Line 173:
 </​code>​ </​code>​
  
 +De asemenea, în Visual Studio Code (cu extensia PlatformIO) aceleași acțiuni se pot face și din tastatură:
 +
 +  * **''​Ctrl''​ + ''​Alt''​ + ''​B''​** – build (compilează proiectul)
 +  * **''​Ctrl''​ + ''​Alt''​ + ''​U''​** – upload pe placă
 +
 +Astfel nu mai este necesar să rulați comenzile manual în terminal.
 ===== Codul sursă ===== ===== Codul sursă =====
  
Line 180: Line 186:
  
 <file cpp main.cpp>​ <file cpp main.cpp>​
 +/​**********************************************************************
 +  Filename ​   : Camera MQTT Client
 +  Description : ESP32-CAM MQTT Image Transfer
 +**********************************************************************/​
 +#include "​esp_camera.h"​
 +#include <​WiFi.h>​
 +#include <​PubSubClient.h>​
 +// CAMERA_MODEL is defined in platformio.ini
 +#include "​camera_pins.h"​
  
 +// ===========================
 +// Configuration
 +// ===========================
 +const char* ssid     = ""; ​      // TODO: Modificați cu SSID-ul rețelei voastre
 +const char* password = ""; ​    // TODO: Modificați cu parola rețelei voastre
 +const char* mqtt_server = "​10.10.10.10";​ // TODO: Modificați cu IP-ul calculatorului (ip addr / ipconfig)
 +const int mqtt_port = 1883;
 +
 +// Topics
 +const char* TOPIC_COMMAND = "​ssproject/​commands";​
 +const char* TOPIC_IMAGE ​  = "​ssproject/​images";​
 +
 +WiFiClient espClient;
 +PubSubClient client(espClient);​
 +
 +// State variables
 +bool streaming = false;
 +bool take_one_picture = false;
 +unsigned long last_capture_time = 0;
 +const unsigned long STREAM_INTERVAL = 100; // ms
 +
 +void setup_camera() {
 +  camera_config_t config = {};
 +  config.ledc_channel ​   = LEDC_CHANNEL_0;​
 +  config.ledc_timer ​     = LEDC_TIMER_0;​
 +  config.pin_d0 ​         = Y2_GPIO_NUM;​
 +  config.pin_d1 ​         = Y3_GPIO_NUM;​
 +  config.pin_d2 ​         = Y4_GPIO_NUM;​
 +  config.pin_d3 ​         = Y5_GPIO_NUM;​
 +  config.pin_d4 ​         = Y6_GPIO_NUM;​
 +  config.pin_d5 ​         = Y7_GPIO_NUM;​
 +  config.pin_d6 ​         = Y8_GPIO_NUM;​
 +  config.pin_d7 ​         = Y9_GPIO_NUM;​
 +  config.pin_xclk ​       = XCLK_GPIO_NUM;​
 +  config.pin_pclk ​       = PCLK_GPIO_NUM;​
 +  config.pin_vsync ​      = VSYNC_GPIO_NUM;​
 +  config.pin_href ​       = HREF_GPIO_NUM;​
 +  config.pin_sccb_sda ​   = SIOD_GPIO_NUM;​
 +  config.pin_sccb_scl ​   = SIOC_GPIO_NUM;​
 +  config.pin_pwdn ​       = PWDN_GPIO_NUM;​
 +  config.pin_reset ​      = RESET_GPIO_NUM;​
 +  config.xclk_freq_hz ​   = 20000000;
 +  config.pixel_format ​   = PIXFORMAT_JPEG;​
 +  ​
 +  if (psramFound()) {
 +    Serial.println("​PSRAM found!"​);​
 +    config.frame_size ​   = FRAMESIZE_VGA;​
 +    config.jpeg_quality ​ = 12; 
 +    config.fb_count ​     = 2;
 +  } else {
 +    Serial.println("​No PSRAM found, using DRAM"​);​
 +    config.frame_size ​   = FRAMESIZE_SVGA;​
 +    config.jpeg_quality ​ = 12; 
 +    config.fb_count ​     = 1;
 +    config.fb_location ​  = CAMERA_FB_IN_DRAM;​
 +  }
 +  ​
 +  Serial.println("​Initializing camera..."​);​
 +  esp_err_t err = esp_camera_init(&​config);​
 +  if (err != ESP_OK) {
 +    Serial.printf("​Camera init failed with error 0x%x\n",​ err);
 +    return;
 +  }
 +  Serial.println("​Camera Ready!"​);​
 +}
 +
 +void callback(char* topic, byte* payload, unsigned int length) {
 +  Serial.println(">>>​ CALLBACK FIRED <<<"​);​
 +  String message;
 +  for (int i = 0; i < length; i++) {
 +    message += (char)payload[i];​
 +  }
 +  Serial.printf("​Topic:​ %s\n", topic);
 +  Serial.printf("​Message:​ [%s] (len=%u)\n",​ message.c_str(),​ length);
 +
 +  if (String(topic) == TOPIC_COMMAND) {
 +    if (message == "​CAPTURE"​) {
 +      take_one_picture = true;
 +      Serial.println("​=>​ Action: take_one_picture = true"​);​
 +    } else if (message == "​START-LIVE"​) {
 +      streaming = true;
 +      Serial.println("​=>​ Action: Streaming Started"​);​
 +    } else if (message == "​STOP-LIVE"​) {
 +      streaming = false;
 +      Serial.println("​=>​ Action: Streaming Stopped"​);​
 +    } else {
 +      Serial.println("​=>​ Unknown command, ignoring"​);​
 +    }
 +  } else {
 +    Serial.println("​=>​ Wrong topic, ignoring"​);​
 +  }
 +}
 +
 +void reconnect() {
 +  while (!client.connected()) {
 +    Serial.print("​Attempting MQTT connection..."​);​
 +    String clientId = "​ESP32CamClient-";​
 +    clientId += String(random(0xffff),​ HEX);
 +    Serial.printf("​ (clientId=%s)\n",​ clientId.c_str());​
 +    ​
 +    if (client.connect(clientId.c_str())) {
 +      Serial.println("​MQTT connected!"​);​
 +      bool subOk = client.subscribe(TOPIC_COMMAND);​
 +      Serial.printf("​Subscribe to '​%s':​ %s\n", TOPIC_COMMAND,​ subOk ? "​OK"​ : "​FAILED"​);​
 +      Serial.printf("​Buffer size: %d\n", client.getBufferSize());​
 +      Serial.printf("​Free heap: %u bytes\n",​ ESP.getFreeHeap());​
 +    } else {
 +      Serial.print("​failed,​ rc=");
 +      Serial.print(client.state());​
 +      Serial.println("​ try again in 5 seconds"​);​
 +      delay(5000);​
 +    }
 +  }
 +}
 +
 +void setup() {
 +  Serial.begin(115200);​
 +  delay(1000);​
 +  Serial.println();​
 +  Serial.println("​============================"​);​
 +  Serial.println(" ​ ESP32-CAM MQTT Client"​);​
 +  Serial.println("​============================"​);​
 +  Serial.printf("​Free heap at start: %u bytes\n",​ ESP.getFreeHeap());​
 +  Serial.printf("​PSRAM size: %u bytes\n",​ ESP.getPsramSize());​
 +
 +  setup_camera();​
 +
 +  Serial.printf("​Connecting to WiFi: %s\n", ssid);
 +  WiFi.begin(ssid,​ password);
 +  while (WiFi.status() != WL_CONNECTED) {
 +    delay(500);
 +    Serial.print("​."​);​
 +  }
 +  Serial.printf("​\nWiFi connected! IP: %s\n", WiFi.localIP().toString().c_str());​
 +
 +  client.setServer(mqtt_server,​ mqtt_port);
 +  client.setCallback(callback);​
 +  client.setBufferSize(65000); ​
 +}
 +
 +void captureAndPublish() {
 +    camera_fb_t * fb = esp_camera_fb_get();​
 +    if (!fb) {
 +        Serial.println("​Camera capture failed"​);​
 +        return;
 +    }
 +    ​
 +    if (client.publish(TOPIC_IMAGE,​ (const uint8_t*)fb->​buf,​ fb->​len)) {
 +        Serial.printf("​Image published: %u bytes\n",​ fb->​len);​
 +    } else {
 +        Serial.println("​Publish failed"​);​
 +    }
 +    ​
 +    esp_camera_fb_return(fb);​
 +}
 +
 +unsigned long last_heartbeat = 0;
 +
 +void loop() {
 +  if (!client.connected()) {
 +    Serial.println("​MQTT disconnected,​ reconnecting..."​);​
 +    reconnect();​
 +  }
 +  client.loop();​
 +
 +  unsigned long now = millis();
 +
 +  // Print a heartbeat every 5 seconds so you know the loop is running
 +  if (now - last_heartbeat > 5000) {
 +    Serial.printf("​[heartbeat] millis=%lu connected=%d streaming=%d free_heap=%u\n",​
 +                  now, client.connected(),​ streaming, ESP.getFreeHeap());​
 +    last_heartbeat = now;
 +  }
 +  ​
 +  if (take_one_picture) {
 +    Serial.println("​Taking single picture..."​);​
 +    captureAndPublish();​
 +    take_one_picture = false;
 +  }
 +  ​
 +  if (streaming && (now - last_capture_time > STREAM_INTERVAL)) {
 +    captureAndPublish();​
 +    last_capture_time = now;
 +  }
 +}
 </​file>​ </​file>​
 +
 +<note warning>​Nu deschideți ''​Serial Monitor''​ în Visual Studio Code, deoarece este foarte posibil să-și dea ''​RESET''​ placa.</​note>​
  
 ==== Receiver Python (''​receiver/​receiver.py''​) ==== ==== Receiver Python (''​receiver/​receiver.py''​) ====
Line 326: Line 528:
     * Folosiți comanda ''​Upload''​ din PlatformIO sau terminal: ''​pio run -t upload''​.     * Folosiți comanda ''​Upload''​ din PlatformIO sau terminal: ''​pio run -t upload''​.
   - **Testare**:​   - **Testare**:​
-    * După resetare, camera se va conecta la WiFi (urmăriți Serial Monitor).+    * După resetare, camera se va conecta la Wi-Fi.
     * Din fereastra receiver-ului,​ apăsați ''​b''​ pentru a porni live stream-ul.     * Din fereastra receiver-ului,​ apăsați ''​b''​ pentru a porni live stream-ul.
     * Verificați latența și calitatea imaginii.     * Verificați latența și calitatea imaginii.
ss/laboratoare/03.1773680637.txt.gz · Last modified: 2026/03/16 19:03 by ciprian.popescu0411
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0