πŸš€ RikMakersHub Pro

5 + 1 bonus Elite-Tier Microcontroller Engineering Blueprints

πŸ† Enter RikMakersHub ( 80+ Different Microcontroller Projects Blueprints ) πŸš€

🌿 Project 1: Automated Smart Greenhouse Array (ESP32 Master-Slave I2C Protocol) State Award Winner πŸ†

Distributed Architecture 2x Arduino Uno 2x ESP32 NodeMCU

System Architecture: Master-Slave array sharing data over an isolated I2C bus channel. The dual Arduinos isolate high-frequency local hardware telemetry reading and relay switching arrays, while the dual ESP32 cores process secure dual-band Wi-Fi packet uploads, IoT database synchronization, and encrypted override command scripts.

πŸ”Œ System Inter-Chip Connections & Code Matrices

Bus Map: Uno-1 (Sensor Node) & Uno-2 (Actuator Controller) connect as Slaves to ESP32 Master-1 via hardware SDA/SCL lines with 4.7k Pull-up Resistors.

[Master ESP32 Network Sync Code]

#include <Wire.h>
#include <WiFi.h>
// Distributed Master Control Core
void setup() {
  Wire.begin(21, 22); // Custom SDA, SCL pins
  WiFi.begin("RikMakersNet", "SecurePass123");
}
void loop() {
  Wire.requestFrom(8, 6); // Request sensor telemetry packet from Uno Slave 8
  // Fast loop network processing routine...
}

🧭 Project 2:Autonomous Maze-Solving Rover (Arduino Uno Flood-Fill Algorithm)

Arduino Uno3x Ultrasonic SensorsL293D

πŸ› οΈ Components

πŸ”Œ Circuit Diagram & Code

Sensors to D2-D3, D11-D12, A0-A1. Motors to Shield M1-M4.

#include 

// Maze Dimensions
const int SIZE = 5; 
int maze[SIZE][SIZE];
int walls[SIZE][SIZE]; // Bitmask: 1=North, 2=East, 4=South, 8=West

// Robot State
int x = 0, y = 0; // Current position
int dir = 0;      // 0:North, 1:East, 2:South, 3:West

// Pin Definitions
#define TRIG_F 2
#define ECHO_F 3
// ... Define other sensors and motor pins ...

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

void loop() {
  updateWalls();      // Check sensors for walls
  floodFill(2, 2);    // Goal is cell (2,2)
  moveToBestCell();   // Determine next move based on lowest neighboring value
}

// 1. Initialize maze with distances to goal (Manhattan distance)
void initializeMaze() {
  for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
      maze[i][j] = abs(i - 2) + abs(j - 2); 
    }
  }
}

// 2. Flood Fill logic to update cell values
void floodFill(int targetX, int targetY) {
  // Simple version: Iteratively update cell values based on neighbors
  bool changed = true;
  while (changed) {
    changed = false;
    for (int i = 0; i < SIZE; i++) {
      for (int j = 0; j < SIZE; j++) {
        if (i == targetX && j == targetY) continue;
        
        int minDist = 255;
        // Check North (if no wall)
        if (!(walls[i][j] & 1) && i > 0) minDist = min(minDist, maze[i-1][j]);
        // ... Check East, South, West ...
        
        if (maze[i][j] != minDist + 1) {
          maze[i][j] = minDist + 1;
          changed = true;
        }
      }
    }
  }
}

// 3. Movement logic
void moveToBestCell() {
  // Check neighbors, find smallest value in 'maze' array, and command motors
}

πŸ”’ Project 3:Encrypted Security Safe (Microcontroller Non-Volatile EEPROM Storage)

Arduino UnoMFRC522Keypad

πŸ› οΈ Components

πŸ”Œ Circuit Diagram & Code

RFID SPI to D13-D9. Keypad to D8-D1. LCD via I2C.

#include 
#include 
#include 
#include 
#include 
#include 
#include 

// --- Configuration ---
const byte ROWS = 4; 
const byte COLS = 4; 
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; 
byte colPins[COLS] = {6, 7, 8, 9}; 

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
Servo lockServo;
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Master override code (Layer 2)
const char* masterCode = "A1234";
char inputBuffer[10];
byte bufferIndex = 0;
bool isAdminMode = false;

// EEPROM addresses
const int HASH_START_ADDR = 0;
const int HASH_LENGTH = 32; // SHA-256 produces 32 bytes

void setup() {
  Serial.begin(9600);
  lockServo.attach(10);
  lockServo.write(0); // Locked position
  
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("System Ready");
  delay(1000);
  lcd.clear();
}

void loop() {
  char customKey = customKeypad.getKey();
  
  if (customKey) {
    handleKeyPress(customKey);
  }
}

void handleKeyPress(char key) {
  if (key == '#') { // Enter key
    inputBuffer[bufferIndex] = '\0';
    processInput();
    bufferIndex = 0;
  } else if (key == '*') { // Clear key
    bufferIndex = 0;
    lcd.clear();
    lcd.print("Enter Pin:");
  } else {
    inputBuffer[bufferIndex] = key;
    lcd.setCursor(bufferIndex, 1);
    lcd.print('*');
    bufferIndex++;
  }
}

void processInput() {
  // Check for Layer 2: Administrator Override
  if (strcmp(inputBuffer, masterCode) == 0) {
    isAdminMode = true;
    lcd.clear();
    lcd.print("Admin Mode");
    delay(1000);
    lcd.print("New Pin:");
    bufferIndex = 0;
    return;
  }

  if (isAdminMode) {
    saveNewPassword(inputBuffer);
    isAdminMode = false;
    lcd.clear();
    lcd.print("Pin Updated!");
    delay(1000);
    lcd.clear();
  } else {
    // Check for Layer 1: User Authentication
    if (verifyPassword(inputBuffer)) {
      lcd.clear();
      lcd.print("Access Granted");
      lockServo.write(90); // Unlock
      delay(5000);
      lockServo.write(0); // Lock
      lcd.clear();
    } else {
      lcd.clear();
      lcd.print("Access Denied");
      delay(1000);
      lcd.clear();
    }
  }
}

bool verifyPassword(char* inputPass) {
  byte inputHash[HASH_LENGTH];
  computeHash(inputPass, inputHash);

  // Compare input hash with stored hash in EEPROM
  for (int i = 0; i < HASH_LENGTH; i++) {
    if (EEPROM.read(HASH_START_ADDR + i) != inputHash[i]) {
      return false;
    }
  }
  return true;
}

void saveNewPassword(char* newPass) {
  byte newHash[HASH_LENGTH];
  computeHash(newPass, newHash);

  // Save the new hash to EEPROM
  for (int i = 0; i < HASH_LENGTH; i++) {
    EEPROM.update(HASH_START_ADDR + i, newHash[i]);
  }
}

void computeHash(const char* input, byte* output) {
  SHA256 sha256;
  sha256.update((uint8_t*)input, strlen(input));
  sha256.finalize(output, HASH_LENGTH);
}
 

πŸ”‘ Project 4:Biometric Vehicle Ignition System (Arduino Nano & AS608 Relay Control)

Arduino NanoAS608Relay

πŸ› οΈ Components

πŸ”Œ Circuit Diagram & Code

AS608 TX/RX to D2/D3. Relay to D4.

#include 
#include 

// Define pins for the fingerprint sensor
SoftwareSerial mySerial(2, 3); // RX, TX
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

const int relayPin = 4; // Pin to trigger the ignition relay

void setup() {
  Serial.begin(9600);
  while (!Serial); 
  delay(100);
  
  Serial.println("\n\nBiometric Vehicle Ignition System Initializing...");

  // Set the data rate for the sensor serial port
  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH); // Set HIGH to ensure relay is off (if using Active LOW relay module)
}

void loop() {
  getFingerprintIDez();
  delay(50); // Don't ned to run this at full speed
}

int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK) {
    Serial.println("Fingerprint not found! Access Denied.");
    return -1;
  }

  // Found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);

  // Trigger the ignition
  Serial.println("Vehicle Started!");
  digitalWrite(relayPin, LOW); // Turn ON the ignition relay (Assuming Active-LOW)
  delay(3000); // Keep ignition engaged/on for 3 seconds (adjust as needed)
  
  digitalWrite(relayPin, HIGH); // Turn OFF relay after simulated start
  Serial.println("Ignition turned off. Drive safely.");

  return finger.fingerID;
}

πŸ”‹Project 5: Solar-Powered Telemetry Logger (Pro Mini 3.3V & INA219 Current Sensor)

Pro Mini 3.3VINA219SD Card

πŸ› οΈ Components

πŸ”Œ Circuit Diagram & Code

INA219 to A5/A4. SD Card via SPI (D13, D12, D11, D4).

#include 
#include 

// --- Configurable Settings ---
int tolerance = 10;           // LDR reading difference tolerance to prevent jitter
int stepSize = 1;             // Degrees to move servo on each check

// --- Pin Definitions ---
const int ldrTopPin    = A0;
const int ldrBottomPin = A1;
const int ldrLeftPin   = A2;
const int ldrRightPin  = A3;

Servo servoVertical;
Servo servoHorizontal;

// Starting angles for the servos
int posVertical = 90;
int posHorizontal = 90;

void setup() {
  servoVertical.attach(9);
  servoHorizontal.attach(10);
  
  // Set servos to center position on boot
  servoVertical.write(posVertical);
  servoHorizontal.write(posHorizontal);
  delay(500); 
}

void loop() {
  // 1. WAKE UP & TRACK SUN
  trackSun();

  // 2. LOG DATA (Add your SD logging or EEPROM write functions here)
  logData();

  // 3. DEEP SLEEP (Approx. 1 minute)
  // Watchdog timer max is 8s, so we loop it 8 times (8s * 7.5 = 60s)
  for (int i = 0; i < 8; i++) {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}

void trackSun() {
  int top = analogRead(ldrTopPin);
  int bottom = analogRead(ldrBottomPin);
  int left = analogRead(ldrLeftPin);
  int right = analogRead(ldrRightPin);

  // Calculate averages
  int avgVert = (top + bottom) / 2;
  int avgHoriz = (left + right) / 2;

  // --- VERTICAL AXIS CONTROL ---
  if (abs(top - bottom) > tolerance) {
    if (top > bottom) {
      posVertical += stepSize;
    } else {
      posVertical -= stepSize;
    }
  }

  // --- HORIZONTAL AXIS CONTROL ---
  if (abs(left - right) > tolerance) {
    if (left > right) {
      posHorizontal -= stepSize; // Reverse as needed depending on LDR orientation
    } else {
      posHorizontal += stepSize;
    }
  }

  // Constrain servo limits
  posVertical = constrain(posVertical, 0, 180);
  posHorizontal = constrain(posHorizontal, 0, 180);

  // Apply positions
  servoVertical.write(posVertical);
  servoHorizontal.write(posHorizontal);

  // Small delay for servos to reach position before sleeping
  delay(15); 
}

void logData() {
  // Placeholder for logger function. 
  // Disable low power configurations briefly if needed.
}

🦾 Project 6:BLE Kinematic Robotic Arm (ESP32 & PCA9685 I2C Servo Driver)

ESP32BLEPCA9685

πŸ› οΈ Components

πŸ”Œ Circuit Diagram & Code

PCA9685 to 21/22. Servos to PCA9685 channels 0-3.

#include 
#include 
#include 
#include 
#include 
#include 

// --- BLE UUIDs ---
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART standard for simple TX/RX
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

// --- Pin Definitions for Servos ---
const int servoPins[4] = {13, 12, 14, 27}; // Base, Shoulder, Elbow, Gripper
Servo servos[4];

BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;

// --- Low-Latency BLE Callbacks ---
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        deviceConnected = true;
        // Request lower connection latency (min 10ms, max 20ms) for high-speed, real-time control
        pServer->updateConnParams(pServer->getConnId(), 8, 16, 0, 400); 
    };

    void onDisconnect(BLEServer* pServer) {
        deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
        std::string rxValue = pCharacteristic->getValue();

        if (rxValue.length() > 0) {
            // Parse incoming CSV string (e.g., "90,45,120,30")
            // Note: For production use, consider sending byte arrays instead of strings to cut down latency further.
            int angles[4];
            int index = 0;
            char *token = strtok((char*)rxValue.c_str(), ",");
            while (token != NULL && index < 4) {
                angles[index++] = atoi(token);
                token = strtok(NULL, ",");
            }

            // Apply constraints & move servos
            for (int i = 0; i < 4; i++) {
                if(angles[i] >= 0 && angles[i] <= 180) {
                    servos[i].write(angles[i]);
                }
            }
        }
    }
};

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

    // Attach Servos
    for(int i = 0; i < 4; i++) {
        servos[i].setPeriodHertz(50);
        servos[i].attach(servoPins[i], 500, 2400); // Standard micro-servo range (500-2400us)
    }

    // Initialize BLE
    BLEDevice::init("ESP32_Robot_Arm");
    BLEServer *pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    BLEService *pService = pServer->createService(SERVICE_UUID);

    pTxCharacteristic = pService->createCharacteristic(
                            CHARACTERISTIC_UUID_TX,
                            BLECharacteristic::PROPERTY_NOTIFY
                        );
    pTxCharacteristic->addDescriptor(new BLE2902());

    BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                            CHARACTERISTIC_UUID_RX,
                            BLECharacteristic::PROPERTY_WRITE
                        );
    pRxCharacteristic->setCallbacks(new MyCallbacks());

    pService->start();

    // Start Advertising
    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(SERVICE_UUID);
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);  // functions that help with low-latency connection settings
    pAdvertising->setMinPreferred(0x12);
    BLEDevice::startAdvertising();
    
    Serial.println("Waiting a client connection to notify...");
}

void loop() {
    // Bluetooth connection handles all processing in the callback, keep loop clear for IK logic
    // To send sensor feedback to your app (like live encoder angles), you can use:
    // pTxCharacteristic->setValue(String(current_angle));
    // pTxCharacteristic->notify();
    
    delay(10);
}