Go Down

Topic: Interpreting sensor input for robot. (Read 2369 times) previous topic - next topic

Crock101

I don't understand, no matter what i do that error message still pops up. What even more puzzling is that when i isolate the code for that sensor the error message goes away. Also i haven't got the values for c from the sensor yet, I will have them on Monday though.

retronet_RIMBA1ZO


I don't understand, no matter what i do that error message still pops up. What even more puzzling is that when i isolate the code for that sensor the error message goes away.

what do you mean by 'isolate' ? cut the section away ? or comment it out ?
look at where it is being declared, you are calling the function even before it has been declared.
(ie. you are telling the robot to DO (THIS) but you haven't even told it what THIS is


Also i haven't got the values for c from the sensor yet, I will have them on Monday though.

ahh yes, you're right - but i don't think it'll be that straightforward - let's see what the 'c' comes out as first; you will need just a short sketch with this section
Code: [Select]
  while(Wire.available())   
  {
    Wire.requestFrom(2, 6);
    char c = Wire.read();   
    Serial.print(c);         
  }

to test and see what is coming in from the I2C sensor - don't forget that '2' will have to be changed accordingly to the actual address.

Crock101

By isolate i mean i put it in it's own sketch like this:
Code: [Select]
const int pingPin = 7;

void setup() {
  Serial.begin(9600);
}

void loop()
{
  long duration, inches, cm;

  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);

  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  delay(100);
}

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

When i do this the error message goes away even though it's the exact same code. Any suggestions?

retronet_RIMBA1ZO


...
...
When i do this the error message goes away even though it's the exact same code. Any suggestions?

it's not "suggestion" - it's getting you to understand the facts.
you really need to read that link i gave on variable scope.

it's NOT the exact same code.

the WHOLE thing is ONE sketch, you're referring to a different function and that is infact how it needs to be done, and that is to give it a global scope - previously you had it declared INSIDE the loop() function - THAT'S WHY you were getting that error.

Crock101

#34
Mar 10, 2014, 07:50 pm Last Edit: Mar 11, 2014, 12:37 am by Crock101 Reason: 1
I got the sensor and ran the code you sent me with the beacon in front of the sensor to read the data from it and the serial monitor wrote this: Vrs 1.4iTechnNewIRDr0000000Vers 1.4HiTechncNeIRDir0000000ers Also I changed the ultrasonic sensor code to this
Code: [Select]
#include <Wire.h>
const int pingPin = 11;
unsigned int duration, inches;
char c = Wire.read();
int LeftF= 5;
int RightF= 2;
int LeftB= 3;
int RightB= 4;
void setup()
{
 pinMode(RightF,OUTPUT);
 pinMode(LeftF,OUTPUT);
 pinMode(LeftB,OUTPUT);
 pinMode(RightB,OUTPUT);
 Wire.begin(0x08);
 Serial.begin(9600);
}

void loop()
{
 {
   while(Wire.available())    
   {
     Wire.requestFrom(0x08, 6);    
     Serial.print(c);        
   }

 pinMode(pingPin, OUTPUT);          
 digitalWrite(pingPin, LOW);        
 delayMicroseconds(2);
 digitalWrite(pingPin, HIGH);      
 delayMicroseconds(5);              
 digitalWrite(pingPin, LOW);        
 pinMode(pingPin, INPUT);          
 duration = pulseIn(pingPin, HIGH);
 inches = duration / 74 / 2;        
 Serial.println(inches);            
 delay(200);            


 if (c == )
 {
   digitalWrite(RightF,HIGH);
   digitalWrite(LeftB,HIGH);
   digitalWrite(RightB,LOW);
   digitalWrite(LeftF,LOW);
 }

 if (c == )
 {
   digitalWrite(LeftF,HIGH);
   digitalWrite(RightB,HIGH);
   digitalWrite(RightF,LOW);
   digitalWrite(LeftB,LOW);
 }


 if (c == ) && (inches > 12)
 {
   digitalWrite(LeftF,HIGH);
   digitalWrite(RightF,HIGH);
   digitalWrite(RightB,LOW);
   digitalWrite(LeftB,LOW);
 }  

 if (c == ) && (inches < 3)
 {
   digitalWrite(LeftB,HIGH);
   digitalWrite(RightB,HIGH);
   digitalWrite(RightF,LOW);
   digitalWrite(LeftF,LOW);
 }
 if (c == ) && (inches <= 12) && (inches >= 3)
 {
   digitalWrite(LeftB,LOW);
   digitalWrite(RightB,LOW);
   digitalWrite(RightF,LOW);
   digitalWrite(LeftF,LOW);
 }
}
and the error message is no longer present. Now we can focus on the IR seeker sensor and understanding the data that it is outputting.

retronet_RIMBA1ZO


...
Also I changed the ultrasonic sensor code to this
...
...

i think that looks okay, i'm still new and usually i'll spot mistakes only if the robot behaves different to what i expect.



I got the sensor and ran the code you sent me with the beacon in front of the sensor to read the data from it and the serial monitor wrote this: Vrs 1.4iTechnNewIRDr0000000Vers 1.4HiTechncNeIRDir0000000ers
...
...
and the error message is no longer present. Now we can focus on the IR seeker sensor and understanding the data that it is outputting.

okay - it looks like you've got the connection going well, i saw this in the code from that blog link;

boolean InfraredSeeker::Test()
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(0x08);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 16);
  char Manufacturer_Model[16];
  while(Wire.available() < 16);
  for(byte i=0; i < 16; i++)
  {
    Manufacturer_Model = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
  return strncmp(Manufacturer_Model, "HiTechncNewIRDir", 16)==0;
}

so the first 16 bytes of the output seems to be the manufacturer & model info.

and then the "seeker function" seems to be here;
Code: [Select]
void InfraredSeeker::ReadValues(byte OffsetAddress, byte* buffer)
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(OffsetAddress);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 6);
  while(Wire.available() < 6);
  for(byte i = 0; i < 6; i++)
  {
    buffer[i] = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
}

giving you 6 bytes at a time.

this is now starting to get into territory that i'm also learning about - so hopefully someone more expert can step in if i'm not saying something quite correct or has better pointers to give.

does the Serial Monitor keep outputting data ?
you do have an IR beacon for the seeker to give feedback on, right ?

actually, you could just run that whole IRSeeker.ino code as is and see what happens on Serial Monitor - then you can slowly take out the relevant bits (possibly all of it !) for what you need.

Crock101

So I merged my code with the library's code like this:
Code: [Select]
#include <Wire.h>
const int pingPin = 11;
unsigned int duration, inches;
int LeftF= 5;
int RightF= 2;
int LeftB= 3;
int RightB= 4;

/*
  IRSeeker.ino - A library/class for the HiTechnic IRSeeker V2 infrared sensor.
Created by Birk Blechschmidt, August 1, 2013.
Released into the public domain.
*/

struct InfraredResult
{
  byte Direction;
  byte Strength;
};

class InfraredSeeker
{
public:
  static void Initialize();
  static boolean Test();
  static void ReadACRaw(byte* buffer);
  static void ReadDCRaw(byte* buffer);
  static InfraredResult ReadAC();
  static InfraredResult ReadDC();
  static int DirectionAngle(byte Direction);
private:
  static InfraredResult PopulateValues(byte* buffer);
  static void ReadValues(byte OffsetAddress, byte* buffer);
  static const int Address = 0x10 / 2; //Divide by two as 8bit-I2C address is provided
};

void InfraredSeeker::Initialize()
{
  Wire.begin();
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(0x00);
  Wire.endTransmission();
  while(Wire.available() > 0)
    Wire.read();
}

boolean InfraredSeeker::Test()
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(0x08);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 16);
  char Manufacturer_Model[16];
  while(Wire.available() < 16);
  for(byte i=0; i < 16; i++)
  {
    Manufacturer_Model[i] = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
  return strncmp(Manufacturer_Model, "HiTechncNewIRDir", 16)==0;
}

void InfraredSeeker::ReadValues(byte OffsetAddress, byte* buffer)
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(OffsetAddress);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 6);
  while(Wire.available() < 6);
  for(byte i = 0; i < 6; i++)
  {
    buffer[i] = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
}

void InfraredSeeker::ReadACRaw(byte* buffer)
{
  ReadValues(0x49, buffer);
}

void InfraredSeeker::ReadDCRaw(byte* buffer)
{
  ReadValues(0x42, buffer);
}

InfraredResult InfraredSeeker::PopulateValues(byte* buffer)
{
  InfraredResult Data;
  Data.Direction = buffer[0];
  if(buffer[0] != 0)
  {
    if(buffer[0] % 2 == 0)
    {
      Data.Strength = (buffer[buffer[0] / 2] + buffer[buffer[0] / 2 + 1]) / 2;
    }
    else
    {
      Data.Strength = buffer[buffer[0] / 2 + 1];
    }
  }
  else
  {
    Data.Strength = 0;
  }
  return Data;
}

InfraredResult InfraredSeeker::ReadAC()
{
  byte buffer[6];
  ReadACRaw(buffer);
  return PopulateValues(buffer);
}

InfraredResult InfraredSeeker::ReadDC()
{
  byte buffer[6];
  ReadDCRaw(buffer);
  return PopulateValues(buffer);
}

int DirectionAngle(byte Direction)
{
  return Direction * 30 - 150;
}

void setup()
{
  pinMode(RightF,OUTPUT);
  pinMode(LeftF,OUTPUT);
  pinMode(LeftB,OUTPUT);
  pinMode(RightB,OUTPUT);
  Serial.begin(9600);
  Serial.println("HiTechnic IRSeeker V2");
  Serial.println();
  Serial.println();
  Serial.println("Dir\tAngle\tStrength");
  Serial.println();
  InfraredSeeker::Initialize();
}

void loop()
{   
  InfraredResult InfraredBall = InfraredSeeker::ReadAC();
  Serial.print(InfraredBall.Direction);
  Serial.print("\t");
  Serial.print(DirectionAngle(InfraredBall.Direction));
  Serial.print("\t");
  Serial.print(InfraredBall.Strength);
  Serial.println();
  delay(500); //optional
 
  pinMode(pingPin, OUTPUT);         
  digitalWrite(pingPin, LOW);       
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);       
  delayMicroseconds(5);             
  digitalWrite(pingPin, LOW);       
  pinMode(pingPin, INPUT);           
  duration = pulseIn(pingPin, HIGH);
  inches = duration / 74 / 2;       
  Serial.println(inches);           
  delay(200);              


  if (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5)
  {
    digitalWrite(RightF,HIGH);
    digitalWrite(LeftB,HIGH);
    digitalWrite(RightB,LOW);
    digitalWrite(LeftF,LOW);
  }

  if (InfraredBall.Direction > 5) && (InfraredBall.Direction <= 9)
  {
    digitalWrite(LeftF,HIGH);
    digitalWrite(RightB,HIGH);
    digitalWrite(RightF,LOW);
    digitalWrite(LeftB,LOW);
  }


  if (InfraredBall.Direction == 5 ) && (inches > 12)
  {
    digitalWrite(LeftF,HIGH);
    digitalWrite(RightF,HIGH);
    digitalWrite(RightB,LOW);
    digitalWrite(LeftB,LOW);
  } 

  if (InfraredBall.Direction == 5 ) && (inches < 3)
  {
    digitalWrite(LeftB,HIGH);
    digitalWrite(RightB,HIGH);
    digitalWrite(RightF,LOW);
    digitalWrite(LeftF,LOW);
  }
  if (InfraredBall.Direction == 5 ) && (inches <= 12) && (inches >= 3)
  {
    digitalWrite(LeftB,LOW);
    digitalWrite(RightB,LOW);
    digitalWrite(RightF,LOW);
    digitalWrite(LeftF,LOW);
  }
}
It should tell the robot what to do, the only problem is i keep on getting this error message: expected identifier before '(' token on this line of code:
Code: [Select]
if (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5). What does it want me to fix?

retronet_RIMBA1ZO

#37
Mar 12, 2014, 07:52 am Last Edit: Mar 12, 2014, 07:57 am by retronet_RIMBA1ZO Reason: 1

So I merged my code with the library's code like this:
Code: [Select]
...
...
...
It should tell the robot what to do,

you're diving headlong into pasting library codes into your main sketch with "Class" and double colons "::" - this is ahead of where i am, but if the code seems to work, then good for you !!



the only problem is i keep on getting this error message: expected identifier before '(' token on this line of code:
Code: [Select]
if (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5). What does it want me to fix?

this is basic and something i can help with - look at the if statement and what your conditions are.

when you get error messages like expected ... before ... it's usually syntax error and you need to fix something normally related to missing  (or misplaced) brackets, curly-braces, semi-colons or the like.

have a look at the reference page to trouble-shoot what's missing in your code.

EDIT:
look under Boolean Operators - the if section doesn't explain much more than the simplest example.
or something more advanced if you search for "multiple conditions" - on this site;
http://forum.arduino.cc/index.php/topic,90555.0.html

Crock101

So i just have to change this:
Code: [Select]
if (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5)
to this:
Code: [Select]
if (InfraredBall.Direction >= 1 && InfraredBall.Direction < 5)

retronet_RIMBA1ZO


So i just have to change this:
Code: [Select]
if (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5)
to this:
Code: [Select]
if (InfraredBall.Direction >= 1 && InfraredBall.Direction < 5)

correct.

as you start to make more complex conditions, sorting them by brackets to determine precedence becomes important.
infact, the above could also be written this way just to be even more clear;
Code: [Select]
if ( (InfraredBall.Direction >= 1) && (InfraredBall.Direction < 5) )
the IDE helps you keep track of all these brackets and clickng Ctrl-T and Ctrl-R should help you spot any "imbalance".

Crock101

OK, I'll clean up the rest of the code and I'll start testing tomorrow. I'll get back to you with the results.

retronet_RIMBA1ZO

okay, good luck - i'll be away for a cuppla days - hopefully someone else can help if i'm not back yet.

Crock101

The test was a success, the robot will follow me now. Now i just need to install the circuitry on the robot and i will be good to go. I'll upload pictures and a video once i'm done. Thank you so much for spending your time to help me. I really can't thank you enough.

Go Up