Remotely control a DC motor with Toit PubSub API and ESP32

Toit motor control

In this article, we’ll have a look at Toit’s PubSub API and show how we can use it to control a small DC motor remotely using Toit. An N20 geared motor will be hooked up with an L9110s motor driver to control its speed as well as direction. A potential application of such a setup could be a remotely controlled water pump in agriculture as IoT is playing a major role in the agricultural sector.

For those who are not familiar with Toit, it is a modern IoT platform that enables a low-cost ESP32 MCU to work as a full computer. Toit provides you with everything you need to develop software: cloud, out-of-the-box connectivity, a web-based console to monitor everything, and even a new programming language. This new high-level language makes development faster and we’ll see more about it in the further sections.

Components used

  1. ESP32 Dev module
  2. 6V N20 DC geared motor
  3. L9110s motor driver
  4. A micro USB cable for connecting ESP32 to PC
  5. Breadboard and connecting wires

Setting up the motor hardware

The L9110s is a dual-channel DC motor driver which can drive two motors independently up to 12V and a current of 800mA each. This motor driver can also be used for driving a single low-power stepper motor. For our purpose, we’ll be using only one of its channels for controlling a single 6V DC motor. The motor driver has an H-bridge configuration and takes PWM inputs, which will allow for speed control as well. Below is the complete circuit diagram

Toit motor control circuit

Working of PubSub API

PubSub API is quite similar to the MQTT protocol, which is highly used for IoT messaging. Just like MQTT, PubSub is also based on topic names. They define the topics using two conventions: device and cloud. The ‘device:’ prefix is to be used for intra-device communications whereas the ‘cloud:’ prefix is to be used when communicating with external devices over the cloud.

For our use case, we’ll have two cloud topics. “motor/run” will be used for sending the motor speed and direction commands, and the “motor/ack” will be used as feedback or acknowledgment that the command was executed successfully. By having its own messaging API, Toit provides seamless communication for IoT with its platform.

Programming with Toit and running the motor

1) Python API

First, we’ll set up the Python program through which we’ll be sending the motor commands. Toit provides a publicly available gRPC API with API packages and examples for languages including Java, Python, and NodeJS.

Follow the Python API installation here and generate the Toit’s API key with these instructions. Make sure to note down this API secret as it will be used further. For now, we’ll be using the example code available on Toit’s GitHub that can send and receive messages. Create a new Python file and copy the code from here. Once that is done, just edit the topic names as:

 

// define PubSub topics

INCOMING_TOPIC = “cloud:motor/ack”

OUTGOING_TOPIC = “cloud:motor/run”

We also need to create a PubSub subscription on the cloud, which can be done using the following command:

$ toit pubsub subscription create cloud:motor/ack MotorControl

With this, the Python API part is done and we can move on to programming the ESP32 with Toit.

2) Toit

The Toit code starts with importing the required libraries. We require GPIO, its PWM functionality, and the PubSub library

// import necessary libraries

import gpio.pwm as gpio

import gpio

import pubsub

Next, we define the incoming and outgoing topic names which we discussed in the previous section.

// define PubSub topics

INCOMING_TOPIC ::= “cloud:motor/run”

OUTGOING_TOPIC ::= “cloud:motor/ack”

Coming in the main function, we define the two PWM pins for motor control. ESP32’s GPIO 26 and 27 are used which generate a PWM signal of frequency 490 Hz.

 // Initialize PWM pins for motor control

 motor_pin_a := gpio.Pin 26 –output

 motor_pwm := gpio.Pwm –frequency=490

 motor_1a := motor_pwm.start motor_pin_a

 

 motor_pin_b := gpio.Pin 27 –output

 

 motor_1b := motor_pwm.start motor_pin_b

Next, we wait and check for any new message on the incoming topic and print the message once received. The message which we are sending is in the form of “<direction> <speed>”. Direction can be cw (clockwise), ccw (counter-clockwise) or stop. The speed should be in the range of 0.0 to 1.0 which will be fed as the duty factor for the PWM signals. Once the message is received, we split the direction and speed commands and store them in separate variables.

// Check for any new message on INCOMING_TOPIC

 pubsub.subscribe INCOMING_TOPIC : | msg/pubsub.Message |

   print “Received: $msg.payload.to_string

 

   // Split and separately save the direction and speed commands

   received_msg := msg.payload.to_string.split ” “

 

   direction := received_msg[0]

   speed/float := 0.0

Finally, we have a bunch of if-else statements to check the direction and set it accordingly along with the speed. After everything is executed, we send a “Done” message as feedback to the Python API.

   // Check for direction and set the speed

   if direction == “stop”:

     speed = 0.0

   else:

     speed = float.parse received_msg[1]

 

   if direction == “ccw”:

     motor_1a.set_duty_factor speed

     motor_1b.set_duty_factor 0.0

   else if direction == “cw”:

     motor_1a.set_duty_factor 0.0

     motor_1b.set_duty_factor speed

   else:

     motor_1a.set_duty_factor 0.0

     motor_1b.set_duty_factor 0.0

 

   // Send acknowledgement

   pubsub.publish OUTGOING_TOPIC “Done”

Now, run the Python file using the command:

$ python3 main.py MotorControl

Where MotorControl is the name of the subscription topic which we created earlier. Enter the API secret for your generated API key and it will be ready to take in motor control commands.

After that, run the Toit program using the command:

$ toit run motor.toit

or

$ toit run -d <device-name> motor.toit

Now, with both the sides running, start entering the commands in the format “<direction> <speed>”. For example “cw 0.5” for running motor in the clockwise direction at 50% of its full speed, “ccw 1.0” for running in the counter-clockwise direction at its full speed or “stop” to bring the motor to halt. The demo video below explains it better.

You can find the Python as well as the Toit program in this GitHub repository.

Share on facebook
Share on twitter
Share on linkedin

Leave a Reply