diff --git a/.github/workflows/build_release_bins.yml b/.github/workflows/build_release_bins.yml
index fd414b7f..ba4e20cf 100644
--- a/.github/workflows/build_release_bins.yml
+++ b/.github/workflows/build_release_bins.yml
@@ -40,7 +40,7 @@ jobs:
       matrix: ${{fromJson(needs.setup.outputs.matrix)}}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - name: Build OpenIris Firmware
@@ -68,7 +68,7 @@ jobs:
         run: |
           echo "FIRMWARE_NAME=$(cat ESP/build/${{ matrix.target_name }}${{ matrix.target_build_type }}/firmware_name.txt)" >> $GITHUB_ENV
       - name: Archive Firmware Binaries
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: ${{ matrix.target_name }}${{ matrix.target_build_type }}-firmware
           #path: "./ESP/.pio/build/${{ matrix.target_name }}${{ matrix.target_build_type }}/${{ env.FIRMWARE_NAME }}.bin"
@@ -80,17 +80,17 @@ jobs:
     needs: [build]
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - name: Create Directory
         run: mkdir -p build
       - name: Download Firmware Files
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v4
         with:
           path: build/
       - name: Setup node
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: 18
       - run: npm install -g conventional-changelog-conventionalcommits@6
@@ -117,6 +117,6 @@ jobs:
     timeout-minutes: 10
     steps:
       - name: "♻️ remove build artifacts"
-        uses: geekyeggo/delete-artifact@v1
+        uses: geekyeggo/delete-artifact@v5
         with:
           name: ${{ matrix.target_name }}${{ matrix.target_build_type }}-firmware
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db93df25..9dc7e0e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,29 @@
 [![semantic versioning](https://img.shields.io/badge/semantic%20versioning-2.0.0-green.svg)](https://semver.org)
 > All notable changes to this project will be documented in this file
 
+## [2.7.0-beta.2](https://github.com/EyeTrackVR/OpenIris/compare/v2.7.0-beta.1...v2.7.0-beta.2) (2025-01-12)
+
+
+### 🍕 Features
+
+* Add camera resolution configuration support ([#79](https://github.com/EyeTrackVR/OpenIris/issues/79)) ([5c76e01](https://github.com/EyeTrackVR/OpenIris/commit/5c76e01c5e466c8cc7ef4cd43e78a763af00c06e))
+
+## [2.7.0-beta.1](https://github.com/EyeTrackVR/OpenIris/compare/v2.6.0...v2.7.0-beta.1) (2025-01-11)
+
+
+### 🍕 Features
+
+* Add support for ov5640 cameras ([14d2cb0](https://github.com/EyeTrackVR/OpenIris/commit/14d2cb0858cd65452f2ce1cee9a3a1f68d8f7f51))
+* Fix ov5640 support implementation after beta cleanup ([4894c22](https://github.com/EyeTrackVR/OpenIris/commit/4894c2205864d5a7d52e37c81b14ff7dc46517d4))
+* fix usb streaming on wroom boards, add support for babble custom board  ([049b160](https://github.com/EyeTrackVR/OpenIris/commit/049b16078ec5c07042652f2de3545ea6b69de6a9))
+* Move logging in serial streaming so that we at least attempt to get new frame ([53a3d4b](https://github.com/EyeTrackVR/OpenIris/commit/53a3d4bcd603e2fd07546621628e69de88e4139a))
+* Refactor commands and serial manager to support updated commands payload ([811a9f8](https://github.com/EyeTrackVR/OpenIris/commit/811a9f898a3f1bdb1e20ffd6f0d6e77a4533f52c))
+
+
+### 🐛 Bug Fixes
+
+* serial output for esp32cams and other boards not supporting higher frequency baud rate ([01e5e28](https://github.com/EyeTrackVR/OpenIris/commit/01e5e280ad26d2709231fe6aa2a96d1991cbf360))
+
 ## [2.6.0](https://github.com/EyeTrackVR/OpenIris/compare/v2.5.0...v2.6.0) (2024-07-14)
 
 
diff --git a/ESP/ini/boards.ini b/ESP/ini/boards.ini
index 8115cbf8..868b7fcc 100644
--- a/ESP/ini/boards.ini
+++ b/ESP/ini/boards.ini
@@ -190,7 +190,10 @@ upload_flags = --no-stub
 
 [env:Babble-wrooms-s3]
 board = esp32-s3-devkitc-1
-board_build.flash_mode = qio  ; qio_qspi
+board_upload.flashsize = "4MB"
+board_upload.flash_size=4MB
+board_upload.maximum_size = 4194304
+board_build.flash_mode = qio
 board_build.arduino.memory_type = qio_qspi
 build_type = debug
 build_flags = ${env.build_flags}
@@ -200,9 +203,27 @@ build_flags = ${env.build_flags}
 			 ${pinoutSWROOMBABBLES3.build_flags}
 upload_flags = --no-stub
 
+[env:Babble-wrooms-s3_release]
+board = esp32-s3-devkitc-1
+board_upload.flashsize = "4MB"
+board_upload.flash_size=4MB
+board_upload.maximum_size = 4194304
+board_build.flash_mode = qio
+board_build.arduino.memory_type = qio_qspi
+build_type = debug
+build_flags = ${env.build_flags}
+			 -DCORE_DEBUG_LEVEL=1
+			 -DDEBUG_MODE=0
+             -DSERIAL_MANAGER_USE_HIGHER_FREQUENCY
+			 ${pinoutSWROOMBABBLES3.build_flags}
+upload_flags = --no-stub
+
 [env:Babble_USB-wrooms-s3]
 board = esp32-s3-devkitc-1
-board_build.flash_mode = qio  ; qio_qspi
+board_upload.flashsize = "4MB"
+board_upload.flash_size=4MB
+board_upload.maximum_size = 4194304
+board_build.flash_mode = qio
 board_build.arduino.memory_type = qio_qspi
 build_type = debug
 build_flags = ${env.build_flags}
@@ -211,6 +232,25 @@ build_flags = ${env.build_flags}
 			 -DETVR_EYE_TRACKER_USB_API
 			 -DARDUINO_USB_MODE=1
 			 -DARDUINO_USB_CDC_ON_BOOT=1
+			 -DARDUINO_FLASH
+             -DSERIAL_MANAGER_USE_HIGHER_FREQUENCY
+			 ${pinoutSWROOMBABBLES3.build_flags}
+upload_flags = --no-stub
+
+[env:Babble_USB-wrooms-s3_release]
+board = esp32-s3-devkitc-1
+board_upload.flashsize = "4MB"
+board_upload.flash_size=4MB
+board_upload.maximum_size = 4194304
+board_build.flash_mode = qio
+board_build.arduino.memory_type = qio_qspi
+build_type = debug
+build_flags = ${env.build_flags}
+			 -DCORE_DEBUG_LEVEL=1
+			 -DDEBUG_MODE=0
+			 -DETVR_EYE_TRACKER_USB_API
+			 -DARDUINO_USB_MODE=1
+			 -DARDUINO_USB_CDC_ON_BOOT=1
              -DSERIAL_MANAGER_USE_HIGHER_FREQUENCY
 			 ${pinoutSWROOMBABBLES3.build_flags}
 upload_flags = --no-stub
diff --git a/ESP/ini/dev_config.ini b/ESP/ini/dev_config.ini
index e028ff06..e338c40d 100644
--- a/ESP/ini/dev_config.ini
+++ b/ESP/ini/dev_config.ini
@@ -5,7 +5,7 @@
 platform = https://github.com/platformio/platform-espressif32.git
 framework = arduino
 monitor_speed = 115200
-custom_firmware_version = 2.6.0
+custom_firmware_version = 2.7.0
 monitor_rts = 0
 monitor_dtr = 0
 monitor_filters =
@@ -46,6 +46,7 @@ build_flags =
 
 	'-DOTA_PASSWORD=${ota.otapassword}'    ; Set the OTA password
 	'-DOTA_LOGIN=${ota.otalogin}'
+	'-DCAM_RESOLUTION=${cam.resolution}'
 
 	-O2                    ; optimize for speed
 	-DASYNCWEBSERVER_REGEX ; enable regex in asyncwebserver
diff --git a/ESP/ini/user_config.ini b/ESP/ini/user_config.ini
index e91ed658..a67a540e 100644
--- a/ESP/ini/user_config.ini
+++ b/ESP/ini/user_config.ini
@@ -18,3 +18,6 @@ otapassword = "12345678"
 
 [development]
 serial_flush_enabled = 0
+
+[cam]
+resolution = FRAMESIZE_240X240
\ No newline at end of file
diff --git a/ESP/lib/library.json b/ESP/lib/library.json
index 53b99d39..991c6de2 100644
--- a/ESP/lib/library.json
+++ b/ESP/lib/library.json
@@ -20,7 +20,7 @@
     "include": "/lib/src"
   },
   "dependencies": {},
-  "version": "2.6.0",
+  "version": "2.7.0",
   "frameworks": "arduino",
   "platforms": "espressif32"
 }
diff --git a/ESP/lib/src/data/config/project_config.cpp b/ESP/lib/src/data/config/project_config.cpp
index 9154b1ea..05ea095b 100644
--- a/ESP/lib/src/data/config/project_config.cpp
+++ b/ESP/lib/src/data/config/project_config.cpp
@@ -1,4 +1,5 @@
 #include "project_config.hpp"
+#include "sensor.h"
 
 ProjectConfig::ProjectConfig(const std::string& name,
                              const std::string& mdnsName)
@@ -53,7 +54,7 @@ void ProjectConfig::initConfig() {
   this->config.camera = {
       .vflip = 0,
       .href = 0,
-      .framesize = 4,
+      .framesize = (uint8_t)CAM_RESOLUTION,
       .quality = 7,
       .brightness = 2,
   };
@@ -200,7 +201,7 @@ void ProjectConfig::load() {
   /* Camera Config */
   this->config.camera.vflip = getInt("vflip", 0);
   this->config.camera.href = getInt("href", 0);
-  this->config.camera.framesize = getInt("framesize", 4);
+  this->config.camera.framesize = getInt("framesize", (uint8_t)CAM_RESOLUTION);
   this->config.camera.quality = getInt("quality", 7);
   this->config.camera.brightness = getInt("brightness", 2);
 
diff --git a/ESP/lib/src/io/camera/cameraHandler.cpp b/ESP/lib/src/io/camera/cameraHandler.cpp
index 7b51bdb7..323b4e82 100644
--- a/ESP/lib/src/io/camera/cameraHandler.cpp
+++ b/ESP/lib/src/io/camera/cameraHandler.cpp
@@ -63,7 +63,7 @@ void CameraHandler::setupCameraPinout() {
 
 void CameraHandler::setupBasicResolution() {
   config.pixel_format = PIXFORMAT_JPEG;
-  config.frame_size = FRAMESIZE_240X240;
+  config.frame_size = CAM_RESOLUTION;
 
   if (!psramFound()) {
     log_e("[Camera]: Did not find psram, setting lower image quality");
@@ -108,6 +108,10 @@ void CameraHandler::setupCameraSensor() {
   camera_sensor->set_aec2(camera_sensor, 0);         // 0 = disable , 1 = enable
   camera_sensor->set_ae_level(camera_sensor, 0);     // -2 to 2
   camera_sensor->set_aec_value(camera_sensor, 300);  // 0 to 1200
+  // Use a lower aec value for babble to better isolate the face with illuminators 
+  #ifdef CONFIG_CAMERA_MODULE_SWROOM_BABBLE_S3
+    camera_sensor->set_aec_value(camera_sensor, 100);  // 0 to 1200
+  #endif
 
   // controls the gain
   camera_sensor->set_gain_ctrl(camera_sensor, 0);  // 0 = disable , 1 = enable
@@ -195,7 +199,29 @@ void CameraHandler::loadConfigData() {
   log_d("Loading camera config data done");
 }
 
-int CameraHandler::setCameraResolution(framesize_t frameSize) {
+#ifdef CONFIG_CAMERA_MODULE_SWROOM_BABBLE_S3
+int CameraHandler::setCameraResolution(framesize_t frameSize) {   // For Babble, use a firmware crop as shown by Physdude
+  if (camera_sensor->pixformat == PIXFORMAT_JPEG) {
+    try {
+        int outputSize = 240;
+
+        int baseRes = 2; //CIF 
+        int ROIsize = 240; 
+        int startPointX = 80; 
+        int startPointY = 28; 
+
+        return camera_sensor->set_res_raw(camera_sensor, baseRes, 0, 0, 0, startPointX, startPointY, ROIsize, ROIsize, outputSize, outputSize, 0, 0);
+
+    } catch (...) {
+      // they sent us a malformed or unsupported frameSize - rather than crash -
+      // tell them about it
+      return -1;
+    }
+  }
+  return -1;
+}
+#else
+int CameraHandler::setCameraResolution(framesize_t frameSize) {   // By default, use the standard method. 
   if (camera_sensor->pixformat == PIXFORMAT_JPEG) {
     try {
       return camera_sensor->set_framesize(camera_sensor, frameSize);
@@ -207,6 +233,7 @@ int CameraHandler::setCameraResolution(framesize_t frameSize) {
   }
   return -1;
 }
+#endif
 
 int CameraHandler::setVFlip(int direction) {
   return camera_sensor->set_vflip(camera_sensor, direction);