My toilet flush project

Hi, I am new to Arduino, and already made a prototype for my toilet flusher system. Attached link is my code and wiring diagram

The problem is, after running a while, the Arduino freezes up and stopped working, I will have to power off and on again, then it will work.

I change the sensor reading duration to from 10ms to 500ms, and it improves, however after few days, it started to freeze again.

I hope someone can give me some guidance, thanks.

P/s sorry for my bad English.

Place your files here so people do not have to go to some obscure site and then play around with all sorts of programs just to see what you have.

1 Like

Hello vneit

Welcome to the best ever Arduino Forum.

As already mentioned post your sketch, well formated, with comments and in so called code tags "</>" and a none-Fritzing schematic to see how we can help.

Have a nice day and enjoy programming in C++ and learning.

1 Like

Is that a smell sensor?

.
please activate your debug messages and copy/paste the output of the serial Monitor so we can see when your sketch is freezing.

please post your code here in the forum to get help from others.

please describe what your program should do. A program flow chart would be nice, it helps you and us to debug your program.

Well, the code is here, extracted from the zip file in post #1, but the OP has not cleaned up the compiler errors yet:

#include <Wire.h>
unsigned short lenth_val = 0;
unsigned char i2c_rx_buf[16];
int manualbut = 4;
int valveon = 8;
int valveoff = 9;
int buttonState = 0;
int PreparingToFlush = 0;
int count = 0;
void setup()
{
  Wire.begin();
  //Serial.begin(9600);
  pinMode(valveon, OUTPUT);
  pinMode(valveoff, OUTPUT);
  pinMode(microwave, INPUT);
  pinMode(manualbut, INPUT_PULLUP);
  digitalWrite(valveon, LOW);
  digitalWrite(valveoff, HIGH);
  delay(1000);
  digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
  digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF
  //Serial.println("Initializing... Valve OFF!");

}

//###################### ADJUST SENSOR READING TIME
int ReadDistance() {
  SensorRead(0x00, i2c_rx_buf, 2);
  lenth_val = i2c_rx_buf[0];
  lenth_val = lenth_val << 8;    lenth_val |= i2c_rx_buf[1];
  delay(500);
  return lenth_val;
}

void loop() {


  //###################### SENSOR MEASURING ALGORITHM
  int x = ReadDistance();
  //Serial.print(x);
  //Serial.println(" mm");


  //###################### ADJUST TRIGGER DISTANCE
  if (x < 500) {
    //Serial.println("DETECTED HUMAN, AUTHORIZE TO FLUSH");
    PreparingToFlush = 1;
  }

  //###################### ADJUST DISTANCE CONSIDER HUMAN LEFT
  if (PreparingToFlush == 1 && x > 500) { //if a person has been detected
    //Serial.println(" HUMAN LEFT,AUTO FLUSHING for 5 SEC!!");
    digitalWrite(valveon, HIGH);
    digitalWrite(valveoff, LOW);
    //###################### ADJUST FLUSHING TIME
    delay(5000);
    digitalWrite(valveon, LOW);//LOW = ON / HIGH = OFF
    digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF
    delay(500);
    digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
    digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF
    //Serial.println("FINISH AUTO FLUSHING!!");
    PreparingToFlush = 0; //reset the trigger
    //Serial.println("TIMEOUT for 3 second before next trigger!");
    //###################### ADJUST MINIMUM TIME WHEN USER ABLE TO TRIGGER THE SENSOR AGAIN
    //delay(3000);
    x = 2000;

  }

  //###################### MANUAL FLUSHING
  int sensorVal = digitalRead(4);
  if (sensorVal == LOW)
  {
    //Serial.println("MANUAL FLUSHING!!");
    digitalWrite(valveon, HIGH);
    digitalWrite(valveoff, LOW);
    delay(8000);
    digitalWrite(valveon, LOW);
    digitalWrite(valveoff, HIGH);
    //Serial.println("FINISH MANUAL FLUSHING!!");
    delay(500);
    digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
    digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF
    PreparingToFlush = 0; //reset the trigger
    x = 2000;
  }
}

void SensorRead(unsigned char addr, unsigned char* datbuf, unsigned char cnt)
{
  unsigned short result = 0;
  // step 1: instruct sensor to read echoes
  Wire.beginTransmission(82); // transmit to device #82 (0x52)
  // the address specified in the datasheet is 164 (0xa4)
  // but i2c adressing uses the high 7 bits so it's 82
  Wire.write(byte(addr));      // sets distance data address (addr)
  Wire.endTransmission();      // stop transmitting
  // step 2: wait for readings to happen
  delay(1);                   // datasheet suggests at least 30uS
  // step 3: request reading from sensor
  Wire.requestFrom(82, cnt);    // request cnt bytes from slave device #82 (0x52)
  // step 5: receive reading from sensor
  if (cnt <= Wire.available()) { // if two bytes were received
    *datbuf++ = Wire.read();  // receive high byte (overwrites previous reading)
    *datbuf++ = Wire.read(); // receive low byte as lower 8 bits
  }
}

Hi, @vneit
Welcome to the forum.

Thanks Tom... :smiley: :+1: :coffee: :australia:

That looks OK as far as I can see. I'd say though that that the code in ReadDistance() should be in SensorRead() and ReadDistance() dropped altogether.
Since it appears to work, but erratically, I'd first start suspecting I2C pull up resistors. Without knowing what the I2C sensor is I can only say that using an int16_t (instead of a uint16_t) to swap two bytes looks odd but may be correct.

Hi,
This is @vneit diagram.


Can you please post links to spec of the sensor and the output device you are controlling?

Thanks for the diagram, but a proper schematic labeling all components and labels on pins would be helpful.
Please include your power supply and its specs.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

It's ok to post a Fritzing schematic, if Fritzing is what you prefer to use. What @paulpaulson should have said was to use the Schematic View of Fritzing, not the Breadboard View, which many beginners post because they do not understand the difference between the two views.

you're right, I was thinking something else

Hi, here are the specs and working flow for my toilet flush project

Automatic Flush Mode
1)TOF10120 Sensor measuring distance every 500ms ( range of detection 500mm)
2)If human detected at < 500mm, prepare to flush
3)Human left, detection > 500mm, Relay switch +5v to solenoid valve and flush for 5sec
4)After 5 seconds, Relay switch -5v to solenoid valve to close the valve

Manual Flush mode
1)Human pressed manual flush button
2)Relay switch +5v to solenoid valve and flush for 8sec
3) After 8 seconds, Relay switch -5v to solenoid valve to close the valve

Components Specification
1)Arduino Nano
2)Power supply 5VDC, 2A
3)TOF10120, Distance Measuring Sensor


4) 2 Channel Relay Module With Opto-Isolator (5V)
5) Manual button 2P

Wiring Diagram

Thanks Tom, I am still figuring out how to paste scrollable text in a post

Read this again, it tells you how to post the code;

State machine:
Waiting
Human detected
Flush

Button changes state direct to flush
After flush state returns to waiting

Here's the code,

#include <Wire.h>
unsigned short lenth_val = 0;
unsigned char i2c_rx_buf[16];
int manualbut = 4;
int valveon = 8;
int valveoff = 9;
int buttonState = 0;
int PreparingToFlush=0;
int count=0;
void setup()
{
     Wire.begin(); 
     //Serial.begin(9600);
     pinMode(valveon, OUTPUT);
     pinMode(valveoff, OUTPUT);
     pinMode(manualbut, INPUT_PULLUP);
     digitalWrite(valveon, LOW);
     digitalWrite(valveoff, HIGH);
      delay(1000);
  digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
  digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF  
     //Serial.println("Initializing... Valve OFF!");   
     
}

//###################### ADJUST SENSOR READING TIME
int ReadDistance(){
    SensorRead(0x00,i2c_rx_buf,2);
    lenth_val=i2c_rx_buf[0];
    lenth_val=lenth_val<<8;    lenth_val|=i2c_rx_buf[1];
    delay(500);
    return lenth_val;
}

void loop() {
  

//###################### SENSOR MEASURING ALGORITHM
  int x=ReadDistance();
  //Serial.print(x);
  //Serial.println(" mm");


//###################### ADJUST TRIGGER DISTANCE
  if(x < 500) {
    //Serial.println("DETECTED HUMAN, AUTHORIZE TO FLUSH");
    PreparingToFlush=1;
  }

//###################### ADJUST DISTANCE CONSIDER HUMAN LEFT
  if (PreparingToFlush==1 && x > 500){ //if a person has been detected
  //Serial.println(" HUMAN LEFT,AUTO FLUSHING for 5 SEC!!");
  digitalWrite(valveon, HIGH);
  digitalWrite(valveoff, LOW);
//###################### ADJUST FLUSHING TIME
  delay(5000);
  digitalWrite(valveon, LOW);//LOW = ON / HIGH = OFF
  digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF
  delay(500);
  digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
  digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF  
  //Serial.println("FINISH AUTO FLUSHING!!");
  PreparingToFlush=0;  //reset the trigger
  //Serial.println("TIMEOUT for 3 second before next trigger!");
//###################### ADJUST MINIMUM TIME WHEN USER ABLE TO TRIGGER THE SENSOR AGAIN
  //delay(3000);
  x = 2000;

} 

//###################### MANUAL FLUSHING
int sensorVal = digitalRead(4);
if(sensorVal == LOW)
{
//Serial.println("MANUAL FLUSHING!!");
digitalWrite(valveon, HIGH);
digitalWrite(valveoff, LOW);
delay(8000);
digitalWrite(valveon, LOW);
digitalWrite(valveoff, HIGH);
//Serial.println("FINISH MANUAL FLUSHING!!");
delay(500);
digitalWrite(valveon, HIGH);//LOW = ON / HIGH = OFF
digitalWrite(valveoff, HIGH);//LOW = ON / HIGH = OFF  
PreparingToFlush=0;  //reset the trigger
x = 2000;
}
}

void SensorRead(unsigned char addr,unsigned char* datbuf,unsigned char cnt) 
{
  unsigned short result=0;
  // step 1: instruct sensor to read echoes
  Wire.beginTransmission(82); // transmit to device #82 (0x52)
  // the address specified in the datasheet is 164 (0xa4)
  // but i2c adressing uses the high 7 bits so it's 82
  Wire.write(byte(addr));      // sets distance data address (addr)
  Wire.endTransmission();      // stop transmitting
  // step 2: wait for readings to happen
  delay(1);                   // datasheet suggests at least 30uS
  // step 3: request reading from sensor
  Wire.requestFrom(82, cnt);    // request cnt bytes from slave device #82 (0x52)
  // step 5: receive reading from sensor
  if (cnt <= Wire.available()) { // if two bytes were received
    *datbuf++ = Wire.read();  // receive high byte (overwrites previous reading)
    *datbuf++ = Wire.read(); // receive low byte as lower 8 bits
  }
}

Here's the compile message:


In file included from XXXXXXXX.ino:1:0:
C:\Users\XXXXXXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h: In function 'void SensorRead(unsigned char, unsigned char*, unsigned char)':
C:\Users\XXXXXXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h:68:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int)
     uint8_t requestFrom(int, int);
             ^~~~~~~~~~~
C:\Users\XXXXXXX\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h:65:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t)
     uint8_t requestFrom(uint8_t, uint8_t);
             ^~~~~~~~~~~
Sketch uses 3510 bytes (11%) of program storage space. Maximum is 30720 bytes.
Global variables use 245 bytes (11%) of dynamic memory, leaving 1803 bytes for local variables. Maximum is 2048 bytes.

Figured it out, thanks =)

Pseudocode
In loop;
State = waiting

Switch case
Waiting
{do whatever to sense humans and poll buttons and if detected state = detected or flush

Human detected
{once human no longer detected and whatever other conditions are met or button pressed state =flush}
Flush
{whatever to flush and state = waiting}

Putting Resetfunc() on auto and manual operation, hope this will solve it.

Update, problem seem to be solved by installing snubber across the solenoid valve, thanks for help.