Datalogger de posicionamiento con Raspberry Pi y Azure


CÓDIGO

AzureIoTRegistryManagerApp C #
Este es el código de acceso y gestión Azure Registro Hub IO, haciendo uso de la clase RegistryManager.
////The MIT License(MIT)
////Copyright(c) 2016 BardaanA

////Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

////The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

////THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Threading.Tasks;

// These are the Microsoft's recommended libraries to access
// and make changes to Azure IoT Hub's Registry
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Exceptions;

// This namespace which also dictates the name of the Assembly can be anything you desire.
namespace AzureIoTRegistryManagerApp
{
    class Program
    {
        // RegistryManager object which is going to do most of the work for our application
        static RegistryManager registryManager;
        // This here is the Connection String that you copied from the IoT Hub Shared Access Policies > iothubowner > Shared access keys; remember??
        static string connectionString = "Don't forget to replace this with your own connection string";
        // Keeps track of the registry access status
        static string registryAccessStatus = "";

        static void Main(string[] args)
        {
            try
            {
                // Let's try and create a Registry Manager using our connection string, shall we?
                registryManager = RegistryManager.CreateFromConnectionString(connectionString);
                registryAccessStatus = "Successfuly connected to the IoT Hub registry"; // Yay!
            }
            catch(Exception ex)
            {
                Console.WriteLine("Registry access failed!  {0}",ex.Message);  // Bummer!!
            }
            // Check if RegistryManager was created successfully
            if(registryManager != null)
            {
                Console.WriteLine("*****************************************************");
                Console.WriteLine("===== Welcome to the Azure IoT Registry Manager =====");
                Console.WriteLine();
                Console.WriteLine("++ {0} ++",registryAccessStatus);
                Console.WriteLine();
                int menuSelection = 0;
                while(menuSelection != 3)  // Loop to keep you going...
                {
                    Console.WriteLine("  1) Add device into registry");
                    Console.WriteLine("  2) Remove device from the registry");
                    Console.WriteLine("  3) Close this application");
                    Console.WriteLine("------------------------------------");
                    Console.Write("Enter your selection: ");
                    menuSelection = int.Parse(Console.ReadLine());
                    Console.WriteLine();
                    switch(menuSelection)
                    {
                        case 1:
                            Console.Write("Enter device name that you want to register: ");
                            string deviceName = Console.ReadLine();
                            Console.WriteLine();
                            if(deviceName.Length > 0 && !deviceName.Contains(" "))  // Weak validation :)
                            {
                                // Calling method that actually adds the device into the registry
                                AddDevice(deviceName).Wait();
                            }
                            else
                            {
                                Console.WriteLine("---");
                                Console.WriteLine("Enter valid name!");
                                Console.WriteLine("---");
                            }
                            break;
                        case 2:
                            Console.Write("Enter name of the device to be removed: ");
                            string deviceRemoveName = Console.ReadLine();
                            Console.WriteLine();
                            if(deviceRemoveName.Length > 0 && !deviceRemoveName.Contains(" "))  // Weak validation :(
                            {
                                // Calling method that actually removes the device from the registry
                                RemoveDevice(deviceRemoveName).Wait();
                            }
                            else
                            {
                                Console.WriteLine("---");
                                Console.WriteLine("Enter valid name!");
                                Console.WriteLine("---");
                            }
                            break;
                        case 3:
                            // Breaks out of the loop
                            break;
                        default:
                            Console.WriteLine("---");
                            Console.WriteLine("Choose valid entry!");
                            Console.WriteLine("---");
                            break;
                    }
                }
                // Closes the RegistryManager access right before exiting the application
                registryManager.CloseAsync().Wait();
            }
        }

        // Method used to add device into the Registry, takes in a string as a parameter
        private static async Task AddDevice(string deviceId)
        {
            // A Device object
            Device device;
            try
            {
                // Lets try and create a Device into the Device Registry
                device = await registryManager.AddDeviceAsync(new Device(deviceId));
                if(device != null)
                {
                    Console.WriteLine("Device: {0} added successfully!",deviceId); // Hooray!
                }
            }
            catch(DeviceAlreadyExistsException)  // What?
            {
                Console.WriteLine("---");
                Console.WriteLine("This device has already been registered...");// When did I do that??
                Console.WriteLine("---");
                device = await registryManager.GetDeviceAsync(deviceId);
            }
            Console.WriteLine();
            Console.WriteLine("Generated device key: {0}",device.Authentication.SymmetricKey.PrimaryKey);  // Now you're talking!
            Console.WriteLine();
        }

        // Method used to remove a device from the Device Registry, takes a string as a parameter
        private static async Task RemoveDevice(string deviceId)
        {
            try
            {
                // Lets try and get rid of the Device from our registry, using the device id.
                await registryManager.RemoveDeviceAsync(deviceId);
                Console.WriteLine("Device: {0} removed successfully!",deviceId);  // Yup!
            }
            catch(DeviceNotFoundException)
            {
                Console.WriteLine("---");
                Console.WriteLine("This device has not been registered into this registry!");  // Are you sure??
                Console.WriteLine("---");
            }
        }
    }
}

Fuente aqui

Controle su Roomba con Arduino y Android


 

iRobot Roomba Create2 es una a  plataforma grande y muy asequible para el desarrollo de la robótica, costando alrededor de US$ 200 permitiendo  una variedad de métodos de programación. Como  comienzo mjrovi usó  un Arduino y una aplicación Android para mover el robot  por puerto serie  consiguiendo asi controlar  sus motores, LEDS y sonido.

Como uno de los ganadores de 2016 del concurso de robótica   en Instructables, mjrovi recibió como premio un iRobot Roomba Create2.

 

 

La Roomba es un robot de impulsión diferenciada, con 2 ruedas motrices y una rueda  central  guía. Su velocidad va hasta 500 mm/s y puede ser mandado a ir hacia arriba o hacia atrás.
Para señalización, contamos con cuatro 7 segmentos display y 5 LEDs :

  • Limpiar
  • Punto
  • Muelle
  • ADVERTENCIA/Check
  • Suciedad/escombros

Como sensores internos, tenemos entre otros:

  • Detector de acantilado (4 en el frente)
  • Detectores Bump (frente 2)
  • Codificadores de rueda

Para la programación, el documento: iRobot® Create® 2 abierto interfaz (OI) debe ser utilizado.El Roomba puede ser programado en 3 modos:

  1. Modo pasivo:Al enviar el comando de Start o cualquiera de los comandos de modo de limpieza (por ejemplo, punto limpio, muelle buscar), la OI entra en modo pasivo. Cuando la OI está en modo pasivo, puede solicitar y recibir datos de los sensores usando cualquiera de los comandos del sensor, pero no puede cambiar los parámetros de comando actuales para los actuadores (motores, altavoces, luces, controladores de lado de baja, salidas digitales) a otra cosa.
  2. Modo seguro :Le da un control completo de Roomba, con excepción de las siguientes condiciones relacionadas con la seguridad:
    Cargador conectado y alimentado:detección de una caída de rueda (en cualquier rueda),detección de un acantilado mientras se mueve hacia adelante (o hacia atrás con un pequeño radio de torneado, menos de un radio de robot) o si ocurre una de las condiciones relacionadas con la seguridad mientras que el OI es en modo seguro, Roomba detiene todos los motores y vuelve al modo pasivo.
  3. Modo completo:Le da un control completo sobre Roomba, todos de sus actuadores y todas las condiciones relacionadas con la seguridad que están restringidas cuando la OI en modo seguro, como el modo completo se apaga el acantilado, caída de rueda y características de seguridad cargador interno.

Comunicaciones

Para  programar la Romba  la lista de  materiales  usada es la siguiente:

  • iRobot Create2
  • Arduino UNO
  • Módulo Bluetooth HC-06
  • Pulsador

Para la comunicación entre la Roomba y Arduino, se utilizará el puerto Serial. Por defecto, Roomba comunica a 115.200 baudios, pero para comunicarse con Arduino, se cambiará a 19.200.

Hay 2 formas de establecer la tasa de baudios de Roomba:

  1. Mientras que apagar Roomba, continúan mantenga pulsado el botón de encendido o limpiar después de que la luz se ha apagado. Después de unos 10 segundos, Roomba juega una melodía descendente de las echadas. Roomba se comunicará a 19.200 baudios hasta que el procesador pierde energía de la batería o la tasa de baudios se modifica explícitamente a través de la OI.
  2. Utilizar el pin de cambio de tasa de baudios (pin 5 del conector mini-DIN) para cambiar la velocidad en baudios de Roomba. Después de encender la Roomba, esperar 2 segundos y luego pulso el cambio de la tasa de baudios baja tres veces. Cada impulso debe durar entre 50 y 500 milisegundos. Roomba se comunicará a 19200 baudios hasta que el procesador pierde energía de la batería o la tasa de baudios se modifica explícitamente a través de la OI.

 

El diagrama de arriba muestra cómo la Arduino debe conectarse al conector mini-DIN de Roomba

 

 

Lo primero creo que debe hacerse cuando un Roomba de programación es «Despertar» el robot y  Definir el modo (segura o completa)

Nosotros podemos  hacer  un «wake-up», enviar un poco de pulso al pin mini-DIN 5 (detección de dispositivo de entrada) como se muestra en la siguiente función:
void wakeUp (void)
{
setWarningLED(ON);
digitalWrite(ddPin, HIGH);
delay(100);
digitalWrite(ddPin, LOW);
delay(500);
digitalWrite(ddPin, HIGH);
delay(2000);
}

Para empezar a Roomba deberán enviarse 2 códigos de siempre: «START» [128] y el modo, en nuestro caso «Modo seguro» [131]. Si usted quiere un «modo completo», debe enviarse en su lugar el código [132].
void startSafe()
{
Roomba.write(128); //Start
Roomba.write(131); //Safe mode
delay(1000);
}

 

Como se describe en la introducción, el Roomba tiene 5 LEDs:

  • Energía/limpiar (bicolor rojo/verde e intensidad controladas)
  • Punto (verde, intensidad fija)
  • Muelle (verde, intensidad fija)
  • ADVERTENCIA/Check (naranja, intensidad fija)
  • Suciedad/escombros (azul, fija la intensidad)

 

Control de leds

Todos los LEDs pueden ser ordenados mediante código [139]
Para controlar el LED de encendido, debe enviar dos bytes de datos a Roomba: «color» y la «intensidad».
Color:

  • Verde = 0
  • Naranja = 128
  • rojo = 255

Intensidad:

  • Bajo = 0
  • Max = 255

La función setPowerLED (colores bytes, setIntensity bytes) lo hace:

void setPowerLED(byte setColor, byte setIntensity)
{
color = setColor;
intensity = setIntensity;
Roomba.write(139);
Roomba.write((byte)0x00);
Roomba.write((byte)color);
Roomba.write((byte)intensity);
}

Por ejemplo, para encender el LED de POWER de color naranja en la mitad de su intensidad, usted puede llamar a la función como bramido:setPowerLED (128, 128);

Encender los 4 LEDs restantes, deberán utilizarse las siguientes funciones:
setDebrisLED(ON);
setDockLED(ON);
setSpotLED(ON);
setWarningLED(ON);

Todas las funciones anteriores tiene un código similar a este:
void setDebrisLED(bool enable)
{
debrisLED = enable;
Roomba.write(139);
Roomba.write((debrisLED ? 1 : 0) + (spotLED ? 2 : 0) + (dockLED ? 4 : 0) + (warningLED ? 8 : 0));
Roomba.write((byte)color);
Roomba.write((byte)intensity);
}

Básicamente, la diferencia será la línea: debrisLED = habilitar;  debe modificarse permitiendo a cada uno de los otros LEDs (spotLED, dockLED, warningLED).

 

Envío de mensajes

Roomba tiene cuatro 4 displays de 7 segmentos que puede utilizar para enviar mensajes de dos maneras::
[163] código: Dígitos LED crudo (numérico)
[164] código: Dígitos LED de ASCII (aproximación de letras y códigos especiales)
Para mostrar números  debe enviar el código [163], siguiendo las 4 digitas a mostrar. La función: setDigitLEDs (bytes digit1 digit2 bytes, digit3 bytes, digit4 bytes) lo hace para usted:

void setDigitLEDs(byte digit1, byte digit2, byte digit3, byte digit4)
{
Roomba.write(163);
Roomba.write(digit1);
Roomba.write(digit2);
Roomba.write(digit3);
Roomba.write(digit4);
}

Por ejemplo, para mostrar «1, 2, 3, 4», debe llamar a la función: setDigitLEDs (1, 2, 3, 4);

Con el código [164], es posible enviar aproximación de ASCII.

La función setDigitLEDFromASCII (dígitos de byte, char letra) hace esto para nosotros:
void setDigitLEDFromASCII(byte digit, char letter)
{
switch (digit){
case 1:
digit1 = letter;
break;
case 2:
digit2 = letter;
break;
case 3:
digit3 = letter;
break;
case 4:
digit4 = letter;
break;
}
Roomba.write(164);
Roomba.write(digit1);
Roomba.write(digit2);
Roomba.write(digit3);
Roomba.write(digit4);
}

Para simplificar, crear una nueva función para enviar los 4 dígitos al mismo tiempo:
void writeLEDs (char a, char b, char c, char d)
{
setDigitLEDFromASCII(1, a);
setDigitLEDFromASCII(2, b);
setDigitLEDFromASCII(3, c);
setDigitLEDFromASCII(4, d);
}

Por ejemplo, para mostrar «STOP», usted debe llamar a la función: writeLEDs (‘s’, ‘ t ‘, ‘ o ‘, ‘p’);

Mover la  Roomba

Para la movilidad, Roomba tiene 2 motores independientes que pueden programarse para ejecutar 500mm/s. Hay varios comandos que pueden utilizarse para controlar el robot. Los principales son:

  • Código [137]: Unidad == > debe enviar +-velocidad en mm/s y +-radio en mm
  • Codigo [145] de código: Impulsión directa == > debe enviar izquierda velocidad en mm/s (+ para adelante y para atrás)
  • Código [146]: Unidad PWM == > debe enviar +-datos PWM para la izquierda y derecha las ruedas

 

A continuación el código para estas 3 opciones:

void drive(int velocity, int radius)
{
clamp(velocity, -500, 500); //def max and min velocity in mm/s
clamp(radius, -2000, 2000); //def max and min radius in mm

Roomba.write(137);
Roomba.write(velocity >> 8);
Roomba.write(velocity);
Roomba.write(radius >> 8);
Roomba.write(radius);
}

//—————————————————————

void driveWheels(int right, int left)
{
clamp(right, -500, 500);
clamp(left, -500, 500);

Roomba.write(145);
Roomba.write(right >> 8);
Roomba.write(right);
Roomba.write(left >> 8);
Roomba.write(left);
}

//—————————————————————
void driveWheelsPWM(int rightPWM, int leftPWM)
{
clamp(rightPWM, -255, 255);
clamp(leftPWM, -255, 255);

Roomba.write(146);
Roomba.write(rightPWM >> 8);
Roomba.write(rightPWM);
Roomba.write(leftPWM >> 8);
Roomba.write(leftPWM);
}

Tenga en cuenta que la función de «fijar» define los valores máximos y mínimos que se permitieron la entrada. Esta función se define en el archivo rombaDefines.h:

abrazadera (valor, min, max) (valor < min? min: valor > max? max: valor)
Utilizando el código anterior, se pueden crear funciones más simples para Roomba alrededor de:
/—————————————————————
void turnCW(unsigned short velocity, unsigned short degrees)
{
drive(velocity, -1);
clamp(velocity, 0, 500);
delay(6600);
drive(0,0);
}

//—————————————————————
void turnCCW(unsigned short velocity, unsigned short degrees)
{
drive(velocity, 1);
clamp(velocity, 0, 500);
delay(6600);
drive(0,0);
}

//—————————————————————
void driveStop(void)
{
drive(0,0);
}

//—————————————————————
void driveLeft(int left)
{
driveWheels(left, 0);
}

//—————————————————————
void driveRight(int right)
{
driveWheels(0, right);
}

Tenga en cuenta que para girar en ángulo, debe calcularse el argumento de «retraso» específicamente para una velocidad dada

A continuación algunos ejemplos que pueden utilizar para probar los motores:

turnCW (40, 180); girar 180 grados hacia la derecha y parada
driveWheels (20, -20); vuelta
driveLeft(20); girar a la izquierda

Para las pruebas de los motores, es bueno añadir un pulsador externo (en mi caso conectado al Arduino pin 12), para que puedan descargar el código de Arduino, a partir de la Roomba, pero parando la ejecución hasta que se pulsa la tecla. Generalmente, para los motores de prueba lo puedes hacer en la parte de configuración del código.

Como ejemplo, consulte el código de Arduino simple abajo (nota que el código usa funciones y definiciones desarrollaron antes):

«roombaDefines.h»

// Roomba Create2 connection
int rxPin=10;
int txPin=11;
SoftwareSerial Roomba(rxPin,txPin);

//———————————————
void setup()
{
Roomba.begin(19200);

pinMode(ddPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP); // connected to Arduino pin 12 and used for «starting»

delay(2000);

wakeUp (); // Wake-up Roomba
startSafe(); // Start Roomba in Safe Mode

while (digitalRead(buttonPin)) { } // wait button to be pressed to continous run code

turnCW (40, 180); //test Roomba spin clock-wise 180 degrees and stop
}

//———————————————
void loop()
{

}

 

Controlar la Roomba a través de Bluetooth

Para controlar  Roomba de modo inalambrico   vamos a instalar un módulo Bluetooth (HC-06) a nuestro Arduino. El diagrama de arriba muestra cómo hacerlo. Suele ser el HC-06 settle up de fábrica con una velocidad de 9.600. Es importante cambiarlo a 19.200 para ser compatible con la velocidad de la comunicación de Arduino-Roomba. Usted puede hacer que el envío un comando AT para el módulo (AT + BAUD5 donde «5» es el código de 19.200).

Para controlar la Roomba, utilizaremos una aplicación genérica que fue desarrollada por jrovai   para el control de robots móviles, con el MIT AppInventor 2: «MJRoBot BT Remote Control». La aplicación puede descargarse gratuitamente de la tienda de Google a través del enlace: aplicación: MJRoBot BT Remote Control.

La aplicación tiene una interfaz sencilla, lo que le permite enviar comandos al módulo de BT en ambos, modo de texto o directamente a través de botones preprogramados (cada vez que se pulsa un botón, un carácter se envía):

  • w: hacia adeñante
  • S: hacia atras
  • d: derecho
  • a: izquierda
  • f: parada
  • p: ON / OFF (no usado en esta primera parte)
  • m: manual / automático (se utiliza para reiniciar Roomba si un obstáculo como un acantilado se encuentra en modo seguro)
  • +: Velocidad +
  • -: Velocidad –

También puede enviar otros comandos como texto si es necesario. También hay una ventana de texto para los mensajes recibidos desde el módulo de BT. Esta característica es muy importante durante la fase de prueba, puede ser utilizado en la misma forma que el «Serial Monitor».

El loop() parte del código será «escuchando» el dispositivo bluetooth y dependiendo del comando recibido, tomar una acción:

void loop()
{
checkBTcmd(); // verify if a comand is received from BT remote control
manualCmd ();
}
La función checkBTcmd() se muestra a continuación:

void checkBTcmd() // verify if a command is received from BT remote control
{
if (BT1.available())
{
command = BT1.read();
BT1.flush();
}
}
Una vez que se recibe un comando, la función manualCmd() tomará la acción apropiada:
void manualCmd()
{
switch (command)
{

case ‘m’:
startSafe();
Serial.print(«Roomba in Safe mode»);
BT1.print(«Roomba BT Ctrl OK – Safe mode»);
BT1.println(‘\n’);
command = ‘f’;
playSound (3);
break;

case ‘f’:
driveStop(); //turn off both motors
writeLEDs (‘s’, ‘t’, ‘o’, ‘p’);
state = command;
break;

case ‘w’:
drive (motorSpeed, 0);
writeLEDs (‘ ‘, ‘g’, ‘o’, ‘ ‘);
state = command;
break;

case ‘d’:
driveRight(motorSpeed);
writeLEDs (‘r’, ‘i’, ‘g’, ‘h’);
break;

case ‘a’:
driveLeft(motorSpeed);
writeLEDs (‘l’, ‘e’, ‘f’, ‘t’);
break;

case ‘s’:
drive (-motorSpeed, 0);
writeLEDs (‘b’, ‘a’, ‘c’, ‘k’);
state = command;
break;

case ‘+’:
if (state == ‘w’)
{
motorSpeed = motorSpeed + 10;
if (motorSpeed > MAX_SPEED)
{
motorSpeed = MAX_SPEED;
}
command = ‘w’;
} else {command = state;}
break;

case ‘-‘:

if (state == ‘w’)
{
motorSpeed = motorSpeed – 10;
}
if (motorSpeed < MIN_SPEED )

{ motorSpeed = MIN_SPEED; }

Serial.println(motorSpeed); command = state; break; } }

 

 

 

El código de Arduino completo utilizado en documentos aquí relacionados se puede encontrar en GITHUB en https://github.com/Mjrovai/Roomba_BT_Ctrl

Varias de las funciones que   el autor  ha creado en su  programa se basaron en la biblioteca de crear 2 desarrollada por Dom Amato. Puede descargar la librería completa en‎: https://github.com/brinnLabs/Create2.

 

Enlace original al proyecto en Instructables.com.