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?