Go Down

Topic: Maxbotix UltraSonic sensor I2C problem (Read 469 times) previous topic - next topic

Abdulaziz14

Oct 06, 2017, 07:20 pm Last Edit: Nov 08, 2017, 05:11 pm by Abdulaziz14
Hi

I have a Project for my graduation in College. It's about Smart Water Tank. The idea is to try to implement as many sensors as we can - as a group - that relate to our studies in Electrical Engineering. We have more than one problem. I don't know if I can post them all but it will be confusing. So, I will only explain this problem in this topic.

I'm using I2C Maxbotix Ultrasonic sensor ( MB7247 ) to measure the level of the water. I'm using Mega 2560. They provided the code for it, but it was for the UNO. I'm not good at programming, but I tried to use this sensor with Mega and yes I did change the pins ( SDA 20 and SCL 21) to match it to Mega. That didn't work when I upload the code. I don't know if I need to also change PORTC:

Code: [Select]
#define SCL_PIN 5              //Default SDA is Pin5 PORTC for the UNO -- you can set this to any tristate pin
#define SCL_PORT PORTC
#define SDA_PIN 4              //Default SCL is Pin4 PORTC for the UNO -- you can set this to any tristate pin
#define SDA_PORT PORTC
#include <SoftI2CMaster.h>     //You will need to install this library
//LCD part Begin
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
/*-----( Declare Constants )-----*/
//none in original

/*-----( Declare objects )-----*/
// set the LCD address to 0x20 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

/*-----( Declare Variables )-----*/
//none
//LCD part End

void setup(){
  // Initialize both the serial and I2C bus
  Serial.begin(9600); // for serial monitor 
 
 
//LCD B
  lcd.begin(20,4);
  // LCD Backlight ON
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.print("Water level");
//LCD E

pinMode(LED_BUILTIN, OUTPUT);

  // (OPTIONAL) Check each address for a sensor
 // address_polling_example();

  /*
    Note that I placed the address change example in setup() for a good reason.
    Changing the sensor address causes an EEPROM write, there should only be ~1,000,000+
      of these writes to the sensor microcontroller over its product lifetime.
    Changing the address is fine, but doing it every second for the next 4 years may
      cause reliability issues.
  */
  // (OPTIONAL) Run an address change example
//  default_address_change_example(); 

  // Your code here
}

void loop()
{
  // (OPTIONAL) Read a sensor at the default address
  read_the_sensor_example();
 
  // Your code here

}



///////////////////////////////////////////////////
// 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;
  }
}



/////////////////////////////////////////
// Function: Change the sensor address //
/////////////////////////////////////////
//Uses the I2C library to change the address of a sensor at a given address
//Collects and reports an error bit where: 1 = there was an error or 0 = there was no error.
//INPUTS: byte oldaddress = the current address of the sensor that we want to change
//INPUTS: byte newddress  = the address that we want to change the sensor to
//OUPUTS: bit  errorlevel = reports if the function was successful in changing the address: 1 = the function had an

/*//      error, 0 = the function was successful
boolean change_address(byte oldaddress,byte newaddress){
  //note that the new address will only work as an even number (odd numbers will round down)
  boolean errorlevel = 0;
  oldaddress = oldaddress & B11111110;  //Do a bitwise 'and' operation to force the last bit to be zero -- we are writing to the address.
  errorlevel = !i2c_start(oldaddress) | errorlevel; //Start communication at the new address and track error codes
  errorlevel = !i2c_write(170) | errorlevel;        //Send the unlock code and track the error codes
  errorlevel = !i2c_write(165) | errorlevel;        //Send the unlock code and track the error codes
  errorlevel = !i2c_write(newaddress) | errorlevel; //Send the new address
  i2c_stop();
  return errorlevel;
}
*/


//////////////////////////////////////////////////////////
// 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; //uncomment to test percentage
  //Take a range reading at the default address of 224 " wrong in OUR case "
  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
  //percentage = map(range, 25, 300, 0, 100); // 2nd and 3rd are low and max for tank

    Serial.print("R:");Serial.println(range);
    //Serial.println(percentage);
    lcd.setCursor (0,1);
    lcd.print("R:"); lcd.print(range); //lcd.print(percentage)
  }
}



So, I changed them to Pin 0 , Pin 1 respectively. Are those AN pins to be sure ?
I got to upload the code fine, but I got these results.
Code: [Select]
Polling addresses...
Couldn't start:2
Couldn't start:4
Couldn't start:6
Couldn't start:8
Address polling complete.
Take a reading at the default address
Change the sensor at the default address to 222
Take a reading at the new address
Change the sensor back to the default address


I used 4.7K resistors,2K resistors. Same problem. Used nothing and I got same result but the difference is only in the speed of polling address "Couldn't start" are slower. Must mean something.

I want your help in this problem and others, but for now I want to make it work.
Thank you in advance

Notes:

Here is the link to the datasheet

The code

Update:

 I got it to work finally. The problem was with the address is different. I think because the one was showing with I2C scan was the 7-bit address. Changed the code to this address and worked!

I used UNO. I did try it with MEGA and it worked but I connected the SDA and SCL wires to 20 and 21. Not sure what is the reasoning behind defining SCL and SDA pins on the code.

But, the reading results are weird. when I put my hand in front of the sensor, the reading reached about 760 which is the maximum reading of the sensor. Is this me or it is just how it works ? [ solved ]


jremington

#1
Oct 06, 2017, 08:00 pm Last Edit: Oct 06, 2017, 08:02 pm by jremington
Those aren't Arduino pin numbers; they are hardware pin numbers for PORTC, SCL and SDA on the Uno.
The corresponding I2C pins are PORTD pin 0 (SCL) and PORTD pin 1 (SCA) on the 2560.

DrDiettrich

It's not a good idea to use any but the standard Wire library to support as many different i2C devices as you like. Why use a software I2C library if a hardware I2C connection is available on every Arduino? See the Wire library examples for scanning I2C devices and more. Add the specific parts of the MaxSonar library to your sketch.

Abdulaziz14

Those aren't Arduino pin numbers; they are hardware pin numbers for PORTC, SCL and SDA on the Uno.
The corresponding I2C pins are PORTD pin 0 (SCL) and PORTD pin 1 (SCA) on the 2560.
Sorry, I worked on this for 2 months and got confused with the files. Apparently I changed them to PORTD. I believe I got same results, but I will try to confirm this again when I get the chance perhaps tomorrow.

For connecting wires, pin 0 (SCL ) is pin 0 ( AN ) on the board ? as I said I'm not good at this.

Can you give me a link to explain what are PORTC PORTD and the relation to their pins on board?

It's not a good idea to use any but the standard Wire library to support as many different i2C devices as you like. Why use a software I2C library if a hardware I2C connection is available on every Arduino? See the Wire library examples for scanning I2C devices and more. Add the specific parts of the MaxSonar library to your sketch.
This is their reasoning
https://www.maxbotix.com/articles/095.htm

What do I need to change to make it for Wire ? I would appreciate the help.

Will this conflict with other sensors using Wire libraries ?

DrDiettrich

The sensor has a really poor design, if it requires a special library for its crippled I2C interface. Be prepared for trouble with any other hardware, that needs attention while a communication with the sensor is going on.

I'd use a sensor with a different interface. RS232 should be easier to use, then you can connect the sensor to one of the free Serial ports of the Mega (Serial1-3).

Abdulaziz14

The sensor has a really poor design, if it requires a special library for its crippled I2C interface. Be prepared for trouble with any other hardware, that needs attention while a communication with the sensor is going on.

I'd use a sensor with a different interface. RS232 should be easier to use, then you can connect the sensor to one of the free Serial ports of the Mega (Serial1-3).
It is an expensive sensor and can't afford to get another. I would like see it running first. Else is a problem for another day.

Also, is it possible to use to 2 Mega for my project with this sensor being on just one Mega board while the others for the rest ? or that just complicated more ?

DrDiettrich

You can use any small Arduino (Mini...) for dealing with that sensor, a Mega is not required for that purpose. Then you can read the sensor and transfer the data alternately, without any possible trouble caused by the sensor library. The Pro Mini uses the same controller than the Uno, for other controllers you may have to adapt the pin numbers in the library as appropriate.

Abdulaziz14

Those aren't Arduino pin numbers; they are hardware pin numbers for PORTC, SCL and SDA on the Uno.
The corresponding I2C pins are PORTD pin 0 (SCL) and PORTD pin 1 (SCA) on the 2560.
I couldn't try it this week. but I believe it has the same problem.

You can use any small Arduino (Mini...) for dealing with that sensor, a Mega is not required for that purpose. Then you can read the sensor and transfer the data alternately, without any possible trouble caused by the sensor library. The Pro Mini uses the same controller than the Uno, for other controllers you may have to adapt the pin numbers in the library as appropriate.
It is just that I have an extra Mega.

Is this the right section to ask about the code or it is in the programming section ?

I create a new topic ?

DrDiettrich

Continue this thread and present your code.

Abdulaziz14

Update: I got it to work finally. The problem was with the address is different. I think because the one was showing with I2C scan was the 7-bit address. Changed the code to this address and worked!

I used UNO. I did try it with MEGA and it worked but I connected the SDA and SCL wires to 20 and 21. Not sure what is the reasoning behind defining SCL and SDA pins on the code.

But, the reading results are weird. when I put my hand in front of the sensor, the reading reached about 760 which is the maximum reading of the sensor. Is this me or it is just how it works ?

Abdulaziz14

#10
Nov 08, 2017, 04:59 pm Last Edit: Nov 08, 2017, 05:30 pm by Abdulaziz14
Tried to implement LCD function to the code but I can't get it to work

I get this error

Code: [Select]

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `ass_i2c_delay_half'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

c:/program files/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `ass_i2c_wait_scl_high'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `i2c_init()'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `i2c_start(unsigned char)'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `i2c_rep_start(unsigned char)'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `i2c_start_wait(unsigned char)'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `ass_i2c_stop'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `ass_i2c_write'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\arduino_build_950996\libraries\NewliquidCrystal\SI2CIO.cpp.o (symbol from plugin): In function `SI2CIO::pinMode(unsigned char, unsigned char)':

(.text+0x0): multiple definition of `i2c_read(bool)'

C:\Users\M\AppData\Local\Temp\arduino_build_950996\sketch\I2C_USonic_Mega_Pins.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\M\AppData\Local\Temp\ccF9qn1o.ltrans0.ltrans.o: In function `i2c_read(bool)':

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:504: undefined reference to `ass_i2c_delay_half'

C:\Users\M\AppData\Local\Temp\ccF9qn1o.ltrans0.ltrans.o: In function `ass_i2c_write':

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:434: undefined reference to `ass_i2c_delay_half'

C:\Users\M\AppData\Local\Temp\ccF9qn1o.ltrans0.ltrans.o: In function `ass_i2c_stop':

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:358: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:358: undefined reference to `ass_i2c_delay_half'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:358: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:358: undefined reference to `ass_i2c_delay_half'

C:\Users\M\AppData\Local\Temp\ccF9qn1o.ltrans0.ltrans.o: In function `i2c_start(unsigned char)':

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:285: undefined reference to `ass_i2c_wait_scl_high'

C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal/SoftI2CMaster.h:285: undefined reference to `ass_i2c_delay_half'

collect2.exe: error: ld returned 1 exit status

Using library NewliquidCrystal in folder: C:\Users\M\Documents\Arduino\libraries\NewliquidCrystal (legacy)
Using library Wire at version 1.0 in folder: C:\Program Files\Arduino\hardware\arduino\avr\libraries\Wire
exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.


I'm not sure if this is the problem @DrDiettrich has talked about.
I'm using latest NewliquidCrystal library from : https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/

DrDiettrich

You must exclude the standard Wire library.

Abdulaziz14

#12
Nov 08, 2017, 06:14 pm Last Edit: Nov 08, 2017, 06:23 pm by Abdulaziz14
You must exclude the standard Wire library.
you mean

Code: [Select]
#include <Wire.h>

?

edit= ops sorry

did remove it same thing

DrDiettrich

I only can see that you are using incompatible libraries. No idea how to fix the errors.

Abdulaziz14

I only can see that you are using incompatible libraries. No idea how to fix the errors.
Which ones ?

I deleted SI2CIO and LiquidCrystal_SI2C files ( h and cpp types )and I got to upload it.

but the sensor does not work and lcd only displays the first line from the setup not the loop.



Go Up