Author Topic: 50$robot_sharp ir rotation..only 90°  (Read 2868 times)

0 Members and 1 Guest are viewing this topic.

Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
50$robot_sharp ir rotation..only 90°
« on: December 19, 2009, 06:02:13 PM »
hi,
I first posted this in the electronic part of the forum but apparently, it's a code problem: I proudly  ;) finished the sharp ir 50$ robot, it works well, it follows me  :) ..but the servo (that is able to rotate 180°) just scans 90°..I used the code that was to download on this site.. does somebody has an idea?
manu

/****************************************************************************
*
*   Copyright (c) 2007 www.societyofrobots.com
*   (please link back if you use this code!)
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
*   $50 Robot with Sharp IR using Stampy Technology v1, May 19th, 2007
*   Simple case-based method for a robot to do edge detection.
*
*
****************************************************************************/

//SoR Include
#include "SoR_Utils.h" //includes all the technical stuff

//global variables
int sharp_IR_reading=0;

int scan_thresh=0;//threshold value of scanning sensor

int scan_angle=30;//position of scanner, in units of servo command
int max_scan_angle=56;//maximum position scanner can rotate to (57)


//this function causes scanning servo to center on edge of object
void scan(void)
   {
   //lower (-) goes right
   //higher (+) goes left
   //30 far right, 50 straight, 56 far left (until it jams)

   /*psuedocode
   object is detected
      scan right object detected
   object not detected
      scan left until object detected*/

   sharp_IR_reading=a2dConvert8bit(3);
   
   if (sharp_IR_reading > scan_thresh)//object detected
      {
      if (scan_angle>41) //overflow protection
         scan_angle-=2;//scan right
      }
   else //object not detected
      {
      if (scan_angle<=max_scan_angle) //maximum servo angle
         scan_angle+=2; //scan left
      //else //if scanned all the way, this forces it to start over
      //   scan_angle=30;
      }
      
   //servo scan code
   servo_scan(scan_angle);
   }


//automatically calculates threshold value before run
void autocalibrate(void)
   {
   scan_thresh=a2dConvert8bit(3);//sensor reading
   }

int main(void)
   {
   //LED_on();

   initialize();
   
   delay_cycles(42000);//two second wait delay

   /*********ADD YOUR CODE BELOW THIS LINE **********/

   //find thresholds
   autocalibrate();

   //LED_off();


   while(1)
      {
      scan();
      
      //object on left
      if(scan_angle > 57)
         robot_turn_left();

      //object on right
      else if(scan_angle < 41)
         robot_turn_right();

      //object is centered
      else
         robot_go_straight();

      delay_cycles(400);//a small delay to prevent crazy oscillations
      }
   /*********ADD YOUR CODE ABOVE THIS LINE **********/

   return 0;
   }


/*********************COMMAND LIST*************************

delay_cycles(cycles);
Delays - you can make your robot wait for a certain amount of time with this function.
Put the number of computational cycles to delay in the ().
23 cycles is about .992 milliseconds
to calculate: 23/.992*(time in milliseconds to delay) = cycles
Check servo datasheet where it says: 'Direction: Clockwise/Pulse Traveling 1500 to 1900usec'

servo_left(speed); and servo_right(speed);
Commands your servos to rotate at a certain speed.
Vary speed (which represents a delay in cycles) from 20 to 50.
Left is for port D0 and right is for port D1.

robot_turn_left(); and robot_turn_right(); and robot_go_straight();
Dont want to deal with speed?
Just call this function and it will 'just work.'

LED_on(); and LED_off();
Turns on and off your LED. The LED is on port D4.
By bringing port D4 low, you are turning on the LED.


variable=a2dConvert8bit(pin);
Reads analog pin. For example, set 'pin' to 5 to read PC5.
'variable' will store the value.

***********************************************************/


Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
Re: 50$robot_sharp ir rotation..only 90°
« Reply #1 on: December 20, 2009, 11:57:42 AM »
 ???   ...anybody.?
maybe I should tell you the servo is this one: http://www.servocity.com/html/hs-322hd_standard_deluxe.html  instead of the HS-311 servo of the tuto, but specifications seem to be almost the same...

Offline Razor Concepts

  • Supreme Robot
  • *****
  • Posts: 1,856
  • Helpful? 53
    • RazorConcepts
Re: 50$robot_sharp ir rotation..only 90°
« Reply #2 on: December 20, 2009, 12:00:49 PM »
Quote from:
This servo can operate 180° when given a pulse signal ranging from 600usec to 2400usec. Since most R/C controllers cannot generate this wide of signal range, you will need to use our servo stretcher for 180° operation.

You will have to adjust the max and min scan values of the scanner servo.

Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
Re: 50$robot_sharp ir rotation..only 90°
« Reply #3 on: December 20, 2009, 03:33:52 PM »
hi,
..I expected a bit it was in this direction...but do you know, where and how I modify this in the code..?..in the SoR_Utils.h or in the 50_robot_sharpIR.c ? thank you
manu

Offline little-c

  • Robot Overlord
  • ****
  • Posts: 186
  • Helpful? 1
Re: 50$robot_sharp ir rotation..only 90°
« Reply #4 on: December 20, 2009, 03:45:28 PM »
I would modify the main code. if it breaks/catces fire ect, then look at the header file. no idea about what your programing in or the function arguments.

question, would you need 180 degrees? shorter scan gives faster responses to obsticals.

it should be a paramiter issue rather than redoing code.

if it starts to be really complicated, post the code your using and I'll have a look. header and main code!

Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
Re: 50$robot_sharp ir rotation..only 90°
« Reply #5 on: December 20, 2009, 04:13:28 PM »
thanx for help, I'm a beginner in code  :-\ ..actually I'd like to rotate 180°, even if slows a bit responses.. at least, I'd like to be able to do it.. and it rotates 90° to the right, but 0° to the left... could be acceptable if it was 45 to the left and 45 to the right, but not in this case..
so I paste the main code and the header below.. thanks to take a look..

/****************************************************************************
*
*   Copyright (c) 2007 www.societyofrobots.com
*   (please link back if you use this code!)
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
*   $50 Robot with Sharp IR using Stampy Technology v1, May 19th, 2007
*   Simple case-based method for a robot to do edge detection.
*
*
****************************************************************************/

//SoR Include
#include "SoR_Utils.h" //includes all the technical stuff

//global variables
int sharp_IR_reading=0;

int scan_thresh=0;//threshold value of scanning sensor

int scan_angle=30;//position of scanner, in units of servo command
int max_scan_angle=56;//maximum position scanner can rotate to (57)


//this function causes scanning servo to center on edge of object
void scan(void)
   {
   //lower (-) goes right
   //higher (+) goes left
   //30 far right, 50 straight, 56 far left (until it jams)

   /*psuedocode
   object is detected
      scan right object detected
   object not detected
      scan left until object detected*/

   sharp_IR_reading=a2dConvert8bit(3);
   
   if (sharp_IR_reading > scan_thresh)//object detected
      {
      if (scan_angle>41) //overflow protection
         scan_angle-=2;//scan right
      }
   else //object not detected
      {
      if (scan_angle<=max_scan_angle) //maximum servo angle
         scan_angle+=2; //scan left
      //else //if scanned all the way, this forces it to start over
      //   scan_angle=30;
      }
      
   //servo scan code
   servo_scan(scan_angle);
   }


//automatically calculates threshold value before run
void autocalibrate(void)
   {
   scan_thresh=a2dConvert8bit(3);//sensor reading
   }

int main(void)
   {
   //LED_on();

   initialize();
   
   delay_cycles(42000);//two second wait delay

   /*********ADD YOUR CODE BELOW THIS LINE **********/

   //find thresholds
   autocalibrate();

   //LED_off();


   while(1)
      {
      scan();
      
      //object on left
      if(scan_angle > 57)
         robot_turn_left();

      //object on right
      else if(scan_angle < 41)
         robot_turn_right();

      //object is centered
      else
         robot_go_straight();

      delay_cycles(400);//a small delay to prevent crazy oscillations
      }
   /*********ADD YOUR CODE ABOVE THIS LINE **********/

   return 0;
   }


/*********************COMMAND LIST*************************

delay_cycles(cycles);
Delays - you can make your robot wait for a certain amount of time with this function.
Put the number of computational cycles to delay in the ().
23 cycles is about .992 milliseconds
to calculate: 23/.992*(time in milliseconds to delay) = cycles
Check servo datasheet where it says: 'Direction: Clockwise/Pulse Traveling 1500 to 1900usec'

servo_left(speed); and servo_right(speed);
Commands your servos to rotate at a certain speed.
Vary speed (which represents a delay in cycles) from 20 to 50.
Left is for port D0 and right is for port D1.

robot_turn_left(); and robot_turn_right(); and robot_go_straight();
Dont want to deal with speed?
Just call this function and it will 'just work.'

LED_on(); and LED_off();
Turns on and off your LED. The LED is on port D4.
By bringing port D4 low, you are turning on the LED.


variable=a2dConvert8bit(pin);
Reads analog pin. For example, set 'pin' to 5 to read PC5.
'variable' will store the value.

***********************************************************/






and the header

/****************************************************************************
*
*   Copyright (c) 2007 www.societyofrobots.com
*   (please link back if you use this code!)
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
*   SoR Utilities v1, March 10th, 2007
*
****************************************************************************/

//AVR includes
#include <avr/io.h>          // include I/O definitions (port names, pin names, etc)
#include <avr/interrupt.h>   // include interrupt support

//AVRlib includes
#include "global.h"      // include global settings
//#include "buffer.h"      // include buffer function library
//#include "uart.h"      // include uart function library
//#include "rprintf.h"   // include printf function library
//#include "timer.h"      // include timer function library (timing, PWM, etc)
#include "a2d.h"      // include A/D converter function library

//define port functions; example: PORT_ON( PORTD, 6);
#define PORT_ON( port_letter, number )         port_letter |= (1<<number)
#define PORT_OFF( port_letter, number )         port_letter &= ~(1<<number)
#define PORT_ALL_ON( port_letter, number )      port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number )      port_letter &= ~(number)
#define FLIP_PORT( port_letter, number )      port_letter ^= (1<<number)
#define PORT_IS_ON( port_letter, number )      ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number )      !( port_letter & (1<<number) )


//************CONFIGURE PORTS************
//configure ports for input or output - specific to ATmega8
void configure_ports(void)
   {
   DDRC = 0x00;  //configure all C ports for input
   PORTC = 0x00; //make sure pull-up resistors are turned off
   DDRD = 0xFF;  //configure all D ports for output
   }
//***************************************

//************DELAY FUNCTIONS************
//wait for X amount of cycles (23 cycles is about .992 milliseconds)
//to calculate: 23/.992*(time in milliseconds) = number of cycles
//or (number of cycles)*.992/23 = time in milliseconds
void delay_cycles(unsigned long int cycles)
   {
   while(cycles > 0)
      cycles--;
   }
//***************************************

//*********SIMPLIFIED FUNCTIONS**********
//functions to make coding easier for a beginner
//but could cause port mixup confusion for intermediate users
void LED_on(void)
   {
   PORT_OFF(PORTD, 4);//turn LED on
   }
void LED_off(void)
   {
   PORT_ON(PORTD, 4);//turn LED off
   }
void servo_left(signed long int speed)
   {
   PORT_ON(PORTD, 0);
   delay_cycles(speed);
   PORT_OFF(PORTD, 0);//keep off
   delay_cycles(200);
   }
void servo_right(signed long int speed)
   {
   PORT_ON(PORTD, 1);
   delay_cycles(speed);      
   PORT_OFF(PORTD, 1);//keep off
   delay_cycles(200);
   }
void servo_scan(signed long int speed)
   {
   PORT_ON(PORTD, 2);
   delay_cycles(speed);      
   PORT_OFF(PORTD, 2);//keep off
   delay_cycles(200);
   }
void robot_turn_left(void)
   {
   servo_left(25);
   servo_right(25);
   }
void robot_turn_right(void)
   {
   servo_left(44);
   servo_right(44);
   }
void robot_go_straight(void)
   {
   servo_left(25);
   servo_right(44);
   }
void hold_position(void)//37
   {
   servo_left(39);//39
   servo_right(35);//35
   }
//***************************************

//*************INITIALIZATIONS***********
void initialize(void)
   {
   //other stuff Im experimenting with for SoR
   //uartInit();  // initialize the UART (serial port)
   //uartSetBaudRate(9600);// set the baud rate of the UART for our debug/reporting output
   //rprintfInit(uartSendByte);// initialize rprintf system

   //timerInit(); // initialize the timer system
   
   configure_ports(); // configure which ports are analog, digital, etc.
   a2dInit(); // initialize analog to digital converter (ADC)
   a2dSetPrescaler(ADC_PRESCALE_DIV32); // configure ADC scaling
   a2dSetReference(ADC_REFERENCE_AVCC); // configure ADC reference voltage

   //rprintf("Initialization Complete\r\n");
   }
//****************************************

Offline little-c

  • Robot Overlord
  • ****
  • Posts: 186
  • Helpful? 1
Re: 50$robot_sharp ir rotation..only 90°
« Reply #6 on: December 20, 2009, 04:21:32 PM »
chuck values at this,

int scan_angle=30;//position of scanner, in units of servo command
int max_scan_angle=56;//maximum position scanner can rotate to (57)

Im guessing its the last one you want to change.

you can also do a hardware fudge, and rotate the servo so 90 left and 0 right scans the correct area.

should be happy! ish...

I can send you some pograming lecture notes/practicals that can be done in c if you want... they are uni ones, but not too hard core!

Offline Conscripted

  • Robot Overlord
  • ****
  • Posts: 291
  • Helpful? 10
Re: 50$robot_sharp ir rotation..only 90°
« Reply #7 on: December 21, 2009, 07:38:10 AM »
I had this exact issue with a micro servo when I built mine. I did exactly what little-c suggested and it worked great. I ended up with....

Code: [Select]
int scan_angle=10;//position of scanner, in units of servo command
int max_scan_angle=56;//maximum position scanner can rotate to (57)

Good luck.
Conscripted

Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
Re: 50$robot_sharp ir rotation..only 90°
« Reply #8 on: December 21, 2009, 02:29:21 PM »
.. I tried different values in both int scan_angle and int max_scan_angle  with different results, some are satisfying, but I'm not able to make it scan 180..
and, also.. if I change these values, do I have to change other values in the code?
could you shortly tell me what these two values correspond to..?
sorry..beginner at work..  ;)

Offline little-c

  • Robot Overlord
  • ****
  • Posts: 186
  • Helpful? 1
Re: 50$robot_sharp ir rotation..only 90°
« Reply #9 on: December 21, 2009, 03:42:19 PM »
poke the guy who wrote the code.

I actuly don't know. I could find out, but that involves reading data sheets, other peoples code and effort!  ::) since Im bodging the laptop to get it to work, have a robot to build, and explaining to parents that 2 kg of electrical stuff isn't junk...

if you don't mind a long wait, and lots of reminders, I might be able to get round to actuly working it out.

but they basicly control whats been pulsed to the servos. errr.... robot tutorials, servos?

sorry have a lot of work on right now.

Offline hopslink

  • Robot Overlord
  • ****
  • Posts: 202
  • Helpful? 14
Re: 50$robot_sharp ir rotation..only 90°
« Reply #10 on: December 21, 2009, 07:47:32 PM »
The value of scan_angle, as the name suggests, is used to set the position of the scanning servo. This is not a measurement in degrees but an arbitrary unit. This will only hold between an lower and upper limit corresponding to the maximum physical movement of the servo used. Different servos may have different limit values for scan_angle. You will have to experiment a bit to find the limit values that are right for yours.

In the code provided the servo is only programmed to scan fully in one direction. This is the limit defined by int max_scan_angle=56. Increase this value steadily by two tracking the point where the servo stops, until the point where the servo doesn't swing any further as you increase max_scan_angle. This is your upper limit and ideally you want to reduce max_scan_angle to slightly (say 4) below this value to prevent premature wear on your servo.

Travelling in the oposite direction the minimum value for scan_angle is set on this line.

Code: [Select]
if (sharp_IR_reading > scan_thresh)//object detected
      {
      if (scan_angle>41) //overflow protection  << HERE
         scan_angle-=2;//scan right
      }

This is not the limit of travel of the servo, but a value chosen to make the robot steer correctly to chase the edge of it's target. Reduce the value 41 here to allow the servo to swing further. Reduce by 2 each time until you find the limit of your servo travel, then increase the value by 4. Hopefully you should now have pretty much 180 degrees of servo swing. You should probably set the values below to match your new limits, or the robot will try to 'turn ahead' of the sensor.
Code: [Select]
while(1)
      {
      scan();
     
      //object on left
      if(scan_angle > 57)        << SET THIS TO YOUR max_scan_angle VALUE
         robot_turn_left();

      //object on right
      else if(scan_angle < 41)   << AND THIS TO YOUR NEW LOWER LIMIT
         robot_turn_right();

      //object is centered
      else
         robot_go_straight();

      delay_cycles(400);//a small delay to prevent crazy oscillations
      }

If you do this you could see some odd behaviour with the robot steering (predict it may now run in circles round a target... try it).

The initial value scan_angle=30 is only used once as the code starts to run so the value set here really has no effect on how the servo operates as the robot runs.

Offline manutTopic starter

  • Jr. Member
  • **
  • Posts: 38
  • Helpful? 0
Re: 50$robot_sharp ir rotation..only 90°
« Reply #11 on: December 30, 2009, 07:18:57 PM »
Hi,
I just saw the your responses...I'm going to work on it :)
I already thank you for this and will let you know if it works
merry christmas and a happy new year..
manu

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: 50$robot_sharp ir rotation..only 90°
« Reply #12 on: January 06, 2010, 02:01:47 AM »
I heavily comment my code to be easily understandable. Just read through the code, try to make sense of it.

For example, it can't be made any more obvious than:
Code: [Select]
int max_scan_angle=56;//maximum position scanner can rotate to
As for how I got the actual numbers? I experimented until it did what I liked. If you use a different servo, a different hardware configuration, etc, you just need to change that number until it works the way you like.

You can also use hyperterminal to change the value in real-time, without reprogramming, by using the UART.