domingo, 15 de junio de 2014

Projecte Final: ArduCotxe

Per Aurora Ripoll i Jose Ángel Mohedano


OBJECTIU: Crear un cotxet Ardudirigit. 

Que és capaç de fer l'ArduCotxe?



  • Avançar i retrocedir.
  • Girar a  la dreta i a l'esquerra. 
  • Parar-se. 
  • Indicar per la pantall LiquidCrystal quins són els moviments que està fent. 

Material necessari

  • Pel control Remot: 
- Arduino Micro Pro
- Protoboard
- Digi XBee(Coordinator AT)
- XBee Explorer 
- Resistències 10 KOhms (x5)
- Botons (x5)
- Cables connectors



  • Pel Cotxe:
- Arduino Uno
- Protoboard
- Digi XBee (Router AT)
- XBee Explorer
- Drivers L293D (x2)
- ServoMotor
- Motors DC de voltatge variable
- Estructura de plàstic
- Rodes i eixos de direcció
- Peces de Mecano
- Panralla LiquidCrystal
- Interruptor
- Porta piles de 6 V
- Cables connectors 
- Brides per subjectar




Funcionament Driver L293D

El driver utilitzat per fer aquest projecte ens permet controlar 2 motors de corrent contínua.



L'esquema bàsic del seu funcionament és el següent:






    • Pins alimentació L239D:
      • Vs (8) : Reb energia pel funcionament dels motors (4.5-36 V)
      • Vss(16): Alimentació del driver (4.5-7 V)
    • Pins d'habilitació: Pins d'intrucció al dirver. ENABLE1 pel motor 1 i ENABLE2 pel motor 2.
    • Pins de control: Ports de connexió a la placa Arduino i que permeten controlar els motors . INPUT1 i INPUT2 pel motor 1 i INPUT3 i INPUT4 pel motor 2. 
    • Pins alimentació motors: OUTPUT1 i OUTPUT2 pel motor 1 i OUTPUT3 i OUTPUT4 pel motor 2.
    • GROUND. Connexió a terra. 


Valors dels pins d'habilitació i control pel funcionament dels motors: 




ServoMotor

Motor amb eix de rendiment controlat. Es pot posicionar dins un rang d'actuació de 180º.

Aquest serà utilitzat per controlar l'eix de gir de les rodes.




1. Muntatge del circuit


  • Control remot:






  • Cotxe


2. Codi


  • Control remot:





int forward = 2;       // pin per anar recte     

int back = 7;          // pin per anar enrere

int right = 4;         // pin per anar a la dreta

int left = 5;          // pin per anar a l'esquerra 

int Stop = 6;          // pin per parar


void setup(){
    pinMode(forward, INPUT);
    pinMode(back, INPUT);
    pinMode(right, INPUT);
    pinMode(left, INPUT);
    pinMode(sos, INPUT);
    Serial1.begin(9600);

}

void loop(){   
  
    // Envia una F quant s'apreta el boto 'forward' (recte)
     
    if(digitalRead(forward) == HIGH && digitalRead(right)== LOW && digitalRead(left)== LOW && digitalRead(back)==LOW && digitalRead(Stop)==LOW)}
        Serial1.print('F');
        delay(30);
    }
    
    // Envia una R quant s'apreta el boto 'right' (dreta)
    
    if(digitalRead(forward) == LOW && digitalRead(right)== HIGH && digitalRead(left)== LOW && digitalRead(back)==LOW && digitalRead(Stop)==LOW){
        Serial1.print('R');            
        delay(30);
    }
    
    // Envia una L quant s'apreta el boto 'left' (esquerra)
    
    if(digitalRead(forward) == LOW && digitalRead(right)== LOW && digitalRead(left)== HIGH && digitalRead(back)==LOW) && digitalRead(Stop)==LOW){
        Serial1.print('L');            
        delay(30);
    }
    
    // Envia una B quant s'apreta el boto 'back' (enrere)
    
    if(digitalRead(forward) == LOW && digitalRead(right)== LOW && digitalRead(left)== LOW && digitalRead(back)==HIGH && digitalRead(Stop)==LOW){
        Serial1.print('B');            
        delay(30);
    }
    
    
   // Envia una S quant s'apreta el boto 'Stop' 
    
    if(digitalRead(forward) == HIGH && digitalRead(right)== LOW && digitalRead(left)== LOW&& digitalRead(back)==HIGH && digitalRead(Stop)==LOW){
        Serial1.print('S');            
        delay(30);
    }  
       


  • Cotxe:

#include <FastIO.h>
#include <I2CIO.h>
#include <LCD.h>
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal_SR.h>
#include <LiquidCrystal_SR2W.h>
#include <LiquidCrystal_SR3W.h>
#include <Wire.h> 
#include <Servo.h> 

Servo myservo;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int missatge;
int input_6v_1=7; 
int input_6v_2=8 ; 
int enable6=6;


void setup(){

    pinMode(input_6v_1, OUTPUT);
    pinMode(input_6v_2, OUTPUT);
    pinMode(enable6, OUTPUT);
    lcd.begin(16,2);
    myservo.attach(9);
    lcd.setCursor(7,0); 

    Serial.begin(9600);
}

void loop(){
  
    if(Serial.available()>0){
     
      missatge = Serial.read();
      
        // Quan es rebi una F:
      
        if (missatge == 'F'){
          
          myservo.write(80);              // El servo es mante recte (en un angle aproximat de 80 graus)
          digitalWrite(enable6, HIGH);    // Activacio del pin d'habilitacio
          digitalWrite(input_6v_1, LOW);  
          digitalWrite(input_6v_2, HIGH); // El motor gira en sentit horari
          delay(30);
          Serial.print("FORWARD");
          lcd.clear();
          lcd.setCursor(3,0);
          lcd.print("FORWARD!");          // Mostra 'forward' per la pantalla LiquidCrystal

          }

        // Quant rebi una R: 

        else if (missatge == 'R'){
          
          myservo.write(105);              // El servo gira a la drata (angle aproximat de 105 graus)
          delay(30);
          Serial.print("RIGHT");
          lcd.clear();
          lcd.setCursor(5,0);
          lcd.print("RIGHT!");             // Mostra 'right' per la pantalla LiquidCrystal
          
         }

       // Quant rebi una L:
       
        else if (missatge == 'L'){
          myservo.write(55);               // El servo gira a l'esquerra (angle aproximat de 55 graus)
          delay(30);
          Serial.print("left");
          lcd.clear();
          lcd.setCursor(5,0);
          lcd.print("LEFT!");              // Mostra 'left' per pantalla
        }
        
        
        // Quant rebi una B:
        
        else if (missatge == 'B'){
          
          myservo.write(80);              // El servo es col·loca recte
          digitalWrite(enable6, HIGH);    // Activacio del pin d'habilitacio
          digitalWrite(input_6v_1, HIGH);
          digitalWrite(input_6v_2, LOW);  // El motor gira en sentit anti horari
          delay(30);
          Serial.print("BACK");
          lcd.clear();
          lcd.setCursor(5,0);
          lcd.print("BACK!");             // Mostra 'back' per la pantall LiquidCrystal
        }
        
        // Quant rebi una S:
        
        else if (missatge == 'S'){        
          myservo.write(80);              
          digitalWrite(enable6, LOW);    //ENABLE = 0. El motor no funciona. 
          delay(30);
          lcd.clear();
          lcd.setCursor(5,0);
          lcd.print("STOP");             // Mostra 'back' per la pantall
        }
     
}
   



3. Demostració



4. Problemes 


A més de complir amb les característiques actuals de l'Arducotxe volien incloure un nou estat funcional anomenat 'emergència'. Aquest seria activat prement un botó i el cotxet reaccionaria augmentant la seva velocitat, fent sonar una sirena, alternant el parpelleig de dos LED'S i mostrant per la pantalla LiquidCrystal la paraula 'URGÈNCIA!'.

Els principals impediments que ens hem trobat han estat els següents:

1) Augment de la velocitat: Control de dos drivers per diferents controls de velocitat.
2) Fer fer sonar la sirena i alternar el parpelleig dels LED's: Aquestes accions no les podem realitzar junt amb la resta de codi ja que no ens deixa interaccionar amb el cotxe mentre sona la sirena o parpelleig els LEDS.

Pensem que aquestes podrien ser unes possibles solucions: 

1) Utilitzar interrupcions amb les quals aconseguiríem que s'executessin tots dos codis "alhora", interrupcions de micro-segons que ens permetrien sentir la sirena alhora que actuem el comandament.

Després d'haver realitzat el muntatge i aconseguits els requisits bàsics proposats ens hem trobat en que el pes de l'estructura del cotxet, amb el circuit inclòs, fa que aquest no pugui aconseguir una velocitat idònia. Això és solucionaria aplicant una font d'alimentació amb major voltatge. 








sábado, 14 de junio de 2014

Lab 6.2: Collecting a Data in a computer

Per Aurora Ripoll i Jose Ángel Mohedano


OBJECTIU: Rebre dades utilitzant Python i les XBees en mode API. 

Per fer-ho s'haurà de configurar l'equip remot per recopilar periòdicament dades d'un o més dels deus pins i enviar-lo al coordinador. El coordinador haurà d'estar configurat en mode API2. En el programa Python creearem una funció que s'encarregarà de la recepció de cada paquet de dades. Em aquest lab ens limitarem a imprimir la informació rebuda per pantalla. 



Material: 

- Protoboard (x2)
- Digi XBee (x2)
- XBee Explorer
- LDR
- Resitencia de 20 kOhms
- Cables connectors
- Ordinador 





1. Circuit






2. Codi 

A executar des de el terminal: 


from xbee import ZigBee

print 'Printing data from remote XBee'

serial port = serial.Serial('COM3', 9600) // Dependrà del port on tinguem connectada la XBee Local
zigbee = ZigBee (serial_port, escaped=True)

while True:
try:
print zigbee.wait_read_frame()
expect KeyboardInterrupt:
break


serial_port.close()



3. Demostració




viernes, 6 de junio de 2014

Lab 6.1: Ping-ing a Sensor

OBJECTIU: Enviar dades des de un ordinador a la placa Arduino mitjançant un codi Python i dues XBees en mode API. 

Una XBee haurà d'estar connectada directament a l'ordinador i en mode Coordinator API. L'altra connectada a la placa Arduino en mode Router API. 

Com que ara interactuarem amb la XBee local utilitzant la llibreria Python, serà necessari que les dues XBees tinguin el mode API igual a 2 (Serial Interfacing, AP).

Mitjançant el codi Python la XBee local anirà enviant paquets en mode broadcast. En aquest cas  només hi ha una altra XBee connectada a la mateixa xarxa i per tant serà l'única receptora. Cada cop que la XBee remota rebi un paquet de la XBee local un LED parpadejarà 3 cops. 


Material necessari:


  • Placa Arduino UNO
  • Placa Protoboard
  • XBees Explorer (x2)
  • Digi XBee (x2)
  • Cables connectors
  • LED
  • Ordinador



1. Muntatge del circuit





2. Codi



Codi Python: 


#! /usr/bin/python

from xbee import ZigBee
import serial

import time
from datetime import datetime

ser = serial.Serial('COM4', 9600)
xbee = ZigBee(ser, escaped=True)

while True:
    try:
        tstart = datetime.now()
        xbee.send('tx',
                  frame_id='A',
                  dest_addr_long='\x00\x13\xa2\x00\x40\x8b\x44\xfa',
                  dest_addr='\xFF\xFE',
                  data='\x03')
        response = xbee.wait_read_frame();
        tend = datetime.now()
        print tend-tstart
        time.sleep(10);
    except KeyboardInterrupt:
        break

ser.close()


Codi Arduino:

#include <XBee.h> int ledPin = 13; XBee xbee = XBee(); XBeeResponse response = XBeeResponse(); // create reusable response objects for responses we expect to handle ZBRxResponse rx = ZBRxResponse(); void flashLed(int pin, int times, int wait) { for (int i = 0; i < times; i++) { digitalWrite(pin, HIGH); delay(wait); digitalWrite(pin, LOW); if (i + 1 < times) { delay(wait); } } } void setup() { Serial.begin(9600); xbee.begin(Serial); pinMode(ledPin, OUTPUT); flashLed(ledPin, 10, 50); // sets the LED off } void loop() { delay(1000); // 1. This will read any data that is available: xbee.readPacket(); if (xbee.getResponse().isAvailable()) { //flashLed(ledPin, 1, 1000); if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) { xbee.getResponse().getZBRxResponse(rx); //flashLed(ledPin, 1, 100); // sets the LED off flashLed(ledPin, rx.getData(0), 200); // sets the LED off } } }

3. Demostració