Close

Adding Speed Control with a BLE App

A project log for Two wheeled speedster

Drum motors from laser printers give this bot tremendous speed at a bargain. Scavenged parts robot with the BLE connection as a bonus!

shanesnipeshane.snipe 12/28/2019 at 17:130 Comments

On one hand, this log is kludging together snippets of example code to control my speedster. On the other hand, this may also be my first noteworthy hack with it comes to how the motor is controlled. Enough spoilers, this is how I did it. 

I have been working with Thunkable off and on for mobile phone apps. I had Thunkable classic working with BLE a couple of years ago but Thunkable X or cross platform did not support BLE until earlier this year. Now it is working and it is fast and it seems very robust.  Check it out at thunkable.com.  Here is the tutorial on BLE. https://www.youtube.com/watch?v=sNpCTsVifo4

The link to my project in thunkable is here. I will continue to work on this but hopefully it continues to be functional!  https://x.thunkable.com/copy/8fb9477a0c64124cb1102b88990c27ed

Obviously, there is some Arduino code that needs to interface with this app. This was my biggest concern when I watched the video but the example code written by Neil Kolban worked flawlessly once I got the UUIDs correct.  Here is the code. It is a standard library example.   https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/examples/BLE_write/BLE_write.ino

So if you came across this hoping to figure out how to hook your ESP BLE to your phone the resources above were sufficient for me to get it going. The rest of this log is about my struggles and triumphs in bending the motors to my will.

First you set up your interface and drop in  you buttons, labels and sliders. You also need the invisible component the BLE. I know I am not winning any design awards with this one but it works!

The slider is meant for speed control and the left and right buttons are for turning.

Here are the blocks I used and an explanation of my understanding of them.  First you need to check if your targeted device is available so you use the scan function and print a list of available devices. 

I have only used this with the live test function on thunkable so far and occasionally I will have to dump it and restart it to make sure I can see the ESP32. However, I have always been able to connect. The scan takes 20-30 seconds.

Next once you see your device pop up on the label, press the connect button and you get an immediate connection. There have been some discussions that the first scanning step can be skipped if you know your device is available. I have yet to try it. Here is the block for connection.

Now the Arduino code has some standard communication in it.  It sends out Hello world until something has been sent to it and then it starts to echo what it receives. So to make sure I can hear from the Arduino I added a receive block. 

So far I have not changed the UUID from the example code but there is link where you can get a new UUID. 

I also included the error code if this is not working. So if I see Hello World or the value I am sending on my phone screen, I know my phone is communicating with the ESP32.

The next blocks are for sending data to the to ESP32 to control the movement.

The motors have a high and a low speed and an enable. The low speed still goes like 20 mph so it was not suitable for indoor use.  I tried to pulse the enable at various PWM frequencies. However, Goldilocks was no where to be found. Either I pulsed to long and it shot across the room or it was I too short and it never really got going. So I was stuck! I considered just making it an outside bot and focusing on turning it but it is December in Chicago and it is too cold outside to run my bot. 

So here is my first real hack for this project. I remember the training I got when i was selling this motor  15 years ago. The motor has a look up table for the initial acceleration. Once it is up to significant speed, the speed is set by the frequency from the crystal. So there seemed to be a chance to replace the crystal with an external signal.  Now this is why I belong to a makerspace. I may be able to come up with theories like this but I was not confident about how to test or implement this theory. Luckily we had a EE in the building and he encouraged me to get the motor running so he could check the signal coming out of the crystal with the scope. There was a crystal in and out on the schematic. We probed both sides of the crystal and saw a similar wave that seemed to be amplified on the out side. So we decided to see if we could use the function generator to make a similar wave to the input side wave.  The wavelength was only 250 ns so it looked like a 4 mHz crystal. We got the crotchety function generator to make something with a similar frequency and high voltage. We then removed the crystal and attached a wire to the low side of the crystal input.

To my delight, the motor started running.  We reduced the frequency on the generator and the motor slowed down and sped up accordingly.  I have a box of these motors and this will make them much more useful.  

I had been struggling to control speed and direction because I was trying to control the speed by  turning on and off the motors. Now I have much finer control available.  

The other issue I have been struggling with for the last year is how to go from the text that is easy to send with BLE to integers that can finely control my device. Going from the ESP32 to the App, apparently if you take your received text and store it as a variable you can change it to and integer. 

https://community.thunkable.com/t/how-to-convert-my-text-number-into-math-block-number/71826

However, for this application I was going the other way. The character received in Arduino needed to be converted to my speed number. After various fails at type conversion, my makerspace came to the rescue again!

char inbyte=0;
char* p;
int i=20;

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

  inbyte = value[0];
  i=atoi(value.c_str());
  Serial.println(i);

I had a switch statement based on the first character in char inbyte. That worked fine I wanted finere resolution.   i=atoi(value.c_str()); seems to  have done it and it is working fine. I send an output from my slider in the app here and the speed updates dynamically from 0-50. 0 is off, 1-49 are pwm values and 50 is full on. 

At this point, I only know how to send one value.  Maybe if set up a different characteristic ID  I can send a number to a separate variable on the ESP32 side. The problem is I  may want to control the speeds of the two motors individually.  Maybe two different sliders.

In any case the goal for today is to replace that frequency generator output with a output from my  ESP 32.  I will also try to add a second slider under a second characteristic uuid and callback and see if I can get two independent streams of data going so I can individually control the motors.

I suppose the other option is to  have on slider from 1-100 and one from 101 to 200.  Based on the number that is sent, the speed for the individual motor can be set in an if then statement.

Discussions