Tecnologia vestible

Per començar Elements d'entrada Programació CircuitPython   Recursos CITCEA
Elements no electrònics Elements de sortida Programació Arduino    
Projectes Elements de control Dades pràctiques   Inici

SubwayCompass

Es tracta d'una canellera que indica a l'usuari la direcció de la parada de metro més propera i les línies que hi passen.

La llista de materials principals és la següent:

1   Placa Flora

1   Sensor GPS

1   Sensor d'acceleració i camp magnètic

1   NeoPixel Ring de 16 LED

1   Portapiles amb piles

A la figura següent podem veure l'esquema de connexions.

esquema

Per calcular les distàncies es fa servir la fórmula del haversine. Per calcular l'angle respecte al nord es calcula la distància descomposada en una component NS i una component EO. Això ens permet calcular l'angle respecte al nord amb el que podrem trobar l'angle respecte a l'orientació de l'usuari. A continuació tenim el llistat del programa:

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <math.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>
//--------------------------------Parades de metro--------------------------------//
float latparades[] = {41.3859, 41.3842, 41.3878, 41.3886};
float lonparades[] = {2.1184, 2.1117, 2.1258, 2.1511};
//Latitud parada Palau Reial = 41.3859 
//Longitud parada Palau Reial = 2.1184  
//Latitud parada Zona Universitària = 41.3842
//Longitud parada Zona Universitària = 2.1117
//Latitud parada Maria Cristina = 41.3878
//Longitud parada Maria Cristina = 2.1258
//Latitud parada Hospital Clínic = 41.3886
//Longitud parada Hospital Clínic = 2.1511
int  a1 = 0;
uint32_t groc = cadena.Color(255, 255, 0);  
uint32_t verd = cadena.Color(0, 255, 0);  
uint32_t blau = cadena.Color(0,0,255);  
uint32_t vermell = cadena.Color(255, 0, 0);  
uint32_t lila = cadena.Color(102,0,102);  
uint32_t taronja = cadena.Color(255,60,0);  
int k=0;
Adafruit_GPS SensorGPS(&Serial1);  
boolean usingInterrupt = false;   
uint32_t timer = millis();
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
Adafruit_NeoPixel cadena = Adafruit_NeoPixel(16, 6, NEO_GRB + NEO_KHZ800);   // NeoPixel a la pota 6
//------------Funció que pasa la latitud proporcionada pel GPS a graus------------//
float NostraLatGraus(){
	float temporaryLat = SensorGPS.latitude; 
	Serial.print("TemporalyLat:");
	Serial.println(temporaryLat);
	float minutesLat; 
	float degreesLat; 
	float secondsLat; 
	float millisecondsLat; 
	degreesLat = trunc(temporaryLat/100);
	minutesLat = temporaryLat - (degreesLat*100);
	secondsLat = (minutesLat - trunc(minutesLat)) * 60;
	millisecondsLat = (secondsLat - trunc(secondsLat)) * 1000;
	minutesLat = trunc(minutesLat);
	secondsLat = trunc(secondsLat);
	float currentDegreesLat = degreesLat + minutesLat/60 + secondsLat/3600 + millisecondsLat/3600000; 
	return currentDegreesLat; 
  }
//------------Funció que pasa la longitud proporcionada pel GPS a graus-----------//
float NostraLongGraus(){  
	float temporaryLong = SensorGPS.longitude;
	Serial.print("TemporalyLat:");
	Serial.println(temporaryLong);
	float minuteLong;
	float minutesLong;  
	float degreesLong; 
	float secondsLong; 
	float millisecondsLong; 
	degreesLong = trunc(temporaryLong/100);
	minutesLong = temporaryLong - (degreesLong*100);
	secondsLong = (minutesLong - trunc(minutesLong)) * 60;
	millisecondsLong = (secondsLong - trunc(secondsLong)) * 1000;
	minutesLong = trunc(minutesLong);
	secondsLong = trunc(secondsLong);
	float currentDegreesLong = degreesLong + minutesLong/60 + secondsLong/3600 + millisecondsLong/3600000; 
	return currentDegreesLong; 
}
//--------------------------------Haversine--------------------------------//
float Haversine(float lat1, float lon1, float lat2, float lon2){
	float ToRad = PI/180.0;
	float R = 6371000;
	float dLat = (lat2-lat1) * ToRad;
	float dLon = (lon2-lon1) * ToRad;
	float a = sin(dLat/2)*sin(dLat/2)+cos(lat1*ToRad)*cos(lat2*ToRad)*sin(dLon/2)*
	sin(dLon/2);
	float c = 2*atan2(sqrt(a), sqrt(1-a));
	float d = R*c;
	return d;
}
//-------------Funcio que ilumina el led corresponent segons l'angle--------------//
int LedSegonsAngle(float ang){
	if (ang>360){
		ang=ang-360;
	}
	if (ang>360){
		ang=ang-360;
	}
	int led=0;
	if ((0 <= ang) && (ang < 22.5)) {
		led=0;
	}
	if ((22.5 <= ang) && (ang < 45)) {
		led=1;
	}
	if ((45 <= ang) && (ang < 67.5)) {
		led=2;
	}
	if ((67.5 <= ang) && (ang < 90)) {
		led=3;
	}
	if ((90 <= ang) && (ang < 112.5)) {
		led=4;
	}
	if ((112.5 <= ang) && (ang < 135)) {
		led=5;
	}
	if ((135 <= ang) && (ang < 157.5)) {
		led=6;
	}
	if ((157.5 <= ang) && (ang < 180)) {
		led=7;
	}
	if ((180 <= ang) && (ang < 202.5)) {
		led=8;
	}
	if ((202.5 <= ang) && (ang < 225)) {
		led=9;
	}
	if ((225 <= ang) && (ang < 247.5)) {
		led=10;
	}
	if ((247.5 <= ang) && (ang < 270)) {
		led=11;
	}
	if ((270 <= ang) && (ang < 292.5)) {
		led=12;
	}
	if ((292.5 <= ang) && (ang < 315)) {
		led=13;
	}
	if ((315 <= ang) && (ang < 337.5)) {
		led=14;
	}
	if ((337.5 <= ang) && (ang < 360)) {
		led=15;
	}
	return led;
}
void setup(void) {
	Serial.begin(9600);
	Serial.println("Magnetometer Test"); Serial.println("");
	if(!mag.begin()) {
		Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
		while(1);
	}
	cadena.begin();         
	cadena.show();
	Serial.begin(115200);   
	SensorGPS.begin(9600);    
	SensorGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); 
	SensorGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   
	delay(1000);
}
void loop(void) {
	//-----Tobem l'angle nord-----//
	sensors_event_t event; 
	mag.getEvent(&event);
	float anglenord = atan2(event.magnetic.y,event.magnetic.x) * 180/PI;
	if (anglenord < 0) {
		anglenord = 360 + anglenord;
	}
	//-----Obtenim les dades del SensorGPS-----//
	char dades = SensorGPS.read();  
	if (SensorGPS.newNMEAreceived()) {    
		Serial.println(SensorGPS.lastNMEA());   
		if (!SensorGPS.parse(SensorGPS.lastNMEA())) {   
			return;  
		}
	}
	if (timer > millis()) {
		timer = millis();
	}
	if (millis() - timer > 2000) {  
		timer = millis();
		Serial.print("Sats: ");   
		Serial.println((int)SensorGPS.satellites);
		if (SensorGPS.satellites > 3) {  
			//-----Obtenim la nostra ubicació en graus-----//
			float Latgnostra=NostraLatGraus(); 
			float Longnostra=NostraLongGraus();
			Serial.print("Latgnostra: ");
			Serial.println(Latgnostra,4);
			Serial.print("Longnostra: ");
			Serial.println(Longnostra,4);
			//cadena.setPixelColor(LedNord,vermell);
			//cadena.show();
			//-----Haversine+Direcció Angle-----//
			//Calculem la  distància entre cada parada i la nostra ubicació
			while (k < 4){
				float DParada=Haversine(latparades[k],lonparades[k],Latgnostra,Longnostra);
				Serial.print("Distancia: ");
				Serial.println(DParada);
				Serial.print("K: ");
				Serial.println(k);
				Serial.print("Lp: ");
				Serial.println(latparades[k]);
				Serial.print("ln: ");
				Serial.println(Latgnostra);        
				if (DParada < 4000){
					float DNS=Haversine(Latgnostra,Longnostra,latparades[k],Longnostra);   
					float DEO=Haversine(Latgnostra,Longnostra,Latgnostra,lonparades[k]);
					float alfa= atan(DEO/DNS);
					float alfag= alfa*180/PI;
					if ((Latgnostra > latparades[k]) && (Longnostra > lonparades[k])){
						alfag=alfag-180;
					}
					if ((Latgnostra > latparades[k]) && (Longnostra < lonparades[k])){
						alfag=alfag+180;
					}
					if ((Latgnostra < latparades[k]) && (Longnostra < lonparades[k])){
						alfag=-alfag+360;
					}
					float angleneopixel=alfag+ anglenord;
					Serial.print("Angleneopixel: ");
					Serial.println(angleneopixel);          
					int LedNeopixel=LedSegonsAngle(angleneopixel);
					Serial.print("LedNeopixel:");
					Serial.println(LedNeopixel);
					//-----Colors de les parades de metro-----//
					if (k == 0){                                     //Palau Reial
						cadena.setPixelColor(LedNeopixel,verd);
						cadena.show(); // Actualitza 
					}
					if  (k == 1){                                    //Zona Universitaria
						cadena.setPixelColor(LedNeopixel,verd);
						cadena.show(); // Actualitza 
						delay(1500);  // Espera un segon
						cadena.setPixelColor(LedNeopixel,taronja);
						cadena.show(); // Actualitza
					}
					if  (k == 2){                                    //Maria Cristina
						cadena.setPixelColor(LedNeopixel,verd);
						cadena.show(); // Actualitza     
					}
					if (k == 3){                                 //Hospital Clínic
						cadena.setPixelColor(LedNeopixel,blau);
						cadena.show(); // Actualitza
					}
				}
				k=k+1;        
			}
			if (k==4){
				k=0;
			}
			delay(1500);
			for (int n = 0; n < 16; n++){
				cadena.setPixelColor(n, 0, 0, 0);  
			}
			cadena.show(); 
		}
		//-----No troba satel·lits-----//
		while (SensorGPS.satellites <= 3){                                                                    
			if (a1 > 15){
				char dades = SensorGPS.read();  
				if (SensorGPS.newNMEAreceived()) {    
					Serial.println(SensorGPS.lastNMEA());   
					if (!SensorGPS.parse(SensorGPS.lastNMEA())) {   
						return;  
					}
				}
				Serial.print("Sats: ");   
				Serial.println((int)SensorGPS.satellites);
				for (int p = 0; p < 16; p++){
					cadena.setPixelColor(p, 0, 0, 0);  
				}
				cadena.show(); 
				delay(100);
				a1 = a1 - 16;
			} else {
				cadena.setPixelColor(a1,25,25,25);  // Pixel a1 vermell
				cadena.show(); // Actualitza
				delay(100);  // Espera mig segon
				a1++;
			}
		}
		for (int n = 0; n < 16; n++){
			cadena.setPixelColor(n, 0, 0, 0);  // Apaga tots els pixels (0 a 15)
		}
		cadena.show(); // Actualitza
		delay(1500);
	}
}

 

 

 

En aquest web, les fotografies marcades amb [AF] són del web d'Adafruit, les marcades amb [SF] del web d'Sparkfun i les marcades amb [AU] del web d'Arduino.

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.