WEMOS Motor Shield firmware for steppers (I2C)

Use your Wemos motor shield with steppers motors I2C custom slave interface

Similar projects worth following
A new application for cheap WEMOS Shield Motor DC driver From full step to 32 microsteps voltage sinoidal microstepping.Editable microstep table ,Many steppers as I2C addresses free in your app.Commands speed, target and resolution.Arduino skecth example, working on ESP82266 and AVR micros..Beta but functional .Includes windows example for FT260 i2c Dongle.Source code and Firmware availalble on Github.

I2C code  based on interrupts , no polling code.

I2C Clock Speed 100Khz

Address 0x32 (editable at HEX file)  


MOTOR_GET_COUNT 0x02: Send 0x02, Read int32 (4 bytes)

MOTOR_SET_COUNT 0x03: Send 0x03 int32 (5bytes)

MOTOR_SET_TARGET 0x04: Send 0x04+ int32 (total 5bytes)

MOTOR_GET_TARGET 0x05; Send 0x05, Read int32 (4 bytes)

MOTOR_SET_TICKS 0x06: Send 0x06+ int32 (total 5bytes)

MOTOR_SET_DIR_RES 0x07: Send 0x07+ int32 (total 5bytes)

 MOTOR_SET_PRESCALER 0x08:Send 0x08+ int32 (total 5bytes)

MOTOR_SET_WAVE_SCALE 0x09:Send 0x09+ int32 (total 5bytes)

MOTOR_SET_SPEED:0x0A:Send 0x0A+float (total 5bytes)
MOTOR_SET_TARGET_SPEED 0x0B:Send 0x0B+float (total 5bytes)

Values for set speed microsteps/s signed  4 bytes float

SET_SPEED set speed with no acceleration SET_TARGET_SPEED accelerate from current set speed.

Speed timer frecuency 48khz tick 20,8us At this moment only min value -65535 to +65535 speed 65535-> 1,3s per microstep positive direction speed 30000->0,65s per microstep positive direction speed -15000->0,3125s per microstep negative direction

Resolution 1-> 32 msteps 2->16 4->8 8->4 counter is always 32 microsteps resolution

Arduino test code (works on AVR and esp8266)

#include <Wire.h>
#define SLAVE_ADDRESS_1 0x32
//Set Commands
#define MYSLAVE_SET_REG 0x01
//GET commands
#define MOTOR_GET_COUNT 0x02
#define MOTOR_SET_COUNT 0x03
#define MOTOR_SET_TARGET 0x04
#define MOTOR_GET_TARGET 0x05
#define MOTOR_SET_TICKS 0x06
#define MOTOR_SET_DIR_RES 0x7
void setup() {
 Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output


int32_t read_wms( uint8_t command, int address)
{ int32_t pos;
  char *pointer;
  char c;

   Wire.requestFrom(address, 4); 
    while (Wire.available()) { 
    char c =;
    return pos;

void write_wms( uint8_t command, int address,int32_t value)
  char *pointer;
  Wire.write( command);

void loop() {

 //goto from 0 to 1000 
 int32_t pos=0;//set motor counter to 0
 int32_t target= 1000;//set desired position 1000
 int32_t speed=3000;//20,8 us * 300 =0.624s  ->16,02 microsteps/s 
 write_wms(MOTOR_SET_COUNT,SLAVE_ADDRESS_1,pos);//send counter
 write_wms(MOTOR_SET_TARGET,SLAVE_ADDRESS_1,target);//target set
 write_wms(MOTOR_SET_TICKS,SLAVE_ADDRESS_1,speed);//command speed
 while ( (pos=read_wms( MOTOR_GET_COUNT ,SLAVE_ADDRESS_1))!=target)
  delay (100);

//motor will turn an stop until reach 1000 counter value

//now we command back 0 pos
  target= 0;//set desired position 1000
 speed=-3000;//20,8 us * 300 =0.624s  ->-16,02 microsteps/s 
 int32_t resolution=2; //motor will no run on 16 msteps 
 write_wms(MOTOR_SET_TARGET,SLAVE_ADDRESS_1,target);//target set
 write_wms(MOTOR_SET_TICKS,SLAVE_ADDRESS_1,speed);//command speed
 while ( (pos=read_wms( MOTOR_GET_COUNT ,SLAVE_ADDRESS_1))!=target)
  delay (100);



Updated firmware

hex - 17.66 kB - 01/18/2019 at 21:21



Arduino skecth for testing shield

ino - 2.02 kB - 12/28/2018 at 12:49


  • Set speed command as Float number

    Angelote01/14/2019 at 19:43 0 comments

    Set speed  as usteps/s command  as float 4 bytes (24,8)format added

    #define MOTOR_GET_COUNT 0x02
    #define MOTOR_SET_COUNT 0x03
    #define MOTOR_SET_TARGET 0x04
    #define MOTOR_GET_TARGET 0x05
    #define MOTOR_SET_TICKS 0x06
    #define MOTOR_SET_DIR_RES 0x07
    #define MOTOR_SET_PRESCALER 0x08
    #define MOTOR_SET_WAVE_SCALE 0x09

    Update Delphi  client for FT260 I2C DONGLE

  • Now tested with WEMOS D1

    Angelote12/28/2018 at 12:53 0 comments

    I have uploaded a arduino Skecth and its works fine with WEMOS D1.

  • Basic and Optional Components

    Angelote12/26/2018 at 16:25 0 comments

    Wemos Motor Shield

    STLink v2 clone (for developing) firmware can be upload by using any usbserial dongle.

    FT260 (to talk I2c from your PC )

    ch340 usb-serial ttl dongle

View all 3 project logs

View all instructions

Enjoy this project?



Seventh Dwarf wrote 02/22/2021 at 10:33 point


let me first thank you for the great work. I think it's the correct idea to move the stepping motor control into the local MCU on the shield, instead of trying to mimic this on the main MCU.
However, the changing from integer to float for the speed doesn't seem to work correctly. Independently what I set for the speed, the actual position, as readback value from the MOTOR_GET_COUNT, goes around zero, like already mentioned by julienhogert.
Following initial settings:
pos = 0
target = 1000
speed = 100.0f

pos goes like 0,0,0,0,0,2,4,5,4,4,4,5,5,5,4 and so on.
Other speed settings give similar results. Changing the endianess of the transmitted float doesn't help.

What is the range of speed? Is it -1.0 to +1.0 or is it -65536.0 to +65536.0 or any other?
Is the float format of the Arduino and the STM32 lib identical?
Thanks for your kind support
best regards

  Are you sure? yes | no

Daniel Herrera wrote 10/11/2020 at 01:02 point

Hi. Do you think this firmware can be ported to the v2.0 board version? So far, it seems I will have to obtain v1.0 board in order to work with stepper motors. Cheers.

  Are you sure? yes | no

fred wrote 06/07/2020 at 14:11 point

Hi, i uploaded the new firmware and now i can get the i2c address, is is 0x30. Uploading the .ino and looking in the terminalwindow i see -1,-1,-1 etc etc.

can someone tell me what i did wrong



  Are you sure? yes | no

julienhogert wrote 03/20/2020 at 18:02 point

Hello Angelote, I tried today your new version of the firmware, but didn't find a way to make it works. I started over with your example, trying to integrate the new "ideas". I put inside the code the questions I Had, Could you please, take a look, and maybe send it me back on GitHub? Here is the code:

Thanks ! Julien

  Are you sure? yes | no

Angelote wrote 03/20/2020 at 18:32 point

I have test latest  code  with the FT260  I2C pc Interface  only.(and  it works fine)

I gonna  make changes on WEMOS Skecth demo to show how to use thew new features, stay tune.

  Are you sure? yes | no

julienhogert wrote 03/23/2020 at 21:12 point

Hello Angelote ! I tried again today to make it works ! but without success, If you have a little time to make an update of your code, it would be great ! Thanks, Julien

  Are you sure? yes | no

Angelote wrote 03/15/2020 at 21:51 point

Sure .I dont remember´just  now If  I uploaded the latest firmware to github  i will check and inform you.

  Are you sure? yes | no

julienhogert wrote 03/15/2020 at 21:10 point

Hello Angelote ! I came back to steppers and I'd like to use the lasts improvements of your code. With the new timer, and the setSpeed... Is there any possibility to upload it? Thanks again for the very good work you did ! Julien

  Are you sure? yes | no

Angelote wrote 03/16/2020 at 19:15 point

I have checked and uploaded firmware with 0x32 and 0x34 adresses at github project repository and update description of new commands at description,Speed ca be set in microsteps/s using 32bit signed float for instant o accelerated settting

  Are you sure? yes | no

Angelote wrote 03/16/2020 at 19:26 point

I forgot you can scale source voltage amplitude with WAVE_SCALE command.Its integer value indicates percentage o full wavE MAGNITUDE values from 0 to 100 by default 50%

  Are you sure? yes | no

julienhogert wrote 03/16/2020 at 21:10 point

Thanks a lot ! That's a very god job. I'll try it these days and give you a feedback if you want ! Thank again ! Julien

  Are you sure? yes | no

Angelote wrote 03/17/2020 at 16:35 point

I just have uploaded corrected firmware,because speed was not set to zero on boot.

  Are you sure? yes | no

Cohbra11 wrote 04/21/2019 at 01:11 point

Thank you everyone for your work on this!  I have what I assume is a simple question, but I cannot figure out how to make use of the standby function using I2C.  I don't see any mention of it in the example, and I would like to have the ability to turn off all power to the motor when it is not needed.


  Are you sure? yes | no

julienhogert wrote 02/01/2019 at 20:59 point

Hey, I still continue working with your "hack". It's really fantastic.
So I still put flesh on the library I began for Wemos_stepper. you can find here :

It's a work in progress, so, there are some function which may not work well, but, just to take a look.

One thing I found very counter-intuitive in your proposal, is the speed. Why didn't you put it in step/s ? So to make the conversion, I make this ugly thing: 

speed_i2c=float( float(STEPS_PER_REV/float(speed)) / float(FREQUENCY_MS*BASE_MS*STEPS_PER_REV) );

but didn't find a way to simplify it. Also, in you system, the maximum of Speed is quite low, something like 700/800 steps/s (when speed_i2c is egal to 1 ), no?

Also, when I change the Microstep, I term of speed, nothing change. I don't go quicker when I'm in fullstep than in quarter... so, how can I go faster? changing the tick?

Last little thing that should be good: When you change the target. the sign of speed should be changed automatically. I did it on the library, but is it difficult to put it in the MC of the stepper? I tried to look a little bit of your code, but still too complicated for me.

Well, again, thanks a lot for you're job. and if you're interested about the Arduino programmation, take a look at the library I did, based on your work and maybe we can talk about this also, because in a way, it's the missing part of the big part you ever did.

Thanks, Julien

  Are you sure? yes | no

Angelote wrote 02/01/2019 at 21:13 point

Thank you Julen , I have made some  modifications including setting current speed and  target in steps/s  using  signed 32bit float  and acceleration/deceleration ramp .

void set_speed(float speed)


if (ticks_x>0xFFFF)
if (dir==0) ticks_x=0xFFFE;
TIM16_ARR = ticks_x;


Now im using TIMER16 which  has a built  repetition register so  I have reduced prescaler value from 1000 to 27  to reach higher speed ratios.

I will upload last  version with fully tested.

  Are you sure? yes | no

julienhogert wrote 02/01/2019 at 21:22 point

So nice ! When it will be available, make me a sign ! About Acceleration/deceleration, I also made a library to manage sequences of movements with all the easing functions, recycling this library : If you want to take a look, tell me and I'll upload my code. Last thing I was working on, is the possibility of an autospeed mode, to follow a sequences of targets at regular interval, typically to follow a complex movement...

  Are you sure? yes | no

Angelote wrote 01/10/2019 at 21:14 point

I´m  migrating the development enviroment from Code:Blocks to  EMBitz IDE  which bundles  its own GCC-ARM  compiler version.I will include a stripped version of opencm3 with is opensource and more easy for developing than  ST device library.

  Are you sure? yes | no

Angelote wrote 01/10/2019 at 21:07 point


You may remove delay statements,I had got  some command overlap issues before, but now All seems i OK.My sofware is all interrupt driven  and  should not block.

Target is the  place to stop, consider, there is not a "Goto" command implemented onto  the microcontroller still.Then you have to command " the rigth direction".

I  still have to write  speed up and down timer interrups acceleration routines but it´s a piece of cake.

Resolution is the number of microsteps  you take each timer overflow .Using the 32msteps as base its posible to switch stepper resolution   "on the fly" keeping a coherent value for the step counter.

Yes there is  fixed 10bits  sine wave table as reference  in FLASh, MOTOR_WAVE _TABLE will scale those values into a writable array, value for this is from 0 to 100, (percentage of fixed value).Probably I will make the fixed table  user writable for microstepping calibration,as we know as stepper has its own optimized wave.

There is still a lot of work but I enjoy it.

  Are you sure? yes | no

julienhogert wrote 01/10/2019 at 17:12 point

Hello ! Thank you so much for the job you've done ! For a long time I was expecting what you did ! I made a little library to integrate your code. you can find it here :
It's very basic, but just made it to be more convenient !
I have some questions :
Why did you put  delay(5), in the i2c command?

Why do you have to inverse speed when you already set the Target?
I will probably tweak it in the library to have only positive values.

why did you invert the resolution? Resolution 1-> 32 msteps 2->16 4->8 8->4 counter is always 32 microsteps resolution. I made a function to put it in a more convenient way (1:full step, 2:half, 4:quarter...)
You put: voltage sinoidal microstepping. does it mean that we can manage the current/voltage/torque of the stepper?
Once again, thank you so much for your job,
I can only help with the "easy part" of the code, but if you need it, I'll be there ! Thanks,

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates