Here's a picture of the prototype without the battery.
Goals and requirements -
- It should be as easy and cheap to make as possible so that I can make several of them.
- It needs to sense some aspect of its environment.
- It needs to be able to interact with other robots of its kind.
- It needs to move in a controllable and repeatable way.
Although it is not my goal, at this point I basically have a line following robot much like dozens of others you can find on the internet, but it actually only follows an edge between light and dark because it only has two sensors, left and right. If you stuck it on a chess board, it would go around tracing the edges of the squares. Actually, I kind of want to try that.
Electronics -
An ATtiny85 running at 8MHz controls everything here. It makes use of the libraries from MIT that are detailed here that allow me to easily program it with Arduino. Here are some other electronics details.
- The two pager motors are driven by 2N7002K N-channel mosfets which conveniently include protection diodes.
- The two clear LED looking things out front are phototransistors, and the red one is a red LED. They work together to determine the lightness of the surface and are also the front legs for the robot. They are spaced about 5mm apart giving the robot a left and right value.
- The battery is a 3.7V LIR2032 that I pulled out of a 100yen solar key chain light.
and here is a picture of the messy underside. Those black things are the mosfets. If you look closely, you can see the SMD resistors soldered between pins. Also, note that the LED and sensor leads run in a gap between the chip and the socket. They are the three solder points in the middle.
Hardware -
As with robot 1, the pager motors were from ebay and I don't have much data on them. They are roughly 2cm long including shaft and 7mm in diameter. They are hot glued to a little piece of protoboard that makes up the chassis. The little red things on the shafts are bits of 22awg wire insulation that provide traction.
The battery connects via a homemade connector using 22awg wire and two short pin sockets. The battery just sticks on top of the chip with some tape. This was done because I have to take it off every time I reprogram the chip or recharge the battery. There is no power switch.
Well, there really isn't much more to say about the hardware.
It works -
There are, of course, some issues. Since the sensors are 5mm apart, it doesn't have a very tight "grip" on the edge between light and dark, so it tends to wobble left and right as the edge bounces between the sensors, occasionally going in just the right direction for a few centimeters. I think this would improve a little if I could place the sensors closer, but they are almost touching already. I have tried a few software adjustments, but the basic problem is still there.
Anyway, you probably want to see a video. Here is a short one.
Also, here are some more pictures.
Since I had some requests, here is the code. It doesn't do much and I haven't really looked at it since I first wrote it. I hope some day I can get back to this project.
/*
Robot version 2
Simpler. ATtiny85, 2 motors, LED, two sensors
Sensor stuff:
both white : no prior : random walk
: prior : turn in direction of last black
one white : ideal situation, move straight
both black : no prior : random walk
: prior : turn in direction of last white
Sorry if that was hard to understand
*/
#include "Arduino.h"
// the pin definitions
#define lmotorpin 1 // PB1 pin 6
#define rmotorpin 0 // PB0 pin 5
#define lsensepin 3 //ADC3 pin 2
#define rsensepin 1 //ADC1 pin 7
#define ledpin 4 //PB4 pin 3
// numbers for random walk and memory
#define steplength 300
#define smallturn 200
#define bigturn 500
#define memtime 1000
uint8_t lspd, rspd;
uint16_t lsenseval, rsenseval, lwhiteval, rwhiteval;
// functions
void testSensors();
void followEdge();
void moveTime(uint8_t lspeed, uint8_t rspeed, uint16_t time);
void move(uint8_t lspeed, uint8_t rspeed);
void stop();
void senseInit();
void flashLED(uint8_t flashes);
// just for convenience and simplicity (HIGH is off)
#define ledoff PORTB |= 0b00010000
#define ledon PORTB &= 0b11101111
void setup(){
pinMode(lmotorpin, OUTPUT);
pinMode(rmotorpin, OUTPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
ledoff;
pinMode(ledpin, OUTPUT);
analogWrite(lmotorpin, 0);
analogWrite(rmotorpin, 0);
lspd = 17;
rspd = 17;
// give a 6 second pause to set the thing on a white surface
lsenseval = 6;
while(lsenseval){
lsenseval--;
flashLED(1);
delay(989);
}
flashLED(4);
delay(500);
senseInit();
}
void loop(){
followEdge();
}
void followEdge(){
// now look for edge
uint8_t lastMove = 1; //0=straight, 1=left, 2=right
unsigned long moveEndTime = 0; // the millis at which to stop
unsigned long randomBits = micros();
unsigned long prior = 0; // after edge encounter set to millis + memtime
uint8_t priorDir = 0; //0=left, 1=right, 2=both
uint8_t lastSense = 1; //0=edge, 1=both white, 2=both black
uint8_t i = 0; // iterator
while(true){
// only update about once every 20ms
delay(18);
// read the value 4 times and average
ledon;
delay(2);
lsenseval = 0;
rsenseval = 0;
for(i=0; i<4; i++){
lsenseval += analogRead(lsensepin);
rsenseval += analogRead(rsensepin);
}
// don't divide by 4 because it is used below
ledoff;
if(randomBits == 0){ randomBits = micros(); }
if((lsenseval > lwhiteval*3) && (rsenseval > rwhiteval*3)){
// both white - if prior turn to black, else random walk
if(lastSense == 2 || millis() < prior){
// turn toward last black or left
if(priorDir == 0){
moveEndTime = millis()+smallturn;
move(0, rspd); // turn left
lastMove = 1;
}else if(priorDir == 1){
moveEndTime = millis()+smallturn;
move(lspd, 0); // turn right
lastMove = 2;
}else{
moveEndTime = millis()+bigturn;
move(0, rspd); // turn left a lot
lastMove = 1;
}
}else{
// random walk
if(millis() < moveEndTime){
// just continue moving
}else{
if(lastMove){
moveEndTime = millis()+steplength;
move(lspd, rspd); // go straight
lastMove = 0;
}else{
if(randomBits & 1){
moveEndTime = millis()+smallturn;
move(0, rspd); // turn left
lastMove = 1;
}else{
moveEndTime = millis()+smallturn;
move(lspd, 0); // turn right
lastMove = 2;
}
randomBits >>= 1;
}
}
}
lastSense = 1;
}else if((lsenseval > lwhiteval*3) || (rsenseval > rwhiteval*3)){
// one white - this is the edge
// just go straight
moveEndTime = millis()+steplength;
move(lspd, rspd); // go straight
lastMove = 0;
lastSense = 0;
prior = millis()+memtime;
if(lsenseval > lwhiteval*3){
// the right one is black
priorDir = 1;
}else{
// the left one is black
priorDir = 0;
}
}else{
// both black - if prior turn to white, else random walk
if(lastSense == 1 || millis() < prior){
// turn toward last white or left
if(priorDir == 0){
moveEndTime = millis()+smallturn;
move(lspd, 0); // turn right
lastMove = 2;
}else if(priorDir == 1){
moveEndTime = millis()+smallturn;
move(0, rspd); // turn left
lastMove = 1;
}else{
moveEndTime = millis()+bigturn;
move(lspd, 0); // turn right a lot
lastMove = 2;
}
}else{
// random walk
if(millis() < moveEndTime){
// just continue moving
}else{
if(lastMove){
moveEndTime = millis()+steplength;
move(lspd, rspd); // go straight
lastMove = 0;
}else{
if(randomBits & 1){
moveEndTime = millis()+smallturn;
move(0, rspd); // turn left
lastMove = 1;
}else{
moveEndTime = millis()+smallturn;
move(lspd, 0); // turn right
lastMove = 2;
}
randomBits >>= 1;
}
}
}
lastSense = 2;
}
}
}
void moveTime(uint8_t lspeed, uint8_t rspeed, uint16_t time){
analogWrite(lmotorpin, lspeed);
analogWrite(rmotorpin, rspeed);
delay(time);
analogWrite(lmotorpin, 0);
analogWrite(rmotorpin, 0);
}
void move(uint8_t lspeed, uint8_t rspeed){
analogWrite(lmotorpin, lspeed);
analogWrite(rmotorpin, rspeed);
}
void stop(){
analogWrite(lmotorpin, 0);
analogWrite(rmotorpin, 0);
}
// stores the average of 16 readings as a white value
void senseInit(){
lwhiteval = 0;
rwhiteval = 0;
ledon;
delay(2);
for(uint8_t i=0; i<16; i++){
lwhiteval += analogRead(lsensepin);
delay(1);
rwhiteval += analogRead(rsensepin);
delay(9);
}
lwhiteval >>= 4;
rwhiteval >>= 4;
ledoff;
}
void flashLED(uint8_t flashes){
while(flashes){
flashes--;
ledon;
delay(200);
ledoff;
if(flashes){ delay(500); }
}
}
hello friend, excellent work, you could make some of these robots, and sell them to me?
ReplyDeletemy email is: admin@levelnoon.com
hello sir,u have done a great work,i would like to try this bot,could you please give the details regarding this, thanks and regards
ReplyDeletemy mail id is: ravikumar.a.93@gmail.com
Could you send me a list of all the things you need to buy? Would be nice of you. :)
ReplyDeletej.emmeborn@gmail.com
RE: all the above comments -
ReplyDeleteI'm glad you are interested in this bot. If you want to know the parts used or the "details regarding this" simply read the post. It is all there. If you have a more specific question, I would be happy to answer it.
Hello friend,
ReplyDeletecould you share the FW with me?
thanks
@Alessandro -
ReplyDeleteSure. I added it to the page above.
it is a phototransistor or a photo resistor? as phototransistor has 3 legs and urs only have 2 of them...
ReplyDeletesachanster19@gmail.com
@Upendra Sachan -
ReplyDeleteIt is a phototransistor. The two legs are the collector and emitter(base is optical). Here is the datasheet: http://www.mouser.com/catalog/specsheets/P_100_AV02-0013EN%20ASDL-6620%20DS%20Dec071.pdf
Most of the parts, (motors, transistors, resistors and sometimes LEDS) can be found in small infrared toy helicopters.
ReplyDeleteIS that a capacitor??? what is the value of that and its connection in the circuit?? Thank you
ReplyDeleteis that a capacitor that i saw in the pictures??? what is the value of that and its connection to the circuit?? Thank you
ReplyDelete@Anonymous -
ReplyDeleteYes, there is a capacitor stuck on the side in the picture. It is 0.1uF and it is across the battery terminals. I guess I left that out of the schematic. My newer designs have a 10uF smd capacitor.
Im experiencing a problem making it, did you change any codes that you uploaded or is it the working code. And what is the use of the capacitor?? thank you
ReplyDelete@Anonymous -
ReplyDeleteThank you for trying to make one. This code is pretty old, but I think it should work. What kind of problems are you having? Did you remember to program the fuses(burn the bootloader)?
The capacitor is just to make the power from the battery a little more stable. Honestly it isn't necessary, but it doesn't hurt. But use a higher value than I did here, something in the 1~10uF range.
im having a problem in sensing, is it okay to use 2n7002 instead of 2n7002k? and when i change the value of lsp and rspd from 17 to 175 the motor goes faster. because when it is in 17 the motor is very slow. Thank you.
ReplyDeleteim having a problem in sensing, is it okay to use 2n7002 instead of 2n7002k? and when i change the value of lsp and rspd from 17 to 175 the motor goes faster. because when it is in 17 the motor is very slow. Thank you. and by the way how to burn the fuses?? is it in arduino ide?
ReplyDelete@Anonymous -
ReplyDeleteYes, the 2n7002 should work I think.
lspd and rspd are the pwm duty cycle values. Of course 175/255 is larger than 17/255 so it will go faster. You can set it to whatever works best for you.
If you have the boards file from the MIT link in the post, you can connect it to arduino running the ISP sketch, select the correct board, ATtiny85 8MHz, and click "burn bootloader" in one of the menus. That sets up the board to work as expected.
As for sensing, it's difficult to know exactly what's wrong. Experiment with it a bit. See if the expected voltages are coming from your sensor circuits. See what happens when you place it on different surfaces.
should i burn the boot loader or upload it or both?? when i burn the boot loader the applicatiion doesnt respond only says burning the boot loader and took a minute. thank you
ReplyDeleteis it okay to use the normal resistors or smd resistors must be used??Thank You
ReplyDelete@Anonymous -
ReplyDeleteIf you click "upload" it will try to upload your attiny sketch to the arduino. That's not what you want to do. Click "burn bootloader" in one of the menus. Then click "upload using programmer" in another menu to upload the sketch to the ATtiny. The MIT site I linked to has a tutorial about it I think.
You can use any type of resistors you want. The only important thing is the ohm value.
IS IT OKAY TO USE CR2032, and how many? because we are having a poblem in operating the two motors. Thank you.
ReplyDelete@Anonymous -
ReplyDeleteYes, you could use CR2032, but the voltage is a little different. I think CR2032 is 3V while LIR2032 is 3.7V. Have you tried changing the pwm values for the motors(lspd, rspd)? Perhaps the values I used were too low for your setup.
what software did you use to program it? and how you put the program to the ic?
ReplyDeleteso where i have to put the strings and how i can attach the computer and the ATtiny85 without an arduino?
ReplyDeleteGood Day,
ReplyDeleteI am Harry from the KS U.K School of robotics. We are willing to pay you £6.00 per robot if you are willing to make 120 units and sell them to us.
Please email kingsonline@gmail.com ASAP.
Yours Sincerely
KS U.K School of robotics
Headmaster
Hello, what are the fuse bits for ATtiny85 ?:)
ReplyDeletehello sir, i am having an error "arduino ISP error" so many of them. how can i fix it?
ReplyDeleteHello sir, your project very well done, good job. I like to try to do the same project to school, can you send me more details for it? My Gmail is velovskidaniel@Gmail.com
ReplyDelete@Anonymous -
ReplyDeleteSorry for the lack of replies here. I have posted some more details and a list of parts on a Hackaday project page: https://hackaday.io/project/581-tiny-robot-family
Dear Sir,
ReplyDeleteI have not ATTINY85, could I use ATTINY13A for this bot?
Thank in advance!
very good,
ReplyDeleteDo you use Arduino to program it..?
Can you give me your smd resistor data sheet ?
ReplyDeleteLooking at your schematic, are you sure that is how you wired the phototransistors? I think the load resistor should be from V+ to drain, and the source should be connected to ground.
ReplyDeleteOne other thing, your code says high is off for the LED, which suggests the pin is sinking current (which is better to do anyways, as the tiny pins can sink more current than source), but the schematic shows the LED being sourced by the pin.
ReplyDeleteI might be wrong and I apologize if so, but I think the pin definition
ReplyDelete#define rsensepin 1 //ADC1 pin 7
should be
#define rsensepin 2 //ADC1 pin 7
since ADC1 is on PB2.
I'm not sure since this is my first time using an ATtiny85
and it seemed to work either way.
Nevertheless, a fun project. Thank you !
I was able to make one of these and it works great. i just had to modify the code a bit and change the motor speed from 17 to about 65 and the bigturn to 250 the small turn to 100 and steplength to 200, running at 16mhz.
ReplyDeletealso to the other person that said the pin labeling is wrong, you're right.
mine was working for a day or two and stopped. it would flash and then soon as it sent power to the motors the attiny would reset. so I added the capacitor of 10uf to the two battery termials and that fixed it.
originally i had motors of 4 by 6 mm but they didnt have enough torque to do it so i got some 6 by 10 mm motors and those have sufficient torque.
the only problem ive noticed with the code is that the white level is only calibrated once. this is a slight problem if your track is lit by a lamp on one side. as it is brighter in some spots than others. but if you use a celling light over it then it works like a charm
I am using 2N7000A instead of 2N7002K. only one motor is working by mosfet. Another one is working but not with mosfet. I have checked mosfet also. Give me some suggestions please.
ReplyDeleteRobot 2 Full Movie Download In Hindi
ReplyDelete