Hello!
I tried my best to get the title that explains my problems.
OK, I have project (another TOPIC for the complete information) that needs about 7 sensors and an I2C LCD with Mega 2560. I would glad to have all my questions and concerns answered.
-
I'm using I2C UltraSonic sensor for water level and I want to control the water pump depending on the output.
sounds easy, right? the problem is the pump will be connected to a second Arduino ( this will have only the pump ) and the goal is to have it connected to the main Arduino - has all the sensors connected - with wireless communication. So, whenever the level reachs a part ( next problem ) , the component responsible for wireless on the main Arduino will send a command to the second Arduino to start/close motor.
My question is can I use this TYPE of component to achieve that? and what is the simple idea for writing its code? -
I wrote a code to achieve the controlling of the pump. ( not wireless, yet )
#define SCL_PIN 0
#define SCL_PORT PORTD
#define SDA_PIN 1
#define SDA_PORT PORTD
#define I2C_TIMEOUT 100
#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#include <SoftI2CMaster.h>
int Relay = 7; // digital pin 7
//LCD part Begin
#define BACKLIGHT_PIN 3
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Set the LCD I2C address
//LCD part End
void setup()
{
// Initialize both the serial and I2C bus
Serial.begin(9600);
//LCD B
lcd.begin(20,4);
// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
//LCD E
lcd.print("Smart Water Tank");
pinMode(LED_BUILTIN, OUTPUT); // digital pin 13 built in LED
}
void loop()
{
read_the_sensor_example();
}
///////////////////////////////////////////////////
// Function: Start a range reading on the sensor //
///////////////////////////////////////////////////
//Uses the I2C library to start a sensor at the given address
//Collects and reports an error bit where: 1 = there was an error or 0 = there was no error.
//INPUTS: byte bit8address = the address of the sensor that we want to command a range reading
//OUPUTS: bit errorlevel = reports if the function was successful in taking a range reading: 1 = the function
// had an error, 0 = the function was successful
boolean start_sensor(byte bit8address){
boolean errorlevel = 0;
bit8address = bit8address & B11111110; //Do a bitwise 'and' operation to force the last bit to be zero -- we are writing to the address.
errorlevel = !i2c_start(bit8address) | errorlevel; //Run i2c_start(address) while doing so, collect any errors where 1 = there was an error.
errorlevel = !i2c_write(81) | errorlevel; //Send the 'take range reading' command. (notice how the library has error = 0 so I had to use "!" (not) to invert the error)
i2c_stop();
return errorlevel;
}
///////////////////////////////////////////////////////////////////////
// Function: Read the range from the sensor at the specified address //
///////////////////////////////////////////////////////////////////////
//Uses the I2C library to read a sensor at the given address
//Collects errors and reports an invalid range of "0" if there was a problem.
//INPUTS: byte bit8address = the address of the sensor to read from
//OUPUTS: int range = the distance in cm that the sensor reported; if "0" there was a communication error
int read_sensor(byte bit8address){
boolean errorlevel = 0;
int range = 0;
byte range_highbyte = 0;
byte range_lowbyte = 0;
bit8address = bit8address | B00000001; //Do a bitwise 'or' operation to force the last bit to be 'one' -- we are reading from the address.
errorlevel = !i2c_start(bit8address) | errorlevel;
range_highbyte = i2c_read(0); //Read a byte and send an ACK (acknowledge)
range_lowbyte = i2c_read(1); //Read a byte and send a NACK to terminate the transmission
i2c_stop();
range = (range_highbyte * 256) + range_lowbyte; //compile the range integer from the two bytes received.
if(errorlevel){
return 0;
}
else{
return range;
}
}
//////////////////////////////////////////////////////////
// Code Example: Read the sensor at the default address //
//////////////////////////////////////////////////////////
void read_the_sensor_example(){
boolean error = 0; //Create a bit to check for catch errors as needed.
int range;
int percentage;
error = start_sensor(112); //Start the sensor and collect any error codes.
if (!error){ //If you had an error starting the sensor there is little point in reading it as you will get old data.
delay(100);
range = read_sensor(112); //reading the sensor will return an integer value -- if this value is 0 there was an error
range = constrain(range, 25, 200);
percentage = map(range, 200, 25, 0, 100); // 2nd and 3rd are low and max for tank
}
Serial.print("R:"); Serial.println(range);
Serial.print("%" );Serial.println(percentage);
lcd.setCursor(3,0);
lcd.print("R="); lcd.println(range);
lcd.setCursor(4,0);
lcd.print("Water level ");
lcd.print("%"); lcd.println(percentage);
if (percentage <= 25)
{
digitalWrite(LED_BUILTIN, HIGH); //start the pump
lcd.clear(); // test or remove
lcd.print("Water Tank low ");
lcd.setCursor(1,0);
lcd.println("Motor Turned On");
delay(500);
}
else if ( percentage == 100 )
{digitalWrite(LED_BUILTIN, LOW); //STOP motor
lcd.clear(); // test or remove
lcd.print("Water Tank Low ");
lcd.setCursor(2,10);
lcd.println("Motor On");
delay(500);
}
}
Used the built-in led to simulate the pump. Tried to test it, but the led ( pump ) doesn't switch off.
I want the led to be HIGH only when the level reaches 25 percent or less and LOW only when the level is 100 percent. I'm not good in programming, not used to do a lot, but I want led to only respond to these conditions. I'm not sure if it has to do with the values in between.
- THE MAIN PROBLEM is that I'm using I2C UltraSonic that uses the SoftI2CMaster library and I2C LCD with the wire library. I tried first to compile and I got errors about multiple files. Deleted SI2CIO and LiquidCrystal_SI2C files ( h and cpp types ) and got them to upload correctly. Then, the sensor stops working and the lcd.print parts under void loop is not showing ( is it wrong? ). I've read there are problems with these libraries. I'm sure how to solve this. Used LCD alone and it was working fine. same with Ultrasonic alone. I'm using 4.7k pull-up resistors.
Another weird problem is even with SCL & SDA defined 0 and 1, I can't establish a connection until I connect it to 21 and 20. am I missing something ?
Sorry for the long post and thank you in advance.