En este tutorial podrás usar tu Raspberry Pi para leer el clima actual de tu localidad a través de una conexión a internet y lo podrás mostrar en tu pantalla LCD Nokia 5110 (PCD8544). Se dará una breve explicación de cómo echar a andar un thread (hilo) y también cómo usar mutexes para evitar que ambos hilos del programa estén haciendo uso de una variable (compartir memoria). También se dará una explicación sobre cómo dejar corriendo una aplicación en tu Raspberry Pi sin tener que estar conectado a ella a través de SSH con el programa 'screen'. Espero te sea de utilidad.
Items necesarios
+ Raspberry Pi correctamente funcional con Raspbian (checa un tutorial anterior)
+ Pantalla LCD Nokia 5110 (click para link de venta)
+ Conexión a internet (Wifi o por Ethernet)
Software necesario
+ Cross compiler ARM sobre Linux para PC (link con tutorial en Hertville)
+ Paquete con código fuente Weather LCD (link de descarga)
Obteniendo datos del clima por internet
El paquete weather-util en Linux te permite descargar las condiciones actuales y futuras del clima en tu localidad a través de tu conexión a internet. Primero necesitas instalarlo en tu Raspberry Pi. Ejecuta los siguientes comandos en tu Pi...
$ sudo apt-get update
$ sudo apt-get install weather-util
Al instalarlo se descargarán varios scripts en Python que harán una conexión al servidor http://weather.noaa.gov/ y bajarán la información actual de tu localidad. Para probar que funciona deberás entrar a la página web indicada y obtener el ID de tu localidad. La ID la obtendrás eligiendo tu país y luego una ciudad. En mi caso, siendo México en la ciudad de Querétaro obtuve la ID MMQT, indicada en el recuadro rojo.

Una vez conociendo tu ID, introduce el comando siguiente en la consola. La aplicación te devolverá varias líneas de información. En vez de MMQT coloca tu propia ID.
pi@pisanlink:~$ weather --id=MMQT
WARNING: the --id option is deprecated and will eventually be removed
Searching via station...
[caching result Queretaro, Qro., Mexico]
Current conditions at Queretaro, Qro.
Last updated Sep 22, 2013 - 12:45 PM EDT / 2013.09.22 1645 UTC
Temperature: 68 F (20 C)
Relative Humidity: 77%
Wind: from the ENE (070 degrees) at 6 MPH (5 KT)
Sky conditions: mostly cloudy
Creando la aplicación en la Pi
Necesitaremos una aplicación que invoque el script de weather y que procese el texto que devuelve para mostrarlo en la LCD. El contenido de la función principal es el siguiente.
00000023 int main(int argc, char **argv)
00000024 {
00000025 char string[100];
00000026 Weather_Data_T weather;
00000027 Weather_Data_T weather_to_print;
00000028
00000029 pthread_t weather_thread;
00000030
00000031 printf("Weather Stats - Raspberry Pin");
00000032
00000033 if(VALID_ID != Weather_Validate_ID(argv[1]))
00000034 {
00000035 printf("Visit http://weather.noaa.gov/ and get a valid location IDn");
00000036 exit(-1);
00000037 }
00000038 strcpy(Weather_ID, argv[1]);
00000039
00000040 pthread_mutex_lock(&Weather_Mutex);
00000041 sprintf(weather.location, "n/a");
00000042 sprintf(weather.temperature, "n/a");
00000043 sprintf(weather.humidity, "n/a");
00000044 sprintf(weather.sky, "n/a");
00000045 sprintf(weather.weather, "n/a");
00000046 sprintf(weather.wind, "n/a");
00000047 pthread_mutex_unlock(&Weather_Mutex);
00000048
00000049 Nokia_5110_Init();
00000050
00000051 /* Start the weather thread, pass the weather ID as well */
00000052 pthread_create(&weather_thread, NULL, Weather_Thread, (void*)&weather);
00000053
00000054 while(1)
00000055 {
00000056 /* Copy the weather data into the printable copy */
00000057 pthread_mutex_lock(&Weather_Mutex);
00000058 weather_to_print = weather;
00000059 pthread_mutex_unlock(&Weather_Mutex);
00000060
00000061 Nokia_5110_Set_Cursor(0, 0);
00000062 Nokia_5110_Putstring(weather_to_print.location);
00000063
00000064 Nokia_5110_Set_Cursor(0, 1);
00000065 sprintf(string, "%s %s Humid", weather_to_print.temperature, weather_to_print.humidity);
00000066 Nokia_5110_Putstring(string);
00000067
00000068 Nokia_5110_Set_Cursor(0, 2);
00000069 sprintf(string, "Sky %s", weather_to_print.sky);
00000070 Nokia_5110_Putstring(string);
00000071
00000072 Nokia_5110_Set_Cursor(0, 3);
00000073 Nokia_5110_Putstring(weather_to_print.weather);
00000074
00000075 Nokia_5110_Set_Cursor(0, 4);
00000076 Nokia_5110_Putstring(weather_to_print.wind);
00000077
00000078 time_t t = time((void*)0);
00000079 struct tm tm = *localtime(&t);
00000080
00000081 Nokia_5110_Set_Cursor(0, 5);
00000082 sprintf(string, "%02d:%02d:%02d %02d%s",
00000083 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mday, &Month_Text[tm.tm_mon][0]);
00000084 Nokia_5110_Putstring(string);
00000085
00000086 bcm2835_delay(500);
00000087 }
00000088
00000089 Nokia_5110_Stop_SPI();
00000090
00000091 return 0;
00000092 }
Inicialmente la aplicación tendrá que recibir el ID para después pasarlo al script weather. Llegará a través del arreglo **argv en la posición 1. Se hace una evaluación sencilla para ver que el ID tenga 4 dígitos.
Weather_Validate_ID(argv[1])
Una vez validado, empezaremos a usar la variable Weather_Data_T weather. En esta variable se estarán depositando los textos que el script weather devuelva y la funcion main los tomará y mostrará en la LCD. Los datos en Weather_Data_T weather serán escritos cada cierto tiempo a través de un hilo que estará corriendo una y otra vez el script weather. Los datos cambiarán en cualquier momento y la aplicación main tiene que ser cuidadosa y no leer datos mientras el script está escribiendo la variable.
Para solucionar esto, se agregó un mutex, que permite que "algo" se modifique o lea por un solo hilo o función. Si el script está modificando los datos, sólo él podrá hacerlo y los demás no podrán leer o modificar los datos mientras el mutex esté activo. Esperarán hasta que el dueño actual libere el recurso.
Para poder usarlo, simplemente hay que usar la librería #include <pthread.h>. Crear una variable mutex pthread_mutex_t Weather_Mutex = PTHREAD_MUTEX_INITIALIZER y después asegurarse de que nadie esté usando nuestro recurso:
00000040 pthread_mutex_lock(&Weather_Mutex);
Si está en uso, la función se quedará esperando hasta que sea liberado. Si no está en uso, la función podrá modificar el recurso inmediatamente.
Una vez que se dejó de usar el recurso, se debe liberar.
00000047 pthread_mutex_unlock(&Weather_Mutex);
rnrn