
JGA25-370 Encoder Gear Motor Library for Proteus V1.0 (12V, Hall)

Hello friends, I hope you all are doing great. Today, I am going to share the new JGA25-370 Encoder Gear Motor Library for Proteus V1.0. If the N20 is the motor of small robots, the JGA25-370 is the motor of the next size up: robot cars that carry a battery pack, two-wheel balancing robots, small conveyors and camera sliders. A 370-size motor behind a round 25 mm metal gearbox, 12 V, and on its back a Hall encoder that tells your Arduino exactly how far and how fast the shaft has turned.
JGA25-370 Encoder Gear Motor Library for Proteus
Latest version: V1.0 (October 2026, this tutorial)
Helping Tools
- Serial Monitor Advance: a serial terminal window for the UART of your board
- Serial Monitor Expert: the serial monitor with extra debugging tools
- LCD Library for Proteus V3.0: 16x2, 20x4 and I2C LCDs to show your readings
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. So we built the motor and its gearbox, and worked out the time of every encoder edge from the shaft's real motion. It took our team a lot of hard work. 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 JGA25-370 Encoder Gear Motor Library for Proteus V1.0:
What is the JGA25-370 Encoder Gear Motor?
The name tells you what it is. JGA25 is the gearbox: a round metal gearbox 25 mm across, with two M3 holes 17 mm apart on its face for mounting and a D-shaped output shaft. 370 is the motor behind it: a brushed DC motor of the common 370 size. The family is huge - gear ratios from 1:4.4 to 1:499, windings for 6, 12 or 24 V - and the one in this library is the popular 12 V, 1:34 motor, about 170 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.
| JGA25-370 12 V 1:34 with a Hall encoder (the model) | |
|---|---|
| Motor | 370-size brushed DC, 7.5 ohm winding, M+ and M- |
| Gearbox | 1:34 metal gears, 25 mm round, D-shaft, two M3 holes 17 mm apart |
| No load | about 170 RPM and 0.12 A at 12 V, about 80 RPM at 6 V |
| Stall | about 1.6 A and 6 kg.cm at 12 V |
| Encoder | 11 pulses per motor turn on C1 and on C2, 90 degrees apart, 3.3 - 5 V |
| Counts per output turn | 374 pulses per channel, 1496 counts with x4 decoding |
| Wires | M+ red, M- white, VCC blue, GND black, C1 yellow, C2 green |
From Pulses to Counts
The encoder watches the motor shaft, which turns 34 times for one turn of the output shaft. It gives 11 pulses per motor turn, so each channel gives 11 x 34 = 374 pulses per output turn. How many counts a sketch gets out of them depends on how many edges it counts:
| Decoding | What the sketch counts | Counts per output turn | One count is |
|---|---|---|---|
| x1 | the rising edges of C1 | 374 | 0.96 degrees |
| x2 | both edges of C1 | 748 | 0.48 degrees |
| x4 | both edges of C1 and of C2 | 1496 | 0.24 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 1496 counts per turn - a quarter of a degree per count, plenty for a robot wheel or a camera slider.
What's New in JGA25-370 Encoder Gear Motor Library for Proteus V1.0
- A real encoder: C1 and C2 are digital outputs with 1496 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.
- 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 D-shaft shows the simulated angle; the C1 / C2 LEDs show the channels.
- Loads and stalls: a LOAD property, load buttons from 1 to 5 kg.cm on the pop-up and a 1.5 kg.cm finger 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 and open-loop PWM, with no library at all.
The JGA25-370 in Proteus
Search JGA25 in Pick Devices; the device JGA25MOTORTEP is in TEPJGA25.LIB (category Electromechanical, DC Motors) and its model is TEPJGA25.DLL. It shows the motor from its shaft end at 2.2 times its real size: the round silver gearbox face, the two M3 mounting holes, the bearing boss and a white dial with a red pointer on the D-shaft. 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.
| Pin | Wire | What the model does with it |
|---|---|---|
| M+ | red | the motor, analog: positive on M+ turns the shaft clockwise |
| M- | white | the motor's other terminal |
| VCC | blue | the encoder's supply, read as logic: low or open and C1 / C2 float |
| GND | black | the encoder's ground |
| C1 | yellow | encoder channel 1, a digital output (leads while turning clockwise) |
| C2 | green | encoder 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 6 kg.cm on a stiff 12 V supply, and at about 5 kg.cm through an L9110S, which loses some of the voltage in its switches. Click the dial while the simulation runs to press a finger on it: 1.5 kg.cm more.
Download JGA25-370 Encoder Gear Motor Library for Proteus
The download link of JGA25-370-Encoder-Gear-Motor-Library-for-Proteus-v1.0.zip (without the source code) will be added here soon. The zip file will contain:
- README.txt: installation, the demo, the wiring, the encoder, real hardware, troubleshooting and the limits.
- Proteus Library Files:
TEPJGA25.LIBandArduinoV4TEP.LIBfrom our Arduino Library for Proteus V4.0. - Proteus Model Files:
TEPJGA25.DLLandTEPARDUINO.DLL. - Proteus Simulation:
JGA25-370-Encoder-Motor-L9110S-ArduinoUnoV4.pdsprj,JGA25_Encoder_Demo.hexand copies of the two DLLs. - Arduino Code:
JGA25_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 JGA25-370 Encoder Gear Motor Library for Proteus
- Close Proteus and extract the whole zip file, for example to your Desktop.
- Copy
TEPJGA25.LIBandArduinoV4TEP.LIBfrom Proteus Library Files into the LIBRARY folder of Proteus (usuallyC:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY). - Copy
TEPJGA25.DLLandTEPARDUINO.DLLfrom 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. - Install our L9110S Motor Driver library the same way from its own zip:
TEPL9110S.LIBinto LIBRARY andTEPL9110S.DLLinto MODELS. - Delete
TEPJGA25.IDXfrom the LIBRARY folder if it is there. - Start Proteus, press P and search for JGA25.
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
Open JGA25-370-Encoder-Motor-L9110S-ArduinoUnoV4.pdsprj. ARD1 is an Arduino UNO V4.0 from our Arduino UNO Library for Proteus V4.0, running JGA25_Encoder_Demo.hex with its serial monitor built in. DRV1 is the L9110S driver in its pop-up version. M1 is the JGA25-370 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.
| From | To | Note |
|---|---|---|
| L9110S A-IA | D5 | PWM, 980 Hz |
| L9110S A-IB | D6 | PWM, 980 Hz |
| L9110S VCC | +12V | the motor supply, 2.5 - 12 V |
| L9110S GND | GND | common with the Arduino |
| JGA25-370 M+ / M- | L9110S A-OA / A-OB | MOTOR A |
| Encoder VCC / GND | 5V / GND | the encoder's supply |
| Encoder C1 / C2 | D2 / D3 | the UNO's two interrupt pins |
| RV1 wiper | A0 | the 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 = 1496; // counts per output turn (x4)
const float RPM_MAX = 170; // 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 long count = 0;
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);
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 4.0 pushes in proportion to the error in counts; the D gain of 25.0 brakes in proportion to the counts that went by in the last 5 ms, so a heavy, fast shaft is slowed before it reaches the target. We tuned the two numbers on a simulation of this motor so the shaft stops without overshooting. 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(4.0 * e - 25.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 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;
iTerm = constrain(iTerm + 0.02 * err, -120, 120);
drive((int)(rpmTarget * 255.0 / RPM_MAX + 0.8 * err + iTerm));
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,006 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 599 counts:
JGA25-370 Encoder Gear Motor demo - The Engineering Projects
L9110S A-IA D5, A-IB D6; encoder C1 D2, C2 D3 (x4: 1496 counts per turn). The shaft follows the pot on A0.
Commands: a 90 | s 1496 | rpm 120 | pwm 50 | stop | zero | knob | help
Pot 410 -> target 599 counts = 144.1 deg
The shaft turns there and stops at 143.9 degrees, count 597, inside the 2-count dead band. Click RV1's arrows and the dial follows. The monitor takes the same commands as the N20 demo, with this motor's numbers:
| Type | What it does | What the run showed |
|---|---|---|
| a 90 | go to 90 degrees and stay | a 270: 269.6 degrees, count 1120 |
| s 1496 | 1496 counts from here: one turn (- = the other way) | one turn and stop |
| rpm 120 | hold 120 RPM (up to 165) with the encoder as the speed sensor | 119.5 RPM CW at 8.7 V, 0.12 A |
| rpm -150 | the same counterclockwise | 150.8 RPM CCW at 10.8 V, C2 leading |
| pwm 100 | open loop, full drive | 165.9 RPM at 11.76 V, 0.12 A |
| stop / zero | both inputs LOW / the count = 0 here | |
| knob | follow the pot again | back to 144.6 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 166 RPM, and then knob:
Count 5858, 2 RPM, PWM 255
Count 5862, 0 RPM, PWM 255
Count 5866, 0 RPM, PWM 255
Count 6165, 132 RPM, PWM 255
Count 8203, 168 RPM, PWM 255
Count 10278, 166 RPM, PWM 255
knob
Following the pot on A0
Pot 410 -> target 599 counts = 144.1 deg
At 601 counts = 144.6 deg - holding
Between "Count 10278" and the hold, the loop reversed a motor running at full speed, wound the shaft 6.5 turns back and stopped on the pot's angle, two counts past 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 Pop-Up Window
At Run the motor opens TEP JGA25-370 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
The banner gives the state, the speed and the drive in one line. The gauge runs from 200 RPM counterclockwise to 200 RPM clockwise with the 150 - 180 RPM rated band marked in orange, and shows the frequency on C1 under the needle: 121 RPM times 374 pulses per turn, divided by 60, is about 757 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 toolbar puts 1, 2, 3 or 5 kg.cm on the shaft, or the finger.
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 121 RPM you see about four 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.
Turn it the other way with rpm -150 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.
Event Log
The Event log is the motor's diary: "steady 166 RPM CW (1034 Hz on C1) at 11.76 V average, 0.12 A", every direction change, every stop, the loads and the warnings. Look at how often it warns about reversals in this run. Every time the PD loop sends a fast motor back, the log says something like "reversed at 150 RPM: 2.30 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.
Graphs, the fourth page, 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 - the page to keep open while you tune the gains.
Stalls, Reversals and the Right Driver
Type pwm 100, choose 5 kg.cm on the toolbar and click the dial. The 6.5 kg.cm on the shaft is more than the motor gives, and it stops: "STALLED - 1.26 A at 0 RPM: the load is too much". All the power now turns into heat. Notice the voltage: the L9110S drops about 2.5 V in its switches at 1.26 A, so the motor sees 9.48 V instead of 12 and stalls at a lower current than it would on a stiff supply.
The Check page puts it in rows with a verdict each. The current row compares 1.26 A, and the 2.23 A peak of the run, 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, 1 Hz on C1. The load row says the motor stalls at about 6 kg.cm. And the encoder row, still green, has the numbers of the whole run: "count 5852 = 3.91 turns, 30138 edges so far".
The driver saw it too. Its own pop-up shows VCC at 12.00 V and a peak current of 2.296 A in red: the reversal at 150 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 light loads, but a JGA25-370 that pushes, climbs or stalls wants a bigger driver - a TB6612FNG (1.2 A, 3.2 A peak) from our TB6612FNG Motor Driver Library for Proteus, an L298N (2 A) or a BTS7960 from our BTS7960 Motor Driver Library for Proteus. The JGA25-370 works with all 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: 30 seconds of simulation took about 2 minutes, with up to 4,100 encoder edges a second at 166 RPM. We checked the model on a PC with 26 automatic tests: 170 RPM and 0.12 A at 12 V, 90 % of the speed in 0.12 s, 78 RPM at 6 V, the speed following 25, 50 and 75 % PWM at 32, 77 and 123 RPM, a reversal at 12 V peaking at 3.0 A, 8 kg.cm stalling at 1.60 A, 3 kg.cm still turning at 86 RPM and 0.85 A, and 1496 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 (4.0 and 25.0 in the demo).
- STALLED: less load, or more drive.
- No dial, no UNO or no monitor:
TEPJGA25.DLLorTEPARDUINO.DLLis 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 JGA25-370
- The driver: a JGA25-370 stalls at about 1.6 A at 12 V and a reversal at full speed peaks near 3 A. The L9110S (0.8 A, 1.5 A peak) is for light loads; a robot wants a TB6612FNG, an L298N or 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.
- Know your motor: JGA25-370s come with gearboxes from 1:4.4 to 1:499 and 6, 12 or 24 V windings. This one is the 12 V 1:34 with an 11-pulse encoder, 1496 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:34 JGA25-370 with an 11-pulse Hall encoder; other ratios and windings are not selectable.
- The plate, the dial, the LEDs, the strip and the finger are TEP additions.
- The model is our own, written from the typical data of the 12 V 1:34 JGA25-370 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 stall, the reversals and the pop-ups. Proteus 7 is not supported.
So, that was all about the JGA25-370 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 robot'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!
























Comments
0