Home | Links | Contact |

Printed from www.nzmeccano.com

Top Home Bottom

A Meccano Segway

(Author: Andre Theberge)

Arduino code

Arduino Sotware to control my Meccano Segway

Write to me at atheberge2@videotron.ca to have the latest copy.

Somehow, cut and paste the text below does not always work, some section of the code in <> and gets dropped

This is an combined example for the Adafruit AF motor with 2 geared-motors on M1 and M2, a Triple-Axis Gyro sensor and a ADXL345 accelerometer

Designed specifically to work with the Adafruit L3GD20 Breakout and ADXL345 breakout, instead of the accel and gyro in the SegBot code. These sensors use I2C to communicate
Modified to work with the IGT3200 gyro (Feb 11th, 2014)

The core program is taken mostly from Chapter 11 of Arduino Robotics: " The Seg-bot "
Copyright JD Warren 2010 (special thanks to Josh Adams for help during testing and coding)

A big portion of the accelerator and gyro code written by Kevin "KTOWN" Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution

Steering potentiometer used to steer bot
Gain potentiometer used to set max speed (sensitivity) %%% Not used
Engage switch (button) used to enable motors %%% Not used

Modified and adapted by Andre Théberge, copyright 2014


// #include // %%% Choose which gyro is being used

// Assign a unique ID to gyro and accel
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

//Adafruit_L3GD20 gyro; // %%% Choose which gyro is being used, comment-out the one you do not want
ITG3200 gyro = ITG3200();

AF_DCMotor motor1(1); // Define motors
AF_DCMotor motor2(2);

// Variables declaration //
// Name Analog input pins
int steeringPot = 3; // connect the steering potentiometer to Analog input 3
int gainPot = 2; // connect the gain potentiometer to Analog input 2

// Name Digital I/O pins
int engage_switch = 4; // connect engage button to digital pin 4
int ledPin = 13;

// value to hold the final angle
long angle = 0;
const int steering_1 = 360; // These constants were used to make the vehicle go in a circle, by forcing a steering value in Read_Pots
const int steering_2 = 300;
const int steering_3 = 180;
const int steering_4 = 120;
int steering_test = steering_1;

const int degree_converter = 1417; // Considering Accel_Raw = 255 x 500 / 90 degree
const long stable_angle = 4245; // 3 degree stable angle --> enable switching on motor
const long trip_angle = 42450; // 30 degree trip angle --> kill the motor

// the following 2 values should add together to equal 100
long gyro_weight = 95;
long accel_weight = 5;

// accelerometer values
int accel_reading;
int accel_raw =0;
const int accel_offset = -160; // %%%%% Set according to your hardware, put zero first and correct if necessary
long accel_angle;
long accel_scale = 500;

// gyroscope values
int ix, iy, iz; // %%% Used only with ITG3200 Gyro
int gyro_raw = 0;
const int gyro_offset = -15; // %%%%% Set according to your hardware, put zero first and correct if necessary
int gyro_reading;
long gyro_rate;
long gyro_scale = 3;
long gyro_angle;
long loop_time = 50;

// engage button variables
int engage = false;
int engage_state = 1;

// timer variables
int last_update;
int cycle_time;
long last_cycle = 0;

// motor speed variables

int m1_speed = 0; // Target speed to be achieved by motors
int m2_speed = 0;
int m1_work = 5; // Work variables for motors
int m2_work = 10;
const int m1_start_offset = 45; // %%%%% Set according to your motors, minimum PWM value to get the motors turning, with a load.
const int m2_start_offset = 45;
byte m1_int_period = 5;
byte m2_int_period = 10;
boolean m1_int_dir =0;
boolean m2_int_dir =0;

int motor_out = 0;
int motor_1_out = 0;
int motor_2_out = 0;

// potentiometer variables
int steer_val;
int steer_range = 15; // %%%%%%
int steer_reading;
int gain_reading;
int gain_val;

// end of Variables

void displaySensorDetails(void)

int16_t I2C_read16(uint8_t reg)

void geared_motors_set_speed(int m1_speed, int m2_speed) else else
if (m2_speed == 0) else else


void setup(void)

/* Set the range to whatever is appropriate for your project */
accel.setRange(ADXL345_RANGE_4_G); // choices are 16, 8, 4 and 2
accel.setDataRate(ADXL345_DATARATE_100_HZ); // choices are from 3200Hz to 25Hz/256 = 0.1Hz

/* Display some basic information on this sensor */
// displaySensorDetails();



Serial.print("Gyro Init... "); // %%% Choose which Gyro gets initialized

///// ADAFRUIT GYRO /////
// Try to initialise and warn if we couldn't detect the chip
if (!gyro.begin(gyro.L3DS20_RANGE_250DPS))
//if (!gyro.begin(gyro.L3DS20_RANGE_500DPS))
//if (!gyro.begin(gyro.L3DS20_RANGE_2000DPS))


///// IGT3200 GYRO /////



void loop()

void sample_accel()

void sample_gyro()

void calculate_angle()

void read_pots()
steering_test = steering_test - 1;
if (steering_test == steering_2) steer_val = 20;
if (steering_test == steering_3) steer_val = 0;
if (steering_test == steering_4) steer_val = -20;

// steer_val = 0; // %%%%% Remove the comment to disable steering

if (angle == 0)
// Gain potentiometer
gain_reading = analogRead(gainPot);
gain_val = map(gain_reading, 0, 1023, 32, 64);
gain_val = 35; // %%%%%%%%%%%

void auto_level()
engage = true; // %%%%%

void update_motor_speed()

// assign steering bias
motor_1_out = motor_out + (steer_val);
motor_2_out = motor_out - (steer_val);

// test for and correct invalid values
if(motor_1_out > 64)
if(motor_1_out < -64)
if(motor_2_out > 64)
if(motor_2_out < -64)

// assign final motor output values
m1_speed = motor_1_out;
m2_speed = motor_2_out;


// write the final output values to the motors
geared_motors_set_speed(m1_speed,m2_speed); // Write 2 values simultaneously to the geared motors.

void time_stamp()
// once the loop cycle reaches 50 mS, reset timer value and proceed

last_cycle = millis();


void serial_print_stuff()

///// Initialize IGT3200 gyro /////

void init_IGT3200_gyro()

gyro.setClockSource(2); // Set Y Gyro as clock reference
delay (100);

gyro.setFSRange(3); // 2000/ sec (only option)
gyro.setFilterBW(4); // 20 Hz filtering
gyro.setSampleRateDiv(9); // 100 Hz sample rate
gyro.setPowerMode(0); // Normal mode
gyro.setXgyroStandby(1); // Turn off Gyro X znd Z
gyro.setITGReady(1); // Left it like the example code (we do not use the interrupts)
delay(100); // startup


Serial.println("Dump registers...");

Serial.print("Device Address = ");

Serial.print("Sample Rate Divider = ");

Serial.print("Full Scale, DLPF = ");
Serial.print(" , ");

Serial.print("Interrupt Config = ");
Serial.print(" , ");
Serial.print(" , ");
Serial.print(" , ");

Serial.print("Interrupt Status = ");
Serial.print(" , ");

Serial.print("Power Management = ");
Serial.print(" , ");
Serial.print(" , ");
Serial.print(" , ");
Serial.print(" , ");

//End Code


If you have any interesting information or comments about this page, please add them here:

Your name:
Your message:
Security check: (Please type in the text to prove you're a person!)
Login status:  You have not yet entered your user name and password. You cannot create or edit documents until you do.
Enter your user name and password to log in

Remember me

If you click on the box marked 'remember me next time', you will not have to log in again on this computer for three months.

If you don't have a user name yet, please click here

Latest documents:

A G gauge model 
(Colin Bull & Richard Smith)
Midlands Meccano Guild
99th Meeting Model Report 
98th Meeting Model Report 
97th Meeting Model Report 
(David Couch)
The Little Tram
An introductory Arduino project 
(G. Eiermann and M. Schild)
A Short History of MARKLIN Metall
96th Meeting Model Report 
83rd Meeting Model Report 
82nd Meeting Model Report 
Picks up three golf balls 
(Roger Marriott)
Midlands Meccano Guild
95th Meeting Model Report 
The Spanner Challenge 
94th Meeting Report 
(Andre Theberge)
Meccano Segway
(Andre Theberge)
A Meccano Segway
Arduino code 
(Andre Theberge)
A Meccano Segway
Assembly instructions 
(Michael J. Walker)
Meet the new MMG President
Geoff Wright 
The Spanner Challenge 
(Michael Walker)
Midlands Meccano Guild
93rd Model Report 
Report by Michael J. Walker. 
92nd Model Report 
(Stan Knight)
Minimal Meccano
Pocket Meccano Sets of the 1970s 
Little Lever, Bolton 
The Spanner Challenge 
91st Model Report 
(Bob Thompson)
Back to the beginning
Shop Display Model 
90th Meeting Report 
(Old Blue Gold)
Getting Old
A screwy story 
The Spanner Challenge 
Model report written by Michael J. Walker 
76th Meeting Report 
Exhibition in Nelson, New Zealand 
(Barry Gerdes)
Meccano Radio
How to flatten  
(Rod Socket)
Dear Mrs Spanner
Survival techniques for the Meccanoman's wife 
(Stan Knight)
The Top Ten Tools
Indispensable Tools for the Meccanoman 
A call for help 
The Spanner Challenge 
For small brass and nickel parts. Also for stripping paint and rotted zinc plating. 
(Stephen Heafield)
Waterslide Transfers
Refurbishing 0 & 00 Aero Models 
Construction details 
or Put Your Hammer Away 
Mobile Morris Crane from 1968 MM 
Bert Love's Blocksetter in colour 
The dangers of internet auctions 
(Rob Thompson pp Terry Bullingh)
BlockSetter Tower
Built by Terry Bullingham 
(Rob Thompson pp John Reid)
Captain Robert Falcon Scott
1912 Polar Sledging Party 
(Niels Gottlob)
Bucket Wheel Excavator
Transcribed from typed document with photos 
Selected Spanner messages 18th to 24th January 
Selected Spanner messages 11th to 17th January 
Selected Spanner messages 4th to 10th January 
(Norbert Klimmek)
Hulett Ore Unloader
A 1 to 32 Scale Model 
(Joe Attard of Malta)
A model ship
(Arup Dasgupta (ISM 652))
My E15R Motor
A repair story 
About Meccano
What is Meccano? 
Thoughts about modern Meccano 
Some hints and tips 
Not many in this condition I'll bet! 
 View all | Chat | Models | Hints and Tips | Opinion | Reviews | Mine