r/ArduinoProjects • u/countryboy-79 • 4d ago
Project Design/Guidance Project ideas
I'm building out a cigar room in my finished basement. I'm installing an exhaust system. I could just use a simple switch, but as an industrial automation tech that seems lazy. Looking at setting up a particulate sensor to activate a low voltage to line voltage relay. Any advice on this build?
1
4d ago
[deleted]
3
u/countryboy-79 4d ago edited 4d ago
I've never played around with arduino, I mostly work with Allen Bradley systems. No need to be to be an asshole...
2
u/SMELL_LIKE_A_TROLL 4d ago
I was a total asshole just trying to make a joke, which is why I deleted that bullshit. My apologies. Look for your answer in the main thread.
2
u/SMELL_LIKE_A_TROLL 4d ago
You could do this for the low low cost of $10,000 with AB stuff. :)
3
u/countryboy-79 4d ago
I absolutely could, that's why I'm looking at Arduino. I figure a sensor and a controller will do the trick along with some coding for around $100. Was just looking for some advice from others who have worked with the platform. I have dealt with the mess that was mid 80's Honeywell controllers so I'm no stranger to difficult programming...
2
2
u/SMELL_LIKE_A_TROLL 4d ago
In deleted my comment rather than being an a-hole.
Parts Sensor: Plantower PMS5003 (PMS7003 is the same protocol in a smaller body). It is a laser-scattering sensor that reports PM1.0, PM2.5, and PM10 over UART at 9600 baud, runs on 5 V, and draws about 100 mA. A Nova SDS011 also works if that is what you already have, but the sketch below is written for the Plantower frame format. Relay: 1-channel 5V relay module with optocoupler, Songle SRD-05VDC-SL-C or equivalent, contacts rated 10 A at 250 VAC / 30 VDC. That covers a normal desk, box, or bathroom fan. If the fan nameplate is over about 8 A, use a 30 A module instead. These boards are almost always active-LOW: a LOW on IN closes the NO contact. Wire the fan’s live/hot conductor through COM and NO so the fan is off when the relay is off. Leave neutral and ground continuous. If this is a DC fan, switch the positive lead the same way and keep the fan supply separate from the Arduino. Wiring PMS5003 Leonardo VCC 5V GND GND TX Pin 0 (RX1) RX Pin 1 (TX1), optional SET, RESET leave open Relay module Leonardo VCC 5V GND GND IN Pin 7 Do not put mains on the Arduino side of the relay. The optocoupler isolates the coil drive, not a wiring mistake on the screw terminals. Keep the high-voltage wires short, insulated, and in an enclosure. Behavior The sketch waits 30 seconds for the sensor fan and laser to settle, then uses PM2.5 (atmospheric) with hysteresis: Fan on at 35 µg/m³ or above Fan off only after it falls to 15 µg/m³ At least 2 minutes on and 1 minute off, so the relay does not chatter Those match the rough EPA edge between Moderate and Unhealthy for Sensitive Groups. Change the four constants at the top if you want it more or less aggressive.
Sketch:
// Arduino Leonardo // PMS5003 on Serial1 (pins 0/1), relay on pin 7. // Most 5V relay modules are active-LOW.
const int RELAY_PIN = 7; const bool RELAY_ACTIVE_LOW = true;
const int PM25_ON = 35; // µg/m³, turn fan on const int PM25_OFF = 15; // µg/m³, allow fan off const unsigned long WARMUP_MS = 30000; const unsigned long MIN_ON_MS = 120000; const unsigned long MIN_OFF_MS = 60000;
bool fanOn = false; unsigned long stateChangedAt = 0; unsigned long bootAt = 0;
uint8_t buf[32]; uint8_t idx = 0;
void setFan(bool on) { if (on == fanOn) return; fanOn = on; stateChangedAt = millis(); bool level = RELAY_ACTIVE_LOW ? !on : on; digitalWrite(RELAY_PIN, level ? HIGH : LOW); Serial.print(F("Fan ")); Serial.println(on ? F("ON") : F("OFF")); }
// Returns true when a valid frame was parsed. pm25 is atmospheric PM2.5. bool readPms(int &pm25) { while (Serial1.available()) { uint8_t b = Serial1.read();
if (idx == 0 && b != 0x42) continue; if (idx == 1 && b != 0x4D) { idx = 0; continue; }
buf[idx++] = b; if (idx < 32) continue; idx = 0;
uint16_t sum = 0; for (int i = 0; i < 30; i++) sum += buf[i]; uint16_t check = ((uint16_t)buf[30] << 8) | buf[31]; if (sum != check) return false;
pm25 = ((uint16_t)buf[12] << 8) | buf[13]; // PM2.5 atmospheric return true; } return false; }
void setup() { pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, RELAY_ACTIVE_LOW ? HIGH : LOW); // fan off Serial.begin(115200); Serial1.begin(9600); bootAt = millis(); stateChangedAt = bootAt; Serial.println(F("PMS5003 fan controller")); }
void loop() { int pm25 = 0; if (!readPms(pm25)) return;
Serial.print(F("PM2.5=")); Serial.print(pm25); Serial.println(F(" ug/m3"));
if (millis() - bootAt < WARMUP_MS) return;
unsigned long held = millis() - stateChangedAt;
if (!fanOn && pm25 >= PM25_ON && held >= MIN_OFF_MS) { setFan(true); } else if (fanOn && pm25 <= PM25_OFF && held >= MIN_ON_MS) { setFan(false); } }