-
1Setting 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.
-
2Working 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.
-
3Programming 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 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 acknowledgment 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
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.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.