Thursday, December 17, 2015

Arduino Console

Everybody needs some time to do nothing,
I mean not do things because you need to do,
but instead to do things just to free your mind

I like to code, and I like electronics so I started wondering which options were in the market to be able perform my own ´experiments´ so after some research I end up with two finalists:

  • RaspberryPI
  • Arduino

Raspberry is awesome in many senses but it adds an additional layer of complexity which discoraged me to take it so I finally end buying an Arduino Nano ´Chinese clone´ for 2$, yes you are reading right, 2$!, I also bought several components to perform experiments: electric resistances, leds lights, a pair of stepper motors, ultrasound sensor, buttons, a joystick, and a pair of TFT screens , each one for about 6-8$ (1.8inches and 2.4 inches).. I felt really like stealing...

 I decided to play with the idea of actualy building my own ´Hardware´ gaming box, so I performed all these steps:


  1. Attach Arduino Nano board to a breadboard
  2. Attach the 1.8 Inches TFT screen to the breadboard
  3. Connect Arduino power-out pins to power lines in the breadboard
  4. Connect TFT pins with Digital data pins D8,D9,D10,D11 and D13
  5. Connect the joystick to Analog pins A0 and A1

And the final hardware setup:



Details for the Nano pin connections

And for the joystick Pins:

Connecting the TFT screen involved a little research as all components came without documentation, but hey Google is always your friend! I end up in a web page from a guy who made the device work and kindly shared how to setup the cables:

http://blog.simtronyx.de/en/a-1-8-inch-tft-color-display-hy-1-8-spi-and-an-arduino/

Arduino (Mini, Nano, Uno)HY-1.8 SPI
D9Pin 07 (A0)
D10 (SS)Pin 10 (CS)
D11 (MOSI)Pin 08 (SDA)
D13 (SCK)Pin 09 (SCK)
D8Pin 06 (RESET)
5V (VCC)Pin 02 (VCC)
GNDPin 01 (GND)
3.3V or 5V (VCC)Pin 15 (LED+)
GNDPin 16 (LED-)
After setting up the hardware I was ready for the coding part, it involved the following steps:

  1. Download and install Arduino IDE from https://www.arduino.cc/en/Main/Software
  2. Download and decompres libraries Adafruit_ST7735 and Adafruit_GFX from https://learn.adafruit.com/adafruit-gfx-graphics-library/overview
  3. Restart Arduino IDE and you are ready!
The only diference regarding code posted by Adafruit is the pin initialization:

#define TFT_PIN_CS   10 // Arduino-Pin an Display CS   
#define TFT_PIN_DC   9  // Arduino-Pin an 
#define TFT_PIN_RST  8  // Arduino Reset-Pin

#include <SPI.h>
#include <Adafruit_GFX.h>    
#include <Adafruit_ST7735.h> 

After this small change you are ready to use the TFT, as a proof of concept I made a simple game to just travel around a mace gathering some kind of diamonds:
 

Red point is the player, and green point is exit of the level, I am actually happy as it was very simple to set up everything and Arduino code is basically C/C++ (my old friend), so I just need to define some variables:

Adafruit_ST7735 screen = Adafruit_ST7735(screen_PIN_CS, screen_PIN_DC, screen_PIN_RST);  

int sensorY = A0; //Analog pin Y ->A0
int sensorX = A1; //Analog pin X ->A1
int sensorValueY = 0;//Value for Y analog pin
int sensorValueX = 0;//Value for X analog pin
int myx =1;//X location of the player
int myy =1;//Y location of the player

int tx=0;//Used to convert joystick X analog input into +-1
int ty=0;//Used to convert joystick Y analog input into +-1

int x=0;//temp variables for loops
int y=0;//temp variables for loops

int tilesize = 10;//Size of the tiles(in pixels)
int mymap[20][20];//Game map

int points =0;//Points..
int level =1;//Level..

Then some functions to draw the map and load levels map:
void DrawMap(){//Draw array on the screen
screen.fillScreen(ST7735_BLACK);
for (x=0;x<14;x++){
  for (y=0;y<14;y++){
    if( mymap[x][y]==1){screen.fillRoundRect(x*tilesize+1,y*tilesize+1,9,9,3,ST7735_CYAN);}//Wall
    if( mymap[x][y]==2){screen.fillRoundRect(x*tilesize+3,y*tilesize+3,5,5,3,ST7735_WHITE);}//Diamond
    if( mymap[x][y]==9){screen.fillRoundRect(x*tilesize+1,y*tilesize+1,9,9,3,ST7735_GREEN);}//End of level
    }
  }  
}

void LoadLevel1(){//Init level array
for (x=0;x<20;x++){
  for (y=0;y<20;y++){
  mymap[x][y]=2;
  }
}

for (x=0;x<13;x++){
   mymap[x][0]=1;
   mymap[x][13]=1;
}
for (x=0;x<14;x++){
   mymap[0][x]=1;
   mymap[12][x]=1;
}

I think it is easy to imagine LoadLevel2 and LoadLevel3 how do they work ;), next step is to perform initialization function from Arduino:

void setup(void) {//Arduino init function
screen.initR(INITR_BLACKTAB);   //Init TFT
LoadLevel1();//Load level 1
DrawMap();//Draw Map
screen.setTextSize(1);
screen.setTextWrap(true); 
screen.setTextColor(ST7735_WHITE);
screen.setCursor(1,140);
screen.print("Points:");//Draw starting points
screen.setCursor(50,140);
screen.print(points);
screen.setCursor(1,150);
screen.print("Level:");//Draw starting level
screen.setCursor(50,150);
screen.print(level);
}//End of setup

Not much to say here, finally there is the game loop:
void loop() {//Game loop (Arduino loop)
tx=0;
ty=0;
sensorValueY = analogRead(sensorY);//Read joystick analog Y
sensorValueX = analogRead(sensorX);//Read joystick analog D
screen.fillRoundRect(myx*tilesize+1,myy*tilesize+1,9,9,3,ST7735_BLACK);//Replace current player location with a black box

//Convert analog values to +1 .. -1
if (sensorValueY>600){ ty=1;}
if (sensorValueY<400){ ty=-1;}
if (sensorValueX>600){ tx=1;}
if (sensorValueX<400){ tx=-1;}

if( mymap[myx+tx][myy+ty]!=1){//is it a wall?
  //No: update player location
  myx+=tx;
  myy+=ty;
}

if( mymap[myx][myy]==2){//is it a coin?
  points++;
  mymap[myx][myy]=0;//Update map 
  screen.fillRect(1,140,140,10,ST7735_BLACK);
  screen.setCursor(1,140);
  screen.print("Points:");//Update points counter
  screen.setCursor(50,140);
  screen.print(points);
 }

if( mymap[myx][myy]==9){//is it end of level?
  level++;
  //If we change level we load new level
  if (level == 1)LoadLevel1();
  if (level == 2)LoadLevel2();
  if (level == 3)LoadLevel3();
  if (level == 4)level=1;//Back to first level
  DrawMap();//Draw map again
  screen.setCursor(1,140);
  screen.print("Points:");
  screen.setCursor(50,140);
  screen.print(points);
  screen.setCursor(1,150);
  screen.print("Level:");
  screen.setCursor(50,150);
  screen.print(level); 
}

screen.fillRoundRect(myx*tilesize+1,myy*tilesize+1,9,9,3,ST7735_RED);//Draw player
delay(100); //Delay to adjust game speed
}//End of loop

Compared with other coding projects I have made I feel shame of this crap coding, but it actually works, it is not very complicated to think in replacing the colored squares with a real tileset, and make some real game clones like Tetris , Asteroids, Mario bross, etc.

More content to come!