Aquest grup va fer un visualitzador d'informació de parades de Bicing. Amb aquest dispositiu, l'usuari pot triar entre tres parades (que se suposa que són les més properes) i obté la disponibilitat de bicicletes de cada tipus així com els punts d'ancoratge que queden lliures. Les dades s'extreuen en format JSON del web de Bicing.
El programa del microcontrolador és el següent:
#define ARDUINOJSON_DECODE_UNICODE 1 #include <ArduinoJson.h> // Carreguem la biblioteca json #include <SPI.h> // Carreguem la biblioteca SPI #include <WiFiNINA.h> // Carreguem la biblioteca WiFiNINA #include "ssd1306.h" // Carreguem la biblioteca pantalla #include "ssd1306_console.h" #include <Adafruit_NeoPixel.h> // Definim botons #define polsdreta 4
int estatBotoAnterior = LOW; // Guarda l'estat previ del botó per no repetir lectures
// Definim NEOPIXEL (INUTIL PER PROGRAMA PERO MOLESTA)
Adafruit_NeoPixel cadena = Adafruit_NeoPixel(3, 1, NEO_GRB + NEO_KHZ800);
Ssd1306Console console;
static uint8_t a = 0;
// A quina xarxa ens conectem
const char idXarxa[] = "REDWIFI_QFZS";
const char contrasenya[] = "3cA2Yy3fdkTkxUhC";
// Servidor d'on obtenim les dades
char server[] = "bicing.barcelona";
char pagina[] = "/get-stations";
// Fem llista de estacions de Bicing objectius
const char* ObjectiuIds[] = {
"\"id\":\"430\"",
"\"id\":\"433\"",
"\"id\":\"435\""
};
int indexEstacio = 0; // Comencem per la primera estació (430)
const char* ObjectiuId = ObjectiuIds[indexEstacio];
unsigned long darreraConnexio = 0;
const unsigned long periodeConnexio = 60000UL; // Actualitzam les dades cada 1 min
int status = WL_IDLE_STATUS;
WiFiSSLClient client;
// Definim caracters amb accents
const uint8_t fontesp_6x8[] PROGMEM = {
0, // Font fixa
6, // Amplada de la font
8, // Alçada de la font
'$', // Primer caràcter de la font (substituirem $ i %)
// à (substituirà a $)
0b00000000,
0b00100001,
0b01010110,
0b01010100,
0b01111000,
0b01000000,
// è (substituirà a %)
0b00000000,
0b00111001,
0b01010110,
0b01010100,
0b01010100,
0b00011000,
0 // Fi de la font
};
void setup(){
//Configurem NEOPIXEL per que no ens molesti
cadena.begin();
cadena.show();
pinMode(polsdreta, INPUT_PULLUP); // Configurem el botó.
// Carreguem la pantalla
ssd1306_128x64_i2c_init();
ssd1306_fillScreen(0);
ssd1306_setFixedFont(ssd1306xled_font6x8);
// Pantalla carregada
Serial.begin(9600); // Monitor sèrie
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("No s'ha trobat el dispositiu Wi-Fi");
while (true); // Bloquegem el programa
}
String versio = WiFi.firmwareVersion();
if (versio < "1.0.0") {
Serial.println("Convindria actualitzar el firmware");
}
while (status != WL_CONNECTED) {
Serial.print("Connectant a la xarxa ");
Serial.println(idXarxa);
status = WiFi.begin(idXarxa, contrasenya);
delay(10000); // Ho tornarem a intentar passats 10 s
}
Serial.print("Connectat a ");
Serial.println(WiFi.SSID());
Serial.print("Estat de la connexió: ");
Serial.println(WiFi.status());
Serial.print("Adreça IP del dispositiu: ");
Serial.println(WiFi.localIP());
Serial.print("Intensitat del senyal: ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
Serial.println();
Serial.println("Anem a connectar al servidor");
}
void loop(){
//Abans de res apaguem el neopixel
cadena.setPixelColor(0, 0, 0, 0); // Pixel 0 apagat
cadena.setPixelColor(1, 0, 0, 0); // Pixel 1 apagat
cadena.show();
// Mirem estat del botó
int lecturaBoto = digitalRead(polsdreta);
// Detectem si el botó acaba de ser premut (ara actua amb LOW)
if (lecturaBoto == LOW && estatBotoAnterior == HIGH) {
indexEstacio++; // Passem a la següent estació
if (indexEstacio > 2) {
indexEstacio = 0; // Tornem a la primera si ens passem
}
ObjectiuId = ObjectiuIds[indexEstacio]; // Actualitzem l'ID actiu
// Mostrem a la pantalla que estem carregant la nova estació
ssd1306_clearScreen();
console.setCursor(0, 0);
console.print("Carregant dades...\n");
darreraConnexio = 0; // Perquè conecti automaticament al servidor després de prémer botó
delay(50); // Petit rebot per estabilitza el botó
}
estatBotoAnterior = lecturaBoto; // Guardem l'estat per a la següent volta
if (client.available()) {
if (client.find("\r\n\r\n")) {
if (client.find(ObjectiuId)) {
if (client.find("\"streetName\":\"")) {
String carrer = client.readStringUntil('"');
if (client.find("\"slots\":")) {
int huecos = client.parseInt();
if (client.find("\"electrical_bikes\":")) {
int elec = client.parseInt();
if (client.find("\"mechanical_bikes\":")) {
int mec = client.parseInt();
client.stop() ;// Pareu de llegir
// Imprimim a la pantalla
ssd1306_clearScreen();
console.setCursor(0, 0);
console.print("Disponibilitat a:\n" );
if(indexEstacio == 0) console.print("Zona uni economia\n");
else if(indexEstacio == 1) console.print("Metro Palau Reial\n");
else console.print("Metro zona uni\n");
console.print(" \n");
console.print(huecos);
console.print(" Espais lliures \n");
console.print(" \n");
console.print(elec);
console.print(" Bicis el");
ssd1306_setFixedFont(fontesp_6x8); // Font amb accents
console.print("%"); // Lletra è
ssd1306_setFixedFont(ssd1306xled_font6x8); // Font normal
console.print("ctriques \n");
console.print(" \n");
console.print(mec);
console.print(" Bicis mec");
ssd1306_setFixedFont(fontesp_6x8); // Font amb accents
console.print("$"); // Lletra à
ssd1306_setFixedFont(ssd1306xled_font6x8); // Font normal
console.print("niques");
}
}
}
}
}
}
}
// Connexió periòdica (o immediata si premem el botó)
if (millis() - darreraConnexio > periodeConnexio || darreraConnexio == 0) {
client.stop();
if (client.connect(server, 443)) {
Serial.print("Demanant dades de l'estació índex: ");
Serial.println(indexEstacio);
client.print("GET ");
client.print(pagina);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
darreraConnexio = millis();
} else {
Serial.println("Ha fallat la connexió");
darreraConnexio = millis();
}
}
}

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