Guillermo Perez Guillen
Created July 29, 2020 © CC BY

TESLA Robot

Cost-effective robotic solution for surface sanitization - Amazon Alexa / Neural Networks / PID Controller / Tesla coil / UV lamp / OpenCV

ExpertFull instructions provided8 days139

Things used in this project

Hardware components

Echo Dot
Amazon Alexa Echo Dot
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Camera Module V2
Raspberry Pi Camera Module V2
×1
Arduino UNO & Genuino UNO
Arduino UNO & Genuino UNO
×1
thingSoC ESP32 WiFi Module
thingSoC ESP32 WiFi Module
×1
Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
×1
Test Cable Assembly, USB to TTL Interface Cable
Test Cable Assembly, USB to TTL Interface Cable
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
Ultrasonic Sensor - SRF05
×1
IR distance sensor - GP2Y0A515K0F
×2
IR distance sensor - GP2Y0A415K0F
×1
SparkFun Full-Bridge Motor Driver Breakout - L298N
SparkFun Full-Bridge Motor Driver Breakout - L298N
×1
4WD Mobile Platform for Robot Car
×1
Grove - Relay
Seeed Grove - Relay
×1
UV lamp 6W
×1
Mini DIY Tesla Coil Kit
×1
Rechargeable Battery, 4.8 V
Rechargeable Battery, 4.8 V
×1
Rechargeable Battery, 7.2 V
Rechargeable Battery, 7.2 V
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1

Software apps and online services

Arduino IDE
Arduino IDE
OpenCV
OpenCV
Python 3.7.3
Amazon Alexa App
FreeCAD
Ultimaker Cura

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)
Smartphone Android 9
Hot glue gun (generic)
Hot glue gun (generic)
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)
Plastic cable ties
Aluminum

Story

Read more

Custom parts and enclosures

Custom Parts of TESLA Robot

STL files

Schematics

TESLA Robot version 1

Schematic diagram

TESLA Robot version 2

Schematic diagram

UV Meter

You can see the electrical connections of the UV meter in the image below

Code

esp32-wroom-32

Arduino
This code must be uploaded to the ESP32-WROOM-32 board.
SECTION 4. ECHO DOT & ESP32-WROOM-32
# AUTHOR: GUILLERMO PEREZ GUILLEN

#include <Arduino.h>
#include <NewPing.h> // SRFO4
#define ultrasonic_pin_1 4 // SRF04
#define ultrasonic_pin_2 25 // SRF05

const int UltrasonicPin = 2; // SRFO4 
const int MaxDistance = 200; // SRFO4

const unsigned int TRIG_PIN=27; //SRF05
const unsigned int ECHO_PIN=26; //SRF05


NewPing sonar(UltrasonicPin, UltrasonicPin, MaxDistance); // SRFO4

#ifdef ESP32
  #include <WiFi.h>
  #define RF_RECEIVER 13
  #define RELAY_PIN_1 12
  #define RELAY_PIN_2 14
#else
  #include <ESP8266WiFi.h>
  #define RF_RECEIVER 5
  #define RELAY_PIN_1 4
  #define RELAY_PIN_2 14
#endif
#include "fauxmoESP.h"

#include <RCSwitch.h>

#define SERIAL_BAUDRATE 115200

#define WIFI_SSID "XXXXXXXXXX"
#define WIFI_PASS "XXXXXXXXXX"

#define LAMP_1 "lamp one"
#define LAMP_2 "lamp two"

fauxmoESP fauxmo;

RCSwitch mySwitch = RCSwitch();

// Wi-Fi Connection
void wifiSetup() {
  // Set WIFI module to STA mode
  WiFi.mode(WIFI_STA);

  // Connect
  Serial.printf("[WIFI] Connecting to %s ", WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  // Wait
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();

  // Connected!
  Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}

void setup() {
  pinMode(ultrasonic_pin_1, OUTPUT); // SRF04
  digitalWrite(ultrasonic_pin_1, LOW); // SRF04

  pinMode(ultrasonic_pin_2, OUTPUT); // SRF05
  digitalWrite(ultrasonic_pin_2, LOW); // SRF05    
  pinMode(TRIG_PIN, OUTPUT); // SRF05
  pinMode(ECHO_PIN, INPUT); // SRF05
  
  // Init serial port and clean garbage
  Serial.begin(SERIAL_BAUDRATE);
  Serial.println();

  // Wi-Fi connection
  wifiSetup();

  // LED
  pinMode(RELAY_PIN_1, OUTPUT);
  digitalWrite(RELAY_PIN_1, LOW);

  pinMode(RELAY_PIN_2, OUTPUT);
  digitalWrite(RELAY_PIN_2, LOW);
  
  mySwitch.enableReceive(RF_RECEIVER);  // Receiver on interrupt 0 => that is pin #2

  // By default, fauxmoESP creates it's own webserver on the defined port
  // The TCP port must be 80 for gen3 devices (default is 1901)
  // This has to be done before the call to enable()
  fauxmo.createServer(true); // not needed, this is the default value
  fauxmo.setPort(80); // This is required for gen3 devices

  // You have to call enable(true) once you have a WiFi connection
  // You can enable or disable the library at any moment
  // Disabling it will prevent the devices from being discovered and switched
  fauxmo.enable(true);
  // You can use different ways to invoke alexa to modify the devices state:
  // "Alexa, turn lamp two on"

  // Add virtual devices
  fauxmo.addDevice(LAMP_1);
  fauxmo.addDevice(LAMP_2);

  fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) {
    // Callback when a command from Alexa is received. 
    // You can use device_id or device_name to choose the element to perform an action onto (relay, LED,...)
    // State is a boolean (ON/OFF) and value a number from 0 to 255 (if you say "set kitchen light to 50%" you will receive a 128 here).
    // Just remember not to delay too much here, this is a callback, exit as soon as possible.
    // If you have to do something more involved here set a flag and process it in your main loop.
        
    Serial.printf("[MAIN] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value);
    if ( (strcmp(device_name, LAMP_1) == 0) ) {
      // this just sets a variable that the main loop() does something about
      Serial.println("RELAY 1 switched by Alexa");
      //digitalWrite(RELAY_PIN_1, !digitalRead(RELAY_PIN_1));
      if (state) {
        digitalWrite(RELAY_PIN_1, HIGH);
      } else {
        digitalWrite(RELAY_PIN_1, LOW);
      }
    }
    if ( (strcmp(device_name, LAMP_2) == 0) ) {
      // this just sets a variable that the main loop() does something about
      Serial.println("RELAY 2 switched by Alexa");
      if (state) {
        digitalWrite(RELAY_PIN_2, HIGH);
      } else {
        digitalWrite(RELAY_PIN_2, LOW);
      }
    }
  });

}

void loop() {
  delay(25);
  int rf_sensor_left = sonar.ping_cm(); // SRFO4
  
  if (rf_sensor_left<30){digitalWrite(ultrasonic_pin_1, HIGH);} // SRFO4
  else {digitalWrite(ultrasonic_pin_1, LOW);} // SRFO4 

  digitalWrite(TRIG_PIN, LOW); // SRFO5
  delayMicroseconds(2); // SRFO5
  digitalWrite(TRIG_PIN, HIGH); // SRFO5
  delayMicroseconds(10); // SRFO5
  digitalWrite(TRIG_PIN, LOW); // SRFO5  

  const unsigned long duration= pulseIn(ECHO_PIN, HIGH); // SRFO5
  int rf_sensor_right = duration/29/2; // SRFO5

  if (rf_sensor_right<30){digitalWrite(ultrasonic_pin_2, HIGH);} // SRFO5
  else {digitalWrite(ultrasonic_pin_2, LOW);} // SRFO5 

  Serial.print("Distance1: ");
  Serial.println(rf_sensor_left);  
  Serial.print("Distance2: ");
  Serial.println(rf_sensor_right);  
  Serial.println("  ");
  
  // fauxmoESP uses an async TCP server but a sync UDP server
  // Therefore, we have to manually poll for UDP packets
  fauxmo.handle();

  static unsigned long last = millis();
  if (millis() - last > 5000) {
    last = millis();
    Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
  }
    
  if (mySwitch.available()) {    
    if (mySwitch.getReceivedValue()==6819768) {
      digitalWrite(RELAY_PIN_1, !digitalRead(RELAY_PIN_1));
    }
    if (mySwitch.getReceivedValue()==9463928) {
      digitalWrite(RELAY_PIN_2, !digitalRead(RELAY_PIN_2));     
    }
    delay(600);
    mySwitch.resetAvailable();
  }
}

neural-network

Python
Code to test our Neural Network.
SECTION 5. NEURAL NETWORKS
import numpy as np

# We create the class 
class NeuralNetwork:

    def __init__(self, layers, activation='tanh'):
        if activation == 'sigmoid':
            self.activation = sigmoid
            self.activation_prime = sigmoid_derivada
        elif activation == 'tanh':
            self.activation = tanh
            self.activation_prime = tanh_derivada

        # Initialize the weights
        self.weights = []
        self.deltas = []
        # Assign random values to input layer and hidden layer
        for i in range(1, len(layers) - 1):
            r = 2*np.random.random((layers[i-1] + 1, layers[i] + 1)) -1
            self.weights.append(r)
        # Assigned random to output layer
        r = 2*np.random.random( (layers[i] + 1, layers[i+1])) - 1
        self.weights.append(r)

    def fit(self, X, y, learning_rate=0.2, epochs=100000):
        # I add column of ones to the X inputs. With this we add the Bias unit to the input layer
        ones = np.atleast_2d(np.ones(X.shape[0]))
        X = np.concatenate((ones.T, X), axis=1)
        
        for k in range(epochs):
            i = np.random.randint(X.shape[0])
            a = [X[i]]

            for l in range(len(self.weights)):
                    dot_value = np.dot(a[l], self.weights[l])
                    activation = self.activation(dot_value)
                    a.append(activation)
            #Calculate the difference in the output layer and the value obtained
            error = y[i] - a[-1]
            deltas = [error * self.activation_prime(a[-1])]
            
            # We start in the second layer until the last one (A layer before the output one)
            for l in range(len(a) - 2, 0, -1): 
                deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_prime(a[l]))
            self.deltas.append(deltas)

            # Reverse
            deltas.reverse()

            # Backpropagation
            # 1. Multiply the output delta with the input activations to obtain the weight gradient.             
            # 2. Updated the weight by subtracting a percentage of the gradient
            for i in range(len(self.weights)):
                layer = np.atleast_2d(a[i])
                delta = np.atleast_2d(deltas[i])
                self.weights[i] += learning_rate * layer.T.dot(delta)

            if k % 10000 == 0: print('epochs:', k)

    def predict(self, x): 
        ones = np.atleast_2d(np.ones(x.shape[0]))
        a = np.concatenate((np.ones(1).T, np.array(x)), axis=0)
        for l in range(0, len(self.weights)):
            a = self.activation(np.dot(a, self.weights[l]))
        return a

    def print_weights(self):
        print("LIST OF CONNECTION WEIGHTS")
        for i in range(len(self.weights)):
            print(self.weights[i])

    def get_weights(self):
        return self.weights
    
    def get_deltas(self):
        return self.deltas

# When creating the network, we can choose between using the sigmoid or tanh function
def sigmoid(x):
    return 1.0/(1.0 + np.exp(-x))

def sigmoid_derivada(x):
    return sigmoid(x)*(1.0-sigmoid(x))

def tanh(x):
    return np.tanh(x)

def tanh_derivada(x):
    return 1.0 - x**2

########## CAR NETWORK

nn = NeuralNetwork([6,3,4],activation ='tanh')
X = np.array([[0,0,0,0,0,0],   
              [0,0,0,0,0,1],   
              [0,0,0,0,1,0],   
              [0,0,0,0,1,1],   
              [0,0,0,1,0,0],   
              [0,0,0,1,0,1],   
              [0,0,0,1,1,0],   
              [0,0,0,1,1,1],   
              [0,0,1,0,0,0],  
              [0,0,1,0,0,1],   
              [0,0,1,0,1,1],   
              [0,0,1,1,0,0],   
              [0,0,1,1,0,1],   
              [0,0,1,1,1,1],   
              [0,1,0,0,0,0],   
              [0,1,0,0,0,1],   
              [0,1,0,0,1,0],   
              [0,1,0,1,0,0],   
              [0,1,0,1,0,1],   
              [0,1,0,1,1,0],   
              [0,1,1,0,0,0],   
              [0,1,1,0,1,0],   
              [0,1,1,1,0,0],   
              [0,1,1,1,1,0],   
              [1,0,0,0,0,0],   
              [1,0,0,0,0,1],   
              [1,0,0,0,1,0],   
              [1,0,0,0,1,1],   
              [1,0,0,1,0,0],   
              [1,0,0,1,0,1],   
              [1,0,0,1,1,0],   
              [1,0,0,1,1,1],   
              [1,0,1,0,0,0],   
              [1,0,1,0,0,1],   
              [1,0,1,0,1,1],   
              [1,0,1,1,0,0],   
              [1,0,1,1,0,1],   
              [1,0,1,1,1,1],   
              [1,1,0,0,0,0],   
              [1,1,0,0,0,1],   
              [1,1,0,0,1,0],   
              [1,1,0,1,0,0],   
              [1,1,0,1,0,1],   
              [1,1,0,1,1,0],   
              [1,1,1,0,0,0],   
              [1,1,1,0,1,0],   
              [1,1,1,1,0,0],   
              [1,1,1,1,1,0],   
             ])
# the outputs correspond to starting (or not) the motors
y = np.array([[0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop              
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop                
              [1,0,1,0], # forward 
              [1,0,1,0], # forward 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left 
              [0,1,0,1], # back
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [1,0,0,1], # turn-right 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left
              [1,0,0,1], # turn-right
              [0,1,1,0], # turn-left              
              [1,0,0,1], # turn-right 
              [1,0,1,0], # forward 
              [1,0,1,0], # forward
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right 
              [0,1,0,1], # back 
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right              
              [1,0,0,1], # turn-right            
             ])
nn.fit(X, y, learning_rate=0.03,epochs=550001)
 
def valNN(x):
    return (int)(abs(round(x)))
 
index=0
for e in X:
    prediccion = nn.predict(e)
    print("X:",e,"expected:",y[index],"obtained:", valNN(prediccion[0]),valNN(prediccion[1]),valNN(prediccion[2]),valNN(prediccion[3]))
    index=index+1

graphic

Python
Code to graph the Cost function.
SECTION 5. NEURAL NETWORKS
import numpy as np

# We create the class 
class NeuralNetwork:

    def __init__(self, layers, activation='tanh'):
        if activation == 'sigmoid':
            self.activation = sigmoid
            self.activation_prime = sigmoid_derivada
        elif activation == 'tanh':
            self.activation = tanh
            self.activation_prime = tanh_derivada

        # Initialize the weights
        self.weights = []
        self.deltas = []
        # Assign random values to input layer and hidden layer
        for i in range(1, len(layers) - 1):
            r = 2*np.random.random((layers[i-1] + 1, layers[i] + 1)) -1
            self.weights.append(r)
        # Assigned random to output layer
        r = 2*np.random.random( (layers[i] + 1, layers[i+1])) - 1
        self.weights.append(r)

    def fit(self, X, y, learning_rate=0.2, epochs=100000):
        # I add column of ones to the X inputs. With this we add the Bias unit to the input layer
        ones = np.atleast_2d(np.ones(X.shape[0]))
        X = np.concatenate((ones.T, X), axis=1)
        
        for k in range(epochs):
            i = np.random.randint(X.shape[0])
            a = [X[i]]

            for l in range(len(self.weights)):
                    dot_value = np.dot(a[l], self.weights[l])
                    activation = self.activation(dot_value)
                    a.append(activation)
            #Calculate the difference in the output layer and the value obtained
            error = y[i] - a[-1]
            deltas = [error * self.activation_prime(a[-1])]
            
            # We start in the second layer until the last one (A layer before the output one)
            for l in range(len(a) - 2, 0, -1): 
                deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_prime(a[l]))
            self.deltas.append(deltas)

            # Reverse
            deltas.reverse()

            # Backpropagation
            # 1. Multiply the output delta with the input activations to obtain the weight gradient.             
            # 2. Updated the weight by subtracting a percentage of the gradient
            for i in range(len(self.weights)):
                layer = np.atleast_2d(a[i])
                delta = np.atleast_2d(deltas[i])
                self.weights[i] += learning_rate * layer.T.dot(delta)

            if k % 10000 == 0: print('epochs:', k)

    def predict(self, x): 
        ones = np.atleast_2d(np.ones(x.shape[0]))
        a = np.concatenate((np.ones(1).T, np.array(x)), axis=0)
        for l in range(0, len(self.weights)):
            a = self.activation(np.dot(a, self.weights[l]))
        return a

    def print_weights(self):
        print("LIST OF CONNECTION WEIGHTS")
        for i in range(len(self.weights)):
            print(self.weights[i])

    def get_weights(self):
        return self.weights
    
    def get_deltas(self):
        return self.deltas

# When creating the network, we can choose between using the sigmoid or tanh function
def sigmoid(x):
    return 1.0/(1.0 + np.exp(-x))

def sigmoid_derivada(x):
    return sigmoid(x)*(1.0-sigmoid(x))

def tanh(x):
    return np.tanh(x)

def tanh_derivada(x):
    return 1.0 - x**2

########## CAR NETWORK

nn = NeuralNetwork([6,3,4],activation ='tanh')
X = np.array([[0,0,0,0,0,0],   
              [0,0,0,0,0,1],   
              [0,0,0,0,1,0],   
              [0,0,0,0,1,1],   
              [0,0,0,1,0,0],   
              [0,0,0,1,0,1],   
              [0,0,0,1,1,0],   
              [0,0,0,1,1,1],   
              [0,0,1,0,0,0],  
              [0,0,1,0,0,1],   
              [0,0,1,0,1,1],   
              [0,0,1,1,0,0],   
              [0,0,1,1,0,1],   
              [0,0,1,1,1,1],   
              [0,1,0,0,0,0],   
              [0,1,0,0,0,1],   
              [0,1,0,0,1,0],   
              [0,1,0,1,0,0],   
              [0,1,0,1,0,1],   
              [0,1,0,1,1,0],   
              [0,1,1,0,0,0],   
              [0,1,1,0,1,0],   
              [0,1,1,1,0,0],   
              [0,1,1,1,1,0],   
              [1,0,0,0,0,0],   
              [1,0,0,0,0,1],   
              [1,0,0,0,1,0],   
              [1,0,0,0,1,1],   
              [1,0,0,1,0,0],   
              [1,0,0,1,0,1],   
              [1,0,0,1,1,0],   
              [1,0,0,1,1,1],   
              [1,0,1,0,0,0],   
              [1,0,1,0,0,1],   
              [1,0,1,0,1,1],   
              [1,0,1,1,0,0],   
              [1,0,1,1,0,1],   
              [1,0,1,1,1,1],   
              [1,1,0,0,0,0],   
              [1,1,0,0,0,1],   
              [1,1,0,0,1,0],   
              [1,1,0,1,0,0],   
              [1,1,0,1,0,1],   
              [1,1,0,1,1,0],   
              [1,1,1,0,0,0],   
              [1,1,1,0,1,0],   
              [1,1,1,1,0,0],   
              [1,1,1,1,1,0],   
             ])
# the outputs correspond to starting (or not) the motors
y = np.array([[0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop              
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop                
              [1,0,1,0], # forward 
              [1,0,1,0], # forward 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left 
              [0,1,0,1], # back
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [1,0,0,1], # turn-right 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left
              [1,0,0,1], # turn-right
              [0,1,1,0], # turn-left              
              [1,0,0,1], # turn-right 
              [1,0,1,0], # forward 
              [1,0,1,0], # forward
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right 
              [0,1,0,1], # back 
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right              
              [1,0,0,1], # turn-right            
             ])
nn.fit(X, y, learning_rate=0.03,epochs=550001)
 
def valNN(x):
    return (int)(abs(round(x)))
 
index=0
for e in X:
    prediccion = nn.predict(e)
    print("X:",e,"expected:",y[index],"obtained:", valNN(prediccion[0]),valNN(prediccion[1]),valNN(prediccion[2]),valNN(prediccion[3]))
    index=index+1

########## WE GRAPH THE COST FUNCTION
import matplotlib.pyplot as plt
deltas = nn.get_deltas()
valores=[]
index=0
for arreglo in deltas:
valores.append(arreglo[1][0] + arreglo[1][1])
index=index+1
plt.plot(range(len(valores)), valores, color='b')
plt.ylim([0, 1])
plt.ylabel('Cost')
plt.xlabel('Epochs')
plt.tight_layout()
plt.show()

generate-arduino-code

Python
We generate the Arduino code: Hidden weights and Output weights.
SECTION 5. NEURAL NETWORKS
import numpy as np

# We create the class 
class NeuralNetwork:

    def __init__(self, layers, activation='tanh'):
        if activation == 'sigmoid':
            self.activation = sigmoid
            self.activation_prime = sigmoid_derivada
        elif activation == 'tanh':
            self.activation = tanh
            self.activation_prime = tanh_derivada

        # Initialize the weights
        self.weights = []
        self.deltas = []
        # Assign random values to input layer and hidden layer
        for i in range(1, len(layers) - 1):
            r = 2*np.random.random((layers[i-1] + 1, layers[i] + 1)) -1
            self.weights.append(r)
        # Assigned random to output layer
        r = 2*np.random.random( (layers[i] + 1, layers[i+1])) - 1
        self.weights.append(r)

    def fit(self, X, y, learning_rate=0.2, epochs=100000):
        # I add column of ones to the X inputs. With this we add the Bias unit to the input layer
        ones = np.atleast_2d(np.ones(X.shape[0]))
        X = np.concatenate((ones.T, X), axis=1)
        
        for k in range(epochs):
            i = np.random.randint(X.shape[0])
            a = [X[i]]

            for l in range(len(self.weights)):
                    dot_value = np.dot(a[l], self.weights[l])
                    activation = self.activation(dot_value)
                    a.append(activation)
            #Calculate the difference in the output layer and the value obtained
            error = y[i] - a[-1]
            deltas = [error * self.activation_prime(a[-1])]
            
            # We start in the second layer until the last one (A layer before the output one)
            for l in range(len(a) - 2, 0, -1): 
                deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_prime(a[l]))
            self.deltas.append(deltas)

            # Reverse
            deltas.reverse()

            # Backpropagation
            # 1. Multiply the output delta with the input activations to obtain the weight gradient.             
            # 2. Updated the weight by subtracting a percentage of the gradient
            for i in range(len(self.weights)):
                layer = np.atleast_2d(a[i])
                delta = np.atleast_2d(deltas[i])
                self.weights[i] += learning_rate * layer.T.dot(delta)

            if k % 10000 == 0: print('epochs:', k)

    def predict(self, x): 
        ones = np.atleast_2d(np.ones(x.shape[0]))
        a = np.concatenate((np.ones(1).T, np.array(x)), axis=0)
        for l in range(0, len(self.weights)):
            a = self.activation(np.dot(a, self.weights[l]))
        return a

    def print_weights(self):
        print("LIST OF CONNECTION WEIGHTS")
        for i in range(len(self.weights)):
            print(self.weights[i])

    def get_weights(self):
        return self.weights
    
    def get_deltas(self):
        return self.deltas

# When creating the network, we can choose between using the sigmoid or tanh function
def sigmoid(x):
    return 1.0/(1.0 + np.exp(-x))

def sigmoid_derivada(x):
    return sigmoid(x)*(1.0-sigmoid(x))

def tanh(x):
    return np.tanh(x)

def tanh_derivada(x):
    return 1.0 - x**2

########## CAR NETWORK

nn = NeuralNetwork([6,3,4],activation ='tanh')
X = np.array([[0,0,0,0,0,0],   
              [0,0,0,0,0,1],   
              [0,0,0,0,1,0],   
              [0,0,0,0,1,1],   
              [0,0,0,1,0,0],   
              [0,0,0,1,0,1],   
              [0,0,0,1,1,0],   
              [0,0,0,1,1,1],   
              [0,0,1,0,0,0],  
              [0,0,1,0,0,1],   
              [0,0,1,0,1,1],   
              [0,0,1,1,0,0],   
              [0,0,1,1,0,1],   
              [0,0,1,1,1,1],   
              [0,1,0,0,0,0],   
              [0,1,0,0,0,1],   
              [0,1,0,0,1,0],   
              [0,1,0,1,0,0],   
              [0,1,0,1,0,1],   
              [0,1,0,1,1,0],   
              [0,1,1,0,0,0],   
              [0,1,1,0,1,0],   
              [0,1,1,1,0,0],   
              [0,1,1,1,1,0],   
              [1,0,0,0,0,0],   
              [1,0,0,0,0,1],   
              [1,0,0,0,1,0],   
              [1,0,0,0,1,1],   
              [1,0,0,1,0,0],   
              [1,0,0,1,0,1],   
              [1,0,0,1,1,0],   
              [1,0,0,1,1,1],   
              [1,0,1,0,0,0],   
              [1,0,1,0,0,1],   
              [1,0,1,0,1,1],   
              [1,0,1,1,0,0],   
              [1,0,1,1,0,1],   
              [1,0,1,1,1,1],   
              [1,1,0,0,0,0],   
              [1,1,0,0,0,1],   
              [1,1,0,0,1,0],   
              [1,1,0,1,0,0],   
              [1,1,0,1,0,1],   
              [1,1,0,1,1,0],   
              [1,1,1,0,0,0],   
              [1,1,1,0,1,0],   
              [1,1,1,1,0,0],   
              [1,1,1,1,1,0],   
             ])
# the outputs correspond to starting (or not) the motors
y = np.array([[0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop              
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop
              [0,0,0,0], # stop
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop 
              [0,0,0,0], # stop                
              [1,0,1,0], # forward 
              [1,0,1,0], # forward 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left 
              [0,1,0,1], # back
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [0,1,1,0], # turn-left 
              [1,0,0,1], # turn-right 
              [0,1,1,0], # turn-left
              [0,1,1,0], # turn-left
              [1,0,0,1], # turn-right
              [0,1,1,0], # turn-left              
              [1,0,0,1], # turn-right 
              [1,0,1,0], # forward 
              [1,0,1,0], # forward
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right 
              [0,1,0,1], # back 
              [1,0,0,1], # turn-right 
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right
              [1,0,0,1], # turn-right              
              [1,0,0,1], # turn-right            
             ])
nn.fit(X, y, learning_rate=0.03,epochs=550001)
 
def valNN(x):
    return (int)(abs(round(x)))
 
index=0
for e in X:
    prediccion = nn.predict(e)
    print("X:",e,"expected:",y[index],"obtained:", valNN(prediccion[0]),valNN(prediccion[1]),valNN(prediccion[2]),valNN(prediccion[3]))
    index=index+1


########## WE GENERATE THE ARDUINO CODE
def to_str(name, W):
    s = str(W.tolist()).replace('[', '{').replace(']', '}')
    return 'float '+name+'['+str(W.shape[0])+']['+str(W.shape[1])+'] = ' + s + ';'

# We get the weights trained to be able to use them in the arduino code
pesos = nn.get_weights();

print('// Replace these lines in your arduino code:')
print('// float HiddenWeights ...')
print('// float OutputWeights ...')
print('// With trained weights.')
print('\n')
print(to_str('HiddenWeights', pesos[0]))
print(to_str('OutputWeights', pesos[1]))

tesla-robot

Arduino
This code must be uploaded to the Arduino UNO board.
SECTION 5. NEURAL NETWORKS
// AUTHOR: GUILLERMO PEREZ GUILLEN
// Project: TESLA Robot

#define ENA 3
#define ENB 5
#define IN1 8
#define IN2 9
#define IN3 10
#define IN4 11

/******************************************************************
   NETWORK CONFIGURATION
******************************************************************/
const int ESP32_pin_1= 6; // ESP32 input pin 1 - starting
const int ESP32_pin_2 = 7; // ESP32 input pin 2 - SRF04
const int ESP32_pin_3 = 12; // ESP32 input pin 3 - SRF05
const int InputNodes = 7; // includes BIAS neuron
const int HiddenNodes = 4; //includes BIAS neuron
const int OutputNodes = 4;
int i, j;
double Accum;
double Hidden[HiddenNodes];
double Output[OutputNodes];
float HiddenWeights[7][4] = {{-4.618963658666277, 4.3001137618883325, 7.338055706191847, 2.7355309007172375}, {2.599633307446623, -7.649705724376986, -14.69443684121685, -3.65366992422193}, {-0.7777191662679982, 1.9860139431844053, 5.914809078303235, 0.03170277380327093}, {-2.309653145069323, 6.8379997039119775, 8.892299055796917, 0.6046238076393062}, {1.3276547120093833, 5.085574619860947, 2.384944264717347, 0.05753178068519734}, {-2.7696264005599858, 6.797226565794283, 3.5374247269984713, 0.5475825968169957}, {0.8118152131237218, -1.9324229493484606, -5.264294920291424, -0.036800281071245555}};
float OutputWeights[4][4] = {{-1.6342640637903814, 0.006920937706630823, -5.179205882976105, -0.40268984302793936}, {-1.0162353344988182, 1.3405072244655225, -4.241619375014734, 0.6682851389512594}, {1.3692632942485174, -1.3884291338648505, -0.9245235380688354, 2.246128813012694}, {-1.9802299382328057, 0.06512857708456388, -0.030302930346753857, -3.314024844617794}};

int error=0;
int dif,difAnt=0;
const float Kp=0.1;
const float Kd=0.1;

void setup() {	
	Serial.begin(9600);
	pinMode(A0, INPUT); //left sensor
	pinMode(A1, INPUT); //center sensor
	pinMode(A3, INPUT); //right sensor 
	pinMode(IN1, OUTPUT);
	pinMode(IN2, OUTPUT);
	pinMode(IN3, OUTPUT);
	pinMode(IN4, OUTPUT);
	pinMode(ENA, OUTPUT);
	pinMode(ENB, OUTPUT);
  pinMode(ESP32_pin_1, INPUT); 
  pinMode(ESP32_pin_2, INPUT);
  pinMode(ESP32_pin_3, INPUT);  
} 

void loop()
{

double TestInput[] = {0, 0, 0};
double input1=0,input2=0,input3=0,input4=0,input5=0,input6=0;
    
float volts0 =  analogRead(A0)*0.0048828125;  // value from sensor * (5/1024) 
float volts1 =  analogRead(A1)*0.0048828125;  // value from sensor * (5/1024) 
float volts2 =  analogRead(A3)*0.0048828125;  // value from sensor * (5/1024)

dif = analogRead(A3) - analogRead(A0);	// PID CONTROLLER
error = floor(Kp*(dif)+Kd*(difAnt-dif));	// PID CONTROLLER
difAnt=dif;	// PID CONTROLLER
int d0 = constrain(150 - error, 0, 150);//left speed - PID CONTROLLER
int d1 = constrain(150 + error, 0, 150);//right speed - PID CONTROLLER

float ir_sensor_left =  6*pow(volts0, -1); // worked out from datasheet graph //GP2Y0A51SK0F - 2 a 15 cm
float ir_sensor_center = 12.4*pow(volts1, -1); // worked out from datasheet graph //GP2Y0A41SK0F - 4 a 30 cm
float ir_sensor_right = 5.2*pow(volts2, -1); // worked out from datasheet graph //GP2Y0A51SK0F - 2 a 15 cm

if(digitalRead(ESP32_pin_1) == HIGH){input1=1;} // START TO MOVE
else {input1=0;} // STOP

if (ir_sensor_left<15){input2=1;} // IR SENSOR LEFT
else {input2=0;}

if(digitalRead(ESP32_pin_2) == HIGH){input3=1;} // RF SENSOR LEFT
else {input3=0;}
	
if (ir_sensor_center<30){input4=1;}  // IR SENSOR CENTER
else {input4=0;}

if(digitalRead(ESP32_pin_3) == HIGH){input5=1;} // RF SENSOR RIGHT
else {input5=0;}

if (ir_sensor_right<15){input6=1;} // IR SENSOR RIGHT
else {input6=0;}

/******************************************************************
    WE CALL THE FEEDFORWARD NETWORK WITH THE INPUTS
******************************************************************/

  Serial.print("Input1:");
  Serial.println(input1);
  Serial.print("Input2:");
  Serial.println(input2);
  Serial.print("Input3:");
  Serial.println(input3);  
  Serial.print("Input4:");
  Serial.println(input4);
  Serial.print("Input5:");
  Serial.println(input5);
  Serial.print("Input6:");
  Serial.println(input6); 
  Serial.println("   ");   
  
//THESE ARE THE THREE INPUTS WITH VALUES OF 0 TO 1 ********************
  TestInput[0] = 1.0;//BIAS UNIT
  TestInput[1] = input1;
  TestInput[2] = input2;
  TestInput[3] = input3;  
  TestInput[4] = input4;
  TestInput[5] = input5;
  TestInput[6] = input6;  

// THIS FUNCTION IS TO GET THE OUTPUTS **********************************
  InputToOutput(TestInput[0], TestInput[1], TestInput[2], TestInput[3], TestInput[4], TestInput[5], TestInput[6]); //INPUT to ANN to obtain OUTPUT

  int out1 = round(abs(Output[0]));
  int out2 = round(abs(Output[1]));
  int out3 = round(abs(Output[2]));
  int out4 = round(abs(Output[3]));
  Serial.print("Output1:");
  Serial.println(out1);
  Serial.print("Output2:");
  Serial.println(out2);
  Serial.print("Output3:");
  Serial.println(out3);
  Serial.print("Output4:");
  Serial.println(out4);  
  Serial.println("   ");

/******************************************************************
    DRIVE MOTORS WITH THE NETWORK OUTPUT
******************************************************************/
  analogWrite(ENA, d0);
  analogWrite(ENB, d1);
  digitalWrite(IN1, out1 * HIGH); 
  digitalWrite(IN2, out2 * HIGH); 
  digitalWrite(IN3, out3 * HIGH);
  digitalWrite(IN4, out4 * HIGH);
  delay(20);
}

void InputToOutput(double In1, double In2, double In3, double In4, double In5, double In6, double In7)
{
  double TestInput[] = {0, 0, 0, 0, 0, 0, 0};
  TestInput[0] = In1;
  TestInput[1] = In2;
  TestInput[2] = In3;
  TestInput[3] = In4;
  TestInput[4] = In5;
  TestInput[5] = In6;
  TestInput[6] = In7;    

/******************************************************************
    CALCULATE ACTIVITIES IN HIDDEN LAYERS
******************************************************************/

  for ( i = 0 ; i < HiddenNodes ; i++ ) {	// We go through the four columns of the hidden weights
    Accum = 0;
    for ( j = 0 ; j < InputNodes ; j++ ) {	// Three values of the entry line and each column of hidden weights
      Accum += TestInput[j] * HiddenWeights[j][i] ;
    }
    Hidden[i] = tanh(Accum) ; // We obtain a matrix of a line with four values
  }

/******************************************************************
    CALCULATE ACTIVATION AND ERROR IN THE OUTPUT LAYER
******************************************************************/

  for ( i = 0 ; i < OutputNodes ; i++ ) {
    Accum = 0;
    for ( j = 0 ; j < HiddenNodes ; j++ ) {
        Accum += Hidden[j] * OutputWeights[j][i] ;
    }
    Output[i] = tanh(Accum) ;//tanh
  }
}

arduino_pro_mini

Arduino
SECTION 11. OPENCV
#include <Servo.h>
int data_x = 0;
int data_y = 0;
int data[1];
Servo myservo_x;
Servo myservo_y;// create servo object to control a servo

void setup() {
  Serial.begin(9600);
  myservo_x.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo_y.attach(10);
  myservo_x.write(90);
  myservo_y.write(90);
}

void loop() {
  while (Serial.available() >= 2) {
    for (int i = 0; i < 2; i++) {
      data[i] = Serial.read();
    }

    myservo_x.write(data[0]);
    myservo_y.write(data[1]);

    Serial.println(data[0]);
    Serial.println(data[1]);
  }
  
}

tesla_robot

Python
SECTION 11. OPENCV
# import the necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
import serial
import struct
a=0
b=0
x1=0
y1=0
ser = serial.Serial('/dev/ttyUSB0',9600)

# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))

#Load a cascade file for detecting faces
backless_stool_cascade = cv2.CascadeClassifier('backless_stool.xml')

# allow the camera to warmup
time.sleep(0.1)
count = 0

# capture frames from the camera
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
        image = frame.array
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        backless_stool = backless_stool_cascade.detectMultiScale(gray, 1.3, 5)
        for (x,y,w,h) in backless_stool:
                a=int((2*x+w)/2)
                b=int((2*y+h)/2)
                x1=int(a/3.66)
                y1=int(b/2.55)
                ser.write(struct.pack('>BB', x1,y1))
                cv2.rectangle(image, (x,y), (x+w,y+h), (255,0,0), 2)
                count += 1
        # show the frame
        cv2.imshow("Frame", image)
        key = cv2.waitKey(1) & 0xFF

        # clear the stream in preparation for the next frame
        rawCapture.truncate(0)

        # if the `q` key was pressed, break from the loop
        if key == ord("q"):
                break

backless_stool

XML
SECTION 11. OPENCV
<?xml version="1.0"?>
<opencv_storage>
<backless_stool type_id="opencv-haar-classifier">
  <size>
    24 24</size>
  <stages>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 1 24 5 -1.</_>
                <_>
                  6 1 12 5 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0397395193576813</threshold>
            <left_val>0.7192983031272888</left_val>
            <right_val>-0.9534887075424194</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  5 0 15 8 -1.</_>
                <_>
                  5 2 15 4 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0531278103590012</threshold>
            <left_val>0.8463115096092224</left_val>
            <right_val>-0.7269961833953857</right_val></_></_></trees>
      <stage_threshold>-0.1071771979331970</stage_threshold>
      <parent>-1</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  2 12 7 12 -1.</_>
                <_>
                  2 18 7 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0133920600637794</threshold>
            <left_val>-0.8974360227584839</left_val>
            <right_val>0.5737708210945129</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 20 23 4 -1.</_>
                <_>
                  1 22 23 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>4.9831178039312363e-003</threshold>
            <left_val>-0.9548441171646118</left_val>
            <right_val>0.3902384042739868</right_val></_></_></trees>
      <stage_threshold>-0.5071976184844971</stage_threshold>
      <parent>0</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  9 3 6 9 -1.</_>
                <_>
                  11 6 2 3 9.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0372356586158276</threshold>
            <left_val>-0.6481481790542603</left_val>
            <right_val>0.7608699202537537</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  7 13 14 10 -1.</_>
                <_>
                  7 18 14 5 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0301237292587757</threshold>
            <left_val>-0.8192288279533386</left_val>
            <right_val>0.5084651708602905</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  7 7 7 2 -1.</_>
                <_>
                  7 8 7 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-3.0422038980759680e-004</threshold>
            <left_val>-0.9449316263198853</left_val>
            <right_val>0.4629398882389069</right_val></_></_></trees>
      <stage_threshold>-1.0044369697570801</stage_threshold>
      <parent>1</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  3 12 18 12 -1.</_>
                <_>
                  3 18 18 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0779372230172157</threshold>
            <left_val>-0.7446808815002441</left_val>
            <right_val>0.6603776216506958</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  16 4 8 1 -1.</_>
                <_>
                  16 4 4 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-5.1782950758934021e-003</threshold>
            <left_val>0.4554198980331421</left_val>
            <right_val>-0.6620771884918213</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 0 22 12 -1.</_>
                <_>
                  11 0 11 12 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0287767406553030</threshold>
            <left_val>0.5085014104843140</left_val>
            <right_val>-0.9999982714653015</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  17 0 2 12 -1.</_>
                <_>
                  17 0 2 6 2.</_></rects>
              <tilted>1</tilted></feature>
            <threshold>-0.0668981373310089</threshold>
            <left_val>0.8492817878723145</left_val>
            <right_val>-0.1955482959747315</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  7 0 12 2 -1.</_>
                <_>
                  7 0 6 2 2.</_></rects>
              <tilted>1</tilted></feature>
            <threshold>-7.0841149426996708e-003</threshold>
            <left_val>0.6581171751022339</left_val>
            <right_val>-0.7529721260070801</right_val></_></_></trees>
      <stage_threshold>-0.4417186081409454</stage_threshold>
      <parent>2</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  10 3 9 3 -1.</_>
                <_>
                  13 6 3 3 3.</_></rects>
              <tilted>1</tilted></feature>
            <threshold>0.0386693887412548</threshold>
            <left_val>-0.4960631132125855</left_val>
            <right_val>0.8630141019821167</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  5 3 15 4 -1.</_>
                <_>
                  5 5 15 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0142873600125313</threshold>
            <left_val>-0.6801661849021912</left_val>
            <right_val>0.6148207783699036</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 2 16 5 -1.</_>
                <_>
                  4 2 8 5 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0175723508000374</threshold>
            <left_val>0.5339154005050659</left_val>
            <right_val>-0.8775107264518738</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  9 2 6 19 -1.</_>
                <_>
                  11 2 2 19 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0111840097233653</threshold>
            <left_val>-0.6239606142044067</left_val>
            <right_val>0.7567353248596191</right_val></_></_></trees>
      <stage_threshold>-2.0176169928163290e-003</stage_threshold>
      <parent>3</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 7 24 4 -1.</_>
                <_>
                  12 7 12 4 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0206772498786449</threshold>
            <left_val>-0.9701492786407471</left_val>
            <right_val>0.4887219965457916</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  4 0 16 2 -1.</_>
                <_>
                  4 1 16 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0211514104157686</threshold>
            <left_val>0.9800416231155396</left_val>
            <right_val>-0.5131117105484009</right_val></_></_></trees>
      <stage_threshold>-0.0243896804749966</stage_threshold>
      <parent>4</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 6 14 -1.</_>
                <_>
                  3 3 3 14 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0364018604159355</threshold>
            <left_val>0.8000000715255737</left_val>
            <right_val>-0.6545457243919373</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  20 0 4 2 -1.</_>
                <_>
                  22 0 2 1 2.</_>
                <_>
                  20 1 2 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>6.4766027207951993e-005</threshold>
            <left_val>0.3156177997589111</left_val>
            <right_val>-0.9415168762207031</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 11 1 12 -1.</_>
                <_>
                  0 17 1 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>1.5091469686012715e-004</threshold>
            <left_val>0.4079472124576569</left_val>
            <right_val>-0.9225099086761475</right_val></_></_></trees>
      <stage_threshold>0.0690192282199860</stage_threshold>
      <parent>5</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 8 11 16 -1.</_>
                <_>
                  0 16 11 8 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0101257404312491</threshold>
            <left_val>-0.8571429252624512</left_val>
            <right_val>0.4615387022495270</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  15 10 9 12 -1.</_>
                <_>
                  15 13 9 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-4.1803130879998207e-003</threshold>
            <left_val>0.2836835980415344</left_val>
            <right_val>-0.5653936862945557</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 1 3 -1.</_>
                <_>
                  0 4 1 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>8.9554123405832797e-005</threshold>
            <left_val>0.4197803139686585</left_val>
            <right_val>-1.0000009536743164</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  22 1 2 4 -1.</_>
                <_>
                  22 2 2 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.2630630226340145e-004</threshold>
            <left_val>-0.7179523110389710</left_val>
            <right_val>0.1920651048421860</right_val></_></_></trees>
      <stage_threshold>-0.8716313242912293</stage_threshold>
      <parent>6</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 1 3 -1.</_>
                <_>
                  0 4 1 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.0623309935908765e-004</threshold>
            <left_val>-0.8666666746139526</left_val>
            <right_val>0.5200002193450928</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  16 5 6 9 -1.</_>
                <_>
                  18 5 2 9 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0319604910910130</threshold>
            <left_val>0.7408257722854614</left_val>
            <right_val>-0.3691309988498688</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  2 11 20 1 -1.</_>
                <_>
                  12 11 10 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>4.0972880087792873e-003</threshold>
            <left_val>0.4528208971023560</left_val>
            <right_val>-0.9418817162513733</right_val></_></_></trees>
      <stage_threshold>-0.7829769253730774</stage_threshold>
      <parent>7</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  8 0 8 4 -1.</_>
                <_>
                  8 2 8 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0105510400608182</threshold>
            <left_val>0.5769231915473938</left_val>
            <right_val>-0.6250002980232239</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 10 24 5 -1.</_>
                <_>
                  0 10 12 5 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0239332895725966</threshold>
            <left_val>0.4182483851909638</left_val>
            <right_val>-0.9770908951759338</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  3 12 4 12 -1.</_>
                <_>
                  3 12 2 6 2.</_>
                <_>
                  5 18 2 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-6.5914168953895569e-003</threshold>
            <left_val>0.8027929067611694</left_val>
            <right_val>-0.4880040884017944</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  23 3 1 3 -1.</_>
                <_>
                  23 4 1 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>1.0756860137917101e-004</threshold>
            <left_val>0.3319399058818817</left_val>
            <right_val>-0.9648504853248596</right_val></_></_></trees>
      <stage_threshold>-0.5562319755554199</stage_threshold>
      <parent>8</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 2 3 -1.</_>
                <_>
                  0 4 2 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.2125170178478584e-004</threshold>
            <left_val>-0.8108109235763550</left_val>
            <right_val>0.4761906862258911</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  22 2 2 6 -1.</_>
                <_>
                  23 2 1 3 2.</_>
                <_>
                  22 5 1 3 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-2.6081630494445562e-004</threshold>
            <left_val>-0.6938291788101196</left_val>
            <right_val>0.1398365050554276</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 2 2 6 -1.</_>
                <_>
                  0 4 2 2 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>5.4505438311025500e-004</threshold>
            <left_val>0.4776296913623810</left_val>
            <right_val>-0.8856533765792847</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  23 1 1 20 -1.</_>
                <_>
                  23 6 1 10 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>7.8087239526212215e-003</threshold>
            <left_val>0.1218660026788712</left_val>
            <right_val>-0.9483538866043091</right_val></_></_></trees>
      <stage_threshold>-0.9051445126533508</stage_threshold>
      <parent>9</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 1 3 -1.</_>
                <_>
                  0 4 1 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-6.1423881561495364e-005</threshold>
            <left_val>-0.8055555820465088</left_val>
            <right_val>0.4531252086162567</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  23 5 1 12 -1.</_>
                <_>
                  23 8 1 6 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>1.9589499570429325e-003</threshold>
            <left_val>0.1941449046134949</left_val>
            <right_val>-0.9999995231628418</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  9 0 2 1 -1.</_>
                <_>
                  9 0 1 1 2.</_></rects>
              <tilted>1</tilted></feature>
            <threshold>5.8449467178434134e-004</threshold>
            <left_val>-0.6846153736114502</left_val>
            <right_val>0.4672062098979950</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 8 24 14 -1.</_>
                <_>
                  12 8 12 7 2.</_>
                <_>
                  0 15 12 7 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0309738796204329</threshold>
            <left_val>-0.8576679825782776</left_val>
            <right_val>0.3903138041496277</right_val></_></_></trees>
      <stage_threshold>-0.9057124853134155</stage_threshold>
      <parent>10</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 2 20 20 -1.</_>
                <_>
                  1 2 10 10 2.</_>
                <_>
                  11 12 10 10 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0108273997902870</threshold>
            <left_val>-0.9622641801834106</left_val>
            <right_val>0.3469389975070953</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  23 0 1 9 -1.</_>
                <_>
                  23 3 1 3 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.2067460193065926e-004</threshold>
            <left_val>-0.8528633713722229</left_val>
            <right_val>0.3308951854705811</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  2 8 6 3 -1.</_>
                <_>
                  4 8 2 3 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0147369699552655</threshold>
            <left_val>0.8104264140129089</left_val>
            <right_val>-0.4081099033355713</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  10 0 9 1 -1.</_>
                <_>
                  13 0 3 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>4.1425650124438107e-004</threshold>
            <left_val>0.2163763046264648</left_val>
            <right_val>-0.7226182818412781</right_val></_></_></trees>
      <stage_threshold>-0.6976581215858460</stage_threshold>
      <parent>11</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 0 10 4 -1.</_>
                <_>
                  1 2 10 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0115176895633340</threshold>
            <left_val>0.5229359269142151</left_val>
            <right_val>-0.6263738870620728</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 0 24 24 -1.</_>
                <_>
                  12 0 12 12 2.</_>
                <_>
                  0 12 12 12 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0611945390701294</threshold>
            <left_val>-0.8847184777259827</left_val>
            <right_val>0.3812389969825745</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  2 7 7 12 -1.</_>
                <_>
                  2 11 7 4 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-5.9631778858602047e-003</threshold>
            <left_val>0.3928265869617462</left_val>
            <right_val>-0.7859526276588440</right_val></_></_></trees>
      <stage_threshold>0.0310439206659794</stage_threshold>
      <parent>12</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  9 0 6 1 -1.</_>
                <_>
                  11 0 2 1 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>4.5093629159964621e-004</threshold>
            <left_val>0.3611111938953400</left_val>
            <right_val>-0.9285718798637390</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  23 0 1 8 -1.</_>
                <_>
                  23 2 1 4 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.0347829665988684e-003</threshold>
            <left_val>-0.9142392873764038</left_val>
            <right_val>0.1227196976542473</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  3 2 16 8 -1.</_>
                <_>
                  3 6 16 4 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0356906391680241</threshold>
            <left_val>-0.7475386857986450</left_val>
            <right_val>0.4589936137199402</right_val></_></_></trees>
      <stage_threshold>-0.3468585908412933</stage_threshold>
      <parent>13</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 3 1 4 -1.</_>
                <_>
                  0 4 1 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-3.0378170777112246e-005</threshold>
            <left_val>-0.8461539149284363</left_val>
            <right_val>0.4074076116085053</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  14 5 6 6 -1.</_>
                <_>
                  16 5 2 6 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0280334800481796</threshold>
            <left_val>-0.3366034030914307</left_val>
            <right_val>0.7873615026473999</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 7 5 4 -1.</_>
                <_>
                  1 8 5 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>1.2439950369298458e-003</threshold>
            <left_val>0.3421046137809753</left_val>
            <right_val>-0.9999991059303284</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  21 0 2 21 -1.</_>
                <_>
                  21 7 2 7 3.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-0.0229012705385685</threshold>
            <left_val>-0.6711586713790894</left_val>
            <right_val>0.0878137573599815</right_val></_></_></trees>
      <stage_threshold>-0.7528389096260071</stage_threshold>
      <parent>14</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 22 21 2 -1.</_>
                <_>
                  0 23 21 1 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>4.1951439925469458e-004</threshold>
            <left_val>-0.7662339210510254</left_val>
            <right_val>0.4796749949455261</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  22 10 2 14 -1.</_>
                <_>
                  23 10 1 7 2.</_>
                <_>
                  22 17 1 7 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>1.2045910261804238e-004</threshold>
            <left_val>0.1558558940887451</left_val>
            <right_val>-0.4598528146743774</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 1 1 10 -1.</_>
                <_>
                  1 6 1 5 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>6.8978767376393080e-004</threshold>
            <left_val>0.4189130961894989</left_val>
            <right_val>-0.8768467903137207</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  0 0 24 3 -1.</_>
                <_>
                  0 0 12 3 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>0.0284243300557137</threshold>
            <left_val>0.3624621927738190</left_val>
            <right_val>-0.9427158236503601</right_val></_></_></trees>
      <stage_threshold>-0.5039803981781006</stage_threshold>
      <parent>15</parent>
      <next>-1</next></_>
    <_>
      <trees>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  1 7 2 4 -1.</_>
                <_>
                  1 8 2 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-7.5075658969581127e-005</threshold>
            <left_val>-0.7681161165237427</left_val>
            <right_val>0.4045804142951965</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  11 17 8 2 -1.</_>
                <_>
                  13 17 4 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-1.6034709988161922e-003</threshold>
            <left_val>0.3553181886672974</left_val>
            <right_val>-0.4333913028240204</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  5 17 8 2 -1.</_>
                <_>
                  7 17 4 2 2.</_></rects>
              <tilted>0</tilted></feature>
            <threshold>-6.2464210204780102e-003</threshold>
            <left_val>0.8650658726692200</left_val>
            <right_val>-0.3416143953800201</right_val></_></_>
        <_>
          <_>
            <feature>
              <rects>
                <_>
                  13 1 2 12 -1.</_>
                <_>
                  10 4 2 6 2.</_></rects>
              <tilted>1</tilted></feature>
            <threshold>8.4396954625844955e-003</threshold>
            <left_val>-0.2594197988510132</left_val>
            <right_val>0.4685227870941162</right_val></_></_></trees>
      <stage_threshold>-0.6298450827598572</stage_threshold>
      <parent>16</parent>
      <next>-1</next></_></stages></backless_stool>
</opencv_storage>

uv-meter

Arduino
This code must be uploaded to the Arduino Mega 2560 board.
SECTION 7. TESLA COIL & UV LAMP
//AUTHOR: GUILLERMO PEREZ GUILLEN

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;      
#include <TouchScreen.h>

int16_t BOXSIZE;
uint16_t ID, currentcolor;
uint8_t Orientation = 0;    //PORTRAIT
String UVIndex = "0";
String Index = " ";  

// Assign human-readable names to some common 16-bit color values:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

void setup()
{
    while (!Serial);
  Serial.begin(57600);
   
    uint16_t tmp;
    tft.reset();
    ID = tft.readID();
    tft.begin(ID);
    tft.setRotation(Orientation);
    tft.fillScreen(BLACK);
}
 
void loop()
{
  float sensorVoltage;
  float sensorValue;

  sensorValue = analogRead(A8);
  sensorVoltage = (sensorValue * (5.0 / 1023.0))*1000;  //Voltage in miliVolts

////////////////////////// UV Index

  if(sensorVoltage<50.0)
  {
    UVIndex = "0";
    Index = "LOW";
  }
  else if (sensorVoltage>=50.0 && sensorVoltage<227.0)
  {
    UVIndex = "0";
    Index = "LOW";
  }
  else if (sensorVoltage>=227 && sensorVoltage<318)
  {
    UVIndex = "1";
    Index = "LOW";    
  }
  else if (sensorVoltage>=318 && sensorVoltage<408)
  {
    UVIndex = "2";
    Index = "LOW";    
  }else if (sensorVoltage>=408 && sensorVoltage<503)
  {
    UVIndex = "3";
    Index = "MEDIUM";    
  }
  else if (sensorVoltage>=503 && sensorVoltage<606)
  {
    UVIndex = "4";
    Index = "MEDIUM";    
  }else if (sensorVoltage>=606 && sensorVoltage<696)
  {
    UVIndex = "5";
    Index = "MEDIUM";    
  }else if (sensorVoltage>=696 && sensorVoltage<795)
  {
    UVIndex = "6";
    Index = "HIGH";    
  }else if (sensorVoltage>=795 && sensorVoltage<881)
  {
    UVIndex = "7";
    Index = "HIGH";    
  }
  else if (sensorVoltage>=881 && sensorVoltage<976)
  {
    UVIndex = "8";
    Index = "VERY HIGH";    
  }
  else if (sensorVoltage>=976 && sensorVoltage<1079)
  {
    UVIndex = "9";
    Index = "VERY HIGH";    
  }
  else if (sensorVoltage>=1079 && sensorVoltage<1170)
  {
    UVIndex = "10";
    Index = "VERY HIGH";    
  }
  else if (sensorVoltage>=1170)
  {
    UVIndex = "11";
    Index = "THE HIGHEST";    // EXTREMELY HIGHEST
  }
  
/////////////////////////////////////
    
  Serial.print("sensor reading = ");
  Serial.print(sensorValue);
  Serial.println("");
  Serial.print("sensor voltage = ");
  Serial.print(sensorVoltage);
  Serial.println(" V");
  Serial.print("UV Index = ");
  Serial.print(UVIndex);

   tft.setCursor(0, 5);
   tft.setTextSize(3);   
   tft.setTextColor(MAGENTA, BLACK);   
   tft.println("  UV METER");
   tft.println(" ");   
   tft.setTextColor(YELLOW, BLACK);
   tft.println("mV: " + String(sensorVoltage) + "  ");
   tft.println(" ");
   tft.println("UVIndex: " + String(UVIndex) + " ");  
   tft.setTextColor(WHITE, BLACK);
   tft.println(" ");      
   tft.println(String(Index) + "     ");       
   delay(1000);
}

TESLA Robot codes

TESLA Robot version 1, and TESLA Robot version 2

Credits

Guillermo Perez Guillen

Guillermo Perez Guillen

40 projects • 39 followers
Communications and Electronics Engineering, and Writer... "Don´t Expect Different Results If Your Habits Are The Same" A Einstein

Comments