Introduction: Custom Robot Apps -- No Android Programming Required
The above robot control app is NOT build into pfodApp
The display and controls are completely defined by the sketch you load into your Robot.
You can add extra buttons and controls as you need by editing your sketch. No Android Programming Required.
Step 1: Introduction
This instructable covers the design of your own custom Robot control Android apps using pfodApp. No Android programming necessary. DFRobot's Flamewheel robot is used as an example project, but, as you will see below, you can design your own custom control interface.
Robots usually come with apps supplied, but you are then restricted to only what the app can do. However using the general purpose pfodApp you can design your own interface the way you want it and with the added features you want.
pfodApp will connect via and Bluetooth Low Energy (BLE), Bluetooth Classic, WiFi, Ethernet and also SMS. Many robots come with BLE communication, however because there is no BLE UART standard defined, each manufacturer implements his own.
pfodApp currently supports the following manufacturer’s 'standards' :- DFRobot Romeo BLE, DFRobot BLUNO (e.g. Flamewheel etc), Arduino101, BBC micro:bit, RFduno, RedBearLab, Nordic BLE UART, Adafruit BLE UART, Adafruit BLE SPI, HM-10 (e.g. ITEAD BLE Shield)
This instructable is also available on-line at Custom Robot Apps with pfodApp for Android
Step 2: Parts List
For this example project you will need (prices as at May 2017, not including shipping) :-
- Flamewheel ~ US40 (also 4 x AAA alkaline batteries and an M3 screw driver)
- USB A to Micro cable ~US$5
- pfodApp ~ US10
- An Android mobile - V4.4.2 or higher
- Arduino IDE V1.8.2 and a computer to run it on
- pfodParser library
Step 3: Software
The Flamewheel is powered by a Romeo BLE mini board with has an UNO processor, a motor driver chip and a TI BLE module connected to TX/RX pins. This makes the Arduino side of the BLE connection simple. You just read and write to the Serial connection at 115200 baud. The TI BLE module also handles the USB connection. The Android app side of the BLE connection normally requires a detailed knowledge of Android programming, however pfodApp handles all of that for you. No Android programming required.
BLE Config
My board came with Firmware V1.97 and I left it at that as it seemed to be the latest for this board.
You can configure the TI BLE module via AT commands from the USB connection. (See the BLUNO wiki) :-
- Open the Arduino IDE, check the Romeo BLE mini has been detected as an UNO on a com port.
- Open Serial Monitor and set the baud rate to 115200 and set “No Line Endings”. Then type +++ and click Send to get into AT cmd mode the successful response is “Enter AT mode”
- Then change the line endings back to “Both NL & CR” and execute the following commands
AT+VERSION=?
responds
V1.97
AT+SETTING=DEFAULT
responds
OK
AT+BLUNODEBUG=OFF
responds
OK
AT+USBDEBUG=OFF
responds
OK
AT+EXIT
responds
OK
This turns off the BLE debug output to the USB connection. You can turn it on if you want to monitor the BLE messages on the Arduino Serial Monitor.
To compile the sketch, download and install the pfodParser library and load the Flamewheel.ino sketch into your IDE and select Board → Arduino/Genuino UNO and program the Romeo BLE mini.
Programming tip: You can reprogram your Flamewheel after construction. Make sure there is no BLE connection. Remove one battery and plug in the USB to re-program.
That is the software complete.
Step 4: Hardware
The Flamewheel kit went together easily, but here are a few tips:-
Flamewheel Construction Tips
- Put a cloth under the construction to catch dropped screws so they don't bounce away. (Fortunately the kit came with spare screws)
- Install A1 and A3 so the writing faces outwards on both, so the cutouts are aligned.
- Don't over tighten the self tapping (pointed) screws or you will strip the thread you are making in the wood. The circuit board can be a little loose and the wheels are a press fit and don't need to be screwed down tight
- Hold the wheel when tightening the retaining screw (D3) so you don't turn the motor gears in reverse.
- In spite of what the video shows – Don't set your robot alight !!
Step 5: Operation
Download the pfodApp and setup a new BLE connection for the Flamewheel. See pfodAppForAndroidGettingStarted.pdf for details on how to create a new connection.
Then when you connect, pfodApp will load this dwg from your Flamewheel sketch.
Put your finger in the center and move it forward of backward to drive the Flamewheel. Move you finger left or right from the center line to turn. If you go to the left or right edge, the Flamewheel will spin on the spot. Anywhere on the Stop line stops the Flamewheel. It will also stop if you lift you finger off the screen.
As mentioned above this dwg and all the controls are completely defined by the sketch you loaded into the Flamewheel, so you can customize the user interface by editing the your Arduino code. No android programming required. See below for details.
Step 6: The Sketch Code
The flamewheel.ino sketch has three basic parts.
1) Loading the menu and drawing,
2) Processing the user's input
3) Calculating the left and right wheel speed.
See Custom Arduino Controls for Android for a detailed tutorial on pfodApp dwg support, loading dwgs and creating controls.
1) Loading the menu and drawing
When pfodApp connects it send the 'get main menu' command, {.} and the parser parses it the extract the '.' You can see in the loop() code where this is handled and the main menu is sent back.
if ('.' == cmd) {<br> // pfodApp has connected and sent {.} , it is asking for the main menu if (!parser.isRefresh()) { sendMainMenu(); // send back the menu designed } else { sendMainMenuUpdate(); // menu is cached just send update } stop(); // always start stopped
The main menu msg returned is {,~Flamewheel`0~V1|+A~a}
See the pfodSpecification.pdf for all the details of the pfod messages.
The +A~a defines a dwg menu item, '+', that contains a dwg that can be loaded via the 'a' dwg load cmd. When pfodApp process this response it requests the dwg by sending the {a`0} command.
Further down the loop() you can see
} else if ('a' == cmd) { // pfodApp is asking to load dwg 'a'<br> if (!parser.isRefresh()) { // not refresh send whole dwg sendDrawing_a(); } else { // refresh just update drawing state sendDrawingUpdates_a(); }
which sends back the dwg definition. The supporting pfodDwgs methods included in the pfodParser library are used to create the dwg.
<p>pfodDwgs dwgs(&parser); // drawing support<br>int cols = 23; int rows = 25; … … … void sendDrawing_a() { dwgs.start(cols, rows, dwgs.WHITE); // background defaults to WHITE if omitted i.e. dwgs.start(50,30); parser.sendVersion(); // send the parser version to cache this image // draw the axies, leave space for the text dwgs.line().size(0, rows - 4).offset((cols) / 2.0, 2).send(); dwgs.line().size(cols / 5.0f, 0).offset(cols / 2.0f - cols / 10.0f, (rows) / 2.0f).send(); dwgs.line().size(cols / 5.0f, 0).offset(0, (rows) / 2.0f).send(); dwgs.line().size(cols / 5.0f, 0).offset(cols - cols / 5.0f, (rows) / 2.0f).send(); // add the labels dwgs.label().fontSize(-3).offset(cols / 2.0f, 1).text(F("Forward")).send(); dwgs.label().fontSize(-3).offset(cols / 2.0f, rows - 1).text(F("Back")).send(); dwgs.label().fontSize(-5).offset(cols / 2.0f - cols / 5.0f, (rows) / 2.0f).text(F("Stop")).send(); dwgs.label().fontSize(-5).offset(cols / 2.0f + cols / 5.0f, (rows) / 2.0f).text(F("Stop")).send(); // define the active touch zone and its cmd dwgs.touchZone().cmd(touchZoneCmd).size(cols, rows).filter(dwgs.DOWN + dwgs.DRAG + dwgs.UP).send(); // close dwg dwgs.end(); }</p>
This defines a dwg 23 cols wide by 25 row high. pfodApp will automatically scale the dwg up to width of the mobile's screen. The cols and rows set the touch resolution. As well as drawing some lines and adding some labels, a touchZone is defined that covers the entire dwg.
<p>dwgs.touchZone().cmd(touchZoneCmd).size(cols, rows).filter(dwgs.DOWN + dwgs.DRAG + dwgs.UP).send();</p>
TouchZones are normally invisible but you can turn on Debug on the connections setup screen to make them visible, as shown in the above screen shot.
The touch filter is set to send a messages when the use puts their finger DOWN, DRAGS their finger or lifts their finger UP. DRAG messages are only sent if there is a change in col,row position touched on the dwg. You choose the dwgs cols,rows size to give you the touch resolution you need while limiting the number of messages sent.
2) Processing the user's input
When the user touches the dwg inside the touchZone, pfodApp sends a command like {V1:A~p`12`7`1}
The pfodParser parser parses this command and returns the first char of the command, i.e. 'A' (The leading V1 is the menu/dwg version string that pfodApp has already cached).
The 'A' command it is handled by this section of the loop() code.
<p>} else if ('A' == cmd) { // user touched menu item 'A'<br> // in the main Menu of Flamewheel char dwgCmd = parser.parseDwgCmd(); // parse rest of dwgCmd, return first char of active cmd if (dwgCmd == (touchZoneCmd)) { colTouched = parser.getTouchedCol(); rowTouched = parser.getTouchedRow(); col = colTouched - zeroCol; // + = right row = -(rowTouched - zeroRow); // + == forward calculateWheelSpeed(); } if (parser.getTouchType() == dwgs.UP) { // stop when user lifts finger off dwg stop(); } sendDrawingUpdates_a(); // always send back a response or pfodApp will timeout</p>
parser.parseDwgCmd() parses the rest of the command as a dwg command and returns the touchzone cmd 'p'
Once parseDwgCmd() has been called you can pickup the col and row touched with parser.getTouchedCol() and parser.getTouchedRow() i.e. 12 and 7 in this example message. This is location where the user touched in the dwg in the touchzone.
The col and row relative to the center of the dwg is then calculated and calculateWheelSpeed() called to set the left and right wheel speed.
Then the type of touch that triggered this command is retrieved using parser.getTouchType(), 1 in this example, and if it was a finger UP (dwgs.UP == 4) then stop() is called.
Finally sendDrawingUpdates_a() is called to update the dwg if required. You must always respond to every message pfodApp sends or the connection will timeout. In this project the dwg is not updated as the user touches it so the dwg update is empty and sendDrawingUpdates_a() just sends back {+}
As you can see the code to process the user's touch is simple.
3) Calculating the left and right wheel speed
Having calculated the col and row the user touched relative to the dwg center, calculatedWheelSpeed() calculates the left and right wheel speed in the range -255 to +255 as needed by DFRobotRomeoBLEMini. The row sets the speed and the col sets the left / right wheel speed difference. As you move off the center line the speed of one wheel is reduced, reaching zero at the edge.
The code in calculatedWheelSpeed() makes a few adjustments. If the row is not zero, 1 is added/subtracted so that the min speed is ~46 so the motor does not stall at low speed. The scaling factor for the speed is rows * 23 so a value of 11 ~= 255, but the rows +1 goes from 2 to 13. The extra rows top and bottom allow the user to easily place their finger at near the top and bottom edge of the drawing to get maximum speed. The wheelspeed is limited to +/-255
Then the wheel speed is adjusted for starting and reversing. If you go from 0 to 255 in one step, the surge in motor current interferes with the BLE connection, also if you go from 0 to some slow speed the motor sticks and may not start, so when starting the speed always goes from 0 to 128 for 100ms before reverting to the requested speed. Also when the user moves their finger around the center position from forward to back, the code insures that the motor always stops in between again to limit the current surge.
Finally the col value is squared (i.e. col * col) to give the % reduction from wheelspeed for one wheel so that the Flamewheel turns. Using col * col gives a small adjustments either side of the center line for ease of driving in a straight line, but produces stronger turns further from the center. At the edge the Flamewheel just spins on one wheel.
Step 7: Next Steps
The Flamewheel kit really only needs this one control, but other robots will need other controls, buttons, sliders etc. to adjust settings and perform actions. You can add these extra controls to your sketch and have them displayed on the pfodApp without doing any Android programming.
See Custom Arduino Controls for Android for examples of adding buttons and sliders to a drawing. You also have to option of adding sub-menus and extra menu items below the drawing. These menu items can be buttons, sliders, labels etc. The free pfodDesigner app lets you add these and will then generate the sketch code for you.
Conclusion
This Flamewheel robot controller app illustrates how easy it is for you to create your own custom robot app (no Android Programming required) that connects to a variety of BLE standards all using the same pfodApp.
pfodAppV3 provides a small set of powerful Arduino drawing primitives that let you create your own custom Android controls. The touch zone and touch actions give you control over how user input is handled and can provide the user with immediate feedback for their actions. (This example did not use touch actions see Custom Arduino Controls for Android for examples that do.)
The pfodParser library simplifies creating the drawing messages. The separate pfodDwgControls library contains a number of pre-built controls ready to use, including slider, buttons and on-screen help.
Setting a version string enables caching of the menu and drawing by pfodApp, reducing bandwidth and speeding up display.