Remotely control a DC motor with Toit's PubSub API

Using an ESP32 programmed with Toit to control an N20 DC motor over the Toit platform's cloud

Public Chat
Similar projects worth following

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. 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.

  • 1 × ESP32 DevKit Microcontroller board
  • 1 × 6V N20 DC geared motor
  • 1 × L9110s motor driver

  • 1
    Setting up the 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.

  • 2
    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.

  • 3
    Programming and running the codes

    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
         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
         motor_1a.set_duty_factor 0.0
         motor_1b.set_duty_factor 0.0
       // Send acknowledgment
       pubsub.publish OUTGOING_TOPIC "Done"

     Now, run the Python file using the command:

    python3 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

    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.

View all 3 instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

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