Here is a quick review of the hardware needed, to get yours going. Of course you will want an LCD panel. Digistump offers a complete LCD Shield Kit. I don't know if they are still available, but if you already have one you are nearly ready to go.
I just checked eBay and see that you can purchase an I2C 16x2 Serial LCD just like the one you see in the video for less than $10.
If you are going with your own components you will need two pull up resistors to get your digispark and LCD to talk to each other. Check Part 1 of this series for info on how to hook it up.
Finally you will need a push button and pull down resistor for the user input. I used a 1K resistor for my project, but even a 10K should work just fine. The hook up is described in the sketch comments.
The sketch below is fully documented, I have highlighted the code that has been added since Part 5.
If you are paying attention you will notice that every time you power your digispark down and back up again, the high score goes back to zero. Look at the video again. That wasn't the case it already had a high score. In our next post we will show you how to teach Sparky to remember values when the power is removed and recall them when he powers up again later. C U then.
/* ATtiny85 as an I2C Master Ex2 BroHogan 1/21/11
* Modified for Digistump - Digispark LCD Shield by Erik Kettenburg 11/2012
* SETUP:
* ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U
* ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND
* ATtiny Pin 5 = SDA on DS1621 & GPIO ATtiny Pin 6 = (D1) to LED2
* ATtiny Pin 7 = SCK on DS1621 & GPIO ATtiny Pin 8 = VCC (2.7-5.5V)
* NOTE! - It's very important to use pullups on the SDA & SCL lines!
* PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib.
* This ex assumes A0-A2 are set HIGH for an addeess of 0x3F
* LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib.
* TinyWireM USAGE & CREDITS: - see TinyWireM.h
*/
// Number Flip-Flop by Budd Churchward, WB7FHC, @barnacleBudd
/* Place a push button on your board
* Put a 1K resistor between one pin on the button and ground
* Place a jumper between pin 5 and a point between the button and resistor
* Place a jumper between 5V and the other side of the button
*/
#include <TinyWireM.h> // I2C Master lib for ATTinys which use USI - comment this out to use with standard arduinos
#include <LiquidCrystal_I2C.h> // for LCD w/ GPIO MODIFIED for the ATtiny85
#define GPIO_ADDR 0x27 // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A - 0x27 is the address of the Digispark LCD modules.
LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines
String winner ="0123456789"; // a test string to easily see if game is over
String workingString = "0123456789"; // these get scrambled
int rnd; // will hold a random number for us.
int myButton = 5; // hook button to pin 5 with pull down resistor see notes above
int btnPress; // is it down or is it up
byte tick = 0; // counts the digits we plan to flip
unsigned long myTime; // used with mySpeed to set tick rate
int mySpeed = 1000; // start with a 1 second interval
int highScore = 0; // so the first score will always beat it
int thisScore = 120; // start with 120 points
void setup(){
TinyWireM.begin(); // initialize I2C lib - comment this out to use with standard arduinos
lcd.init(); // initialize the lcd
lcd.clear(); // clear the screen
lcd.backlight(); // turn on the backligth
pinMode (myButton, INPUT); // pin 5
pinMode(1, OUTPUT); //LED on Model A // we light the LED when the button is pressed
scramblePrompt(); // Go pick random numbers until user presses button
scrambleString(); // puts digits in random order
displayWorkingString(); // prints digits
lcd.setCursor(12,1); // move to bottom right corner
lcd.print(thisScore); // show starting score
delay(1000);
myTime = millis(); // start timer
}
void loop() {
btnPress = digitalRead(myButton); // read pin 5
if (btnPress==1){ // When button is down ...
digitalWrite(1,1); // light up on-board LED
//lcd.setCursor(0,1);
//lcd.print(char(tick+48));
//lcd.setCursor(2,0);
//lcd.print(' ');
flip(); // go flip some digits
delay(1000);
}else{ // When button is up ...
digitalWrite(1,0); // turn off on-board LED
}
if(millis() - myTime > mySpeed ){ // when we have waited long enough
shiftLeft(); // move the current digit left
myTime = millis(); // reset interval timer
}
}
void flip(){
int i=0; // a counter
if(tick==1){tick=10;} // power play, flip all if only 1 digit
tick--; // undo the last increment, we don't need it
do {
swap(i,tick-i); // swap two digits
i++; // increment counter
} while (i<=(tick/2)); // do half of them and we're done
displayWorkingString(); // put the new order on the screen
tick= 0; // reset the digit counter
myTime = millis(); // reset the interval timer
}
void shiftLeft(){
if (tick < 10){ // keep us in the range...
lcd.setCursor(tick + 2,0); // move to spot in front of our digit
lcd.print(workingString[tick]); // put a copy of digit in the new spot
lcd.print(' '); // erase the original digit
tick++; // increment the digit counter
thisScore--; // subtract a point
int x = 12; // cursor location for score when its 3 digits
if(thisScore<100){x++;} // nudge location for 2 digit score
if(thisScore<10){x++;} // nudge again if only 1 digit
lcd.setCursor(x,1); // set the cursor location
lcd.print(' '); // erase digit if we are dropping from 100's to 10's
lcd.print(thisScore); // show current score
if(thisScore==0){ // When points are all gone ...
youLose(); // Tell the user he lost
return; // go back to loop()
}
}else{ // if user doesn't press the button...
tick=0; // start again at the beginning
displayWorkingString(); // move the digits back in place
}
}
void scramblePrompt(){
lcd.noCursor(); // some LCDs want to flash at you
lcd.print("NUMBER FLIP-FLOP"); // show the title on the top line
lcd.setCursor(0,1); // move to the bottom line
lcd.print("Press Button Now"); // prompt the user to press the button
do {
rnd=random(9); // pick random numbers over and over
} while (!digitalRead(myButton)); // until user presses the button
}
void scrambleString() {
lcd.clear(); // clear the screen
lcd.print("NUMBER FLIP-FLOP"); // print the title again
for (int i=0; i<10; i++){ // do this once for each digit
rnd=random(9); // pick a random spot
swap(i,rnd); // swap two of the digits
}
delay(1000);
lcd.clear(); // clear the screen again
lcd.setCursor(0,1); // move to bottom row
lcd.print("HS="); // print the high score
lcd.print(highScore);
}
void swap(int x, int y){
byte hold=workingString[x]; // store the first digit
workingString[x]=workingString[y]; // copy the second digit to the first spot
workingString[y]=hold; // put the first digit in the second spot
}
void displayWorkingString(){
lcd.setCursor(2,0); // move to top row
lcd.print(' '); // erase the first digit
lcd.print(workingString); // put the whole string back in place
if (workingString==winner){ // if the digits are all in order ...
youWin(); // go do the cool stuff for the winner
}
}
void youWin(){
lcd.setCursor(0,1); // move to the second row
if(thisScore > highScore){ // when we get a new high score
lcd.print("HIGH SCORE!");
highScore = thisScore; // update the new high score
}else{ // when score doesn't beat high score
lcd.print("WINNER");
}
delay(3000);
mySpeed = mySpeed - 50; // lower mySpeed means faster game
if(mySpeed<400){mySpeed=400;} // don't go too fast
playAgain(); // Do it all again
}
void youLose(){
lcd.setCursor(0,1); // move to the second row
lcd.print("YOU LOSE");
delay(3000);
mySpeed = mySpeed + 200; // higher mySpeed means slower game
if(mySpeed>1000){mySpeed=1000;} // never slower than once a second
playAgain(); // do it all again
}
void playAgain(){
lcd.clear(); // clear the screen
scrambleString(); // go mix up the digits again
displayWorkingString(); // show us the new order
thisScore = 120; // start again with 120 points
}
Hei.
ReplyDeleteGreat game and great project.
I just finished setting up a Digispark with your game on it but I am terrible at playing. I can't even win the game.
Can you provide some tips and maybe further instructions as to how the rules of the game work?
Thanks
This excellent is undoubtedly fantastic. Most of these minuscule truth is generated applying broad range connected with accreditation know-how. When i benefit taking that approach lots. gecey.com/transparent-monitor
ReplyDelete