| 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 |
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 Sensor d'acceleració i camp magnètic
1 NeoPixel Ring de 16 LED
A la figura següent podem veure l'esquema de connexions.

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.

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