# ─────────────────────────────────────────────────────────────────────────────
# Smart PLC Condition Monitor — Single Machine Version
# K.K. Wagh Institute | Dept. E&TC | Group 19
# Guide: Prof. Smita A. Karpe
#
# SENSORS:
# GP20 (1-Wire) = DS18B20 #1 → Motor Temp (−55 to +125 °C)
# GP21 (1-Wire) = DS18B20 #2 → Bearing Temp (−55 to +125 °C)
# GP26 (ADC0) = Potentiometer → Vibration Level (0-3.3V simulated)
# GP27 (ADC1) = ACS712-5A → Current Sensor (0-5A, centered at 2.5V)
# (Each DS18B20 with 4.7 kΩ pull-up to 3.3V)
#
# STATUS OUTPUTS:
# GP0 = Green LED (NORMAL)
# GP1 = Yellow LED (WARNING)
# GP2 = Red LED (CRITICAL)
# GP3 = Buzzer (CRITICAL alarm)
#
# RELAY & MOTOR CONTROL:
# GP4 = Relay → Machine Power Control
# GP6 = STEP (A4988 stepper driver)
# GP7 = DIR (A4988 stepper driver)
# GP8 = EN (A4988 stepper driver)
#
# THRESHOLDS:
# Temperature: NORMAL < 60°C, WARNING 60-79°C, CRITICAL ≥ 80°C
# Current: NORMAL < 3A, WARNING 3-4A, CRITICAL ≥ 4A
# Vibration: NORMAL < 1.5V, WARNING 1.5-2.5V, CRITICAL ≥ 2.5V
#
# STAGE LOGIC:
# NORMAL → Relay ON + Motor FAST
# WARNING → Relay ON + Motor SLOW
# CRITICAL → Relay OFF + Motor STOP
# ─────────────────────────────────────────────────────────────────────────────
import onewire, ds18x20
from machine import Pin, ADC
import time
# ── DS18B20 Setup (2 separate 1-Wire buses) ──────────────────────────────────
OW_PINS = [20, 21] # GP20 → Motor Temp, GP21 → Bearing Temp
_buses = []
_sensors = []
_roms = []
print("Scanning DS18B20 sensors...")
for gp in OW_PINS:
ow = onewire.OneWire(Pin(gp))
ds = ds18x20.DS18X20(ow)
rm = ds.scan()
_buses.append(ow)
_sensors.append(ds)
_roms.append(rm)
status = f"{len(rm)} sensor found" if rm else "NOT FOUND (using 25.0C)"
print(f" GP{gp}: {status}")
def read_all_temps():
"""Trigger all DS18B20 conversions at once, wait, then read all."""
for ds in _sensors:
try:
ds.convert_temp()
except:
pass
time.sleep_ms(750) # DS18B20 max conversion time
temps = []
for ds, rm in zip(_sensors, _roms):
if rm:
try:
t = ds.read_temp(rm[0])
temps.append(round(t, 1) if -55 <= t <= 125 else 25.0)
except:
temps.append(25.0)
else:
temps.append(25.0)
return temps
# ── ADC Setup (Potentiometer + Current Sensor) ───────────────────────────────
vib_adc = ADC(26) # GP26 → Potentiometer (Vibration simulation)
curr_adc = ADC(27) # GP27 → ACS712 Current Sensor
def read_vibration():
"""Read potentiometer voltage (0-3.3V) as vibration level."""
raw = vib_adc.read_u16()
voltage = (raw / 65535) * 3.3
return round(voltage, 2)
def read_current():
"""Read ACS712 sensor and convert to current (A).
ACS712-5A: 185 mV/A, centered at 2.5V (Vcc/2)
For Pico: Vcc = 3.3V, so center = 1.65V
Sensitivity = 0.185 V/A
Current = (Vsensor - 1.65) / 0.185
"""
raw = curr_adc.read_u16()
voltage = (raw / 65535) * 3.3
# ACS712 offset at 1.65V for 3.3V supply
current = abs((voltage - 1.65) / 0.185)
return round(current, 2)
# ── Status LEDs + Buzzer ──────────────────────────────────────────────────────
LED_G = Pin(0, Pin.OUT)
LED_Y = Pin(1, Pin.OUT)
LED_R = Pin(2, Pin.OUT)
BUZZER = Pin(3, Pin.OUT)
# ── Relay Coil (Machine power control) ───────────────────────────────────────
RELAY = Pin(4, Pin.OUT, value=1) # HIGH = relay ON = Machine powered
# ── A4988 Stepper Driver ──────────────────────────────────────────────────────
STEP = Pin(6, Pin.OUT, value=0)
DIR = Pin(7, Pin.OUT, value=1)
EN = Pin(8, Pin.OUT, value=0) # LOW = enabled
def pulse(pin):
pin.value(1)
time.sleep_us(5)
pin.value(0)
def get_stage(val, warn_thresh, crit_thresh):
if val >= crit_thresh: return "CRITICAL"
if val >= warn_thresh: return "WARNING"
return "NORMAL"
def clamp(v, lo, hi):
return max(lo, min(hi, v))
# ── Startup Banner ────────────────────────────────────────────────────────────
print()
print("=" * 70)
print(" Smart PLC Monitor — Single Machine Version")
print(" K.K. Wagh Institute | Dept. E&TC | Group 19")
print("")
print(" SENSOR PIN TYPE")
print(" Motor Temp GP20 DS18B20 #1 (click sensor → set temp)")
print(" Bearing Temp GP21 DS18B20 #2 (click sensor → set temp)")
print(" Vibration GP26 Potentiometer (slide to adjust 0-3.3V)")
print(" Current GP27 ACS712-5A (simulated)")
print("")
print(" THRESHOLDS:")
print(" Temperature: NORMAL < 60°C WARNING 60-79°C CRITICAL ≥ 80°C")
print(" Current: NORMAL < 3A WARNING 3-4A CRITICAL ≥ 4A")
print(" Vibration: NORMAL < 1.5V WARNING 1.5-2.5V CRITICAL ≥ 2.5V")
print("")
print(" STAGE ACTIONS:")
print(" NORMAL → Relay ON + Motor RUNNING (fast)")
print(" WARNING → Relay ON + Motor RUNNING (slow)")
print(" CRITICAL → Relay OFF + Motor STOPPED")
print("=" * 70)
print()
# ── Main Loop ─────────────────────────────────────────────────────────────────
prev_stage = ""
tick = 0
STEP_US = {"NORMAL": 1200, "WARNING": 5000, "CRITICAL": 0}
while True:
# ── Read all sensors ──────────────────────────────────────────────────────
motor_temp, bearing_temp = read_all_temps()
vibration_v = read_vibration()
current_a = read_current()
# ── Stage classification ──────────────────────────────────────────────────
rows = [
("Motor Temp", motor_temp, "C", get_stage(motor_temp, 60, 80)),
("Bearing Temp", bearing_temp, "C", get_stage(bearing_temp, 60, 80)),
("Current", current_a, "A", get_stage(current_a, 3, 4)),
("Vibration", vibration_v, "V", get_stage(vibration_v, 1.5, 2.5)),
]
# Overall system stage (worst case)
if any(r[3] == "CRITICAL" for r in rows): system = "CRITICAL"
elif any(r[3] == "WARNING" for r in rows): system = "WARNING"
else: system = "NORMAL"
# ── Drive all outputs ─────────────────────────────────────────────────────
is_crit = (system == "CRITICAL")
LED_G.value(system == "NORMAL")
LED_Y.value(system == "WARNING")
LED_R.value(is_crit)
BUZZER.value(is_crit)
RELAY.value(0 if is_crit else 1)
EN.value(1 if is_crit else 0)
spd = STEP_US[system]
# ── Print sensor table ────────────────────────────────────────────────────
print()
print(" +─────── MACHINE CONDITION MONITOR ──────+")
for r in rows:
print(" | {:16s} {:6.2f} {:2s} [{:8s}] |".format(r[0], r[1], r[2], r[3]))
print(" +─────────────────────────────────────────+")
relay_status = "ON-RUNNING" if not is_crit else "TRIPPED-STOP"
motor_status = {"NORMAL": "FAST", "WARNING": "SLOW", "CRITICAL": "STOPPED"}[system]
print(" | Relay Status: {:>21s} |".format(relay_status))
print(" | Motor Speed: {:>21s} |".format(motor_status))
print(" | SYSTEM STATUS: {:>21s} |".format(system))
print(" +─────────────────────────────────────────+")
if system != prev_stage:
print()
if system == "CRITICAL":
print(" *** CRITICAL — Relay TRIPPED, Machine STOPPED!")
elif system == "WARNING":
print(" *** WARNING — Parameters rising, motor slowing!")
elif prev_stage:
print(" *** NORMAL — Relay ON, Machine RUNNING at full speed!")
prev_stage = system
# ── Step motor for one cycle ──────────────────────────────────────────────
if spd == 0:
time.sleep_ms(100) # Just wait if stopped
else:
steps = max(1, min(300, 1_000_000 // spd))
for _ in range(steps):
pulse(STEP)
time.sleep_us(spd)
tick += 1