La scoperta dei primi videogiochi con Arduino laboratorio 10 Ottobre 2020 Linolab

Ecco i progetti per questa lezione:

 Prime esperienze con luci e suoni!

#include <Tone.h>
Tone speakerpin;
byte button[] = {2, 3, 4, 5};
byte ledpin[] = {8, 9, 10, 11};  
int buttonstate = 0;  

void setup() {
  Serial.begin(9600);
  speakerpin.begin(12); 
  
  for(int x=0; x<4; x++)  
  {
    pinMode(ledpin[x], OUTPUT);
  }
  
  for(int x=0; x<4; x++) 
  {
    pinMode(button[x], INPUT); 
    digitalWrite(button[x], HIGH); 
  }

}

void loop() {

  for(int x = 0; x<4; x++) {
    buttonstate = digitalRead(button[x]);

    if(buttonstate == LOW && x == 0) {
      digitalWrite(ledpin[0], HIGH);
      speakerpin.play(NOTE_G4, 100);
      delay(200);
      digitalWrite(ledpin[0], LOW);
    }

    if(buttonstate == LOW && x == 1) {
      digitalWrite(ledpin[1], HIGH);
      speakerpin.play(NOTE_A4, 100);
      delay(200);
      digitalWrite(ledpin[1], LOW);
    }

    if(buttonstate == LOW && x == 2) {
      digitalWrite(ledpin[2], HIGH);
      speakerpin.play(NOTE_B4, 100);
      delay(200);
      digitalWrite(ledpin[2], LOW);
    }

    if(buttonstate == LOW && x == 3) {
      digitalWrite(ledpin[3], HIGH);
      speakerpin.play(NOTE_C5, 100);
      delay(200);
      digitalWrite(ledpin[3], LOW);
    }
  }
}

scarica il codice
Per questo progetto si necessita anche di questa libreria

Un gioco di memoria!

utilizziamo il circuito e lalibreria dell’esercizio precedente.

#include <Tone.h>
Tone speakerpin;
int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4};
int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500};
int note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};
int duration[] = {100, 100, 100, 300, 100, 300};
byte button[] = {2, 3, 4, 5};
byte ledpin[] = {8, 9, 10, 11};  
int turn = 0;  
int buttonstate = 0;  
int randomArray[100]; 
int inputArray[100];  


void setup() {
  Serial.begin(9600);
  speakerpin.begin(12); 
  
  for(int x=0; x<4; x++)  
  {
    pinMode(ledpin[x], OUTPUT);
  }
  
  for(int x=0; x<4; x++) 
  {
    pinMode(button[x], INPUT); 
    digitalWrite(button[x], HIGH); 
  }

  randomSeed(analogRead(0)); 
  for (int thisNote = 0; thisNote < 13; thisNote ++) {
    
     speakerpin.play(starttune[thisNote]);

     if (thisNote==0 || thisNote==2 || thisNote==4 || thisNote== 6)
     {
       digitalWrite(ledpin[0], HIGH);
     }
     if (thisNote==1 || thisNote==3 || thisNote==5 || thisNote== 7 || thisNote==9 || thisNote==11)
     {
       digitalWrite(ledpin[1], HIGH);
     }
     if (thisNote==8 || thisNote==12)
     {
       digitalWrite(ledpin[2], HIGH);
     }  
     if (thisNote==10)
     {   
       digitalWrite(ledpin[3], HIGH);
     }
     delay(duration2[thisNote]);

     speakerpin.stop();
     digitalWrite(ledpin[0], LOW);
     digitalWrite(ledpin[1], LOW);
     digitalWrite(ledpin[2], LOW);
     digitalWrite(ledpin[3], LOW);
     delay(25);
    }
  delay(1000);
}
 
void loop() 
{   
  for (int y=0; y<=99; y++)
  {

    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
  
    for (int thisNote = 0; thisNote < 6; thisNote ++) {
   
     speakerpin.play(note[thisNote]);
  
     delay(duration[thisNote]);
  
     speakerpin.stop();
     delay(25);
    }
    
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    delay(1000);
  
    for (int y=turn; y <= turn; y++)
    {
      Serial.println(""); 
      Serial.print("Turn: ");
      Serial.print(y);
      Serial.println("");
      randomArray[y] = random(1, 5); 
      for (int x=0; x <= turn; x++)
      {
        Serial.print(randomArray[x]);
      
        for(int y=0; y<4; y++)
        {
      
          if (randomArray[x] == 1 && ledpin[y] == 8) 
          {  
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_G3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }

          if (randomArray[x] == 2 && ledpin[y] == 9) 
          {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_A3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
  
          if (randomArray[x] == 3 && ledpin[y] == 10) 
          {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_B3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }

          if (randomArray[x] == 4 && ledpin[y] == 11) 
          {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_C4, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
        }
      }
    }
    input();
  }
}
 
 
 
void input() { 

  for (int x=0; x <= turn;)
  { 

    for(int y=0; y<4; y++)
    {
      
      buttonstate = digitalRead(button[y]);
    
      if (buttonstate == LOW && button[y] == 2)
      {
        digitalWrite(ledpin[0], HIGH);
        speakerpin.play(NOTE_G3, 100);
        delay(200);
        digitalWrite(ledpin[0], LOW);
        inputArray[x] = 1;
        delay(250);
        Serial.print(" ");
        Serial.print(1);
        if (inputArray[x] != randomArray[x]) {
          fail();                              
        }                                     
        x++;
      }
       if (buttonstate == LOW && button[y] == 3)
      {
        digitalWrite(ledpin[1], HIGH);
        speakerpin.play(NOTE_A3, 100);
        delay(200);
        digitalWrite(ledpin[1], LOW);
        inputArray[x] = 2;
        delay(250);
        Serial.print(" ");
        Serial.print(2);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }

      if (buttonstate == LOW && button[y] == 4)
      {
        digitalWrite(ledpin[2], HIGH);
        speakerpin.play(NOTE_B3, 100);
        delay(200);
        digitalWrite(ledpin[2], LOW);
        inputArray[x] = 3;
        delay(250);
        Serial.print(" ");
        Serial.print(3);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }

      if (buttonstate == LOW && button[y] == 5)
      {
        digitalWrite(ledpin[3], HIGH);
        speakerpin.play(NOTE_C4, 100);
        delay(200);
        digitalWrite(ledpin[3], LOW);
        inputArray[x] = 4;
        delay(250);
        Serial.print(" ");
        Serial.print(4);
        if (inputArray[x] != randomArray[x]) 
        {
          fail();
        }
        x++;
      }
    }
  }
  delay(500);
  turn++; 
}

void fail() { 
 
  for (int y=0; y<=2; y++)
  { //Flashes lights for failure
    
    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
    speakerpin.play(NOTE_G3, 300);
    delay(200);
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    speakerpin.play(NOTE_C3, 300);
    delay(200);
  }
  delay(500);
  turn = -1;
}

scarica il codice

Snake!

#include "LedControl.h" // LedControl library is used for controlling a LED matrix. Find it using Library Manager or download zip here: https://github.com/wayoda/LedControl


// --------------------------------------------------------------- //
// ------------------------- user config ------------------------- //
// --------------------------------------------------------------- //

// there are defined all the pins
struct Pin {
  static const short joystickX = A3;   // joystick X axis pin
  static const short joystickY = A2;   // joystick Y axis pin
  static const short joystickVCC = 15; // virtual VCC for the joystick (Analog 1) (to make the joystick connectable right next to the arduino nano)
  static const short joystickGND = 14; // virtual GND for the joystick (Analog 0) (to make the joystick connectable right next to the arduino nano)

  static const short potentiometer = A4; // potentiometer for snake speed control

  static const short CLK = 10;   // clock for LED matrix
  static const short CS  = 11;  // chip-select for LED matrix
  static const short DIN = 12; // data-in for LED matrix
};

// LED matrix brightness: between 0(darkest) and 15(brightest)
const short intensity = 8;

// lower = faster message scrolling
const short messageSpeed = 5;

// initial snake length (1...63, recommended 3)
const short initialSnakeLength = 3;


void setup() {
  Serial.begin(115200);  // set the same baud rate on your Serial Monitor
  initialize();         // initialize pins & LED matrix
  calibrateJoystick(); // calibrate the joystick home (do not touch it)
  showSnakeMessage(); // scrolls the 'snake' message around the matrix
}


void loop() {
  generateFood();    // if there is no food, generate one
  scanJoystick();    // watches joystick movements & blinks with food
  calculateSnake();  // calculates snake parameters
  handleGameStates();

  // uncomment this if you want the current game board to be printed to the serial (slows down the game a bit)
  dumpGameBoard();
}





// --------------------------------------------------------------- //
// -------------------- supporting variables --------------------- //
// --------------------------------------------------------------- //

LedControl matrix(Pin::DIN, Pin::CLK, Pin::CS, 1);

struct Point {
  int row = 0, col = 0;
  Point(int row = 0, int col = 0): row(row), col(col) {}
};

struct Coordinate {
  int x = 0, y = 0;
  Coordinate(int x = 0, int y = 0): x(x), y(y) {}
};

bool win = false;
bool gameOver = false;

// primary snake head coordinates (snake head), it will be randomly generated
Point snake;

// food is not anywhere yet
Point food(-1, -1);

// construct with default values in case the user turns off the calibration
Coordinate joystickHome(500, 500);

// snake parameters
int snakeLength = initialSnakeLength; // choosed by the user in the config section
int snakeSpeed = 1; // will be set according to potentiometer value, cannot be 0
int snakeDirection = 0; // if it is 0, the snake does not move

// direction constants
const short up     = 1;
const short right  = 2;
const short down   = 3; // 'down - 2' must be 'up'
const short left   = 4; // 'left - 2' must be 'right'

// threshold where movement of the joystick will be accepted
const int joystickThreshold = 160;

// artificial logarithmity (steepness) of the potentiometer (-1 = linear, 1 = natural, bigger = steeper (recommended 0...1))
const float logarithmity = 0.4;

// snake body segments storage
int gameboard[8][8] = {};




// --------------------------------------------------------------- //
// -------------------------- functions -------------------------- //
// --------------------------------------------------------------- //


// if there is no food, generate one, also check for victory
void generateFood() {
  if (food.row == -1 || food.col == -1) {
    // self-explanatory
    if (snakeLength >= 64) {
      win = true;
      return; // prevent the food generator from running, in this case it would run forever, because it will not be able to find a pixel without a snake
    }

    // generate food until it is in the right position
    do {
      food.col = random(8);
      food.row = random(8);
    } while (gameboard[food.row][food.col] > 0);
  }
}


// watches joystick movements & blinks with food
void scanJoystick() {
  int previousDirection = snakeDirection; // save the last direction
  long timestamp = millis();

  while (millis() < timestamp + snakeSpeed) {
    // calculate snake speed exponentially (10...1000ms)
    float raw = mapf(analogRead(Pin::potentiometer), 0, 1023, 0, 1);
    snakeSpeed = mapf(pow(raw, 3.5), 0, 1, 10, 1000); // change the speed exponentially
    if (snakeSpeed == 0) snakeSpeed = 1; // safety: speed can not be 0

    // determine the direction of the snake
    analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold ? snakeDirection = up    : 0;
    analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold ? snakeDirection = down  : 0;
    analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold ? snakeDirection = left  : 0;
    analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold ? snakeDirection = right : 0;

    // ignore directional change by 180 degrees (no effect for non-moving snake)
    snakeDirection + 2 == previousDirection && previousDirection != 0 ? snakeDirection = previousDirection : 0;
    snakeDirection - 2 == previousDirection && previousDirection != 0 ? snakeDirection = previousDirection : 0;

    // intelligently blink with the food
    matrix.setLed(0, food.row, food.col, millis() % 100 < 50 ? 1 : 0);
  }
}


// calculate snake movement data
void calculateSnake() {
  switch (snakeDirection) {
    case up:
      snake.row--;
      fixEdge();
      matrix.setLed(0, snake.row, snake.col, 1);
      break;

    case right:
      snake.col++;
      fixEdge();
      matrix.setLed(0, snake.row, snake.col, 1);
      break;

    case down:
      snake.row++;
      fixEdge();
      matrix.setLed(0, snake.row, snake.col, 1);
      break;

    case left:
      snake.col--;
      fixEdge();
      matrix.setLed(0, snake.row, snake.col, 1);
      break;

    default: // if the snake is not moving, exit
      return;
  }

  // if there is a snake body segment, this will cause the end of the game (snake must be moving)
  if (gameboard[snake.row][snake.col] > 1 && snakeDirection != 0) {
    gameOver = true;
    return;
  }

  // check if the food was eaten
  if (snake.row == food.row && snake.col == food.col) {
    food.row = -1; // reset food
    food.col = -1;

    // increment snake length
    snakeLength++;

    // increment all the snake body segments
    for (int row = 0; row < 8; row++) {
      for (int col = 0; col < 8; col++) {
        if (gameboard[row][col] > 0 ) {
          gameboard[row][col]++;
        }
      }
    }
  }

  // add new segment at the snake head location
  gameboard[snake.row][snake.col] = snakeLength + 1; // will be decremented in a moment

  // decrement all the snake body segments, if segment is 0, turn the corresponding led off
  for (int row = 0; row < 8; row++) {
    for (int col = 0; col < 8; col++) {
      // if there is a body segment, decrement it's value
      if (gameboard[row][col] > 0 ) {
        gameboard[row][col]--;
      }

      // display the current pixel
      matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 0 : 1);
    }
  }
}


// causes the snake to appear on the other side of the screen if it gets out of the edge
void fixEdge() {
  snake.col < 0 ? snake.col += 8 : 0;
  snake.col > 7 ? snake.col -= 8 : 0;
  snake.row < 0 ? snake.row += 8 : 0;
  snake.row > 7 ? snake.row -= 8 : 0;
}


void handleGameStates() {
  if (gameOver || win) {
    unrollSnake();

    showScoreMessage(snakeLength - initialSnakeLength);

    if (gameOver) showGameOverMessage();
    else if (win) showWinMessage();

    // re-init the game
    win = false;
    gameOver = false;
    snake.row = random(8);
    snake.col = random(8);
    food.row = -1;
    food.col = -1;
    snakeLength = initialSnakeLength;
    snakeDirection = 0;
    memset(gameboard, 0, sizeof(gameboard[0][0]) * 8 * 8);
    matrix.clearDisplay(0);
  }
}


void unrollSnake() {
  // switch off the food LED
  matrix.setLed(0, food.row, food.col, 0);

  delay(800);

  // flash the screen 5 times
  for (int i = 0; i < 5; i++) {
    // invert the screen
    for (int row = 0; row < 8; row++) {
      for (int col = 0; col < 8; col++) {
        matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 1 : 0);
      }
    }

    delay(20);

    // invert it back
    for (int row = 0; row < 8; row++) {
      for (int col = 0; col < 8; col++) {
        matrix.setLed(0, row, col, gameboard[row][col] == 0 ? 0 : 1);
      }
    }

    delay(50);

  }


  delay(600);

  for (int i = 1; i <= snakeLength; i++) {
    for (int row = 0; row < 8; row++) {
      for (int col = 0; col < 8; col++) {
        if (gameboard[row][col] == i) {
          matrix.setLed(0, row, col, 0);
          delay(100);
        }
      }
    }
  }
}


// calibrate the joystick home for 10 times
void calibrateJoystick() {
  Coordinate values;

  for (int i = 0; i < 10; i++) {
    values.x += analogRead(Pin::joystickX);
    values.y += analogRead(Pin::joystickY);
  }

  joystickHome.x = values.x / 10;
  joystickHome.y = values.y / 10;
}


void initialize() {
  pinMode(Pin::joystickVCC, OUTPUT);
  digitalWrite(Pin::joystickVCC, HIGH);

  pinMode(Pin::joystickGND, OUTPUT);
  digitalWrite(Pin::joystickGND, LOW);

  matrix.shutdown(0, false);
  matrix.setIntensity(0, intensity);
  matrix.clearDisplay(0);

  randomSeed(analogRead(A5));
  snake.row = random(8);
  snake.col = random(8);
}


void dumpGameBoard() {
  String buff = "\n\n\n";
  for (int row = 0; row < 8; row++) {
    for (int col = 0; col < 8; col++) {
      if (gameboard[row][col] < 10) buff += " ";
      if (gameboard[row][col] != 0) buff += gameboard[row][col];
      else if (col == food.col && row == food.row) buff += "@";
      else if (col == snake.col && row == snake.row) buff += "#";
      else buff += "-";
      buff += " ";
    }
    buff += "\n";
  }
  Serial.println(buff);
}





// --------------------------------------------------------------- //
// -------------------------- messages --------------------------- //
// --------------------------------------------------------------- //

const PROGMEM bool snakeMessage[8][56] = {
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

const PROGMEM bool gameOverMessage[8][90] = {
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

const PROGMEM bool scoreMessage[8][58] = {
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

const PROGMEM bool digits[][8][8] = {
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 1, 1, 1, 0},
    {0, 1, 1, 1, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 1, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 1, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 1, 1, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 1, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 0, 0, 1, 1, 1, 0, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 1, 1, 1, 0, 0},
    {0, 0, 1, 0, 1, 1, 0, 0},
    {0, 1, 0, 0, 1, 1, 0, 0},
    {0, 1, 1, 1, 1, 1, 1, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 1, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 0, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 1, 1, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 1, 0},
    {0, 0, 0, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0}
  }
};


// scrolls the 'snake' message around the matrix
void showSnakeMessage() {
  [&] {
    for (int d = 0; d < sizeof(snakeMessage[0]) - 7; d++) {
      for (int col = 0; col < 8; col++) {
        delay(messageSpeed);
        for (int row = 0; row < 8; row++) {
          // this reads the byte from the PROGMEM and displays it on the screen
          matrix.setLed(0, row, col, pgm_read_byte(&(snakeMessage[row][col + d])));
        }
      }

      // if the joystick is moved, exit the message
      if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
              || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
              || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
              || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {
        return; // return the lambda function
      }
    }
  }();

  matrix.clearDisplay(0);

  // wait for joystick co come back
  while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
          || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
          || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
          || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}

}


// scrolls the 'game over' message around the matrix
void showGameOverMessage() {
  [&] {
    for (int d = 0; d < sizeof(gameOverMessage[0]) - 7; d++) {
      for (int col = 0; col < 8; col++) {
        delay(messageSpeed);
        for (int row = 0; row < 8; row++) {
          // this reads the byte from the PROGMEM and displays it on the screen
          matrix.setLed(0, row, col, pgm_read_byte(&(gameOverMessage[row][col + d])));
        }
      }

      // if the joystick is moved, exit the message
      if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
              || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
              || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
              || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {
        return; // return the lambda function
      }
    }
  }();

  matrix.clearDisplay(0);

  // wait for joystick co come back
  while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
          || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
          || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
          || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}

}


// scrolls the 'win' message around the matrix
void showWinMessage() {
  // not implemented yet // TODO: implement it
}


// scrolls the 'score' message with numbers around the matrix
void showScoreMessage(int score) {
  if (score < 0 || score > 99) return;

  // specify score digits
  int second = score % 10;
  int first = (score / 10) % 10;

  [&] {
    for (int d = 0; d < sizeof(scoreMessage[0]) + 2 * sizeof(digits[0][0]); d++) {
      for (int col = 0; col < 8; col++) {
        delay(messageSpeed);
        for (int row = 0; row < 8; row++) {
          if (d <= sizeof(scoreMessage[0]) - 8) {
            matrix.setLed(0, row, col, pgm_read_byte(&(scoreMessage[row][col + d])));
          }

          int c = col + d - sizeof(scoreMessage[0]) + 6; // move 6 px in front of the previous message

          // if the score is < 10, shift out the first digit (zero)
          if (score < 10) c += 8;

          if (c >= 0 && c < 8) {
            if (first > 0) matrix.setLed(0, row, col, pgm_read_byte(&(digits[first][row][c]))); // show only if score is >= 10 (see above)
          } else {
            c -= 8;
            if (c >= 0 && c < 8) {
              matrix.setLed(0, row, col, pgm_read_byte(&(digits[second][row][c]))); // show always
            }
          }
        }
      }

      // if the joystick is moved, exit the message
      if (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
              || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
              || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
              || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {
        return; // return the lambda function
      }
    }
  }();

  matrix.clearDisplay(0);

  //  // wait for joystick co come back
  //  while (analogRead(Pin::joystickY) < joystickHome.y - joystickThreshold
  //          || analogRead(Pin::joystickY) > joystickHome.y + joystickThreshold
  //          || analogRead(Pin::joystickX) < joystickHome.x - joystickThreshold
  //          || analogRead(Pin::joystickX) > joystickHome.x + joystickThreshold) {}

}


// standard map function, but with floats
float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

scarica il codice
Per questo progetto si necessita anche di questa libreria

I primi test con lo schermo LCD!

#include <LiquidCrystal.h>

#define PIN_BUTTON 2
#define PIN_AUTOPLAY 1
#define PIN_READWRITE 10
#define PIN_CONTRAST 12
int x = 0;
String str = "Hello World!";

LiquidCrystal lcd(11, 9, 6, 5, 4, 3);

void setup(){
  pinMode(PIN_READWRITE, OUTPUT);
  digitalWrite(PIN_READWRITE, LOW);
  pinMode(PIN_CONTRAST, OUTPUT);
  digitalWrite(PIN_CONTRAST, LOW);
  pinMode(PIN_AUTOPLAY, OUTPUT);
  digitalWrite(PIN_AUTOPLAY, HIGH);  
  lcd.begin(16, 2);
  lcd.print(str);
}

void loop(){
}

scarica il codice

Un primitivo Super Mario!

lo schema è quello dell’esercizio precedente

#include <LiquidCrystal.h>

#define PIN_BUTTON 2
#define PIN_AUTOPLAY 1
#define PIN_READWRITE 10
#define PIN_CONTRAST 12

#define SPRITE_RUN1 1
#define SPRITE_RUN2 2
#define SPRITE_JUMP 3
#define SPRITE_JUMP_UPPER '.'         // Use the '.' character for the head
#define SPRITE_JUMP_LOWER 4
#define SPRITE_TERRAIN_EMPTY ' '      // User the ' ' character
#define SPRITE_TERRAIN_SOLID 5
#define SPRITE_TERRAIN_SOLID_RIGHT 6
#define SPRITE_TERRAIN_SOLID_LEFT 7

#define HERO_HORIZONTAL_POSITION 1    // Horizontal position of hero on screen

#define TERRAIN_WIDTH 16
#define TERRAIN_EMPTY 0
#define TERRAIN_LOWER_BLOCK 1
#define TERRAIN_UPPER_BLOCK 2

#define HERO_POSITION_OFF 0          // Hero is invisible
#define HERO_POSITION_RUN_LOWER_1 1  // Hero is running on lower row (pose 1)
#define HERO_POSITION_RUN_LOWER_2 2  //                              (pose 2)

#define HERO_POSITION_JUMP_1 3       // Starting a jump
#define HERO_POSITION_JUMP_2 4       // Half-way up
#define HERO_POSITION_JUMP_3 5       // Jump is on upper row
#define HERO_POSITION_JUMP_4 6       // Jump is on upper row
#define HERO_POSITION_JUMP_5 7       // Jump is on upper row
#define HERO_POSITION_JUMP_6 8       // Jump is on upper row
#define HERO_POSITION_JUMP_7 9       // Half-way down
#define HERO_POSITION_JUMP_8 10      // About to land

#define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1)
#define HERO_POSITION_RUN_UPPER_2 12 //                              (pose 2)

LiquidCrystal lcd(11, 9, 6, 5, 4, 3);
static char terrainUpper[TERRAIN_WIDTH + 1];
static char terrainLower[TERRAIN_WIDTH + 1];
static bool buttonPushed = false;
static int timeDelay = 150;

void initializeGraphics(){
  static byte graphics[] = {
    // Run position 1
    B01100,
    B01100,
    B00000,
    B01110,
    B11100,
    B01100,
    B11010,
    B10011,
    // Run position 2
    B01100,
    B01100,
    B00000,
    B01100,
    B01100,
    B01100,
    B01100,
    B01110,
    // Jump
    B01100,
    B01100,
    B00000,
    B11110,
    B01101,
    B11111,
    B10000,
    B00000,
    // Jump lower
    B11110,
    B01101,
    B11111,
    B10000,
    B00000,
    B00000,
    B00000,
    B00000,
    // Ground
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    // Ground right
    B00011,
    B00011,
    B00011,
    B00011,
    B00011,
    B00011,
    B00011,
    B00011,
    // Ground left
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
    B11000,
  };
  int i;
  // Skip using character 0, this allows lcd.print() to be used to
  // quickly draw multiple characters
  for (i = 0; i < 7; ++i) {
    lcd.createChar(i + 1, &graphics[i * 8]);
  }
  for (i = 0; i < TERRAIN_WIDTH; ++i) {
    terrainUpper[i] = SPRITE_TERRAIN_EMPTY;
    terrainLower[i] = SPRITE_TERRAIN_EMPTY;
  }
}

// Slide the terrain to the left in half-character increments
//
void advanceTerrain(char* terrain, byte newTerrain){
  for (int i = 0; i < TERRAIN_WIDTH; ++i) {
    char current = terrain[i];
    char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1];
    switch (current){
      case SPRITE_TERRAIN_EMPTY:
        terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY;
        break;
      case SPRITE_TERRAIN_SOLID:
        terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID;
        break;
      case SPRITE_TERRAIN_SOLID_RIGHT:
        terrain[i] = SPRITE_TERRAIN_SOLID;
        break;
      case SPRITE_TERRAIN_SOLID_LEFT:
        terrain[i] = SPRITE_TERRAIN_EMPTY;
        break;
    }
  }
}

bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) {
  bool collide = false;
  char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION];
  char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION];
  byte upper, lower;
  switch (position) {
    case HERO_POSITION_OFF:
      upper = lower = SPRITE_TERRAIN_EMPTY;
      break;
    case HERO_POSITION_RUN_LOWER_1:
      upper = SPRITE_TERRAIN_EMPTY;
      lower = SPRITE_RUN1;
      break;
    case HERO_POSITION_RUN_LOWER_2:
      upper = SPRITE_TERRAIN_EMPTY;
      lower = SPRITE_RUN2;
      break;
    case HERO_POSITION_JUMP_1:
    case HERO_POSITION_JUMP_8:
      upper = SPRITE_TERRAIN_EMPTY;
      lower = SPRITE_JUMP;
      break;
    case HERO_POSITION_JUMP_2:
    case HERO_POSITION_JUMP_7:
      upper = SPRITE_JUMP_UPPER;
      lower = SPRITE_JUMP_LOWER;
      break;
    case HERO_POSITION_JUMP_3:
    case HERO_POSITION_JUMP_4:
    case HERO_POSITION_JUMP_5:
    case HERO_POSITION_JUMP_6:
      upper = SPRITE_JUMP;
      lower = SPRITE_TERRAIN_EMPTY;
      break;
    case HERO_POSITION_RUN_UPPER_1:
      upper = SPRITE_RUN1;
      lower = SPRITE_TERRAIN_EMPTY;
      break;
    case HERO_POSITION_RUN_UPPER_2:
      upper = SPRITE_RUN2;
      lower = SPRITE_TERRAIN_EMPTY;
      break;
  }
  if (upper != ' ') {
    terrainUpper[HERO_HORIZONTAL_POSITION] = upper;
    collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true;
  }
  if (lower != ' ') {
    terrainLower[HERO_HORIZONTAL_POSITION] = lower;
    collide |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true;
  }
  
  byte digits = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1;
  
  // Draw the scene
  terrainUpper[TERRAIN_WIDTH] = '\0';
  terrainLower[TERRAIN_WIDTH] = '\0';
  char temp = terrainUpper[16-digits];
  terrainUpper[16-digits] = '\0';
  lcd.setCursor(0,0);
  lcd.print(terrainUpper);
  terrainUpper[16-digits] = temp;  
  lcd.setCursor(0,1);
  lcd.print(terrainLower);
  
  lcd.setCursor(16 - digits,0);
  lcd.print(score);

  terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave;
  terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave;
  return collide;
}

// Handle the button push as an interrupt
void buttonPush() {
  buttonPushed = true;
}

void setup(){
  pinMode(PIN_READWRITE, OUTPUT);
  digitalWrite(PIN_READWRITE, LOW);
  pinMode(PIN_CONTRAST, OUTPUT);
  digitalWrite(PIN_CONTRAST, LOW);
  pinMode(PIN_BUTTON, INPUT);
  digitalWrite(PIN_BUTTON, HIGH);
  pinMode(PIN_AUTOPLAY, OUTPUT);
  digitalWrite(PIN_AUTOPLAY, HIGH);
  
  // Digital pin 2 maps to interrupt 0
  attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING);
  
  initializeGraphics();
  
  lcd.begin(16, 2);
}

void loop(){
  static byte heroPos = HERO_POSITION_RUN_LOWER_1;
  static byte newTerrainType = TERRAIN_EMPTY;
  static byte newTerrainDuration = 1;
  static bool playing = false;
  static bool blink = false;
  static unsigned int distance = 0;
  
  if (!playing) {
    drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3);
    if (blink) {
      lcd.setCursor(0,0);
      lcd.print("Press Start");
    }
    delay(250);
    blink = !blink;
    if (buttonPushed) {
      initializeGraphics();
      heroPos = HERO_POSITION_RUN_LOWER_1;
      playing = true;
      buttonPushed = false;
      distance = 0;
    }
    return;
  }

  // Shift the terrain to the left
  advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY);
  advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY);
  
  // Make new terrain to enter on the right
  if (--newTerrainDuration == 0) {
    if (newTerrainType == TERRAIN_EMPTY) {
      newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK;
      newTerrainDuration = 2 + random(10);
    } else {
      newTerrainType = TERRAIN_EMPTY;
      newTerrainDuration = 10 + random(10);
    }
  }
    
  if (buttonPushed) {
    if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos = HERO_POSITION_JUMP_1;
    buttonPushed = false;
  }  

  if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) {
    playing = false; // The hero collided with something. Too bad.
  } else {
    if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == HERO_POSITION_JUMP_8) {
      heroPos = HERO_POSITION_RUN_LOWER_1;
    } else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] != SPRITE_TERRAIN_EMPTY) {
      heroPos = HERO_POSITION_RUN_UPPER_1;
    } else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) {
      heroPos = HERO_POSITION_JUMP_5;
    } else if (heroPos == HERO_POSITION_RUN_UPPER_2) {
      heroPos = HERO_POSITION_RUN_UPPER_1;
    } else {
      ++heroPos;
    }
    ++distance;
    
    digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW);
  }
  delay(timeDelay);
}

scarica il codice

Arduino e i suoi sensori laboratorio 23 Novembre 2019 Linolab

Ecco i progetti per questa lezione:

 La fotoresistenza un sensore per la luminosità!

arduino-crepuscolare-led-e-fotoresistenza-bb.png

int luminosita;  //Il valore letto dalla fotoresistenza
int ledPin = 10;  //Il pin del led

void setup() {
}

void loop() {
  luminosita = analogRead(A0);  //Lettura della luminosità
  luminosita = luminosita/4;  //Adeguiamo il valore della luminosità
  analogWrite(ledPin,luminosita);  //Mettiamo il valore letto per il led
  delay(10);  //Aspetta 10 ms
}

scarica il codice

Pilotiamo un LED col suono!

microphone-sound-sensor_bb.png

int ledPin=13;
int sensorPin=7;
boolean val =0;
boolean ledState = HIGH;

void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);
  Serial.begin (9600);
} 
void loop (){
  val =digitalRead(sensorPin);
  Serial.println (val);
  // Quando il sensore percepisce un suono accende o spegne il LED
  if (val==HIGH) {
    ledState = !ledState;
  }
    digitalWrite(ledPin, ledState);
    delay(100);
}

scarica il codice

Pilotiamo dei LED con il telecomando a infrarossi!

Arduino-IR-Remote-Receiver-Controlling-LEDs.png

#include 

const int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;
const int redPin = 10;
const int greenPin = 11;
int redState = HIGH;
int greenState = HIGH;


void setup(){
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
}
//Leggiamo i segnali del telecomando per accedere e spegnere i LED
void loop(){
    if (irrecv.decode(&results)){

        switch(results.value){
          case 0xFF38C7: //Keypad button "5"
          redState = !redState;
          break;
          case 0xFF18E7: //Keypad button "2"
          greenState = !greenState;
          break;
          }
        digitalWrite(redPin, redState);
        digitalWrite(greenPin, greenState);
        irrecv.resume(); 
    }
}

scarica il codice

Un LED RGB con il telecomando!

Arduino-IR-Remote-Receiver-RGBLED.png

#include  
const int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;
const int bPin = 9;
const int rPin = 10;
const int gPin = 5;
int rState = 0;
int gState = 0;
int bState = 0;
int step = 85;


void setup(){
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pinMode(rPin, OUTPUT);
  pinMode(gPin, OUTPUT);
  pinMode(bPin, OUTPUT);
}
//Con i tasti 1,2,3,4,5,6 del telecomando infrarossi mandiamo un segnale che viene interbretato da Arduino
// e modifica i liveeli di colore del LED RGB
void loop(){
    if (irrecv.decode(&results)){
        Serial.println(results.value, HEX);
        switch(results.value){
          
          case 0xFF38C7: //Keypad button "5"
          if (gState > 0){
            gState = gState - step;
          }
          break;
          
          case 0xFF18E7: //Keypad button "2"
          if (gState < 255){             gState = gState + step;           }           break;                      case 0xFF10EF: //Keypad button "4"           if (rState > 0){
            rState = rState - step;
          }
          break;
          
          case 0xFF30CF: //Keypad button "1"
          if (rState < 255){             rState = rState + step;           }           break;                      case 0xFF5AA5: //Keypad button "6"           if (bState > 0){
            bState = bState - step;
          }
          break;
          
          case 0xFF7A85: //Keypad button "3"
          if (bState < 255){
            bState = bState + step;
          }
          break;
          }
          
        analogWrite(rPin, rState);
        analogWrite(gPin, gState);
        analogWrite(bPin, bState);
        irrecv.resume(); 
    }
}

scarica il codice

Misuriamo le distanze con il sensore ad ultrasuoni!

Ultrasonic Sensor_bb.png

// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
const int buzzer = 6;
int notes[] = {196, 220, 247, 294, 330, 392, 440, 494, 588, 660}; 

// defines variables
long duration;
int distance;

void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(buzzer, OUTPUT); // Sets the buzzer pin as output
Serial.begin(9600); // Starts the serial communication
}

void loop() {
// reset di pulizia
digitalWrite(trigPin, LOW);
delayMicroseconds(2);

// abilitiamo il trig per 10 millisecondi
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// Leggiamo il tempo dell'eco che ci dice quanto tempo è passato tra invio e ricezione
duration = pulseIn(echoPin, HIGH);

// Calcoliamo la distanza
distance= duration*0.034/2;

// Stampo la distanza su monitor
Serial.print("Distance: ");
Serial.println(distance);

if (distance <= 120 && distance >= 5){
  tone(buzzer, (120-distance)*10);
} else {
  noTone(buzzer);
}
}

scarica il codice

Da zero a Led! laboratorio 5 ottobre 2019 Linolab

Ecco i progetti per questa lezione:

Accendiamo un LED con un pulsante!

Arduino Led con pulsante.png

//imposto le variabili

int ledPin = 13;
int buttonPin = 7;
int buttonState = LOW;
int ledState = LOW;

void setup() {
// inizializzo il Pin del LED
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}

// la funzione loop continua ad andare all'infinito
void loop() {
buttonState = digitalRead(buttonPin); //leggo lo stato del bottone
ledState = buttonState; //imposto lo stato del led
digitalWrite(ledPin, ledState); //accendo/spengo il led in base allo stato del bottone
}

scarica il codice

Facciamo lampeggiare un LED

Arduino Lampeggiante.jpg

//imposto le variabili

int ledPin = 10;
int blinkTime = 1000;

void setup() {
// inizializzo il Pin del LED
pinMode(ledPin, OUTPUT);
}

// la funzione loop continua ad andare all'infinito
void loop() {
digitalWrite(ledPin, HIGH); //accendo il led
delay(blinkTime); //aspetto 1 secondo
digitalWrite(ledPin, LOW); //spengo il led
delay(blinkTime); //aspetto 1 secondo

}

scarica il codice

La sirena della polizia!

Arduino Sirena.jpg

//imposto le variabili

int ledPin1 = 13;
int ledPin2 = 12;
int blinkTime = 1000;

void setup() {
// inizializzo il Pin del LED
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}

// la funzione loop continua ad andare all'infinito
void loop() {
digitalWrite(ledPin1, HIGH); //accendo il led 1
digitalWrite(ledPin2, LOW); //spengo il led 2
delay(blinkTime); //aspetto 1 secondo
digitalWrite(ledPin1, LOW); //spengo il led
digitalWrite(ledPin2, HIGH); //accendo il led 2
delay(blinkTime); //aspetto 1 secondo

}

scarica il codice

Regoliamo la luminosità!

Arduino Potenziometro.png

// Imposto le variabili per i pin su Arduino
const int analogInPin = A0; // Pin di input analogico per il potenziometro
const int analogOutPin = 9; // pin analogico di output per il led

//imposto le variabili per il programma

int sensorValue = 0; // variabile per il valore dato dal sensore
int outputValue = 0; // valore da dare in output per il led

void setup() {
//setup dei pin
pinMode(analogInPin, INPUT);
pinMode(analogOutPin, OUTPUT);
}

void loop() {
sensorValue = analogRead(analogInPin); //Leggo il valore in input
outputValue = map(sensorValue, 0, 1023, 0, 255); //conversione dei valori per l'output
analogWrite(analogOutPin, outputValue); //modifico il valore in output al led
delay(2); //piccola pausa
}

scarica il codice

Costruiamo un semaforo!

Arduino Semaforo.png

//imposto le variabili per i pin dei Led

int rLedPin1 = 2;
int yLedPin1 = 3;
int gLedPin1 = 4;
int rLedPin2 = 5;
int yLedPin2 = 6;
int gLedPin2 = 7;

//variabili per i tempi dei led

int greenTime = 4000;
int yellowTime = 2000;
int redTime = 1000;

void setup() {
// imposto i pin come Output

pinMode(rLedPin1, OUTPUT);
pinMode(yLedPin1, OUTPUT);
pinMode(gLedPin1, OUTPUT);
pinMode(rLedPin2, OUTPUT);
pinMode(yLedPin2, OUTPUT);
pinMode(gLedPin2, OUTPUT);

}

void loop() {
//verde sull'1 e rosso sul 2
digitalWrite(rLedPin1, LOW);
digitalWrite(yLedPin1, LOW);
digitalWrite(gLedPin1, HIGH);
digitalWrite(rLedPin2, HIGH);
digitalWrite(yLedPin2, LOW);
digitalWrite(gLedPin2, LOW);

delay(greenTime);

//giallo sull'1 e rosso sul 2
digitalWrite(rLedPin1, LOW);
digitalWrite(yLedPin1, HIGH);
digitalWrite(gLedPin1, LOW);
digitalWrite(rLedPin2, HIGH);
digitalWrite(yLedPin2, LOW);
digitalWrite(gLedPin2, LOW);

delay(yellowTime);

//tutto rosso
digitalWrite(rLedPin1, HIGH);
digitalWrite(yLedPin1, LOW);
digitalWrite(gLedPin1, LOW);
digitalWrite(rLedPin2, HIGH);
digitalWrite(yLedPin2, LOW);
digitalWrite(gLedPin2, LOW);

delay(redTime);

//rosso sull'1 e verde sul 2
digitalWrite(rLedPin1, HIGH);
digitalWrite(yLedPin1, LOW);
digitalWrite(gLedPin1, LOW);
digitalWrite(rLedPin2, LOW);
digitalWrite(yLedPin2, LOW);
digitalWrite(gLedPin2, HIGH);

delay(greenTime);

//rosso sull'1 e giallo sul 2
digitalWrite(rLedPin1, HIGH);
digitalWrite(yLedPin1, LOW);
digitalWrite(gLedPin1, LOW);
digitalWrite(rLedPin2, LOW);
digitalWrite(yLedPin2, HIGH);
digitalWrite(gLedPin2, LOW);

delay(yellowTime);

//tutto rosso
digitalWrite(rLedPin1, HIGH);
digitalWrite(yLedPin1, LOW);
digitalWrite(gLedPin1, LOW);
digitalWrite(rLedPin2, HIGH);
digitalWrite(yLedPin2, LOW);
digitalWrite(gLedPin2, LOW);

delay(redTime);

scarica il codice

Semaforo con passaggio pedonale!

//imposto le variabili per i pin dei Led

int rLedPin1 = 2;

int yLedPin1 = 3;

int gLedPin1 = 4;

int rLedPin2 = 5;

int yLedPin2 = 6;

int gLedPin2 = 7;

int bluePin = 8;

int buttonPin = 9;

int bState = LOW;

//variabili per i tempi dei led

int greenTime = 4000;

int yellowTime = 2000;

int redTime = 1000;

void setup() {

// imposto i pin come Output

pinMode(rLedPin1, OUTPUT);

pinMode(yLedPin1, OUTPUT);

pinMode(gLedPin1, OUTPUT);

pinMode(rLedPin2, OUTPUT);

pinMode(yLedPin2, OUTPUT);

pinMode(gLedPin2, OUTPUT);

pinMode(bluePin, OUTPUT);

pinMode(buttonPin, INPUT);

}

void pedonale() {

bState = digitalRead(buttonPin);

if (bState == HIGH){

digitalWrite(bluePin, HIGH);

delay(greenTime*2);

digitalWrite(bluePin, LOW);

}

}

void loop() {

//verde sull'1 e rosso sul 2

digitalWrite(rLedPin1, LOW);

digitalWrite(yLedPin1, LOW);

digitalWrite(gLedPin1, HIGH);

digitalWrite(rLedPin2, HIGH);

digitalWrite(yLedPin2, LOW);

digitalWrite(gLedPin2, LOW);

pedonale();

delay(greenTime);

//giallo sull'1 e rosso sul 2

digitalWrite(rLedPin1, LOW);

digitalWrite(yLedPin1, HIGH);

digitalWrite(gLedPin1, LOW);

digitalWrite(rLedPin2, HIGH);

digitalWrite(yLedPin2, LOW);

digitalWrite(gLedPin2, LOW);

pedonale();

delay(yellowTime);

//tutto rosso

digitalWrite(rLedPin1, HIGH);

digitalWrite(yLedPin1, LOW);

digitalWrite(gLedPin1, LOW);

digitalWrite(rLedPin2, HIGH);

digitalWrite(yLedPin2, LOW);

digitalWrite(gLedPin2, LOW);

pedonale();

delay(redTime);

//rosso sull'1 e verde sul 2

digitalWrite(rLedPin1, HIGH);

digitalWrite(yLedPin1, LOW);

digitalWrite(gLedPin1, LOW);

digitalWrite(rLedPin2, LOW);

digitalWrite(yLedPin2, LOW);

digitalWrite(gLedPin2, HIGH);

pedonale();

delay(greenTime);

//rosso sull'1 e giallo sul 2

digitalWrite(rLedPin1, HIGH);

digitalWrite(yLedPin1, LOW);

digitalWrite(gLedPin1, LOW);

digitalWrite(rLedPin2, LOW);

digitalWrite(yLedPin2, HIGH);

digitalWrite(gLedPin2, LOW);

pedonale();

delay(yellowTime);

//tutto rosso

digitalWrite(rLedPin1, HIGH);

digitalWrite(yLedPin1, LOW);

digitalWrite(gLedPin1, LOW);

digitalWrite(rLedPin2, HIGH);

digitalWrite(yLedPin2, LOW);

digitalWrite(gLedPin2, LOW);

pedonale();

delay(redTime);

}

 

Scarica il codice

Programmi e Utility gratuite per PC

In questo articolo vi presento alcuni programmi gratuiti molto utili che vi consiglio per utilizare al meglio il vostro pc.

7-zip    7ziplogo

7-zip è un programma di compressione di file che lavora col formato archivio 7z, e può leggere e scrivere in molti altri tipi di file archivio. È un ottimo programma per comprimere ed estrarre file, dalle straordinarie capacità di compressione. Piccolo e compatto, ma anche veloce ed efficace, nonché dotato di utility interessanti. Supporta i seguenti formati tanto per compressione come per decompressione: 7z, ZIP, GZIP, BZIP2 e TAR. Supporta i seguenti formati per decompressione: RAR, CAB, ISO, ARJ, LZH, CHM, Z, CPIO, RPM, DEB E NSIS.


CCleaner    cc_128

CCleaner è un software freeware che permette l’ottimizzazione delle prestazioni, la protezione della privacy e la pulizia dei registri di sistema e altre tracce d’uso per varie versioni del sistema operativo Microsoft Windows. È sviluppato da Piriform Ltd., ed è un software molto noto e diffuso, che ha ottenuto anche vari riconoscimenti.
È possibile utilizarlo anche per disinstallare i programmi installati e gestire i programmi che vengono eseguiti all’avvio.


dopdf    doPdf

doPDF è un programma che permette in modo semplice di trasformare qualsiasi documento in PDF attraverso il comando stampa attraverso una stampante virtuale.


filezilla    filezillas

FileZilla è un software gratuito che ti consente di caricare o scaricare files su un server, per esempio: gli elementi del tuo sito su o dal tuo hosting. È dotato di un interfaccia grafica utente intuitiva. Veloce e affidabile, Filezilla è gratuito e multipiattaforma.


freeocr

FreeOCR è un programma per il riconoscimento dei caratteri da file pdf, file immagine e scansioni si collega direttamente allo scanner e produce un testo quasi privo di errori.
Un punto a svantaggio e la perdita di formattazione del testo.


Lupas Rename 2000    lupas-rename-2000_19159

Lupas Rename è un piccolo freeware che funziona su tutti i Windows recenti, disponibile in molte lingue compreso l’italiano, che non necessita di installazione e che svolge egregiamente il suo arduo compito in maniera semplice e potente.Con Lupas è possibile rinominare file e cartelle utilizzando tantissime opzioni: sequenze numeriche e alfabetiche, aggiungere caratteri o numeri ai nomi dei file e cartelle esistenti.


Notepad++    Notepad++_Logo

Notepad++ è un editor di codice gratuito che supporta la maggior parte dei linguaggi. Completo ed intuitivo inserisce sistemi di riduzione del codice, inserimento di Macro, autocompletamento, colorazione selettiva del codice e sistemi di revisione.


pure text    puretext

Pure text è una utility che non necessita di installazione e serve ad eliminare la formattazione dei testi copiati ottenendo il puro testo.


RIOT    riot-banner-logo

RIOT è un programma che ci consente di ridurre lo spazio occupato da un’immagine, per esempio se la dobbiamo postare sul Web; per far ciò non utilizza formati strani (anzi, è in grado di caricare immagini di tantissimi formati), o particolari algoritmi di compressione, bensì cerca di farci utilizzare al meglio strumenti che abbiamo già.


Sketchup    SketchUp-Logo

SketchUp è un CAD che permette la modellazione solida in modo semplice e intuitivo utile per realizare progetti di qualsiasi natura. È presente una vasta libreria online di modelli creati dagli utenti che è possibile utilizzare nei propri progetti semplicemente scaricndoli.


teamviewer    teamviewer-icon200x200

TeamViewer è un programma che permette la condivisione del desktop tra duePc e il trasferimento file ed il controllo remoto ad alto livello senza particolari configurazioni attraverso un id e password. Le ultime versioni sono compatibili con PC MAC smartphone e tablet.


VLC    largeVLC

VLC è un riproduttore multimediale multi-piattaforma gratuito che riproduce moltissimi file multimediali così come DVD, CD audio, VCD e diversi protocolli di trasmissione.
Inoltre è molto utile per convertire i formati audio e video ed è in grado di riparare molti file corrotti.

ISS – Stazione Spaziale Internazionale

la stazione spaziale internazionale è una stazione dedicata alla ricerca scientifica gestita da:

  • Stati Uniti NASA
  • Russia RKA
  • Unione europea ESA
  • Giappone JAXA
  • Canada CSA

La sua orbità è compresa tra i 330 km e i 435 km di altitudine e viaggia a circa 27600 km/h facendo 15,5 orbite al giorno
Costruità a partire dal 1998 e si prevede il completamento per il 2017.
la stazione attualmente è adibita a laboratorio per viaggi spaziali e come laborattorio per esperimenti di biologia, chimica, medicina, fisiologia, e fisica in uno stato di micrgravità inoltre è molto utile per osservazioni astronomiche e metereologiche.

Assemblaggio

L’assemblaggio della Stazione Spaziale Internazionale ha costituito un imponente sforzo di architettura spaziale, iniziato nel novembre del 1998. I moduli russi, con l’eccezione di Rassvet, sono stati messi in orbita tramite lanciatori senza equipaggio e agganciati in modo automatico. Tutti gli altri elementi sono stati portati grazie ai voli dello Space Shuttle e assemblati dai membri dell’equipaggio della navetta o della stazione per mezzo di attività extraveicolari e con l’utilizzo del braccio robotico. Al 5 giugno 2011, sono state effettuate complessivamente 159 passeggiate spaziali finalizzate all’assemblaggio per un totale di oltre 1000 ore di lavoro, 127 di queste passeggiate hanno avuto origine dalla stazione, le rimanenti 32 hanno avuto luogo dalla navetta ancorata ad essa.


Lavori all’esterno della ISS sulla Nuova Zelanda.

Alimentazione

La stazione è alimentata tramite quattro coppie di pannelli fotovoltaici da 890 m2 che forniscono 120 kW con una tensione di 160 Volt in corrente continua che viene poi convertita in 124 Volt per l’utilizzo

Supporto Vitale

L’Environmental Control and Life Support System (ECLSS) della Stazione Spaziale Internazionale (il sistema di supporto vitale) provvede a controllare le condizioni atmosferiche, la pressione, il livello di ossigeno, l’acqua e la presenza di eventuali fiamme libere. Il suo scopo è mantenere le condizioni atmosferiche ma raccoglie, processa e immagazzina anche gli scoli della stazione. Per esempio il sistema ricicla i fluidi provenienti dai servizi igienici e condensa il vapore acqueo. L’anidride carbonica viene rimossa dall’aria. Altri sottoprodotti del metabolismo umano, come il metano dagli intestini e l’ammoniaca dal sudore, vengono rimossi con filtri a carbone attivo. L’ossigeno è prodotto dall’elettrolisi dell’acqua.

L’atmosfera a bordo della ISS è simile a quella terrestre e si compone di una miscela di azoto e ossigeno ad una pressione di 101,3 kPa (14,7 psi) pari al valore della pressione atmosferica al livello del mare. Questa scelta garantisce il comfort dell’equipaggio e assicura una maggiore sicurezza rispetto ad un’atmosfera composta unicamente da ossigeno puro, a maggior rischio di incendio: un incidente di questo tipo causò la morte dell’equipaggio dell’Apollo 1.

Schema dell’orbita della ISS intorno alla terra.

La vita a bordo

Il fuso orario utilizzato a bordo della ISS è il Coordinated Universal Time (UTC). Nelle ore notturne, le finestre vengono coperte per dare l’impressione di oscurità, poiché nella stazione il sole sorge e tramonta per 16 volte al giorno. Durante le visite dello Space Shuttle, l’equipaggio della ISS segue per lo più il Mission Elapsed Time (MET), che è un fuso orario flessibile strutturato in base al tempo di lancio della missione shuttle. Quando l’UTC e il MET sono discordanti di parecchie ore, l’equipaggio della stazione si adegua a partire da alcuni giorni prima e dopo dell’arrivo dello shuttle, in una pratica nota come “spostamento del sonno”. La giornata tipo per l’equipaggio inizia con la sveglia alle 06:00, seguita da attività di post-sonno e un controllo generale della stazione. L’equipaggio poi consuma la prima colazione e partecipa ad un briefing di pianificazione quotidiana con il Controllo Missione. Il lavoro inizia poi circa alle 08:10. La pausa pranzo inizia alle 13:05 e dura circa un’ora, il pomeriggio è dedicato a diverse attività che si concludono alle 19:30 con una cena e un briefing. Gli astronauti si recano a dormire alle 21:30. In generale, l’equipaggio lavora dieci ore al giorno in un giorno feriale e cinque ore il sabato, con il resto del tempo dedicato al riposo o ai lavori rimasti incompiuti.

Esercizio fisico

Gli effetti più negativi dell’assenza di peso a lungo termine sono l’atrofia muscolare e l’osteopenia da volo spaziale. Altri effetti significativi includono la ridistribuzione dei fluidi, un rallentamento del sistema cardiovascolare, la riduzione della produzione di globuli rossi, i disturbi dell’equilibrio e un indebolimento del sistema immunitario. Sintomi minori includono la perdita di massa corporea, congestione nasale, disturbi del sonno, eccesso di flatulenza e gonfiore del viso. Questi effetti scompaiono rapidamente al ritorno a terra. Per evitare alcuni di questi effetti negativi, la stazione è dotata di due tapis roulant, alcuni attrezzi per il sollevamento di pesi e una cyclette, ogni astronauta passa almeno due ore al giorno a compiere esercizi. Gli astronauti utilizzano corde elastiche per agganciare se stessi al tapis roulant. I ricercatori ritengono che l’esercizio fisico sia una buona protezione per le ossa e serva anche a contenere la perdita di massa muscolare che si ha quando si vive per lungo tempo senza gravità.

Igiene

La ISS non è dotata di una doccia, invece, i membri dell’equipaggio possono lavarsi con un getto d’acqua, salviette umidificate e sapone erogato da un tubetto. Gli astronauti sono dotati anche di uno shampoo e un dentifricio commestibile per risparmiare acqua. Ci sono due bagni sulla ISS, entrambi di progettazione russa, situati su Zvezda e Tranquility. I rifiuti solidi sono raccolti in sacchi individuali che sono immagazzinati in un contenitore di alluminio. Una volta che i contenitori sono pieni vengono trasferiti al veicolo spaziale Progress per lo smaltimento. I rifiuti liquidi vengono raccolti e trasferiti al sistema di recupero dell’acqua, dove vengono riciclati sotto forma di acqua potabile.

Cibo e bevande

La maggior parte del cibo mangiato da parte degli equipaggi della stazione è congelato, refrigerato o in scatola. I menu sono studiati dagli astronauti, con l’aiuto di un dietista, prima della missione. Poiché il senso del gusto è ridotto in orbita, il cibo piccante è uno dei preferiti di molti equipaggi. Ogni membro dell’equipaggio ha pacchetti singoli di alimenti e li cuoce nella cucina di bordo dotata di due scaldavivande, un frigorifero e un distributore di acqua sia calda che fredda. Le bevande sono fornite sotto forma di polvere disidratata che poi viene mescolata con acqua prima del consumo. Le bevande e le zuppe vengono sorseggiate tramite sacchetti di plastica con cannucce, mentre il cibo solido è mangiato con coltello e forchetta, i quali sono attaccati ad un vassoio magnetico. Qualsiasi alimento in grado di produrre residui come briciole e frammenti di cibo deve essere raccolto per evitare l’intasamento dei filtri d’aria della stazione e delle altre attrezzature.

Dormire nello spazio

La stazione prevede alloggi per ogni membro dell’equipaggio permanente, con due “stazioni di sonno” poste nel segmento russo e altre quattro nel modulo Tranquility. Gli alloggi statunitensi sono realizzati in cabine dimensionate per una persona e insonorizzate. All’interno un membro dell’equipaggio è in grado di dormire in un sacco a pelo, ascoltare musica, usare un computer portatile e conservare oggetti personali in un cassetto di grandi dimensioni o in reti fissate alle pareti. L’alloggio fornisce inoltre una lampada da lettura e una mensola. Gli equipaggi in visita alla stazione che non hanno un proprio alloggio assegnato, possono dormire in un sacco a pelo attaccato al muro. Gli alloggi degli equipaggi sono ben ventilati, altrimenti gli astronauti potrebbero svegliarsi senza fiato e per privazione di ossigeno, a causa della bolla composta dalla propria anidride carbonica espirata che potrebbe venire a formarsi.

Vedere la stazione spaziale

La stazione spaziale essendo di grandi dimensioni è visibile dalla terra a occhio nudo su internet ci sono diversi siti e applicazioni per telefono che indicano i momenti in cui si può vedere.

Stazione spaziale fotografata dalla terra

Velocità angolare della ISS:

\omega = v/r
\omega = 27600 \text{km/h}/6771km = 4 \text{rad/h}

Velocità orbitale della ISS:

v = \sqrt{\dfrac{G M_{p}}{r}}
v = \sqrt{\dfrac{6,67\cdot 10^{-11}\text{N}\cdot \text{m}^{2} / \text{kg}^{2} \cdot 5,97 \cdot 10^{24} \text{kg}}{6,771 \cdot 10^{6} \text{m}}} = 7668,73 \text{m}/\text{s} = 27607,43 \text{km}/\text{h}

Video di presentazione alla stazione spaziale