Loading...

Ritorna a Playground Italiano

Articoli di Arduino su Wired Italia

  • Come costruire un Joystick per PC/Mac con una Leonardo per giocare a SuperTuxKart
  • Cosm: un database a cui collegare Arduino e controllare l'andamento dei sensori dal web
  • Twitting Plant La pianta che twitta quando ha sete. [Internet of Things]
  • Lampada twitter: una lampada che cambia colore seguendo un certo hashtag o un account.
  • OpenEnergyMonitor: usiamo Arduino per monitorare i nostri consumi e non solo.



Come costruire un Joystick per PC/Mac con una Leonardo per giocare a SuperTuxKart

Collegamenti


Rappresentazione Fritzing dei collegamenti con una breadboard



Schema elettico dei collegamenti


Sketch

#define KeysNum 9  // Numero di tasti necessari per usare tutti
                   // i comandi di tuxkart per ogni giocatore

//Soglia massima e minima per interpretare il joystick come input digitale
#define joy_leftThreshold 600
#define joy_rightThreshold 300
#define joy_upThreshold 600
#define joy_downThreshold 300

// serve per creare una lista, in pratica sostituisce i numeri con dei nomi
// molto figo, non strettamente necessario. Dopo frena non li ho piu' usati
enum playerPin {
  sinistra, destra, accelera, frena, fuoco, nitro, curvaStretta, guardaDietro, riposiziona };

/* Player 1 controls */
// questo array contiene i pin da assengare ai controlli
// seguendo la convenzione in "enum playerPin"
const int p1_pins[KeysNum] = {
  A0, A1, 0, 1, 2, 3, 4 };  //<-nota che posso prendere anche 0 e 1 perche' sulla leonardo
                            //la seriale hw e' non viene usata per comunicare col PC

// array che contiene i corripondenti tasti che la leonardo
// preme simulando di essere una tastiera
char p1_keyboardKeys[9] = {
  KEY_LEFT_ARROW, KEY_RIGHT_ARROW, KEY_UP_ARROW, KEY_DOWN_ARROW, ' ', 'n', 'v', 'b', KEY_BACKSPACE };

/* Player 2 controls */
//valgono gli stessi commenti del player 1
const int p2_pins[KeysNum] = {
  A2, A3, 5, 6, 7, 8, 9 };

char p2_keyboardKeys[9] = {
  'a', 'd', 'w', 's', 'q', 'e', '1', '2', '3' };

void setup()
{
  //inizializzo i pin come INPUT
  inizializzaPlayer(p1_pins);
  inizializzaPlayer(p2_pins);

  Serial.begin(9600);
}

void loop()
{
  leggiController(p1_pins, p1_keyboardKeys);
  leggiController(p2_pins, p2_keyboardKeys);
}

// funzione per inizializzare i pin come INPUT.
// usando l'array per contenere i pin posso fare tutto con un ciclo for
// e posso usare la stessa funzione per piu' giocatori
void inizializzaPlayer (const int *pins) //<- se il puntatore confonde lo togliamo
{
  for(int i=0; i<KeysNum; i++)
    pinMode(pins[i], INPUT);
}

// questa funzione riceve come parametri:
// [*pins]    - i piedini assegnati al controller del giocatore X
// [*keylist] - l'elenco dei tasti dalla tastiera da emulare per contollare il gioco
//
// Scandisce in sequenza ogni input di arduino e se attivo associa il
// corrispondente tasto della tastiera.
void leggiController (const int *pins, char *keyList)
{
  int direzione, throttle;
 
  // ciclo for per scandire tutti i tasti della tastiera
  for(int i=0; i<KeysNum; i++)
  {
    // sinistra e' un elemento della enum...vale 1
    if(i == sinistra){
      // leggo l'asse X del joystick
      direzione = analogRead( pins[0] );
      // se supero la soglia devo mandare il comando corrispondente
      if( direzione > joy_leftThreshold )
        Keyboard.press(keyList[sinistra]);
      else
        // devo rilasciare anche il tasto della tastiera
        // quando sul controller il rispettivo comando non viene premuto
        Keyboard.release(keyList[sinistra]);
    }

    else if(i == destra) {
      // ho già letto il pin dell'asse X prima, non c'e' bisogno di rifarlo
      if( direzione < joy_rightThreshold )
        Keyboard.press(keyList[destra]);
      else
        Keyboard.release(keyList[destra]);
    }

    // uguale all'asse X ma per l'asse Y che controlla freno ed acceleratore
    else if(i == accelera) {
      throttle = analogRead( pins[1] );
      if( throttle > joy_upThreshold )
        Keyboard.press(keyList[frena]);
      else
        Keyboard.release(keyList[frena]);
    }

    else if(i == frena) {
      if( throttle < joy_downThreshold )
        Keyboard.press(keyList[accelera]);
      else
        Keyboard.release(keyList[accelera]);
    }

   // ho finito di leggere i piedini analogici
   //
   // posso passare a leggere quelli digitali che, non dovendo comparare
   // delle soglie posso leggere molto più facilmente e in sequenza.
   // Sfruttando la comodita' di aver usato un array
    else {
      if( digitalRead( pins[i] ) == HIGH )
        Keyboard.press(keyList[i]);
      else
        Keyboard.release(keyList[i]);
    }
  }
}


Cosm

Cosm.com è un servizio online che tramite le API che mette a disposizione consente ad un Arduino di inviare i dati che legge dai senori che avete deciso di collegargli. Cosm si preoccuperà di salvare i dati in un database e di mostrarli nella pagina dello stream che avete appositamente creato, i grafici relativi all'andamento temporale delle letture dei vostri sensori.

Per creare il vostro stream di dati personalizzato per prima cosa dovete creare un account su Cosm.com. Una volta che avete accesso alla console, cliccate sul pulsante "+ Device/Feed" per creare una pagina (il feed) dedicato all'Arduino che tra poco programmeremo per inviare i dati. Tra le quattro opzioni selezionate quella chiamata "Something Else" e seguite la procedura, specificando che sarete voi ad inviare i dati a Cosm ( Opzione: No, I will push data to Cosm ).

Al termine della procedura segnatevi il titolo che avete dato al feed e anche il numero che vi da Cosm alla fine.

Manca ancora una cosa affichè il vostro arduino si possa collegare in modo sicuro al vostro account, una chiave di protezione che, dovete generare selezionando il menu "Keys" dal vostro pannello utente. Cosm vi da varie possibilità per cui possa essere valida quella chiave, ad esempio: la potete associare ad un solo feed oppure, decidere di averne una sola per tutti, ecc. Una volta generata scrivetevetela da qualche parte.

Alle Officine Arduino abbiamo deciso di usare dei moduli TinkerKit per collegare un termistore ed una fotoresistenza rispettivamente agli ingressi analogici 0 e 1.

Nel codice è contenuto l'algoritmo di conversione che trasforma il valore di tensione letto dal termistore in una temperatura in gradi centrigradi. Mentre la lettura della luminosità ambientale è rapportata in percentuale del valore analogico letto.

Il codice:

/*
  Officine Arduino Temperature and Light sensors connected to:
  Cosm client with Strings
 
 This sketch connects an analog sensor to Cosm (http://www.cosm.com)
 using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
 the Adafruit Ethernet shield, either one will work, as long as it's got
 a Wiznet Ethernet module on board.
 
 
 This example uses the String library, which is part of the Arduino core from
 version 0019.  
 
 Circuit:
 * Thermistor attached to analog in 0
 * LDR sensor attached to analog in 1
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 Based on the CosmClientString created:
 by Tom Igoe with input from Usman Haque and Joe Saavedra
 customized by Federico Vanzati
 
 http://arduino.cc/en/Tutorial/PachubeClientString
 This code is in the public domain.
 
 */


#include <SPI.h>
#include <Ethernet.h>

                                                                     
#define APIKEY         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // replace your Cosm api key here
#define FEEDID         67409 // replace your feed ID
#define USERAGENT      "Officine Arduino Temperature and Light" // user agent is the project name

const static int Beta = 3950;        // Beta parameter
const static float Kelvin = 273.15;  // 0°C = 273.15 K
const static int Rb = 10000;         // 10 kOhm
const static float Ginf = 120.6685;  // Ginf = 1/Rinf
//The formula to compute the Rinf is:
// Rinf = R0*e^(-Beta/T0) = 4700*e^(-3950/298.15)


// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(192,168,1,100);

// initialize the library instance:
EthernetClient client;

// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(216,52,233,121);      // numeric IP for api.cosm.com
char server[] = "api.cosm.com";   // name address for Cosm API

unsigned long lastConnectionTime = 0;  // last time you connected to the server, in milliseconds
boolean lastConnected = false;  // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000;  //delay between updates to Pachube.com

void setup() {
  // start serial port:
  Serial.begin(9600);
  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // DHCP failed, so use a fixed IP address:
    Ethernet.begin(mac, ip);
  }
  else {
    Serial.print("My IP address is: ");
    for (byte thisByte = 0; thisByte < 4; thisByte++) {
      // print the value of each byte of the IP address:
      Serial.print(Ethernet.localIP()[thisByte], DEC);
      Serial.print(".");
    }
    Serial.println();
  }
}

void loop() {
  // read the analog sensor:
  int sensorReading = analogRead(A0);
  float Rthermistor = Rb * (1023.0 / sensorReading - 1);
  float temperatureC = Beta / (log( Rthermistor * Ginf )) ;
  temperatureC -=  Kelvin;

  int decimal = (int)temperatureC;
  int fraction = (temperatureC - decimal) * 10;

  String dataString = "Temperatura_Ufficio,";
  dataString += decimal;
  dataString += '.';
  dataString += fraction;

  //Reading the LDR and transform in percentage of light
  int ldrReading = map(analogRead(A1), 0, 1023, 0, 100);
 
  dataString += "\nIlluminazione,";
  dataString += ldrReading;

  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
//    Serial.print(decimal);
//    Serial.print(".");
//    Serial.println(fraction);
//    Serial.println();
    Serial.println(dataString);
    Serial.println();
    sendData(dataString);
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void sendData(String thisData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.cosm.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");
    client.println(thisData.length());

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    client.println(thisData);

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
    lastConnectionTime = millis();
}

Come vi sarete già accorti, nelle prime tre costanti dovete scrivere i dati relativi al vostro feed, quelli che vi siete segnati prima.

Se volete avere un'idea del risultato date un occhio al feed di Officine Arduino.


TwittingPlant

La pianta che twitta quando ha sete







Ritorna a Playground Italiano