
Much time has passed since the last article. Frank has changed a lot. Of course, he didn’t become more independent, but it’s safe to say that the platform for experiments is almost ready, and I’ll now spend more time writing code, rather than Lego or a soldering iron.
For those who have not read the latest articles, I suggest reading them by clicking on the following links. For those who are already aware of this project - welcome under cat.
')
“Creating an autonomous robot Frank. Part one"“Creating an autonomous robot Frank. Part two"First, the principle of the work of Frank has completely changed. From four wheels, he moved to four tracks, which greatly facilitated the management and writing code. Because of the way the case and chassis were assembled, there was simply no space inside to put the electronics in there. The only thing that went inside was a 6v battery and 4p servo-motor, which rotated the wheels and were responsible for the angle of rotation. The second attempt was to completely get rid of the turning mechanism and go to the controls by differentiating the speed of the wheels. This venture also failed, because the friction between the wheels and the floor did not allow the wheels to slip a little, and all I achieved with the help of additional gearboxes were sliding gears, which at the end of the experiment cramped and immediately found themselves in the garbage can.

With the tracks everything was easier. Despite the fact that the rubber tracks in Lego are of rather poor quality, the gearbox did its job. Of course, Frank will not be able to participate in the races, but he will obviously be able to carry the load.

So, putting everything inside Frank and collecting everything inside one case, I decided to make a few changes. First, I still wanted to experiment with cameras and stereo vision. Secondly, it was necessary to do something quick in return for the cameras, so that he had at least some idea of the surrounding world. So his head was born.

In my head, I fixed two cameras that are not connected with microchips yet. Just got there ultrasonic sensor and servo-motor, which allows the head to rotate.

Since I got the battery, it became completely autonomous, in the sense that it should no longer be connected to the laptop via USB cable. All communication takes place through a serial wireless port - XBee, which I wrote about earlier. All this and much more made me change the chips, which are now three, if you count the Arduino Due.

Here are the changes that have occurred.
1) I finally soldered XBee onto the circuit. Now it is part of the device.
2) For interest, I put a temperature sensor in there.
3) I made inputs for 4x servo-motors, an ultrasonic sensor, a battery and three solar batteries (they haven’t reached their turn yet)
4) Brought one NXT interface out if I suddenly need to connect some kind of Lego sensor (compass or gyroscope, for example)
5) Since now everything is working on one battery, I made an external switch, and also soldered the capacitor to get rid of the “noise” of the servo-motors.
6) Since the connection of the battery and solar panels is on the external board, and the power wiring itself (which is not finished yet) is on average, I made additional connections between them
7) I powered the battery through one of the analog inputs to measure the voltage.

Naturally, the software has changed!
Like last time, you can download it from my site
Frank - Autonomous VehicleWhat has changed in software?
The way I tried to communicate with the Arduino via XBee using a third-party library was fundamentally wrong. Everything turned out to be much easier. Using the built-in Serial library, everything began to work and be sent. There are small nuances, but about them later.
Now I send all the data that is currently available to me in iFrank, namely:
1) Battery charge
2) Distance to the nearest object (from an ultrasonic sensor)
3) Temperature
4) Current servo motor control variables.
All calculations associated with the data occur in iFrank, in order not to load the Arduino with unnecessary work. iFrank, in turn, monitors the data, and if it is necessary to change them, sends an update. Thus, the rotation of the head and the control of servo-engines. If in iFrank I press the keys to control the rotation of the head, then there is a discrepancy between the “desired” data and the current, which iFrank reports to the Arduino, thereby changing the data. There is also a timer in iFrank, which smoothly changes this difference and, in fact, sends the desired signal.
As you will see in the iFrank and Arduino code, at the end of the signal I send the symbol "*" (in the case of arduino-> iFrank) and "\ n" (in the case of iFrank-> arduino). Since, when reading from a serial port, information comes in chunks, I organized a buffer in iFrank into which information is dumped. An asynchronous timer periodically reads information from there and processes it in chunks separated by "*".
Below is the Arduino code:
Arduino code#include <Servo.h> #include <math.h> //Sensors int dataTemperature = 0; int dataBattaryVoltage = 0; int dataSolarVoltage = 0; int dataMotor1 = 0; int dataMotor2 = 0; int dataSteering1 = 0; int dataSteering2 = 0; int dataCamPan = 0; int dataCamTilt = 0; int dataGyrX = 0; int dataGyrY = 0; int dataGyrZ = 0; int dataAccX = 0; int dataAccY = 0; int dataAccZ = 0; int dataGPSTime = 0; int dataGPSLong = 0; int dataGPSLat = 0; int dataGPSSat = 0; float dataDistance = 0; int dataTemp2 = 0; int dataTemp3 = 0; int dataTemp4 = 0; int dataTemp5 = 0; int dataTemp6 = 0; int dataTemp7 = 0; int dataTemp8 = 0; #define trigPin 31 #define echoPin 30 //Voltage const float referenceVolts = 3.3; const float resistor1 = 20000; const float resistor2 = 2200; const float resistorFactor = resistor2/(resistor1+resistor2); const float boardVoltage = 3.3; const float analogVoltMult = boardVoltage/1024; const int batteryPin = 1; // Servo Code Servo steering1; Servo steering2; Servo motor1; Servo motor2; // Steering initial states float st1_start = 0.0; float st1_end = 180.0; float st1_step = (st1_end-st1_start)/256.0; float st2_start = 0.0; float st2_end = 180.0; float st2_step = (st2_end-st2_start)/256.0; // Steering function 0-256 float steer1(float p){ float v=st1_start+st1_step*p; steering1.write(v); return v;} float steer2(float p){ float v=st2_start+st2_step*p; steering2.write(v); return v;} int pos = 0; // XBEE Code /** XBee xbee = XBee(); unsigned long start = millis(); uint8_t payload[] = { 'H', 'i','t','h','e','r','e' };; Tx16Request tx = Tx16Request(0x4000, payload, sizeof(payload)); TxStatusResponse txStatus = TxStatusResponse(); */ void setup() { // Serial Serial.begin(19200); // Sensors pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); // Servos steering1.attach(2); steering2.attach(3); motor1.attach(4); motor2.attach(5); dataMotor1 = 94; dataMotor2 = 94; dataSteering1 = 130; dataSteering2 = 130; } void loop() { // Read serial input while (Serial.available() > 0) { int st1 = Serial.parseInt(); int st2 = Serial.parseInt(); int mt1 = Serial.parseInt(); int mt2 = Serial.parseInt(); if (Serial.read() == '\n') { dataSteering1 = st1; dataSteering2 = st2; dataMotor1 = mt1; dataMotor2 = mt2; } } // Read temperature dataTemperature = analogRead(0);delay(15); dataTemperature = analogRead(0); dataBattaryVoltage = analogRead(1);delay(15); dataBattaryVoltage = analogRead(1); Serial.print(dataTemperature);Serial.print("|"); Serial.print(dataBattaryVoltage);Serial.print("|"); Serial.print(dataSolarVoltage);Serial.print("|"); Serial.print(dataMotor1);Serial.print("|"); Serial.print(dataMotor2);Serial.print("|"); Serial.print(dataSteering1);Serial.print("|"); Serial.print(dataSteering2);Serial.print("|"); Serial.print(dataCamPan);Serial.print("|"); Serial.print(dataCamTilt);Serial.print("|"); Serial.print(dataGyrX);Serial.print("|"); Serial.print(dataGyrY);Serial.print("|"); Serial.print(dataGyrZ);Serial.print("|"); Serial.print(dataAccX);Serial.print("|"); Serial.print(dataAccY);Serial.print("|"); Serial.print(dataAccZ);Serial.print("|"); Serial.print(dataGPSTime);Serial.print("|"); Serial.print(dataGPSLong);Serial.print("|"); Serial.print(dataGPSLat);Serial.print("|"); Serial.print(dataGPSSat);Serial.print("|"); Serial.print(dataDistance);Serial.print("|"); Serial.print(dataTemp2);Serial.print("|"); Serial.print(dataTemp3);Serial.print("|"); Serial.print(dataTemp4);Serial.print("|"); Serial.print(dataTemp5);Serial.print("|"); Serial.print(dataTemp6);Serial.print("|"); Serial.print(dataTemp7);Serial.print("|"); Serial.print(dataTemp8); Serial.print("*"); steer1(dataSteering1); steer2(dataSteering2); motor1.write(dataMotor1); motor2.write(dataMotor2); delay(100); // Read echo long duration, distance; digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); dataDistance = pulseIn(echoPin, HIGH); }
Some more pictures of Frank

