Arduino and I2C Line Following sensor

Hi! I'm trying to connect the I2C Line Following sensor from RoboticsConnection but i receive nothing from this sensor when using the Wire library and the correct I2C address. Does someone has already tried this sensor with an arduino? Thanks in advance.

Vincent

and the correct I2C address.

Are you sure it is correct?

The Wire library uses a 7 bit address where as most other people use an 8 bit address which includes the r/w bit as the least significant portion. Try the address you are using but shift it one place to the right and then have a separate read and write access at the same address.

P.S. I would also recommend pull up resistors on the bus lines, whilst it might work without them the waveform looks horrible. And you are using analogue 4 & 5 not digital 4 & 5 for the bus?

And you are using analogue 4 & 5 not digital 4 & 5 for the bus?

Do not know if it was any help for post author, but definitely it was for me :D Thank you!

Kuba

I am also planning on doing this. I am new to the arduino, but the sensor says that it outputs "a single byte representing the status of all five sensors and the two additional inputs, in a range from 0 to 127, where 0 means all sensors see 'white' and 127 means all sensors see 'black'."

If you connect this to two analog pins will they be able to read the byte or are they just high and low?

(total noob try not to flame me :))

If you connect this to two analog pins will they be able to read the byte or are they just high and low?

No two of the analogue input pins (Pins 4 & 5) double up as I2C interface pins. You need to load in the I2C library to use these pins in this mode and wire up your I2C device to those pins. This will allow you to read a whole byte through just those two pins. The clever bit is done in your device and the I2C library. See the I2C tutorials in the playground section.

Alright, I looked at a few of the tutorials and I have started to program...

Does anyone have some code I could look at for line following with this thing? I have a basic idea of line following programs, but right now I just have a bunch of if statements... seems inefficient.

If you post what you have (hit the has button in the reply box and paste your code between the braces) then we can see if you are going about it the right way.

Well here is my code for reading the line follower and to test to see if I did it right i made it turn on a led if it reads anything but zero, and the led blink if it is reading zero. I plan to swipe it over a line a few times.

They I2C stuff might be completly wrong because I have just been copying and pasting(i don’t understand it to much even after the tutorial). I would most like to fix that because I think I can figure out most of the line following.

//Creo Line Follower

//*****************************
//Variables and Imports
//*****************************
#include <Wire.h>
#define REGISTER_INPUT (0)
#define REGISTER_OUTPUT (2)
#define REGISTER_CONFIG (6)


long sensors[] = {0, 0, 0, 0, 0};
int sensors_sum = 0;
int control_value = 0;
//Pin Variables
int programSwitch = 2;
int motor1Pin = 3;
int motor2Pin = 4;
int ledPin = 13;

void setup() 
  {
    Wire.begin();
    pinMode(programSwitch, INPUT);
    pinMode(motor1Pin,OUTPUT);
    pinMode(motor2Pin,OUTPUT);
    pinMode(ledPin, OUTPUT);
  }
  
//********************************************************************
// LOOP FUNCTION LOOP FUNCTION LOOP FUNCTION LOOP FUNCTION LOOP FUNCTI
//********************************************************************
if(
void loop()
{
 read_sensors();
 output_leds();
}

//********************************************************************
// READ_SENSORS FUNCTION READ_SENSORS FUNCTION READ_SENSORS FUNCTION R
//********************************************************************
void read_sensors()
{
 int gpio_read(int address) {
  int data = 0;

  //  Send input register address
  Wire.beginTransmission(address);
  Wire.send(REGISTER_INPUT);
  Wire.endTransmission();

  //  Connect to device and request two bytes
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);

  if (Wire.available()) {
    data = Wire.receive();
  }
  if (Wire.available()) {
    data |= Wire.receive() << 8;
  }

  Wire.endTransmission();

  return data;
}

}
//********************************************************************
// OUTPUT_LEDS FUNCTION OUTPUT_LEDS FUNCTION OUTPUT_LEDS FUNCTION 0
//********************************************************************
void output_leds()
{
  if (data > 0)
   {
     digitalWrite(ledPin, HIGH);   // sets the LED on
     // put line following here(if (data) - then corrisponding action
   }
  else
  {
    void loop()                     // Blink Loop(Blinks if the sensor board either reads nothing or all black
    {
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(1000);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(1000);                  // waits for a second
    }
  }
}

I know I left out info in the first if... I fixed it and I feel like it isn't worth a repost lol.

I fixed it and I feel like it isn’t worth a repost

You can always modify a previous posting.

I2C stuff might be completly wrong

Yes it is.

int gpio_read(int address) {
int data = 0;

Will always return 0
now:-
int data = gpio_read( address);

Will read data but put it at the end of the routine that writes stuff to your device to set up the registers.
Also I couldn’t see where you defined “address” this is supposed to be the address of your device.

There might be other errors but just like a compiler I stop at the first big one

I am really not understanding the I2C communication at all. Do you know of a site or do you have code for working I2C code that is just the communication part. I just want to have a value that is the decimal that this line follower will output. I normally would problem solve until I get it, but on this project the rest of the fabrication is going to take up most of the allotted time and I need to get this working asap.

Grumpy: I get what you were saying with the int data=gpio_read(address) but the big picture is kinda a blur to me. How do you find the address of the device? do you mean of the line follower board? Is that just the pin number?

The I2C device, what ever it is, has an address. This is normally formed in two parts one is fixed by the device and the other is up to 3 pins on the device that can be connected high or low. This forms a 7 bit address, without knowing what device you have and what the configurable bits are set to, you can't communicate with it.

So the bit you are not telling us is what device you have, if you know that, you can look up the protocol and know what numbers to send it to get it to do what you want it to do.

In your code you have a variable called address but you are not giving it a value so it will probably default to 0 so you are trying to talk to an I2C device at address 0. That is another reason why you are not getting anywhere.

Do you know of a site or do you have code for working I2C code that is just the communication part

Look at:-- http://www.arduino.cc/playground/Main/InterfacingWithHardware Towards the bottom of the page you will find 5 links giving I2C examples.

I have the robotics connection 5 sensor line follower... My bad I thought i said that earlier. Do you know what the address is for that?

Alright I have read through just about every tutorial I can find… I started from scratch on some code. The point of this code is just to have a variable called “data” and have it return the output of the robotics connection line follower.

Here is it is:

//I2C Communication
//Analog 5 - I2C SCL
//Analog 4 - I2C SDA

#include <Wire.h>

//  I2C device address 0x50
#define REGISTER_INPUT (0)
int data = 0;
void setup()
{
Wire.begin();
}

long address = 0x50
Void sensor_read()
{
  //  Send input register address
  Wire.beginTransmission(address);
  Wire.send(REGISTER_INPUT);
  Wire.endTransmission();

  //  Connect to device and request two bytes
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);

    data = Wire.receive();

  Wire.endTransmission();

  return data;
}

Here is the link to the address information on the line follower: http://www.roboticsconnection.com/p-67-line-following-sensor.aspx

Well now you have an address you can start. I am not sure what that last code is all about. You don't have to hhave the address in a variable, a constant or literial will work just as well.

You are asking for two bytes of data but only reading one:-

Wire.requestFrom(address, 2);
    data = Wire.receive();

Also you are not waiting for the data to become valid. What you need is this:-

Wire.requestFrom(address, 1);
while(!Wire.available()) { }
    data = Wire.receive();

This asks for one byte of data and then waits in a loop, the empty braces, until there is available data from the wire, then it reads it.

The other thing is there is no loop() function so that sketch will not do anything.

Alright I fixed that. I tried running it and I get an error. Here is the code:

//Creo I2C Tester
//Use built in LED to test if the I2C connection works
//Use other led to test middle sensor's reading

//*****************************
//Variables and Imports
//*****************************
#include <Wire.h>
#define REGISTER_INPUT (0)

long sensors[] = {0, 0, 0, 0, 0};
int sensors_sum = 0;
int control_value = 0;
int address = 4;
int ledPin = 13;
void setup() {
  Wire.begin();
  pinMode(ledPin, OUTPUT);
}
//********************************************************************
// LOOP FUNCTION LOOP FUNCTION LOOP FUNCTION LOOP FUNCTION LOOP FUNCTI
//********************************************************************
void loop()
{
 read_sensors();
 output_leds();
}

//********************************************************************
// READ_SENSORS FUNCTION READ_SENSORS FUNCTION READ_SENSORS FUNCTION R
//********************************************************************
void read_sensors()
{
  int gpio_read(int address);
  int data = 0;
  //  Send input register address
  Wire.beginTransmission(address);
  Wire.send(REGISTER_INPUT);
  Wire.endTransmission();

  //  Connect to device and request two bytes
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 1);
  while(!Wire.available()) { }
    data = Wire.receive(); 
  Wire.endTransmission();

  return data;
}
//********************************************************************
// OUTPUT_LEDS FUNCTION OUTPUT_LEDS FUNCTION OUTPUT_LEDS FUNCTION 0
//********************************************************************
void output_leds()
{
  if (data > 0)
   {
     digitalWrite(ledPin, HIGH);   // sets the LED on
     // put line seeing actions here
   }
  else
  {
    void loop()                     // Blink Loop(Blinks if the sensor board either reads nothing or all black
    {
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(1000);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(1000);                  // waits for a second
    }
  }
}

And this is the error:
In function ‘void read_sensors()’:
error: return-statement with a value, in function returning ‘void’ In function ‘void output_leds()’:

Also on the site that I posted the link of it says that the default address is 0x50 does that mean I have to make it a long? (and i guess this means me making the address 4 is wrong, don’t know where I got that from).

Alright I fixed that last error(silly mistake) and I will re-post the code tonight when I get home. I ran the code last night and it showed that it was constantly receiving zero even when I was putting it over a line, so that means it isn't reading the information.

It seems just about right from what I have read in tutorials and from the help I have gotten so far...

Just checking that you corrected the error by making:- void read_sensors() into:- int read_sensors()

and not from removing the "data" from the return statement.

Also I am not sure where an address of 0x04 came from. Use 0x50 or if that doesn't work try 0x28 (I posted the reason earlier)

ummm… yeaaa… I actually did remove data from the return statement and I fixed the address it is now 0x50, but now is my problem not having the return statement?

I made data a global variable and then just removed the return statement.

So your saying that I should change void read_sensors() to an and then put back the return?