📜 ⬆️ ⬇️

We control the machine via Bluetooth from a tablet or phone for Android

Hi, Habr!

Today I will talk about how a programmer can reach with a mid-life crisis in attempts to at least somehow compensate for the lack of fashionable toys in a distant and half-forgotten childhood.

I have already played with radio-controlled helicopters with my sons, well, but in a standard Moscow apartment it is a bit cramped, and it is cold, dirty and windy outside. We'll have to play with cars, good, there is such a device at hand:

The children have already graced them with graffiti and have a little wiped, but it still travels, if we find the console ... But the console is lost somewhere. Well, but there is a tablet with Bluetooth! It remains as they make friends together. A lot of such projects are searched through Google, so let's complicate the task - We make proportional steering and smooth speed adjustment!
')
We will need:

Ruthlessly throwing out the DC motor, which pulled the tie rod, instead of it with a needle file, an assembly gun and other popular methods, we insert the servo drive. We compile a simplest scheme with arduina and other components on a breadboard. I will not give you the connection scheme, I just hooked everything onto the first legs of the Arduin, which even worked with some iteration. After several attempts to arrange everything so that it fit on the native chassis, it turned out like this:



The Bluetooth module is hidden from the bottom of the layout, the dc converter is then stuck on top of the back of the chassis:



It remains to fill in the sketch, since we have the Bluetooth adapter hanging on the same serial port as the USB TTL adapter, before pouring the sketch, do not forget to pull off the RX / TX with the Bluetooth module. By the way, the idea was to use SoftwareSerial for it, but I had to drop it, because SoftwareSerial gives strange spontaneous twitches on a servo drive.

#include <Servo.h> Servo servoSteering; const int servoSignalPin = 7; // servo yellow(signal) pin const int servoMiddle = 88; // servo middle position const int servoMaxAngle = 35; // servo max angle (degrees) const int servoLeftBound = servoMiddle - servoMaxAngle; const int servoRightBound = servoMiddle + servoMaxAngle; int servoPos = servoMiddle; int servoTrim = 0; const int dcMotorA1Pin = 11; // dc motor A+ pin const int dcMotorA2Pin = 12; // dc motor A- pin const int dcMotorPWMPin = 3; // dc motor PWM pin const int ledPin = 13; // data received pin const int dcMotorPWMLowerBound = 128; // dc motor min PWM (min speed) const int dcMotorPWMHighBound = 255; // dc motor max PWM (max speed) int dcMotorDir = 1; // 1 - forward, -1 - backward int dcMotorSpd = 0; // 0 - stand still, value between dcMotorPWMLowerBound and dcMotorPWMHighBound to move const int cmdTimeout = 2000; // max time between commands from rc control, will stop if no new commands arrive typedef enum { NONE = 0, SERVO_L, SERVO_R, TRIM, DCMOTOR_F, DCMOTOR_B, STOP } mode_t; mode_t opMode = NONE; #define IS_DIGIT(x) ('9' >= (x) && '0' <= (x)) unsigned long lastCmd = 0; void setup() { Serial.begin(9600); servoSteering.attach(servoSignalPin); pinMode(dcMotorA1Pin, OUTPUT); pinMode(dcMotorA2Pin, OUTPUT); pinMode(dcMotorPWMPin, OUTPUT); pinMode(ledPin, OUTPUT); digitalWrite(dcMotorA1Pin, 0); digitalWrite(dcMotorA2Pin, 0); analogWrite(dcMotorPWMPin, 0); } void loop() { while (Serial.available()) { digitalWrite(ledPin, HIGH); int ch = Serial.read(); lastCmd = millis(); // save command receive time for later if (opMode == NONE) { switch (ch) { case 'T': case 't': // trim mode opMode = TRIM; break; case 'L': case 'l': // servo left mode opMode = SERVO_L; break; case 'R': case 'r': // servo right mode opMode = SERVO_R; break; case 'F': case 'f': // dc motor move front mode opMode = DCMOTOR_F; break; case 'B': case 'b': // dc motor move back mode opMode = DCMOTOR_B; break; case 'S': case 's': // full stop mode servoPos = servoMiddle + servoTrim; // center front wheels dcMotorDir = 1; // 1st gear dcMotorSpd = 0; // neutral on default: opMode = NONE; break; } } else if (IS_DIGIT(ch)) { switch (opMode) { case TRIM: servoTrim = '5' - ch; break; case SERVO_L: servoPos = servoMiddle + servoTrim - (ch - '0') * servoMaxAngle / 10; if (servoPos < servoLeftBound) servoPos = servoLeftBound; break; case SERVO_R: servoPos = servoMiddle + servoTrim + (ch - '0') * servoMaxAngle / 10; if (servoPos > servoRightBound) servoPos = servoRightBound; break; case DCMOTOR_F: dcMotorDir = 1; dcMotorSpd = ch == '0' ? 0 : dcMotorPWMLowerBound + (dcMotorPWMHighBound - dcMotorPWMLowerBound) * (ch - '0') / 10; break; case DCMOTOR_B: dcMotorDir = -1; dcMotorSpd = ch == '0' ? 0 : dcMotorPWMLowerBound + (dcMotorPWMHighBound - dcMotorPWMLowerBound) * (ch - '0') / 10; break; default: break; } opMode = NONE; } if (dcMotorDir == 1) Serial.print("F "); else Serial.print("R "); Serial.print(dcMotorSpd); Serial.print(" S "); Serial.print(servoPos); Serial.print(" T "); Serial.println(servoTrim); digitalWrite(dcMotorA1Pin, dcMotorDir == 1 ? 1 : 0); digitalWrite(dcMotorA2Pin, dcMotorDir == 1 ? 0 : 1); analogWrite(dcMotorPWMPin, dcMotorSpd); servoSteering.write(servoPos); } if (dcMotorSpd > 0 && (lastCmd + cmdTimeout) < millis()) { // rc control doesn't send anything, out of range or hang up, do full stop dcMotorDir = 1; // 1st gear dcMotorSpd = 0; // neutral on digitalWrite(dcMotorA1Pin, 1); digitalWrite(dcMotorA2Pin, 0); analogWrite(dcMotorPWMPin, 0); servoSteering.write(servoPos); } digitalWrite(ledPin, LOW); } 


Tested via PuTTY from a laptop by sending commands to a Bluetooth-connected device that seems to work. It remains to build an application for Android. Nadergal in the network of images, code samples, tried to glue it, it seems to work:



Along the way, got a glitch with the implementation of Bluetooth on some ICS devices:
code.google.com/p/android/issues/detail?id=34161

It manifested itself on the Lenovo A800, manifested in the fact that an open Bluetooth socket closes immediately. To treat, apparently, only by changing the firmware of the device, all tested workarounds did not work ...

Well, for a snack, the code of the Android application:
github.com/robotsrulz/BluetoothRC

And a short video where the son first tries to drive, but it turns out only in a straight line, and then I try to steer with one hand and continue shooting with the other:
plus.google.com/u/0/photos?pid=5988360256454694594&pids&oid=106468370342958692108

Source: https://habr.com/ru/post/216851/


All Articles