🫐 Raspberry Pi 4 · Embedded C · Industrial IoT

SmartMill Guardian
CNC Machine Health Monitor

A real-time predictive maintenance platform for industrial CNC machines, using vibration FFT analysis, thermal profiling, and on-device ML to prevent catastrophic downtime — saving clients $40K+ per avoided failure event.

⏱ Duration: 2–3 weeks
💰 Budget: from $490
📦 Platform: Raspberry Pi 4B
🔧 Language: Embedded C (C99)
☁️ Cloud: AWS IoT Core
# Key Outcomes
1kHz
Sample Rate
<5ms
Fault Detect
94%
ML Accuracy
60%
Downtime Cut
$40K
Savings/Event
50x
Nodes Scalable
# Problem & Solution

The Problem

  • CNC machines failing without warning — $40K average cost per unplanned outage
  • Existing vibration sensors needed expensive PLCs (Siemens S7) to interpret data
  • No real-time visibility — operators checked machines manually every 4 hours
  • Cloud-only solutions had 2–5 second latency — too slow for safety shutdowns
  • Legacy RS-485 wiring had to be reused — no budget for new fieldbus

The Solution

  • Bare-metal FreeRTOS firmware on RPi 4 — deterministic 1 kHz interrupt-driven sampling
  • On-device FFT (CMSIS-DSP) identifies bearing fault harmonics in milliseconds
  • µTensor ML model trained on 6 months of historical fault data — 94% accuracy
  • Direct Modbus RTU master — bridges PLC data without new wiring
  • 5ms local relay output for safety shutdown before cloud round-trip
# Firmware Architecture (Sample)
vibration_task.c — FreeRTOS vibration sampling task
/* vibration_task.c — 1kHz ADXL345 sampling with FFT fault detection */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "arm_math.h"          /* CMSIS-DSP FFT */
#include "adxl345_drv.h"
#include "alarm_manager.h"

#define FFT_SIZE    1024
#define SAMPLE_HZ   1000
#define BEARING_FREQ_HZ 87.3f   /* BPFO for SKF 6205 bearing */

static float32_t fft_input[FFT_SIZE];
static float32_t fft_output[FFT_SIZE / 2];
static arm_rfft_fast_instance_f32 fft_inst;

void vibration_task(void *pvParams) {
    arm_rfft_fast_init_f32(&fft_inst, FFT_SIZE);
    adxl345_init(SPI_BUS_0, GPIO_CS_PIN);

    TickType_t last_wake = xTaskGetTickCount();

    for (;;) {
        /* Collect 1024 samples at 1kHz — fills buffer in exactly 1.024 s */
        for (int i = 0; i < FFT_SIZE; i++) {
            fft_input[i] = (float32_t) adxl345_read_z_mg();
            vTaskDelayUntil(&last_wake, pdMS_TO_TICKS(1));
        }

        /* Run real FFT in-place */
        arm_rfft_fast_f32(&fft_inst, fft_input, fft_output, 0);
        arm_cmplx_mag_f32(fft_output, fft_output, FFT_SIZE / 2);

        /* Check energy at bearing fault frequency ±2 bins */
        uint32_t bin = (uint32_t)((BEARING_FREQ_HZ * FFT_SIZE) / SAMPLE_HZ);
        float32_t energy = fft_output[bin-2] + fft_output[bin]
                          + fft_output[bin+2];

        if (energy > FAULT_THRESHOLD_MG) {
            alarm_raise(ALARM_BEARING_FAULT, energy);
            relay_set(RELAY_SPINDLE_STOP, RELAY_ON);  /* <5ms HW shutdown */
        }

        mqtt_publish_vibration(fft_output, FFT_SIZE/2, energy);
    }
}
modbus_master.c — RS-485 Modbus RTU for Siemens PLC integration
/* Reads spindle speed + current from Siemens S7-1200 via Modbus RTU */
typedef struct {
    uint16_t spindle_rpm;
    uint16_t motor_current_mA;
    uint16_t coolant_temp_dC;
    uint8_t  fault_bits;
} plc_data_t;

esp_err_t modbus_read_plc(uint8_t slave_id, plc_data_t *out) {
    uint8_t req[] = {slave_id, 0x03, 0x00, 0x64, 0x00, 0x04};
    crc16_append(req, sizeof(req) - 2);

    uart_write_bytes(UART_NUM_2, req, sizeof(req));
    int len = uart_read_bytes(UART_NUM_2, resp_buf, 13,
                               pdMS_TO_TICKS(50));

    if (len == 13 && crc16_valid(resp_buf, len)) {
        out->spindle_rpm      = parse_u16(resp_buf + 3);
        out->motor_current_mA = parse_u16(resp_buf + 5);
        out->coolant_temp_dC  = parse_u16(resp_buf + 7);
        out->fault_bits       = resp_buf[9];
        return ESP_OK;
    }
    return ESP_ERR_TIMEOUT;
}
# Full Tech Stack

Hardware

Raspberry Pi 4B (4GB) ADXL345 (SPI) MLX90614 IR (I²C) MAX485 RS-485 Transceiver 4-Ch Relay HAT 7" DSI Industrial Touch RTC DS3231 Custom breakout PCB (KiCad)

Firmware & Software

Embedded C (C99) FreeRTOS (bare-metal) CMSIS-DSP (FFT) µTensor ML inference Modbus RTU Master MQTT (libmosquitto) AWS IoT Core + Rules InfluxDB + Grafana
# Project Timeline
Week 1
Hardware Design & Bring-up
KiCad schematic + PCB, sensor driver development (ADXL345 SPI, MLX90614 I²C), UART RS-485 loopback tests
Week 2
FreeRTOS Kernel & Task Design
Task hierarchy, ISR design, 1kHz sampling verified with logic analyser, ring buffer implementation
Week 3
FFT Engine & Modbus RTU
CMSIS-DSP integration, fault frequency bin mapping, Siemens S7-1200 Modbus register map, CRC16 implementation
Week 4
ML Model & Cloud Pipeline
µTensor model training (Python), model quantisation (INT8), AWS IoT Core certificate setup, InfluxDB schema
Week 5
Integration, Testing & Documentation
Factory acceptance testing, Grafana dashboards, operator manual, calibration SOP, client handover

Need This for Your Factory?

I'll custom-build a predictive maintenance system around your specific machine type, sensor suite, and PLC brand.