3pi speed problem

Hello,

I received my pololu 3pi from a local dealer. Firstly, I used the preloaded program and understand the parts device. After that I used the simple line follower code from examples. Works fine. Then I used the simple line follower pid. It works fine too. I changed its pid values randomly still no problem.

What I want was adjusting speed with buttons and after adjusting it pid values should adjusts its self. I found a code similar to that purpose. Here it is:

/*
 * This program based on 3pi-linefollower-pid - demo code for the Pololu 3pi Robot
 * 
 * This code will follow a black line on a white background, using a
 * PID-based algorithm.
 *
 * https://www.pololu.com/docs/0J21
 * https://www.pololu.com
 * https://forum.pololu.com
 *
 *
 * Copyright (c) George Eggleston
 * You may freely modify and share this code, as long as you keep this
 * notice intact.  Licensed under the Creative Commons BY-SA 3.0 license:
 *
 * http://creativecommons.org/licenses/by-sa/3.0/
 * 
 */
 

#include <pololu/3pi.h>
 
#include <avr/pgmspace.h>
#include <avr/eeprom.h> 

// Introductory messages.  The "PROGMEM" identifier causes the data to
// go into program space.
const char welcome_line1[] PROGMEM = " Pololu";
const char welcome_line2[] PROGMEM = "3\xf7 Robot";
const char demo_name_line1[] PROGMEM = "PID Opt";
const char demo_name_line2[] PROGMEM = "follower";
const char main_menu1[] PROGMEM = "Main";
const char main_menu2[] PROGMEM = "G  S  C";

// set-up parameters for PID functions
uint8_t mot_high;
#define EE_mot_high (uint8_t*)0

uint8_t prop_f = 100;
#define EE_prop_f (uint8_t*)1

uint8_t integ_f;
#define EE_integ_f (uint8_t*)2

uint8_t der_f;
#define EE_der_f (uint8_t*)3

char is_on = 0;

// A couple of simple tunes, stored in program space.
const char welcome[] PROGMEM = ">g32>>c32";
const char go[] PROGMEM = "L16 cdegreg4";

void initialize(void);
void edit_param(char param_num);
void button_a(void);
void button_b(void);
void button_c(void);
void bat_test(void);
void main_menu(void);

// This is the main function, where the code starts.  All C programs
// must have a main() function defined somewhere.
int main()
{
	unsigned int sensors[5]; // an array to hold sensor values
	unsigned int last_proportional=0;
	long integral=0;

	// set up the 3pi
	initialize();

    main_menu();
    
	// This is the "main loop" - it will run forever.
	for(;;)
	{
	    // is a button pressed?
	    if(!button_is_pressed(ALL_BUTTONS))
	    {
	        // is the robot in line following mode?
	        if(is_on)
	        {
        		// Get the position of the line.  Note that we *must* provide
        		// the "sensors" argument to read_line() here, even though we
        		// are not interested in the individual sensor readings.
        		unsigned int position = read_line(sensors,IR_EMITTERS_ON);

        		// The "proportional" term should be 0 when we are on the line.
        		int proportional = ((int)position) - 2000;

        		// Compute the derivative (change) and integral (sum) of the
        		// position.
        		int derivative = proportional - last_proportional;
        		integral += proportional;

        		// Remember the last position.
        		last_proportional = proportional;

        		// Compute the difference between the two motor power settings,
        		// m1 - m2.  If this is a positive number the robot will turn
        		// to the right.  If it is a negative number, the robot will
        		// turn to the left, and the magnitude of the number determines
        		// the sharpness of the turn.
        		//int power_difference = proportional/20 + integral/10000 + derivative*3/2;
        		int power_difference = 
        		    (prop_f/100) * (proportional/20) + 
        		    (integ_f/100) * (integral/10000) + 
        		    (der_f/100) * derivative*3/2;
        		    

        		// Compute the actual motor settings.  We never set either motor
        		// to a negative value.
        		//mot_high = 60;
        		if(power_difference > mot_high)
        		{
        			power_difference = mot_high;
    			}
        		if(power_difference < -mot_high)
        		{
        			power_difference = -mot_high;
                }
        		if(power_difference < 0)
        		{
        			set_motors(mot_high+power_difference, mot_high);
    			}
        		else
        		{
        			set_motors(mot_high, mot_high-power_difference);
        		}
    		}
		}
		// start line following
		else if(button_is_pressed(BUTTON_A))
		{
		    button_a();
		    bat_test();
		    main_menu();
		}
		// stop line following
		else if(button_is_pressed(BUTTON_B))
		{
		    button_b();
		    main_menu();
		    last_proportional=0;
            integral=0;
		}
		// enter menu to change parameters
		else if(button_is_pressed(BUTTON_C))
		{
		    button_c();
		    main_menu();
		    last_proportional=0;
            integral=0;
		}
	}

}



// Initializes the 3pi, displays a welcome message, calibrates, and
// plays the initial music.
void initialize()
{
	unsigned int counter; // used as a simple timer
	//unsigned int sensors[5]; // an array to hold sensor values

	pololu_3pi_init(2000);
    
    // set initialize parameters for PID functions
    mot_high = eeprom_read_byte(EE_mot_high);
    if(mot_high == 255) // set to a reasonable value if this is the first run
    {
        mot_high = 60;
    }
 
    prop_f = eeprom_read_byte(EE_prop_f);
    if(prop_f == 255)
    {
        prop_f = 100;
    }
    
    integ_f = eeprom_read_byte(EE_integ_f);
    if(integ_f == 255)
    {
        integ_f = 100;
    }
    
    der_f = eeprom_read_byte(EE_der_f);
    if(der_f == 255)
    {
        der_f = 100;
    }

	// Play welcome music and display a message
	print_from_program_space(welcome_line1);
	lcd_goto_xy(0,1);
	print_from_program_space(welcome_line2);
	play_from_program_space(welcome);
	delay_ms(1000);

	clear();
	print_from_program_space(demo_name_line1);
	lcd_goto_xy(0,1);
	print_from_program_space(demo_name_line2);
	delay_ms(1000);

	// Display battery voltage and wait for button press
	while(!button_is_pressed(BUTTON_B))
	{
		int bat = read_battery_millivolts();

		clear();
		print_long(bat);
		print("mV");
		lcd_goto_xy(0,1);
		print("Press B");

		delay_ms(100);
	}

	// Always wait for the button to be released so that 3pi doesn't
	// start moving until your hand is away from it.
	wait_for_button_release(BUTTON_B);
	delay_ms(1000);

	// Auto-calibration: turn right and left while calibrating the
	// sensors.
	for(counter=0;counter<80;counter++)
	{
		if(counter < 20 || counter >= 60)
			set_motors(40,-40);
		else
			set_motors(-40,40);

		calibrate_line_sensors(IR_EMITTERS_ON);
 
		delay_ms(20);
	}
	set_motors(0,0);


	wait_for_button_release(BUTTON_B);

	clear();

	print("Go!");		

	// Play music and wait for it to finish before we start driving.
	play_from_program_space(go);
	while(is_playing());
}
void edit_param(char param_num)
{
    unsigned char button_pressed;
    char par_change = 0;
    for(;;)
    {
        button_pressed = wait_for_button_press(ALL_BUTTONS);
        switch(button_pressed)
        {
        // exit edit_param function
        case BUTTON_A:
            clear();
            print("Return");
            wait_for_button_release(BUTTON_A);
            return;
        // increase parameter
        case BUTTON_B:
            wait_for_button_release(BUTTON_B);
            par_change = +1;
            break;
        // decrease
        case BUTTON_C:
            wait_for_button_release(BUTTON_C);
            par_change = -1;
            break;
        }
        // update parameter and save to eeprom
        switch(param_num)
        {
            case 0:
                mot_high += par_change;
                eeprom_write_byte(EE_mot_high, mot_high);
                lcd_goto_xy(0,1);
		        print("        ");
		        lcd_goto_xy(0,1);
		        print_long((long)mot_high);
                break;
            case 1:
                prop_f += par_change;
                eeprom_write_byte(EE_prop_f, prop_f);
                lcd_goto_xy(0,1);
		        print("        ");
		        lcd_goto_xy(0,1);
		        print_long((long)prop_f);
                break;
            case 2:
                integ_f += par_change;
                eeprom_write_byte(EE_integ_f, integ_f);
                lcd_goto_xy(0,1);
		        print("        ");
		        lcd_goto_xy(0,1);
		        print_long((long)integ_f);
                break;
            case 3:
                der_f += par_change;
                eeprom_write_byte(EE_der_f, der_f);
                lcd_goto_xy(0,1);
		        print("        ");
		        lcd_goto_xy(0,1);
		        print_long((long)der_f);
                break;
        }
    }
}
void main_menu()
{
    clear();
    print_from_program_space(main_menu1);
    lcd_goto_xy(0,1);
    print_from_program_space(main_menu2);
}
// start line following
void button_a()
{
    clear();
    print(" GO!!!");
    is_on = 1;
    wait_for_button_release(BUTTON_A);
}
// stop line following
void button_b()
{
    clear();
    print(" STOP!!!");
    is_on = 0;
    set_motors(0,0);
    wait_for_button_release(BUTTON_B);
}
// menu to change parameters
void button_c()
{
    unsigned char button_pressed;  
    char param_num = 0;
    set_motors(0,0);
    wait_for_button_release(BUTTON_C);
    for(;;)
    {
        clear();
        print("C ");
        // display current parameter
        switch(param_num)
        {
            case 0:
                print("Speed");
                lcd_goto_xy(0,1);
                print_long((long)mot_high);
                break;
            case 1:
                print("Prop");
                lcd_goto_xy(0,1);
                print_long((long)prop_f);
                break;
            case 2:
                print("Integ");
                lcd_goto_xy(0,1);
                print_long((long)integ_f);
                break;
            case 3:
                print("Der");
                lcd_goto_xy(0,1);
                print_long((long)der_f);
                break;
        }
       // 
        button_pressed = wait_for_button_press(ALL_BUTTONS);
        switch(button_pressed)
        {
        // exit menu
        case BUTTON_A:
            clear();
            print("Return");
            wait_for_button_release(BUTTON_A);
            return;
        // switch to the next parameter
        case BUTTON_B:
            clear();
            print("C Param");
            param_num++;
            if(param_num > 3)
            {
                param_num = 0;
            }
            wait_for_button_release(BUTTON_B);
            break;
        // change the value of the current parameter
        case BUTTON_C:
            wait_for_button_release(BUTTON_C);
            edit_param(param_num);
        }
    }
}
// Displays the battery voltage.
void bat_test()
{
	int bat = read_battery_millivolts();
	clear();
	print_long(bat);
	print(" mV");

	delay_ms(2500);
}


But my problem is, after I increase the speed value over “125”, devices shuts it self down after sensor calibration. I want to make it go around 160 - 180.

Do you have any advice for that? What can I do?

Hello.

It sounds like your battery might be discharged. Could you try replacing them with new ones or recharging the batteries you have?

- Jeremy