This is another very simple "Wash Cycle Completed" sensor. It's design uses the same Optocoupler sensing design I used in the Kiddie Smoke Detector project. The only difference is that I'm using 1 AC to DC transformer, and a boost module to boost the washer speaker power to fire the Optocoupler.
Parts:
- 1 Cheap AC/DC converter
- 1 Optocoupler
- 1 Step up Regulator
- 1 Small Proto Board.
- Some wire
Highlights:
Use the Washers .5vdc Signal Piezo to interface with the Pro-Mini. The voltage to the Piezo is to low to drive the Optocoupler so I had to use a boost module to boost the voltage to the Optocoupler. I'm not sure what the long term effect will be on washers control board Piezo drive circuit, so I will follow up if I encounter a problem.
Again Uses the same sketch as the Kiddie Smoke Project, with the only change being to CYCLE_INTERVAL (For my dryer 3 works well)
Sketch:
// Based on Author: Patrick 'Anticimex' Fallberg Interrupt driven binary switch example with dual interrupts
#include <MySensor.h>
#include <SPI.h>
#define SKETCH_NAME "Washer End Cycle"
#define SKETCH_MAJOR_VER "1"
#define SKETCH_MINOR_VER "1"
#define CHILD_ID 3
#define SIREN_SENSE_PIN 3 // Arduino Digital I/O pin for optocoupler for siren
unsigned int SLEEP_TIME = 32400; // Sleep time between reads (in seconds) 32400 = 9hrs?
long CYCLE_COUNTER = 3; // This is the number of times we want the Audio Counter to reach before triggering a signal to controller.
unsigned long CYCLE_INTERVAL = 3; // How long do we want to watch once first detected (in seconds)
//Adjust for your smoke detector, you want to pick up the siren signal at least 3 time to help stop false alarms.
unsigned long CYCLE_RATE = 90; // How fast do we want to move checking the Pin state in the Status Check (in Millis) Adjust for your smoke detector
//Adjust for your smoke detector, you want to pick up the siren signal at least 3 time to help stop false alarms.
unsigned long CYCLE_TIME_OKSTATUS = 8; // How long do we want to watch for "all clear" once we have confirmed an Alarm (in seconds)
unsigned long CYCLE_RATE_OKSTATUS = 500; // How fast do we want to move checking the Pin state when checking for an OK status (in Millis)
int oldValue=1;
int value=0;
MySensor sensor_node;
MyMessage msg(CHILD_ID, V_TRIPPED);
void setup()
{
sensor_node.begin();
// Setup the Siren Pin HIGH
pinMode(SIREN_SENSE_PIN, INPUT_PULLUP);
// Send the sketch version information to the gateway and Controller
sensor_node.sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);
sensor_node.present(CHILD_ID, S_SMOKE);
//Send the state -- Always send Alarm state on power up.
sensor_node.send(msg.setSensor(CHILD_ID).set("1"), true);
}
// Loop will iterate on changes on the BUTTON_PINs
void loop()
{
// Check to see if we have a alarm. I always want to check even if we are coming out of sleep for heartbeat.
AlarmStatus();
// Sleep until we get a audio power hit on the optocoupler or 9hrs
sensor_node.sleep(SIREN_SENSE_PIN-2,FALLING, SLEEP_TIME * 1000UL);
}
void AlarmStatus()
{
// We will check the status now, this could be called by an interrupt or heartbeat
int siren_audio_count =0;
long cycle_time =0;
unsigned long startedAt = millis();
Serial.println("Status Check");
//Read the Pin
value = digitalRead(SIREN_SENSE_PIN);
// If Pin return a 0 (LOW), then we have a Alarm Condition
if (value != 1) {
//We are only going to check for status for CYCLE_INTERVAL time I think this should help stabilize Siren Sensing
while(millis() - startedAt < CYCLE_INTERVAL * 1000)
{
//We are going to check CYCLE_RATE fast
if(millis() - cycle_time > CYCLE_RATE ) {
// save the last time you Checked
cycle_time = millis();
//We will count each time SIREN_SENSE_PIN is 0 (Alarm - LOW) for the above time and at the above rate.
value = digitalRead(SIREN_SENSE_PIN);
if (value != 1)
{
siren_audio_count++;
Serial.print("Audio Count: ");
Serial.println(siren_audio_count);
}
}
}
// Eval siren audio hit count against our limit. If we are => then CYCLE_COUNTER then lets start a loop for "All Clear" reset
// If we continue to return an audio power hit, then we will continue to send to the controller.
if (siren_audio_count>=CYCLE_COUNTER)
{
Serial.println("Alarm Detected");
do
{
//update gateway with bad news.
//sensor_node.send(msg.set("1"));
sensor_node.send(msg.setSensor(CHILD_ID).set("1"), true);
Serial.println("Alarm Detected Sent to gateway");
} while (IsAlarmAllClear()!=1);
}
}
//Pin returned a 1 (High) so there is no alarm.
else
{
IsAlarmAllClear();
}
}
int IsAlarmAllClear()
// We are looking for an gap in time that we no longer see an audio power hit to the optocoupler.
{
int alarmOn =0;
long cycle_time =0;
unsigned long startedAt = millis();
//We are only going to check for status for CYCLE_TIME_OKSTATUS time
while(millis() - startedAt < CYCLE_TIME_OKSTATUS * 1000)
{
//We are going to check CYCLE_RATE_OKSTATUS fast
if(millis() - cycle_time > CYCLE_RATE_OKSTATUS) {
// save the last time you Checked
cycle_time = millis();
int value = digitalRead(SIREN_SENSE_PIN);
if (value != 1) //We are still in an alarm state
{
alarmOn++;
}
}
}
if (alarmOn < 1)
{
// We don't have any sign that we are still in an alarm status
//Send all clear msg to controller
//sensor_node.send(msg.set("0"));
sensor_node.send(msg.setSensor(CHILD_ID).set("0"), true);
// Used to update the node - NOT used for battery check.
sensor_node.sendBatteryLevel(random(1, 100) );
Serial.println("All Clear");
return 1;
}
else
{
// We are still in an alarm status
//The calling function will handle sending NOT CLEAR to controller
Serial.println("NOT CLEAR");
return 0;
}
}
Here a some Pictures:




























































































We may be saying the same thing however... I don't think it matters (AC or DC), if there is a transformer in the circuit, there is going to be a current peak on startup. If you have a filter cap before your transformer, you will see 2 peaks. The first one will be caused by the capacitor charging up, and the second from the inductive load caused by the transformer powering up. I'm thinking the 2nd peak should be much less due to the filter cap.