(Simulide R2162 or higher).


To measure distances there are multiple devices such as measuring tapes, lasers, ultrasounds, etc., but when you want to measure longer distances, measure a terrain with all its potholes and obstacles or measure the perimeter of an irregular property, the “ODOMETER” is used . This measuring equipment consists of a wheel as a sensing element that, when manually rolled over the ground, measures the distance traveled in meters using a counter.
The project that we propose here is based on the design of an odometer, for this we use the Simulide DC motor encoder. In this case, the motor is used passively (for simulation only), so its shaft is attached to the measuring wheel. We have included an OLED screen with a counter of the meters traveled and the value of the wheel radius. For the measurement to be correct, the circumference in meters must be known, which is achieved with the <WHEEL> adjustment potentiometer. When starting up the system enters adjustment mode, by moving the potentiometer you can enter the value of the wheel radius up to a maximum of 1 meter. From this data, the length of the wheel circumference is displayed on the OLED.
Below we detail the controls and use of our odometer:
  • [START/STOP]: In STOP the radio is adjusted and the odometer data in meters can also be deleted and the <STOP> LED flashes continuously. In START the measurement starts. The wheel will rotate if the <PAUSE> switch and the power supply have a voltage between 0 and 5 volts to simulate the measurement speed. In this position the radio can no longer be adjusted and the <STOP> LED turns off. The degree LEDs will begin to move at the rate of rotation of the measuring wheel marking each of the quarters of the wheel where the measurement is taken, these ranges are: 0 to 89 degrees, 90 to 179, 180 to 269 and 270 to 359
  • [RESET] In STOP mode the odometer counter can be reset.
  • ADJUSTMENT POTENTIOMETER. In STOP mode, the wheel radius can be adjusted from 0 to 0.99 meters. The data is displayed on the OLED.
  • MEASURING WHEEL: It is associated with the motor shaft that moves the potentiometer of the internal encoder of the DC motor.

To know more about the odometer:  https://es.wikipedia.org/wiki/Od%C3%B3metro


The project is based on Arduino UNO as a controller. The 128×64-bit monochrome OLED display is connected via I2C. The [RST] and [START/STOP] buttons are connected to D4 and D2 respectively with internal PULLUP. The set of LEDs used as a monitor are connected as shown in the diagram and calculated for a current of about 20mA each. The <WHELL> potentiometer provides a regulated voltage between 0 and 5V through input A3. Through A1, the DC-motor encoder voltage from 0 to 5v is entered. The ENCODER-MONITOR is a complementary encoder position information device. The power supply and the <PAUSE> switch make up the rotation simulation stage, introducing a voltage of 0 to 5V to the motor to simulate the rotation speed of the wheel and therefore the measurement. This speed does not affect the measurement result, nor even its potential variations.


C program for Arduino with the libraries: Wire.h, Adafruit_GFX.h and Adafruit_SSD1306.h. These are very standard and easy to find and download.
The program is commented on its key points. It is worth highlighting the use of the [START/STOP] pushbutton by interruption, a necessary operation given that the loop is mainly occupied with continuous and real-time attention in reading the motor encoder.
// Use Arduino and Simulide R2162.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
int MON=13;
int G1=8, G2=9, G3=10, G4=11;
int MEAS=2;
int RST=4;
int senV;
int dista=A1;            // ENCODER SENSOR
int Wheel=A3;            // RADIUS POTENTIOMETER
int v1, v2, v3, v4;
float radius=0;
float rota=0;
float ruedaR;
float circun;
float rueda4;
int state=HIGH;
int MEASv;

void setup() 
  pinMode(MON, OUTPUT);
  pinMode(G1, OUTPUT); pinMode(G2, OUTPUT); pinMode(G3, OUTPUT); pinMode(G4, OUTPUT);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {for(;;);}   // Address 0x3C
  attachInterrupt(digitalPinToInterrupt(MEAS), RUPTO, RISING); // Interruption

void loop() 
  if (MEASv==LOW)                          // ADJUSTMENT CALCULATION
    ruedaR=analogRead(Wheel);              // V. analog from encoder
    ruedaR=map(ruedaR, 0, 1023, 0, 100);   // Scale (0 to 100) 
    radius=ruedaR/100;                     // Radius
    circun=radius*2*3.14;                  // Circumference
    rueda4=circun/4;                       // Circumference /4
    digitalWrite(MON,HIGH); delay(200); digitalWrite(MON,LOW); delay(50);
    if(digitalRead(RST)==HIGH) {senV=0; rota=0; OLED();}       // RESET
    goto FLA;
  do {senV=analogRead(dista); digitalWrite(G1,HIGH); v1=senV;}  // UP
  while (senV>0 && senV<224);     // RANGE
  digitalWrite(G1,LOW);           // LED
  if (v1>v4) rota=rota+rueda4;    // DIRECTION
  do {senV=analogRead(dista); digitalWrite(G2,HIGH); v2=senV;}  // LEFT
  while (senV>225 && senV<511);
  if (v2>v1) rota=rota+rueda4;
  do {senV=analogRead(dista); digitalWrite(G3,HIGH); v3=senV;}  // RIGHT
  while (senV>512 && senV<767);
  if (v3>v2) rota=rota+rueda4;
  do {senV=analogRead(dista); digitalWrite(G4,HIGH); v4=senV;}  // DOWN
  while (senV>768 && senV<1023);
  if (v3>v4) rota=rota+rueda4;

void OLED()
  display.setTextSize(1);                 // Size 1
  display.setTextColor(BLACK, WHITE);     // White background
  display.setCursor(0, 6);
  display.print(" LONG DISTANCE MEAS. ");
  display.drawLine(0,16,126,16,WHITE);    // LINE X,Y,WIDTH, Y FIN
  display.setCursor(2, 20);
  display.print("WHEEL RADIUS: ");
  display.print(radius);                  // Radius
  display.print(" m");
  display.setCursor(2, 32);
  display.print("CIRCUMFEREN.: ");
  display.print(circun);                 // Circumference
  display.print(" m");
  display.setTextSize(2);                // Size 2
  display.setCursor(6, 46);
  display.print(rota,1);                 // Distance
  display.print(" m");

void RUPTO() 
 state=!state; if (state==LOW) MEASv=LOW; else MEASv=HIGH; // Interruption


The attached zip file typically includes:

  1.  Electrical diagram.
  2. Program.
  3. “data” subcircuits folder.

This data folder contains the subcircuits (custom) created by the author. The presence of this folder is necessary for the execution of the project. 


A subcircuit It is a “custom” circuit that accumulates a set of Simulide base components to obtain a new or an adapted function. These subcircuits are treated by Simulide as another component of its own structure.
Subcircuits are very useful to create a component that does not exist in the simulide set, to compress a complete schematic in a single block and thus improve the complexity and compression of the final circuit where it is integrated or for any other function that you want to have available when making a schematic.

  DC-MOTOR and linear encoder.

The subcircuits must be properly incorporated in the “data” folder of simulide, in the “User Data” folder or in the “data” scheme folder that must be attached together with the schematic of the project itself. Attaching the subcircuits to the Simulide “data” folder is not advisable because they can be lost with updates to it. Attaching them in “User Data” is the correct thing to do. Attaching it to the “data” folder of the diagram is necessary when it is shared.
Creating and locating a subcircuit is simple once you know the procedure that is explained in detail in the simulide tutorials: https://simulide.com/p/subcircuits/
* Communication with the author: Simulide/User/Messages/Defran


Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *