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.
- ESP32 Dev module
- 6V N20 DC geared motor
- L9110s motor driver
- A micro USB cable for connecting ESP32 to PC
- 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
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.
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
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
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
speed = float.parse received_msg
if direction == “ccw”:
else if direction == “cw”:
// 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
$ 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.
Harsh Chaudhary is an engineering student currently pursuing Electrical Engineering. He’s a robotics and tech enthusiast and likes to write about stuff related to IoT and embedded systems. His vision is to use Robotics to make the life of humans easier.