Hello friends, I hope you all are doing great. Today, I am going to share the new JGB37-520 Encoder Gear Motor Library for Proteus V1.0. When a robot car gets heavier, climbs a ramp or carries a real payload, the small round gear motors run out of torque, and the next motor most makers pick is the JGB37-520: a 37 mm metal gearbox with an offset output shaft, a 520-size motor behind it and a Hall encoder on its back. It is the motor of rovers, tracked chassis, conveyors and every PID project that needs real torque.

Updates

JGB37-520 Encoder Gear Motor Library for Proteus

Latest version: V1.0 (October 2026, this tutorial)

Other motors: SG90 Servo · TT Gear Motor · 28BYJ-48 Stepper · NEMA 17 Stepper · MG996R Servo · N20 Encoder Motor · JGA25-370 Encoder Motor · FS90R 360 Servo · 130 DC Motor · A2212 Brushless · X27.168 Gauge · Analog Panel Meter · DC Tachogenerator · LM393 Speed Sensor · MG90S Servo · DS3218 Servo · L12 Linear Servo · RS-775 Motor · JGY-370 Worm Motor · 12V Linear Actuator · Coin Vibration Motor · Mini Submersible Water Pump · 12V Peristaltic Pump · 4-Pin PC Fan · 12V Push-Pull Solenoid · NEMA 23 Stepper Motor · Micro Linear Stepper · TYJ50 Synchronous Motor · Quartz Clock Movement · Air-Core Gauge · Electromechanical Counter · Split-Flap Display · Electric Bell · Wind Turbine · 8520 Coreless Motor · Car Wiper Motor · Car Door Lock Actuator · 12V Solenoid Water Valve · 12V Holding Electromagnet

Motor drivers: L298 · L9110S · TB6612FNG · BTS7960 · A4988 / DRV8825 · 28BYJ-48 + ULN2003 · PCA9685 Servo · Relay Module · 30A Brushless ESC · TB6600 Stepper Driver

Helping Tools

This library gives you the motor and its encoder as one part. The motor is analog and takes its real current from any driver; the encoder is digital and puts out its two square waves with every edge at the moment the shaft really reaches it. The demo runs on our Arduino UNO V4.0, drives the motor from 12 V through our separate L9110S library, and turns the shaft to the angle of a potentiometer with a PD loop - or holds a speed with a PI loop, with the encoder as its speed sensor.

NOTICE: an encoder motor in a simulator is only useful if its pulses come at the right moments and its current is what a driver really has to deliver. Our team put a lot of effort into building this motor, its gearbox and an encoder whose every edge is timed from the shaft's real motion. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the Motor Driver board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the JGB37-520 Encoder Gear Motor Library for Proteus V1.0:

Figure: The JGB37-520 Encoder Gear Motor Library for Proteus: the UNO, the L9110S on +12V and the JGB37-520 holding the angle of RV1, its C1 and C2 LEDs and the driver's power LED lit.

What is the JGB37-520 Encoder Gear Motor?

The name has two parts. JGB37 is the gearbox: a round metal gearbox 37 mm across, with M3 holes on its face for mounting and a 6 mm D-shaped output shaft that sits off the centre of the face - the quickest way to recognise it. 520 is the motor behind it: a brushed DC motor of the 520 size, bigger and stronger than the 370 of our JGA25-370 Encoder Gear Motor Library for Proteus. The family is large, with many gear ratios and windings for 6, 12 or 24 V, and the one in this library is the popular 12 V, 1:90 motor, about 110 RPM with no load.

The encoder version carries a magnet disc on the motor's rear shaft and a small board with two Hall sensors. The sensors give two square waves, C1 and C2, a quarter of a period apart - a quadrature encoder like the KY-040 knob of our Rotary Encoder Library for Proteus, but turned by the motor. The board has six wires: the motor's two, the encoder's supply and ground, and its two outputs.

The JGB37-520 encoder gear motor at a glance
JGB37-520 12 V 1:90 with a Hall encoder (the model)
Motor520-size brushed DC, 5 ohm winding, M+ and M-
Gearbox1:90 metal gears, 37 mm round, 6 mm D-shaft off the centre, M3 mounting holes
No loadabout 110 RPM and 0.15 A at 12 V, about 51 RPM at 6 V
Rated pointabout 85 RPM at 0.65 A
Stallabout 2.4 A and 12 kg.cm at 12 V
Encoder11 pulses per motor turn on C1 and on C2, 90 degrees apart, 3.3 - 5 V
Counts per output turn990 pulses per channel, 3960 counts with x4 decoding
WiresM+ red, M- white, VCC blue, GND black, C1 yellow, C2 green

From Pulses to Counts

The encoder watches the motor shaft, which turns 90 times for one turn of the output shaft. It gives 11 pulses per motor turn, so each channel gives 11 x 90 = 990 pulses per output turn. How many counts a sketch gets out of them depends on how many edges it counts:

Three ways to count the same encoder
DecodingWhat the sketch countsCounts per output turnOne count is
x1the rising edges of C19900.36 degrees
x2both edges of C119800.18 degrees
x4both edges of C1 and of C239600.09 degrees

The order of the edges gives the direction. While the shaft turns clockwise (M+ positive), C1 rises first: C1 leads. Counterclockwise, C2 leads. The demo counts every edge of both channels, x4, for 3960 counts per turn - less than a tenth of a degree per count. That much resolution comes from the high gear ratio: the encoder sits on the fast motor shaft, so every turn of the wheel brings ninety turns of the magnet disc.

What's New in JGB37-520 Encoder Gear Motor Library for Proteus V1.0

  • A real encoder: C1 and C2 are digital outputs with 3960 counts per output turn, C1 leading clockwise and C2 leading counterclockwise.
  • Every edge on time: the model works out when the shaft reaches each count and puts the edge there, between the analog steps of the simulation if need be - up to about 7,000 edges a second at full speed.
  • A 12 V motor with real current: the winding, the back-EMF, the gearbox's friction and losses, the inertia and the load, from any driver, PWM or DC, either way.
  • A dial that turns: the white dial on the offset D-shaft shows the simulated angle; the C1 / C2 LEDs show the channels.
  • Loads and stalls: a LOAD property, load buttons of 2, 4, 6 and 10 kg.cm on the pop-up and a 5 kg.cm hand on the wheel when you click the dial.
  • A pop-up window with four pages - Motor, Graphs, Event log and Check - and a live chart of C1 and C2.
  • It names the problems: a stall, an over-voltage above 14 V, a reversal at speed and an encoder without its supply.
  • A closed-loop demo on our Arduino UNO V4.0 with a 12 V driver: a PD position loop, a PI speed loop with anti-windup and open-loop PWM, with no library at all.

The JGB37-520 in Proteus

Figure: M1 in the running demo: 81 RPM clockwise on the strip, the dial on the offset shaft and both encoder LEDs lit for a moment.

Search JGB37 in Pick Devices; the device JGB37MOTORTEP is in TEPJGB37.LIB (category Electromechanical, DC Motors) and its model is TEPJGB37.DLL. It shows the motor from its shaft end at 1.5 times its real size: the round silver gearbox face with its M3 mounting holes, and the output shaft 6 mm to the right of the centre, carrying a white dial with a red pointer. The dial turns to the simulated angle while the simulation runs, and the strip under the plate gives the speed with its direction, the angle and the encoder count, next to the OPEN PANEL button.

The six wires come out at the left in their usual colours and end on the pins, with the two motor wires at the top and the four encoder wires below them. Two LEDs on the plate follow C1 (yellow) and C2 (green). The plate, the dial, the LEDs and the strip are TEP additions; the real motor has none of them.

The six pins of the JGB37-520
PinWireWhat the model does with it
M+redthe motor, analog: positive on M+ turns the shaft clockwise
M-whitethe motor's other terminal
VCCbluethe encoder's supply, read as logic: low or open and C1 / C2 float
GNDblackthe encoder's ground
C1yellowencoder channel 1, a digital output (leads while turning clockwise)
C2greenencoder channel 2, a digital output (leads while turning counterclockwise)

The only property is LOAD, a constant load on the shaft in kg.cm for the whole run. The motor stalls at about 12 kg.cm on a stiff 12 V supply, and at about 8 kg.cm through an L9110S, which loses some of the voltage in its switches. Click the dial while the simulation runs to put a hand on the wheel: 5 kg.cm more.

Download JGB37-520 Encoder Gear Motor Library for Proteus

Click the button below to download JGB37-520-Encoder-Gear-Motor-Library-for-Proteus-v1.0.zip (about 1.2 MB, without the source code of the models):

JGB37-520 Encoder Gear Motor Library for Proteus V1.0
  • README.txt: installation, the demo, the wiring, the encoder, real hardware, troubleshooting and the limits.
  • Proteus Library Files: TEPJGB37.LIB and ArduinoV4TEP.LIB from our Arduino Library for Proteus V4.0.
  • Proteus Model Files: TEPJGB37.DLL and TEPARDUINO.DLL.
  • Proteus Simulation: JGB37-520-Encoder-Motor-L9110S-ArduinoUnoV4.pdsprj, JGB37_Encoder_Demo.hex and copies of the two DLLs.
  • Arduino Code: JGB37_Encoder_Demo.ino (no library needed).

The driver is a separate library: this package holds only the motor and the UNO. The demo drives the motor through our L9110S motor driver, which has its own download - get it from our L9110S Motor Driver Library for Proteus and install it first, or the demo opens without its driver.

No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.

How to Install JGB37-520 Encoder Gear Motor Library for Proteus

  1. Close Proteus and extract the whole zip file, for example to your Desktop.
  2. Copy TEPJGB37.LIB and ArduinoV4TEP.LIB from Proteus Library Files into the LIBRARY folder of Proteus (usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy TEPJGB37.DLL and TEPARDUINO.DLL from Proteus Model Files into the MODELS folder. The two Arduino files are the ones of our Arduino Library V4.0; if you have it, they are the same.
  4. Install our L9110S Motor Driver library the same way from its own zip: TEPL9110S.LIB into LIBRARY and TEPL9110S.DLL into MODELS.
  5. Delete TEPJGB37.IDX from the LIBRARY folder if it is there.
  6. Start Proteus, press P and search for JGB37.

Tip: keep the Proteus Simulation folder together, because the project needs its .hex file and the DLLs beside it. The library is tested in Proteus 8.5; Proteus 7 is not supported.

The Demo Circuit

Figure: The demo project running: ARD1, DRV1 (the L9110S) with its VCC on +12V, M1 and RV1.

Open JGB37-520-Encoder-Motor-L9110S-ArduinoUnoV4.pdsprj. ARD1 is an Arduino UNO V4.0 from our Arduino UNO Library for Proteus V4.0, running JGB37_Encoder_Demo.hex with its serial monitor built in. DRV1 is the L9110S driver in its pop-up version. M1 is the JGB37-520 on the driver's MOTOR A. RV1 is a 10k potentiometer on A0: the target angle, 0 to 360 degrees. The sheet is A3, because the UNO, the driver and the motor with its six labelled wires do not fit an A4 sheet legibly.

This is a 12 V motor, so the driver's VCC sits on a +12V power terminal. The L9110S takes 2.5 to 12 V on VCC, and its inputs stay 5 V logic, so the UNO drives them directly. The encoder is different: it gets its supply from the UNO's 5V, because its outputs go straight into the UNO's pins.

The wiring (the same in Proteus and on a real board)
FromToNote
L9110S A-IAD5PWM, 980 Hz
L9110S A-IBD6PWM, 980 Hz
L9110S VCC+12Vthe motor supply, 2.5 - 12 V
L9110S GNDGNDcommon with the Arduino
JGB37-520 M+ / M-L9110S A-OA / A-OBMOTOR A
Encoder VCC / GND5V / GNDthe encoder's supply
Encoder C1 / C2D2 / D3the UNO's two interrupt pins
RV1 wiperA0the target angle

The Arduino Code

The demo needs no library. New to Arduino? Start with Arduino Tutorial for Beginners and Introduction to Arduino UNO. Three numbers describe the motor to the sketch: the pins, the counts per output turn and the no-load speed at 12 V, which the speed loop uses for its feed-forward:

const byte IA = 5, IB = 6, ENC_A = 2, ENC_B = 3, POT = A0;
const long CPR = 3960;                         // counts per output turn (x4)
const float RPM_MAX = 110;                     // no load at 12 V

Both encoder channels call one interrupt routine on every change. It builds a two-bit state from C1 and C2 and looks up +1, -1 or 0 from the old state and the new one, which decodes x4 and the direction in one step:

volatile byte lastAB = 0;
// x4 decoding: the previous and the new state of (C1, C2) -> -1, 0, +1 (C1 leading = +)
const int8_t STEP[16] = {0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0};
void encISR() {
  byte ab = (digitalRead(ENC_A) ? 1 : 0) | (digitalRead(ENC_B) ? 2 : 0);
  count += STEP[(lastAB << 2) | ab];
  lastAB = ab;
}
  attachInterrupt(digitalPinToInterrupt(ENC_A), encISR, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENC_B), encISR, CHANGE);

At full speed this routine runs about 7,000 times a second, once every 140 microseconds, which an UNO handles easily. The motor gets PWM on one input of the L9110S and LOW on the other, so the sign of the number is the direction:

void drive(int p) {                            // L9110S: PWM on one input, the other LOW
  pwmNow = constrain(p, -255, 255);
  if (pwmNow >= 0) { analogWrite(IB, 0); analogWrite(IA, pwmNow); }
  else { analogWrite(IA, 0); analogWrite(IB, -pwmNow); }
}

Every 5 ms the loop reads the count, takes the counts that went by since the last pass and turns them into a smoothed speed:

  if (now - loopAt < 5) return;                  // the control loop: every 5 ms
  loopAt = now;
  long c = readCount();
  long dc = c - lastCount; lastCount = c;
  rpmNow += (dc * 60000.0 / 5 / CPR - rpmNow) * 0.2;   // counts per 5 ms -> RPM, smoothed

The position loop is a PD loop. The P gain of 3.0 pushes in proportion to the error in counts; the D gain of 24.0 brakes in proportion to the counts that went by in the last 5 ms, so the heavy geared shaft is slowed before it reaches the target. We tuned the two numbers on a simulation of this motor: 90 degrees in about 0.3 s and 270 degrees in about 0.6 s, with about a third of a degree of overshoot. A dead band of 2 counts and a minimum drive of 40 finish the job:

  if (mode == KNOB || mode == POSITION) {        // PD: the error in counts, the speed in counts per 5 ms
    long e = target - c;
    int p = 0;
    if (labs(e) > 2) { p = (int)constrain(3.0 * e - 24.0 * dc, -255, 255); if (abs(p) < 40) p = p > 0 ? 40 : -40; }
    drive(p);

When the shaft is inside the dead band and no longer moving, the sketch reports the position once:

    if (!arrived && labs(e) <= 2 && dc == 0) {
      arrived = true;
      Serial.print(F("At ")); Serial.print(c); Serial.print(F(" counts = ")); Serial.print(toDeg(c), 1); Serial.println(F(" deg - holding"));
    }

The Speed Loop and Anti-Windup

The speed loop is a PI loop with a feed-forward. The feed-forward guesses the PWM from the target speed and RPM_MAX; the P part corrects the present error; the integral removes what is left, which is what keeps the speed when a load arrives:

  } else if (mode == SPEED) {                    // PI on the RPM, with a feed-forward
    float err = rpmTarget - rpmNow, ff = rpmTarget * 255.0 / RPM_MAX;
    float out = ff + 0.8 * err + iTerm;
    if ((out < 255 || err < 0) && (out > -255 || err > 0))   // anti-windup: no integrating into a full output
      iTerm = constrain(iTerm + 0.02 * err, -120, 120);
    drive((int)(ff + 0.8 * err + iTerm));
  }

The line with the anti-windup comment is there because the simulation showed us we needed it. Our first version added to the integral on every pass. Then we typed rpm -100 while the motor ran at 80 RPM clockwise: during the reversal the error was huge, the integral filled up to its limit, and when the motor reached 100 RPM the full integral kept the driver at full output. The shaft settled at 107 RPM, the most the L9110S could give, and stayed there for seconds. Now the integral stops growing while the output is already at its limit in the direction of the error, and the same command settles at 100.5 RPM. It is a classic PID lesson, and a good example of why a motor model with real inertia is worth having.

The open-loop side of motor speed control is in our older DC Motor Speed Control using Arduino tutorial. The HEX file is in the package; to change the sketch, open it in the Arduino IDE and export the compiled binary, as in How to get the HEX file from Arduino. It needs 10,110 bytes of flash (31 % of the UNO) and 323 bytes of RAM.

Running the Demo

Press Run. The UNO's serial monitor and the pop-ups of the motor and the L9110S open over the schematic; move them aside. RV1 starts at 40 %, so the first target is 1586 counts:

JGB37-520 Encoder Gear Motor demo - The Engineering Projects
L9110S A-IA D5, A-IB D6; encoder C1 D2, C2 D3 (x4: 3960 counts per turn). The shaft follows the pot on A0.
Commands: a 90 | s 3960 | rpm 80 | pwm 50 | stop | zero | knob | help
Pot 410 -> target 1586 counts = 144.2 deg

The shaft turns there and stops at 144.3 degrees, count 1587, inside the 2-count dead band. Click RV1's arrows and the dial follows. Type a command in the monitor and press Enter:

The commands of the demo sketch
TypeWhat it doesWhat the run showed
a 90go to 90 degrees and staya 270: 269.9 degrees, count 2969
s 39603960 counts from here: one turn (- = the other way)one turn and stop
rpm 80hold 80 RPM (up to 105) with the encoder as the speed sensor80.8 RPM CW at 9.0 V, 0.15 A
rpm -100the same counterclockwise100.5 RPM CCW at 11.1 V, C2 leading
pwm 100open loop, full drive106.8 RPM at 11.69 V, 0.15 A
stop / zeroboth inputs LOW / the count = 0 here
knobfollow the pot againback to 144.0 degrees
Figure: ARD1's monitor at the end of the run: the stall under full drive, the release, then knob and the hold at 144.0 degrees.

The end of the run, as the monitor printed it: full drive, a stall under a heavy load, the load lifted, the motor back at 107 RPM, and then knob:

Count 35504, 0 RPM, PWM 255
Count 35512, 0 RPM, PWM 255
Count 35520, 1 RPM, PWM 255
Count 38088, 104 RPM, PWM 255
Count 41602, 107 RPM, PWM 255
knob
Following the pot on A0
Pot 410 -> target 1586 counts = 144.2 deg
At 1584 counts = 144.0 deg - holding

Between "Count 41602" and the hold, the loop reversed a motor running at full speed, wound the shaft about 10 turns back and stopped on the pot's angle, two counts short of the target. A PD loop with a strong D gain does exactly this: it runs back as fast as it can, then brakes hard for the last part of the way. The Graphs page below shows the end of that trip.

The Pop-Up Window

At Run the motor opens TEP JGB37-520 Encoder Gear Motor, a window in the look of our TEP Serial Monitor Advance for Proteus. Its four tabs are Motor, Graphs, Event log and Check, with Settings and Help behind the gear and question mark icons. If you close it, OPEN PANEL on the strip brings it back.

Motor and the Encoder Chart

Figure: The speed loop at 81 RPM clockwise: 9.11 V across the motor, 0.17 A, 1340 Hz on C1, and C1 rising before C2 on the chart.

The banner gives the state, the speed and the drive in one line. The gauge runs from 150 RPM counterclockwise to 150 RPM clockwise, with the band from the rated 85 RPM to the no-load 110 RPM marked in orange, and shows the frequency on C1 under the needle: 81 RPM times 990 pulses per turn, divided by 60, is about 1340 Hz. The live values are the speed, the direction, the average voltage, the current, the drive, the power, the load and the encoder count in counts and turns.

The bottom of the page is the encoder chart: C1 and C2 over the last 5 ms as logic traces, and the drive across M+ / M- under them. At 81 RPM you see almost seven periods of C1 in the 5 ms, and every rising edge of C1 comes a quarter period before the rising edge of C2. That is how the sketch knows it is turning clockwise.

Figure: Counterclockwise at 100 RPM: the banner turns orange, -11.02 V across the motor, 1649 Hz on C1 and C2 leading.

Turn it the other way with rpm -100 and the chart shows the opposite order: C2 leads C1, the voltage is negative and the count runs down. In both pictures the Drive tile reads STEADY - the reason is the driver, as explained below.

Loads on the Shaft

Figure: Full drive with 4 kg.cm on the shaft: 56 RPM, 10.20 V, and 0.90 A, red because it is above what an L9110S gives.

The toolbar of the Motor page puts 2, 4, 6 or 10 kg.cm on the shaft, and the Hand button adds a hand on the wheel. With pwm 100 and 4 kg.cm, a little above the motor's rated load, the speed drops from 107 to 56 RPM and the current rises from 0.15 to 0.90 A. The voltage drops too, from 11.69 to 10.20 V, because the L9110S's switches lose more voltage at the higher current. The Current tile turns red: 0.90 A is more than the 0.8 A an L9110S can give continuously.

Graphs

Figure: Graphs over the last 3 s after knob: the shaft running back at full speed, the braking current, and the stop on the angle.

Graphs draws the speed, the current and the average voltage over the last 1, 3 or 6 seconds as 50 ms averages, with Live and Freeze. Here it shows the end of the knob trip: the speed at full counterclockwise, then the D gain reversing the voltage to brake, with its current peak, and the speed settling at zero as the shaft lands on the pot's angle. Keep this page open while you tune the gains.

Event Log

Figure: The Event log, newest first: steady speeds, direction changes, the loads, the stall and every reversal at speed.

The Event log is the motor's diary: "steady 56 RPM CW (919 Hz on C1) at 10.20 V average, 0.90 A", every direction change, every stop, the loads and the warnings. Look at how often it warns about reversals in this run. Every time a loop sends a fast motor back, the log says something like "reversed at 103 RPM: 3.23 A peak - stop (or brake) first, the driver sees about twice the stall current". Filters show only the drive and speed or only the warnings, and Pause and Clear do what they say.

Stalls, Reversals and the Right Driver

Figure: STALLED: 10 kg.cm plus the 5 kg.cm hand is 15 kg.cm on the shaft - 0 RPM, 1.71 A and 14.68 W of heat.

Type pwm 100, choose 10 kg.cm on the toolbar and click the dial. The 15 kg.cm on the shaft is more than the motor gives, and it stops: "STALLED - 1.71 A at 0 RPM: the load is too much". All the power now turns into heat. Notice the voltage: the L9110S drops about 3.4 V in its switches at 1.71 A, so the motor sees 8.58 V instead of 12 and stalls at a lower current than the 2.4 A it would draw on a stiff supply.

Figure: The Check page during the stall: the current, the speed and the load in red, the peaks in amber, the encoder in green.

The Check page puts it in rows with a verdict each. The current row compares 1.71 A, and the 3.13 A peak of the run so far, with what the common drivers give: an L9110S 0.8 A, an L293D 0.6 A, an L298N 2 A. The speed row says 0 RPM, 2 Hz on C1. The load row says the JGB37-520 stalls at 12 kg.cm on 12 V, less through a weak driver. And the encoder row, still green, has the numbers of the whole run: "count 35488 = 8.96 turns, 75742 edges so far".

Figure: The L9110S's own pop-up after the run: VCC 12.00 V, both channels braked, and the peak of about 3.2 A on motor A in red.

The driver saw it too. Its own pop-up shows VCC at 12.00 V and a peak current of about 3.2 A in red: the reversal at 103 RPM. That is far above the L9110S's rating of 0.8 A continuous and 1.5 A peak. The lesson is the real one: an L9110S is fine for the rated load and for this demo, but a JGB37-520 that pushes, climbs or stalls draws up to 2.4 A, and a reversal at full speed on a stiff supply peaks near 4.6 A. For that, use a BTS7960 from our BTS7960 Motor Driver Library for Proteus, or an L298N for loads up to about 2 A. The JGB37-520 works with any of them.

How the Model Works

The motor is solved by Proteus's analog engine: its speed is an internal node computed together with the driver from the winding resistance, the back-EMF, the gearbox's friction and losses, the inertia and the load, in analog steps of 2 ms or less. The angle is the speed added up over time. The encoder is digital: after each analog step the model knows the angle and the speed, works out when the shaft will reach the next count and puts the edge on C1 or C2 at exactly that time. So the edges are evenly spaced at a steady speed and bunch up or spread out while the motor speeds up or slows down.

The demo runs at about 0.25 x real time on a desktop PC: 38 seconds of simulation took under 3 minutes, with up to 7,000 encoder edges a second at 107 RPM. We checked the model on a PC with 26 automatic tests: 110 RPM and 0.15 A at 12 V, 90 % of the speed in 0.23 s, 51 RPM at 6 V, the speed following 25, 50 and 75 % PWM at 22, 51 and 80 RPM, a reversal at 12 V peaking at 4.6 A, 14 kg.cm stalling at 2.39 A, 3 kg.cm still turning at 82 RPM and 0.71 A, and 3960 counts per turn in the right order both ways.

Why the Motor Says STEADY

Our L9110S model does not switch the motor on and off a thousand times a second; in each analog step it hands the motor the average of its PWM. The speed is exactly what the PWM gives, and the simulation runs much faster. So the motor's Drive tile reads STEADY - "DC, or a driver that averages its PWM". The UNO's 980 Hz PWM is on the L9110S's own pop-up. With a driver that really switches, the motor's pop-up shows the PWM frequency and duty.

Troubleshooting

  • The shaft never turns and the pop-up says NO DRIVE: the driver's inputs (both LOW = stop), its VCC, or the motor wires on the wrong outputs.
  • No driver in the project: install our L9110S library (TEPL9110S.LIB / TEPL9110S.DLL) - it is not in this package.
  • Slow, about half speed: the driver's VCC is on 5 V, not 12 V.
  • The count stays at 0 while it turns: the encoder's VCC or GND, or C1 / C2 on pins the sketch does not read; the Check page says "no supply" when VCC is not HIGH.
  • The count runs backwards: swap C1 and C2, or M+ and M-.
  • It oscillates around the target: lower the P gain or raise the D gain in the sketch (3.0 and 24.0 in the demo).
  • The speed overshoots and sticks at full drive: the integral of the speed loop has wound up; keep the anti-windup line of the demo in your own PI loop.
  • STALLED: less load, or more drive.
  • No dial, no UNO or no monitor: TEPJGB37.DLL or TEPARDUINO.DLL is missing from MODELS and the project folder; a closed monitor opens again with a click on the UNO's USB port.

Things to Know Before Using a Real JGB37-520

  • The driver: a JGB37-520 stalls at about 2.4 A at 12 V and a reversal at full speed peaks near 4.6 A. The L9110S (0.8 A, 1.5 A peak) suits the rated load of about 0.65 A; a robot that pushes or stalls wants a BTS7960.
  • The supply: 12 V from a supply or a 3S Li-ion pack (11.1 - 12.6 V), with GND common to the Arduino.
  • The encoder: 3.3 - 5 V on its VCC. Many boards need no pull-ups; some do, 10k from C1 and C2 to VCC.
  • Direction: swap M+ and M- and both the direction and the sign of the count change; swap C1 and C2 in the sketch or on the wires if the count runs the wrong way.
  • Mounting: the output shaft is off the centre of the gearbox, so a bracket for the JGB37 is not the same as one for a motor with a centred shaft; buy or print one made for it.
  • Know your motor: JGB37-520s come with many gear ratios and 6, 12 or 24 V windings. This one is the 12 V 1:90 with an 11-pulse encoder, 3960 counts per turn; for another, change CPR and RPM_MAX in the sketch.

Limitations of the Simulation

  • Not modelled: the winding inductance, the gear backlash (a real encoder on the motor shaft counts the backlash too), the encoder's duty and phase errors, heating, and the differences between real motors.
  • The motor is the 12 V 1:90 JGB37-520 with an 11-pulse Hall encoder; other ratios and windings are not selectable.
  • The plate, the dial, the LEDs, the strip and the hand are TEP additions.
  • The model is our own, written from the typical data of the 12 V 1:90 JGB37-520 gear motor with a Hall encoder; this library is not made or endorsed by Arduino or Labcenter.
  • Licences: the demo needs no Arduino library; the HEX file contains the Arduino AVR core 1.8.6 with LGPL-licensed code, and the sketch is included. The potentiometer is Proteus's own POT-HG. The L9110S driver is our separate library.
  • Tested in Proteus 8.5 in October 2026 with the demo as shipped: the knob, the angles, the speed loop both ways, open loop, the loads, the stall, the reversals and the pop-ups. Proteus 7 is not supported.

So, that was all about the JGB37-520 Encoder Gear Motor Library for Proteus V1.0. I hope it helps you tune your position and speed loops, and pick the right driver, before your rover's first wheel turns on the bench. If you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!