Introduction: UPDATED: Snake Vision Robot Using Two MLX90614 No Contact Temperature Modules

Picture of UPDATED: Snake Vision Robot Using Two MLX90614 No Contact Temperature Modules

What is Snake Vision?

Most snakes have infrared-sensitive receptors in deep grooves on the snout, which allow them to "see" the radiated heat of warm-blooded prey. Most snakes focus by moving the lens back and forth in relation to the retina, while in the other amniote groups, the lens is stretched. Many nocturnal snakes have slit pupils while diurnal snakes have round pupils.

https://en.wikipedia.org/wiki/Snake

So, what I have is two MLX90614ESF Human Body Infrared Temperature Non-Contact Temperature sensors from IC Station. - These sensors use the I2C bus, what I am doing is using a multiplexer and switching between the two sensors pretty fast. These sensors are very sensitive to changes in temperature (Just like Snakes)

The rapid change from one sensor to the other, could be like changing the of the lens snakes do. (Could be? well it sounds good anyway.)

The sensors are set up at about a 45 degree angle from each other. If both sensors are the same the robot moves forward, if either of the sensors are different - the robot moves in the direction of the higher sensor reading (Moving toward the heat.)

The robot build is pretty simple, so let's get into it.

Step 1: Parts List.

Picture of Parts List.

The basic build is pretty simple only needing a few tools. You should have some basic soldiering skills (most of the electronics come without header on them) Build time, depending on your experience level should be 2 to 4 hours. More experience people can probably build this in a hour to hour and half. Less experienced it may take a little longer.

Tools: Soldiering Iron, Philips head screw driver. you may need a excato knife.

Miscellaneous stuff you may need: electrical tape, glue, breadboard (large one), a couple of small 4 point bread boards (may come in handy). wire, alligator clips, battery pack

Needed for this project:

  • Two (2) MLX90614 Human Body Infrared Temperature Sensor Non-Contact Temperature Module. I'll get more into these sensors later, but they are very simple and easy to use - and very sensitive to even small changes in temperature. IC Station supplied mine for me, and I highly recommend buying these from them - not only was the shipping fast - it was also free. These sensors are about $8.00 U.S. Dollars each, IC station does put them on sale from time to time. http://www.icstation.com/mlx90614esf-human-body-in...
  • I am using a cheap two wheeled robot chassis I found on eBay some time ago, the one pictured is like the one I am using, but any of the two wheeled chassis with the same type of motors should work for this project. These are about $10 U.S. dollars http://www.ebay.com/itm/1Set-2WD-Mini-Round-Double...
  • One (1) L9110 H bridge dual motor driver - This drive uses only 4 wires, 2 are PWM (pulse width modulation). It's a simple board. If you have not used one of these before, it does take a few minutes to wrap your head around how these work. A great tutorial for them can be found here: https://www.bananarobotics.com/shop/How-to-use-the... These can be found on eBay for around $1.00 U.S. Dollar another reason to use them - they are cheap so no harm if you let the factory smoke out. http://www.ebay.com/itm/L9110S-H-bridge-Stepper-Mo...
  • Two (2) CD74HC4067 Multiplex board - these boards are over kill for this project, I only need to MUX two things, these boards are capable of MUXing 16 different things. I also know there are multiplex boards that were designed with I2C use in mind, these weren't - just general I/O plus they can do analog I/O. If you have one of the I2C mux boards that will save some wire, and time, but the code would most likely need to be re-written. (P.S. I'm using these boards, because I have like 20 or 30 of them, I've never used them for anything, and I didn't have a I2C mux board.) You need two one for SDA and one for SCL. They cost about $1.50 U.S. (You can find them cheaper if you buy a lot of them - don't go crazy like me and buy 30 unless you need them LOL) http://www.ebay.com/itm/CD74HC4067-16-Ch-Analog-Di...
  • Arduino Nano or UNO - for my build I am using a nano for the brains, a UNO would work just as well - I think any Arduino board should work (if you do use a different board, check to make sure the PWM wires are still going to PWM pins for the motor) code changes may need to be made for boards other than the NANO or UNO. Nano run about $3.00 U.S. dollars. http://www.ebay.com/itm/MINI-USB-Nano-V3-0-ATmega3...
  • After doing a little testing, I added a LED to indicate when the robot was ready to move. This is optional. But I may add a couple of more LEDs (or a RGB) for each sensor for a visual indicator of temperature.

Total Cost should be between $35 to $50 U.S. depending on what you already own, and what you need to buy and what robot chassis you go with.

The chassis.....

*** UPDATED DEC 6, 2016 - I also added a SR-HC04 ultrasonic sensor, be sure to check out step 10 (UPDATES) for more infor. ***

Step 2: The Chassis....

Picture of The Chassis....

What ever chassis you end up with should have come with a couple of motors, and wheels, and all the hardware needed to build it.

If the motors have wires already attached to them you don't need to worry about soldiering any. Otherwise, you'll want to solider wires to the terminals of the motors - I used just some dupont wire for this. The connectors on the motors are fragile so be careful when you soldier to them. I used green wire for the top, and white wire for the bottom of each motor - you of course can use any color or wire you like.

Also, if you ended up with a chassis that is different from mine. Built it to the instructions that came with it - if no instructions came with it - there are some generic things in common with most of these low cost chassis, but your build will be different.

The bottom level of the robot is the rectangle plastic, you should have four (4) pieces that look like a "T", at least four (4) short stand offs, a caster wheel, at least 4 long screws, and a bunch of other screws and nuts.

in the rectangle piece you will see a couple of slots near what looks like a couple of crosses. In each one of the slots put one of the "T" pieces.

take one of the motors and put it against the bottom of the "T" the holes in the motor should line up, you'll want to take another "T" and put it on the outside of the motor, put two of the long screws in the holes, and nuts on the screws tighten it up.... DO NOT OVER TIGHTEN - you could break the "T" bracket. You'll want to repeat the process for the other side. On mine the rear of the motors actually face the front of the robot.

The caster wheel will match up with four holes on the back of the robot, use the short stand offs to secure it.

Match the holes on the round level with the holes in the first level, and that is where the longer stands go.

Again DO NOT OVER TIGHTEN anything, these are made out of cheap plastic, and very easy to break/crack.

Something that I think would help would be some washers with the screws and nuts, they didn't provide any with mine.

Step 3: My Design Notes.

Picture of My Design Notes.

It's a good habit to write up your ideas, sketch out how you think something should work.

PINS to be used, colors of wires (normally come later, but it's always a good idea to note these so you can troubleshoot later), components needed and how those components will work with each other.

Think about what variables you'll be using, name them, and describe what they do.

Many times when you do this you'll find problems before you even start to code or wire something up.

The more complex something is, the more notes you should make.

Your first notes are probably not going to be your final design, unless you are very very good at writing your ideas down.

I added a some LEDs to mine, after I tested, The LEDs are good for troubleshooting. I updated my notes.

Some of the important stuff, you can see I drew out how the robot will turn. And stated that the right sensor controls the left wheel, and the left sensor controls the right wheel. I also stated what I am calling left and right, front and back.

I then did a little quick "flow".

Right Sensor more heat - spin left wheel till left sensor sees heat.

left sensor more heat - spin right wheel till right sensor see heat

both sensors see heat - move forward.

(In the end I did change this after I found out how the sensors worked. I wrote this up before the sensors got to me from China) This is a good starting point, and a good way to refer back to what you are thinking (should you have to walk away from the project for some reason and come back to it later)

Based on some of my first tests, I also mapped (get it, I used the Arduino map function) some new logic on how the robot works. Actually, I simplified it by doing this. It's simply using the temperature sensors are switches now. (motor on, motor off)

Step 4: Solder Time.

Picture of Solder Time.

Now is the time to solder the headers to the various parts. Not much I can say here.

Plan ahead a little, think about how you'd like to put these parts on the bread board.

For the MUX boards, I soldered the signal pins so they would plug into the bread board, while the "c" pins I soldered so I could connect wires directly to them while it was in a breadboard. (Take a look at the pictures).

My MLX90614 sensors came with straight pins, I had to bend them 90 degrees so the sensors could be put on the bread board and the sensors could "stand".

Depending on your robot chassis you may need or want to also bend the pins for the motor driver (L9110)

And the nano board should plug into the bread board.

You should have soldered wires to the motors while you were building the chassis, but if you didn't you'll want to now.

Something I do to help while I'm soldering the pins is to put them in a bread board, and sit the piece that needs soldered on them. The bread board helps hold the everything in place, and with a little practice and patience, it will also keep the pins straight. This was a little bit of a challenge with how I decided to do the pins for the MUX board - and you can see one leans a little.

Step 5: Understanding the Operation of the MUX Board.

Picture of Understanding the Operation of the MUX Board.

The CD74HC4067 is a 16-Channel Analog Multiplexer/Demultiplexer. What it allows you to do is use 4 digital pins, to control the flow of 1 to 16 other pins. And is bi-directional, meaning it can be used to read senors, or used to send data.

A good tutorial on these can be found here: http://bildr.org/2011/02/cd74hc4067-arduino/

But here is the basics of it, the 4 digital pins are used to connect one of the other 16 pins to the SIG (or SIGNAL) pin. The SIG pin can be connected to any I/O pin on the microcontroller, this includes the serial pins (RX, TX), I2C PINS (SDA, SCL) or any other digital or analog pin.

The 16 I/O pins are marked C0 to C15, and are switched on/off using a binary sequence on the S0 - S3 pins.

The binary sequence is really the number of the PIN you want to connect to.

If you look at the chart above you'll see how with 4 bits you can make the number 15. IE:

0000 binary does equal 0 in decimal. and 0001 binary does equal 1 in decimal.

2 in decimal would be 0010 in binary (notice you need all four bits as either a zero or a one) The one is in the two place holder so it's 0010 binary is 2 decimal.

0101 binary would be 5 decimal (Why? there are zero 8s, one 4, zero 2s, one 1 = 4+1 = 5 decimal)

So for the mux it goes like this:

The order is S3, S2, S1, S0 - 0 represent a LOW and 1 represent a HIGH.

0000 Connects to C0
0001 Connects to C1
0010 Connects to C2
0011 Connects to C3
0100 Connects to C4
0101 Connects to C5
0110 Connects to C6
0111 Connects to C7
1000 Connects to C8
1001 Connects to C9
1010 Connects to C10
1011 Connects to C11
1100 Connects to C12
1101 Connects to C13
1110 Connects to C14
1111 Connects to C15

This is easy to do with a micro-controller, a zero would be a low on a pin, and a one would be a high on that pin.

*The website I refereed to has the S pins listed in the opposite direct, the way "we" would count from S0 to S3 - while, it is saying the same thing, the binary looks out of place and also opposite the way it should look. If you look at the MUX board reading it from left to right the pins are labeled S3, S2, S1, S0 - meaning S0 is the least significant bit *

As you can see, these MUX boards can only have one pin Connected to the SIG pin at a time, but they can be switched very quickly.

For this project, these boards are a little more than what we need, and honestly it does seem strange to use 6 pins up when the sensors technology only need two pins. So lets look at that - the MUX boards are capable for doing 16 pins, so 5 pins to 16 is a pretty good trade off - giving you 11 additional pins to play with. My sensors do not have a easy way (that I know of) to set a different I2C address, so both sensors are on the same address, and we all know that will cause problems. So this seemed like a good solution. And is pretty easy to use and setup.

Next let's look at the L9110 motor driver.....

Step 6: Understanding the L9110 Motor Drive Board.

Picture of Understanding the L9110 Motor Drive Board.

Banana Robotics has a great tutorial on using this device. https://www.bananarobotics.com/shop/How-to-use-the...

These work a little different then my L298 motor drivers. So forget what you know about them (at least just for a minute).

The HG7881 (L9110) is a compact motor driver chip that supports a voltage range from 2.5-12V at 800mA of continuous current. These chips have built-in output clamp diodes to protect your sensitive microcontroller electronics. They are suitable for very small robot projects.
Each HG7881 (L9110) chip is able to drive a single DC motor using two digital control inputs. One input is used to select the motor direction while the other is used to control the motor speed

If IA is Low and IB is LOW - The output to the motor will be LOW, if IA is HIGH and IB is LOW the motor should move forward, if IA is LOW and IB is HIGH the motor should move in reverse. IF IA and IB are both HIGH the output will be OFF

*Note that the actual direction of "forward" and "reverse" depends on how the motors are mounted and wired. You can always change the direction of a motor by reversing its wiring.

The Dual Channel Motor Driver module uses two driver ICs. They recommend using the IA (input A) to control the speed (PWM) and the IB (input B) to control the direction.

These are very simple drives, the voltage used to drive the chip is the same voltage used to drive the motors, this means that if you are using a 5v chip, you should expect to drive 5v motors.

Now that we have a little understanding of two of the main components of this build, let's go build it......

Step 7: Wiring Up the Parts.

Picture of Wiring Up the Parts.

This is where the fun comes in.

I tried to make a Fritzing of the hook up to make it a little easier. There are a number of things that need to be connected, taking you time, and making sure everything is hooked where it belongs is important.

Unfortunately Fritzing didn't have all the parts (L9110 is missing). Also, I added a couple of more LEDs after I made the Fritzing.

The truth is, this is much easier to wire then it looks. But this is where having good notes to start with will really help. There are a lot of wires.

  • On the bread board, you should have two power rails (both will have a Positive rail, and a Negative rail). The two Negative rails can been connected together, and then connected to the ground of the nano. decide on which rail is going to be the 9 volt rail, and which rail is going to be the 5 volt rail. (I had the rail closest to the motor drive and battery be the 9v rail, and the rail closer to the sensors be the 5 volt rail. This saves a little on using long wires.) To make it easier mark them, a little piece of tape on the 9v side or a sharpie, something so you can remember which side is which.
  • The motor driver, my driver board is labeled a little different then what is pictured in the Fritzing diagram. (and your board maybe labeled a different too, there are a few variations of the L9110 board) Generally thou, there is a Input Side (I) and a Output Side (O) - The I side will have four wires labeled B-IA(IA2) B-IB(IB2) A-IA(IA1) A-IB(IB1) there are two wires per side (A and B or 1 and 2 depending on how your board is labeled). It will also have a VCC and GND - VCC will go to the 9v power positive rail, and GND will go to the ground. The O side will also have four wires, B-OA(OA2) B-OB(OB2) A-OA(OA1) A-OB(OB1). On my robot I've decided the #2 or B pins will be the left motor, and the right motor will be on the #1 or A pins. Connect your motors to the O side of the driver board, Left to the #2 side, Right to the #1 side - try to keep the wires going to the top and the bottom of the motor connected the same way to each of there respective sides. On the Input side, B-IA (IA2) to D3 on the Nano, B-IB(IB2) to D5, A-IA(IA1) to D6, A-IB(IB1) to D9.
  • The MUX boards - We have two MUX boards, I've labeled as MUX1 and MUX2 in my diagram. You can see that MUX1 one is used for SDA and MUX2 is used for SCL. That means that each of the 16 I/O lines are going to look like either SDA or SCL to our I2C and Nano devices. Switching is done using a BCD/Binary switching of the input pins of the MUX boards. Since we need these to switch at the same time, Connecting the input pins (S0, S1, S2, S3) to each other, and then on the Nano board S0 to D7, S1 to D8, S2 to D2, and S3 to D13. VCC connects to the 5v rail, GND connects to GND and to EN on each board. On MUX1 C0 connects to the LEFT sensor SDA line, C1 connects to the RIGHT sensor SCL line. On MUX2 C0 connects to the LEFT sensor SCL line, and C1 connects to the RIGHT sensors SCL line. MUX1 SIG pin connects to A4 of the nano, MUX2 SIG pin connects to A5 of the nano.
  • We need to connect power to each of the sensors, VCC to 5v rail, GND to GND - pretty simple there.
  • For the LED pictured, connect the positive side to D12, and the negative side a ground. (I used a green LED but any color should be fine, this is a indication the robot is ready to move)
  • Don't connect a battery yet, when it's time thou, it will connect to the 9v rail (positive to positive, ground to ground)

* I did add some LEDs, which are not pictured. Which were used in troubleshooting. I used two duel color LEDs (RED/GREEN) to save space on the board. This have a common ground, so connect that to ground. The RED side of each goes to pins A0 (right) and A2 (left), The GREEN side goes to pins A1 (right) and A3 (left). When the GREEN leds are on it means that the sensors are seeing ambient temperature. RED means the temperature is higher than ambient. Which also means the opposite motor should be spinning. *

*** UPDATED DEC 6, 2016 - I also added a SR-HC04 ultrasonic sensor, be sure to check out step 10 (UPDATES) for more info. ***

Step 8: The Code....

Picture of The Code....

When I started to write this instructable, the code wasn't quite done - the robot only sort of worked.

As I was writing this, I was working on and thinking about the code. I made a few more small changes to the robot, including a different battery pack. Most of my work was spend on the code, and I came up with an idea to just use the sensors as switches. My original code I was trying to compare the ambient temperature to a the object temperature. (In fact this did work, sort of) - The sensors are very sensitive to small changes, and my original code wasn't fast enough to account for the small change.

You can find my code here: https://github.com/kd8bxp/Snake_Vision_Robot

*NOTE: The Code was fixed on github. I left the errors in here for the learning experience.

Now to explain bits of it....hopefully it makes since how it works.

#define units 1 //1=Fahrenheit,  0=Celius
//Functions:

//rightForward(speed)
//rightBackward(speed)
//leftForward(speed)
//leftBackward(speed)
//stop()
//readRightSensor() - set the mux to read the sensor connected to C0
//readLeftSensor() - set the mux to read the sensor connected to C1
//readSensor() - returns value of current readings
//Setup variables for motors
#define leftMotorPin1   3 //Left IA2   PWM PIN
#define leftMotorPin2   5 //Left IB2 Direction PIN 
#define rightMotorPin1  6 //Right IA1 PWM PIN
#define rightMotorPin2  9 //Right IB1 Direction PIN
#define pwmR  100 //smallest PWM value that will cause motor to spin
#define pwmL  100

At the start of the code, you'll see some defines - most of these you shouldn't have to change, but it's good to know where and what they are. This section is commented pretty good, but let's look at a couple of things.

The units really is a hold over from my original code, with the way the new code works it shouldn't matter if the temperatures are in Fahrenheit or Celius - because I am now just using the sensors as a switch to turn the motors on and off.

The motor functions, most of these are not used in this sketch, they are however included should you (or me) want to add something for the robot to do. Right now rightForward, and leftForward and Stop are used.

the Motor pins are the next set, you shouldn't need to change these. With the L9110 motor driver, if the motor isn't going the direction you want, you have to switch the wires around.

pwmR and pwmL are both the smallest PWM that will cause your wheels to move on the surface you want.

<p>//Setup variables for temperature sensors</p><p>int rightSensor;
int leftSensor;
int rightAmbient; //ambient temperature of sensors
int leftAmbient;
int rightCalibrate;
int leftCalibrate;
int aL;
int sL;
int aR;
int sR;</p>

This little block of code, are variables used to read the sensors, set up the calibration differences between the two sensors, and set the mappings of the reading values.

<p>//Variables for Mux. (multiplexer)<br>/* Special cases - 2 Mux boards are used, one is used for SDA, and
 *  the other is used for SCL. There are two thermal sensors, so only
 *  2 of the 16 ports on the mux are needed, meaning, only one
 *  of the mux control lines needs to be changed to read the two sensors
 *  The code would need to be changed, and expanded to add more I2C sensors
 */</p><p>#define s0  7
#define s1  8
#define s2  2
#define s3 13</p><p>//RED temperatures are higher than ambient, GREEN ambient temperature
#define LED 12  //ready indicator (GREEN)
#define RIGHTREDLED A0 
#define RIGHTGREENLED A1
#define LEFTREDLED A2
#define LEFTGREENLED A3</p>

Here we see the pins the MUX board is connected to in the define s0 to define s3 statements, I don't think you'll need to be changing these, unless maybe you used a board other than a Nano.

And lastly we have the pins that the LEDs are connected to - if you get one of these hooked up backward changes here can help.

That is really all of the setup.

in the setup function, we will attempt to get a average ambient temperature, and use this as a calibration reading. I found that while these sensors are very very good at what they do, they were a little off from each other. So by doing this I was able to zero out the error between the two. The calibration happens pretty fast, but I did put some delays in because they are sensitive and could read your temperature as the ambient temperature if you are close to them. A delay here gives you time to move out of the way. A second delay is just there because I wanted a little longer. During calibration the left and right leds should both be green, if one or the other or both are red, then it sensed something it shouldn't have - try again.

When the robot is ready to move, a green led will come on - and now the robot is ready to sense the heat.

<p>void loop()                     <br>{
readRightSensor();
readLeftSensor();</p><p>aL = map(leftAmbient, -40, leftAmbient, 0.0, pwmL);
sL = map(leftSensor, leftAmbient, leftSensor, pwmL, 0.0);
aR = map(rightAmbient, -40, rightAmbient, 0.0, pwmR);
sR = map(rightSensor, rightAmbient, rightSensor, pwmR, 0.0);
if (leftAmbient >= leftSensor) {sL = 100;}
if (rightAmbient >= rightSensor) {sR = 100;}
rightForward(aL - sL);
leftForward(aR - sR);</p><p>//delay(50); //test code with small delay (may not be needed)</p><p>}</p>

this is were mapping takes place, the sensors get read, and a small comparison is made.

**** NOTE: while doing this write up, I realized there is a error in this part of the code -- actually there are two - do you see them? It's ok, after I am done here, I'll fix the code and get the new version on github asap.

** The variable aL and aR are ambient temperatures of the left and right sensor, that value is being mapped to the pwm value set by the define statements....do you see the error? So Sense the left sensor is controlling the right motor, it's PWM value should be that of the right motor, not the left (pwmR).

**** NOTE 2: The Code was fixed on github. I left the errors in here for the learning experience.

It now checks to see if the sensor reading (object temperature) is less than the ambient temperature in other words is it colder (ice?) - Do you see another error here? sL and sR should be set to a PWM value of the define statements, and should be opposite so sL would equal pwmR.

Next is the little bit of math. an Ambient reading minus the sensor reading - if the sensor reading is zero than the motor should move, if the sensor reading is set to the pwm value then the true pwm will be zero and the motor should stop. This does work, even with the error in logic.

<p>void readRightSensor() {<br>  digitalWrite(s0, LOW);
  //because S1, S2, S3 are already set LOW we don't need to set again
  rightSensor = readSensor() + rightCalibrate;
  rightAmbient = readAmbient();
  if (rightAmbient >= rightSensor) { 
    digitalWrite(RIGHTGREENLED, HIGH); 
    digitalWrite(RIGHTREDLED, LOW); } else {
        digitalWrite(RIGHTGREENLED, LOW);
        digitalWrite(RIGHTREDLED, HIGH);
    }
  }</p><p>void readLeftSensor() {
  digitalWrite(s0, HIGH);
  //because s1, s2, s3 are already set LOW we don't need to set again
  leftSensor = readSensor() + leftCalibrate;
  leftAmbient = readAmbient();
  if (leftAmbient >= leftSensor) { 
    digitalWrite(LEFTGREENLED, HIGH); 
    digitalWrite(LEFTREDLED, LOW); } else {
        digitalWrite(LEFTGREENLED, LOW);
        digitalWrite(LEFTREDLED, HIGH);
    }
}</p>

Here is something interesting to note, because I only needed to pins on the MUX and because those two pins are next to each other in binary counting, I only need to switch one pin on or off. Remember binary 0000 is C0, and binary 0001 is C1, only one pin changes. So these functions, switch sensors, take the reading and the calibration reading, check and turn on LEDs as needed. There is a general function used to read the sensor, because the sensors use the same I2C address only one I2C object was needed. So between these functions I know which sensor I am reading.

<p>void rightForward(int speedOfRotate) {<br>  digitalWrite(rightMotorPin2, LOW);
  analogWrite(rightMotorPin1, speedOfRotate);
}</p><p>void rightBackward(int speedOfRotate) {
  digitalWrite(rightMotorPin2, HIGH);
  analogWrite(rightMotorPin1, speedOfRotate);
}</p><p>void leftForward(int speedOfRotate) {
  digitalWrite(leftMotorPin2, LOW);
  analogWrite(leftMotorPin1, speedOfRotate);
}</p><p>void leftBackward(int speedOfRotate) {
  digitalWrite(leftMotorPin2, HIGH);
  analogWrite(leftMotorPin1, speedOfRotate);
}</p><p>void stop() {
  digitalWrite(leftMotorPin1, LOW);
  digitalWrite(leftMotorPin2, LOW);
  digitalWrite(rightMotorPin1, LOW);
  digitalWrite(rightMotorPin2, LOW);
}</p>

These function deal with motor control.

<p>void calibrateSensors() {<br>  int avg1 = 0;
  int avg2 = 0;
  
  Serial.print("Calibrate Sensors.");
  
  for (int i=0; i<=100; i++) {
    Serial.print(".");
    readRightSensor();
  avg1 = avg1 + rightSensor;
  avg2 = avg2 + rightAmbient;  
  }
  avg1 = avg1 / 100;
  avg2 = avg2 / 100;
  
  rightCalibrate = avg2 - avg1;
  
  avg1 = 0;
  avg2 = 0;
  for (int i=0; i<=100; i++) {
    Serial.print(".");
    readLeftSensor();
    avg1 = avg1 + leftSensor;
    avg2 = avg2 + leftAmbient;
  }
  avg1 = avg1 / 100;
  avg2 = avg2 / 100;
  leftCalibrate = avg2 - avg1;
  Serial.println("");
  Serial.print("Right Calibrate: ");
  Serial.print(rightCalibrate);
  Serial.print(" Left Calibrate: ");
  Serial.println(leftCalibrate);
}</p>

This is the calibration routine, here we take one hundred reading of each sensor, and average the values. It sets the difference between the ambient and object reading and sets that as the calibration reading. (If you are using the serial console, you can see the differences printed out, I left serial printing in for troubleshooting) In other words, if the ambient temperature is 75 degree F, and the object reading is 76 degree F - the difference will be 1 degree. It does this for both sensors, the idea is to both sensors should have the same reading if the robot is sitting and there are no heat sources in front of it. This let any positive change in temperature cause the robot to move toward the heat source.

Step 9: The Video.....

So as I said in the previous step, I did find a error in my logic while I was writing this instructable...but as you can see the robot does most do what it should, and should work a lot better when I get yet another new code.

I'll update the video when it's finished but for now enjoy.

Hopefully you enjoyed this project and build, thank you for looking at it.

** I uploaded a new video after I fixed the code, I've put that new video here, as well as left the old video.

Step 10: Update: Add a Ultrasonic

Picture of Update: Add a Ultrasonic

After many tests and playing around with this, not want it to strike the heat source. I decided to add a simple distance test.

Using a SR-HC04 ultra sonic, with the Trigger Pin connected to PIN 11 on the Nano, the Echo Pin connected to Pin 10 on the Nano, VCC to the 5v bus, and GND to GND bus.

The NewPing.h library is used.

http://playground.arduino.cc/Code/NewPing

It's currently set to stop at about 5 inches from the heat source.

I did move the heat sensors to the lower level of the robot to make room for the ultrasonic.

I have updated the code on github. But let's look at the changes here:

//Setup variables for UltraSonic
int pingSensorIn; int goRobotGo = 0; //Should the robot be moving or stopped #define distance 5 //Stop distance in Inches #define TRIGGER_PIN 11 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN 10 // Arduino pin tied to echo pin on the ultrasonic sensor. #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

the variables pingSensorIn is the reading from the ultrasonic in inches, goRobotGo as it says, tells the robot if it should be moving or not (there are of course other ways to do this). The define distance is the stop distance in inches. The rest is all for starting the ultrasonic.

In void loop this is what has changed:

readPing();
if (goRobotGo) { aL = map(leftAmbient, -40, leftAmbient, 0.0, pwmR); sL = map(leftSensor, leftAmbient, leftSensor, pwmR, 0.0); aR = map(rightAmbient, -40, rightAmbient, 0.0, pwmL); sR = map(rightSensor, rightAmbient, rightSensor, pwmL, 0.0); if (leftAmbient >= leftSensor) {sL = pwmR;} if (rightAmbient >= rightSensor) {sR = pwmL;} rightForward(aL - sL); leftForward(aR - sR); } else { stop(); }

The big change here is to call the reading of the ping, and check the goRobotGo flag - if the flag is true (a one) it will do what it had done before and seek the heat. If goRobotGo is false (or zero) it will do the "stop()" function.

And lastly I added a new function to read the sensor.

void readPing() {
unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS). pingSensorIn = (uS / US_ROUNDTRIP_IN); if (pingSensorIn >= distance) {goRobotGo = 1; } else {goRobotGo = 0;}

}

This is pretty much straight from the ultrasonic (newping) demo code, adding the check for distance and setting the goRobotGo flag as needed.

The original code was named "Snake_vision_robot", I did change that to "Seek_Heat" because I also modified the code to "Run From Heat" - Currently the "run from heat" sketch does not use the ultrasonic, but I plan on changing that soon.

"Run From Heat" Sketch, currently only changed two lines of code from the original version of "Snake_vision_robot" code.

In void loop, changing the rightForward, and leftForward function to rightBackward, and leftBackward

function causes the robot to roll away from the heat source. (But honestly I've not tested this yet, it should work thou :-) )

Comments

About This Instructable

1,111views

19favorites

License:

Bio: I am a Ham Radio operator, computer geek, currently a service tech, robotic hobbyist. I've been &quot;playing&quot; with microcontrolers for the last several years ... More »
More by kd8bxp:Using a Raspberry PI Zero W As an Access Point and MQTT BrokerWemos D1 Mini WIFI Robot (MQTT & UDP)ESP32/X-Project Cheerlight Badge Using MQTT
Add instructable to: