I recently wrote about the cool little DigiSpark ATTiny 85 controller board. This little USB wonder, like the AdaFruit Trinket, is based on the ATTiny85 Microcontroller and has limited I/O, memory and is cheap, very cheap.
One thing it is not short on, however, is uses. This little thing can be used for a variety of things, including games and control applications. For any use, though, you will need some kind of input and some kind of output. In a previous post, I postulated about porting my ‘Battlestar Galactica’ game to the DigiSpark from the Trinket. So, here are the results of that endeavor and some other things as well.
For the backstory of the game and why I wrote it, check out this post. I’ll wait.
Ok, so there are few differences between the Trinket and the DigiSpark, other than size. The way you program it is very similar and the pins are nearly identical. The way you talk to things, is, however, a little different.
The Trinket needed SoftwareSerial. We don’t here, we just use DigitalRead and DigitalWrite and Serial.write to read the button and write to the screen.
The display is a 16×2 Serial LCD from Parallax. The button is actually a ‘controller’ I built a couple of years ago for my game console. I did not use it for that, opting for the Wii Nunchuck instead. So, the controller has three buttons that would be used for left, right and ‘fire’ or action. Here, they just return a 0 if pressed and a 1 when ‘open’. The code periodically polls the controller for a press and then acts on the press to evaluate a hit or miss.
Now, one of the problems I had was the lack of GROUND pins. So, I made a ground bus, a four pin strip with a wire connecting all four pins. I then connected this to ground on the DS and the button and the LCD as well are connected to this bus. I have one free ground pin. Well, what I did not realize was that you can use any pin for ground. While I did not change my connections, I find this pretty cool.
TIP! To use a free pin as ground:
(From the wiki)
You can use an I/O pin as a ground/+5V if you have some left and the current that flow in it is low (a few milliamps if you want the pin to stay around 0V/+5V. If you don’t care about the exact voltage you can go up to 40mA per pin according to the datasheet but it’s good to keep a safety margin).
Configure the pin as an output and set its value to either LOW or HIGH (for ground or +5V
#define button 0 #define gnd 2 void setup() { pinMode (button, INPUT); digitalWrite (button, HIGH); // enable pullup pinMode(gnd, OUTPUT); digitalWrite (gnd, LOW); // use this pin as a ground }
For much more information and tips, go to the wiki, located here.
The game code is below.
Come back for more on this cool little device. Since it is capable of serial i/o, I’m thinking of using the Bluetooth Serial module and connecting the DS to one of my HalfByte Consoles running the graphical serial software for video display from the DS.
Game Code:
#include <TinyPinChange.h> // globals int cylonpos; int oldcylonpos; int cyDirection; int button; int posStart; int lin2Start; int bsgpos; // special characters int bsg; int cylon; // total number of torpedos the ship has left int tShots=10; // the setup routine runs once when you press reset: void waitforbutton(); void moveCylon(); void setup() { // initialize the digital pin as an output. Serial.begin(9600); Serial.write(12); Serial.write(17); //define the ship character Serial.write(249); Serial.write(0x4); Serial.write(0xE); Serial.write(0xE); Serial.write(0x15); Serial.write(0x1F); Serial.write(0x15); Serial.write(0xE); Serial.write(0xE); // baddies Serial.write(251); Serial.write(uint8_t(0x0));//to handle a goofy issue with '0' Serial.write(uint8_t(0x0)); Serial.write(0xE); Serial.write(0x15); Serial.write(0x1F); Serial.write(uint8_t(0x0)); Serial.write(uint8_t(0x0)); Serial.write(uint8_t(0x0)); // the button is on pin 0 pinMode(0,INPUT); // the initial direction is right cyDirection=1; } // the loop routine runs over and over again forever: void loop() { int score; score=0; Serial.write(12); // clear the screen and show the instructions Serial.println("Shoot the Cylon\n"); Serial.println("press btn strt"); // wait for the button waitforbutton(); // define somethings before we start the game loop tShots=10; cylon=3; bsg=1; lin2Start=148; // the baddies appear on line 1 posStart=128; // the good guys on line 2 randomSeed(analogRead(0)); // gen a random seed bsgpos = 8; // our ship starts in the middle of the sector cylonpos=random(0,15); // baddies warp in at a random spot oldcylonpos=cylonpos; Serial.write(12); // clear screen Serial.write(17); // turn on backlight so we can see Serial.write(posStart + cylonpos); // uh oh...the Cylon appeared! Serial.write(cylon); Serial.write(lin2Start+bsgpos); Serial.write(bsg); // and here we are // begin the game while(1){ /* Game loop */ int button; Serial.write(22); // kill the cursor moveCylon(); delay(200); button=digitalRead(0); // check the button if(button==0){ // torpedo fired? if(cylonpos==bsgpos){ // Hit? Serial.write(132); // center 'Hit' on screen Serial.print("** HIT **"); score ++; // update score Serial.write(213); // noise (C at half note, 3rd scale) Serial.write(215); // play the note Serial.write(224); Serial.write(225); if(score==10){ // did we win? Serial.write(12); // clear screen Serial.write(128);// start at beginning Serial.print("You have saved\nthe Galactica."); delay(2000); loop(); // start game again } delay(3000); // did not win yet Serial.write(12); // clear screen Serial.write(lin2Start); // move cursor to beginning of line Serial.write("Score:"); // put up score Serial.print(score); Serial.write(lin2Start+bsgpos); // Since we shot the Cylon, we have to leave the sector, so... Serial.write(0x20); // go into hyperdrive and erase the BSG bsgpos=random(9,15); // calculate new position Serial.write(lin2Start+bsgpos); //...and, we are here Serial.write(bsg); Serial.write(posStart+cylonpos); Serial.write(0x20); cylonpos=random(0,15); // Damn, they found us! oldcylonpos=cylonpos; moveCylon(); } tShots --; // decrement our torpedo inventory if(tShots<1){ // out of ammo? Serial.write(12); // clear screen Serial.write(posStart); // start at beginning of line Serial.print("The Cylons win.\n"); int count=1; // show animation of our ship exploding while (count<10){ Serial.write(lin2Start+bsgpos); Serial.write(bsg); delay(500); Serial.write(lin2Start+bsgpos); Serial.write('*'); delay(500); count++; } loop(); // Play again } } } } void moveCylon(){ // sneaky Cylons...they show up anywhere! Serial.write(posStart+oldcylonpos); Serial.write(0x20); if (random(0,6)>3){ //Cylon warped cylonpos=random(0,15); oldcylonpos=cylonpos; } cylonpos += cyDirection; // figure out which way to move if (cylonpos>15){ cylonpos=15; cyDirection=-1; } if (cylonpos<0){ cylonpos=0; cyDirection=1; } // erase from old spot Serial.write(posStart+oldcylonpos); Serial.write(0x20); Serial.write(posStart+cylonpos); Serial.write(cylon); oldcylonpos=cylonpos; } void waitforbutton(){ int button; button=digitalRead(0); while(button==1){ //wait for button press button=digitalRead(0); delay(1000); } Serial.write(1); delay(1000); Serial.write(12); }