Sunday, February 10, 2013

LCD Game Part 3 - Building the User Interface

Hey, Digisparklers, we're back. In part 2 we learned how to select true random numbers by having the user press a button to start our game. In this part we will start to prepare a way for the user to select how many digits he or she wants to flip. When I wrote this project for the Arduino, I had the luxury of using a 20 column by 4 row display. This time I am limited to only 16 by 2 because that is the only I2C LCD I have at this time. I think I have come up with a clever work-around for this limitation.

When I had more rows to work with I was able to design a cursor that sat at the top of the row under the digits. I still had plenty of room on the screen to display both the current score and a high score for the game. I would like to include both of those scoring features, but that leaves no place for a cursor.

As the video above shows, there is still a way to do both. One at a time, I am sifting the characters in my sting of digits one place to the left. Currently I have set it up to do that at the rate of one per second. Later when we start to build skill levels into the game we will have a way to speed that up to make the puzzle more challenging.

Just for demonstration purposes, the video and the code that we will discuss here, repeats the randomization of the digits and walks through the shifting process. Once the user presses the button to start the game, the button is no longer read by the program so it does nothing but light the LED on the board. We will put it to work in part 4.

So let's look at what makes all this work. The key to digit shifting routine is the command

    lcd.setCursor(tick + 2,0);   

This line determines where the next character we print on the LCD is going to appear.
lcd.setCursor(x,y) requires two values. The first is which column: 0 - 15, and the second is which row: 0-1. With those two items you can print anywhere on the display. Think of it as a starting point. First you print a letter, or a word, here and the next time you print, your characters will be automatically appear in the next position. tick starts out at zero and we increment it each time we print a digit until every digit has been printed again in its new spot. We also use tick to determine which character in the string to print:

    lcd.print(workingString[tick]);

That gives us two copies of the same digit, so we simply follow up by printing a space which erases the unwanted image. We don't need to fuss over where, because we know that it will be the next character after the last one we printed. I have packaged all of this into the following function.


void shiftLeft(){
  if (tick < 10){
      delay(1000);
      lcd.setCursor(tick + 2,0);   
      lcd.print(workingString[tick]);
      lcd.print(' ');
      tick++;
    
    }else{
      delay(1500);
      lcd.clear();
      delay(1500);
      scrambleString();
      displayWorkingString();
      tick = 0;
      
  }
}

The 'else' part of the function is just some temporary code to let us see how this is going to play on our display. To make this all work, we need to add the following highlight line to our loop() function.

void loop()  {
  btnPress = digitalRead(myButton);
  if (btnPress==1){
    digitalWrite(1,1);
  }else{
    digitalWrite(1,0);
  }
  shiftLeft();
}

That let's us test our procedures, we will move the line to a new location later. 

So what's next? We will need to check Sparky's button while the numbers are shifting left. Stop that nonsense in its tracks and flip a batch of digits around. Then we do it all again. As before, you can copy the code we've written so far below and try it yourself. C U next time.















/* 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
 */

//#define DEBUG
#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 game is over
String workingString = "0123456789";    // all the digits that we will scramble at the beginning of the game
int rnd;     // will hold a random number for us.
int myButton = 5; // our button hooks up here
int btnPress;     // is it down or not
byte tick = 0;

void setup(){
  TinyWireM.begin();                    // initialize I2C lib - comment this out to use with standard arduinos
  lcd.init();                           // initialize the lcd 
  lcd.clear();
  lcd.backlight();
  pinMode (myButton, INPUT);
  pinMode(1, OUTPUT); //LED on Model A
  
  scramblePrompt();
  scrambleString();
  displayWorkingString();
  delay(3000);
}

void loop()  {
  btnPress = digitalRead(myButton);
  if (btnPress==1){
    digitalWrite(1,1);
  }else{
    digitalWrite(1,0);
  }
  shiftLeft();
}

void shiftLeft(){
if (tick < 10){
    delay(1000);
    lcd.setCursor(tick + 2,0);   
    lcd.print(workingString[tick]);
    lcd.print(' ');
    tick++;
    
  }else{
    delay(1500);
    lcd.clear();
    delay(1500);
    scrambleString();
    displayWorkingString();
    tick = 0;
    
  }
}

void scramblePrompt(){
  lcd.noCursor();
  lcd.print("NUMBER FLIP-FLOP");
  lcd.setCursor(0,1);
  lcd.print("Press Button Now");
  
  do {
    rnd=random(9);
  } while (!digitalRead(myButton));
 }



void scrambleString() {
  lcd.clear();
  lcd.print("NUMBER FLIP-FLOP");
  
  for (int i=0; i<10; i++){
    rnd=random(9);
    swap(i,rnd);
  }
  delay(2000);
  lcd.clear();
   
}

void swap(int x, int y){
  byte hold=workingString[x];
  workingString[x]=workingString[y];
  workingString[y]=hold;
}
  

void displayWorkingString(){
  lcd.setCursor(3,0);
  lcd.print(workingString);

  lcd.noCursor();
  
}


Saturday, February 9, 2013

LCD Game Part 2 - Random Numbers & Push Buttons

Hey, Digispaklers, good to see you back. In this post we are going to solve the problem of generating random numbers that are truly random. If you go back to the previous post and load the code onto your own Digispark you will see that each time you power up the device, you get the same ten digit number ... that's not very random.

There are various ways to solve this problem, we will demonstrate my favorite. We are going to take advantage of the most random thing we have available: The User!

The plan is simple. When the program launches we will display a message on the LCD telling the user to press a button to begin. While we are waiting for the player to do that, we will send Sparky into a loop chasing his tail and picking random number after random number thousands of times a second. We won't start the game until that button gets pressed. This loop spins so quickly that it is highly unlikely that anyone is going to see the same random pattern twice in a row.

Let's start with the hardware. Of course, you are going to needs a button. Sometime ago I bought a bunch of them on eBay. They are not expensive. The button has four little legs. If you turn it the right way it will straddle the gab down the middle of your breadboard. 

It is important to know that the pins that cross the gap are always connected to each other. The pins that your are switching on and off run parallel to the gap. Be real careful with your board layout. When you plug one of these mini buttons in, you are linking the five points of each side of the board together. You can no longer use these sets of points for two different purposes.

We will use the button to switch 5V on and off and read it on pin 5 of the digispark. It's not quite that simple. Sparky will easily know when the pin is HIGH and the voltage is there, but he get's confused if you take the voltage away. You would think that it should go to LOW, but that might not be so. If nothing is connected to a pin, we say that it is FLOATING. And Sparky might think its LOW one moment and HIGH the next. To sort this out and make things clear, we add a 'pull down' resistor. This locks the pin down and won't let it float. The schematic here shows how we wire it up.

Almost any value resistor from 470 up will do. If your project is going to be battery powered, you will want to use a higher value to make the battery last longer. I use a 1K resistor (brown black red).

Before we go any further, we should make sure we have everything wired right. Add the highlighted lines below to your sketch and try it out. We will use the on-board LED to test our button. This LED already has its own limiting resistor so it is easy to use.


int rnd;     // will hold a random number for us.
int myButton = 5; // our button hooks up here
int btnPress;     // is it down or not


The following two lines go into setup(). These define pin 5, myButton, for input and the on-board LED on pin 1 for output.

  pinMode (myButton, INPUT);
  pinMode(1, OUTPUT); //LED on Model A



These next lines are actually the first ones that we have placed inside our Loop() function.


void loop(){
  btnPress = digitalRead(myButton);
  if (btnPress==1){
    digitalWrite(1,1);
  }else{
    digitalWrite(1,0);
  }
}

We check P5 to see if it is HIGH or LOW, or the way I like to write the code: 1 or 0. Your sketch will do everything it did before, including putting the number on the LCD. If you press the button, you should see the green LED status light come on. It goes off when you release the button.  Make sure this happens before you continue.


Ok, now let's put Sparky to work. Add the following line to startup()

  scramblePrompt();
  scrambleString();
  displayWorkingString();



And then enter the function itself


void scramblePrompt(){
  lcd.noCursor();
  lcd.print("NUMBER FLIP-FLOP");
  lcd.setCursor(0,1);
  lcd.print("Press Button Now");
  
  do {
    rnd=random(9);
  } while (!digitalRead(myButton));
 }


This is where Sparky chases his tail. Our do loop keeps picking random numbers over and over. It also check's pin 5, myButton. !digitalRead(myButton)is an efficient way to see if it is zero. The '!' means NOT. So it keeps looping as long as the pin is 'not 1'. Control won't leave this loop until you press the button. Then it goes back to call the rest of the functions in setup() and you will soon see a new ten digit number. Sparky doesn't have a reset button so you have to pull the power and put it back to see that each time you recycle, you get a new random number.


Before the next post I am going to experiment with two ways of giving the user a way to select how many of the digits on the left he or she wants to flip. One that I have done before involves programming my own character to draw a line across the top of the second row. A new one that I want to test nudges the digits one at a time one place to the left so a scrolling gap works its way across the screen. 

You can copy the whole sketch below. Check back later to see what trick we teach Sparky next. C U then.



Thursday, February 7, 2013

LCD Game Part 1 - Set Up: Number Flip-Flop Intro

If you are just joining us, check out the earlier posts to see how we set up the hardware for this Digispark project. As you see, we are using an LCD connected to our board with I2C.

Before we jump into any code, let me give you an overview of the game itself.

Look at the number in the photo. It might not be obvious at first, but notice that we have a string of all ten digits from 0 to 9 in a scrambled order. The object of the game is to put the numbers into proper order. You do that by flipping the order for the left hand side of the string. Watch how we might do this. In the text below, I will highlight the digits that I want to flip. You will see that their order will be reversed in the next iteration.

As you can see, our game will need a way for the player to select how many digits to flip. We will do this with a moving cursor and require the user to press a push button when the cursor reaches the desired spot. To make the game more challenging, we will start with a point score and subtract from it each time the cursor bounces. If you run out of points before you get the digits back in order, you lose. 

We need a place to start coding, so let's just take the sketch from the DigisparkLCD folder that we were using to test our hardware. We will build the game from there. Load the sketch and the in the file menu select 'Save As' and we will create a new version with the name 'NumFlipFlop'.

Let's declare a few variables to get us started:

String winner ="0123456789";            // a test string to easily see game is over
String workingString = "0123456789";    // the digits that we will scramble
long rnd;     // will hold a random number for us.


And make these changes to the setup() function:

void setup(){
  TinyWireM.begin();            // initialize I2C lib - comment this out to use with standard arduinos
  lcd.init();                   // initialize the lcd 
  lcd.clear();
  lcd.backlight();
  scrambleString();
  displayWorkingString();

}
For now, we will have setup() call two functions. The first one takes our working string and rearranges the digits into a random order.

void scrambleString() {
  lcd.clear();
  lcd.print("NUMBER FLIP-FLOP");
  
  for (int i=0; i<10; i++){
    rnd=random(9);
    swap(i,rnd);
  }
  delay(2000);
  lcd.clear();
   
}

The second one simply puts the digits on the LCD.

void displayWorkingString(){
  lcd.setCursor(3,0);
  lcd.print(workingString);
 
}

The first function repeatedly calls swap() passing the variable from our for loop and a random number which get transposed in our working string:


void swap(int x, int y){
  byte hold=workingString[x];
  workingString[x]=workingString[y];
  workingString[y]=hold;
}

This function treats the string as if it is an array. We set up a variable called hold where we park the first of the pair of digits we want to swap. We then stuff the second digit into the first one's spot. Finally, we grab the one we stored safely in hold and put it into the place where the second one was.

This all seems like it would work just fine, but there is a problem. My Digispark, Sparky, isn't really very clever with his random numbers. Every time I power down and restart him, he puts exactly the same random number on the screen. By definition, that is not random! This is a very common issue game programmers deal with. What we get is often called a pseudo random number. Since the days of the old TRS-80 computers we have had to work around this. We will go over my favorite technique for getting a real random pattern each time we start the game in the next post. To teach Sparky this new trick, we will add our push button. 

You will find the whole sketch below, so you can copy and paste it into your editor and give it a try. CU next time. 


/* 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
 */

//#define DEBUG
#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 game is over
String workingString = "0123456789";    // all the digits that we will scramble at the beginning of the game
long rnd;     // will hold a random number for us.


void setup(){
  TinyWireM.begin();                    // initialize I2C lib - comment this out to use with standard arduinos
  lcd.init();                           // initialize the lcd 
  lcd.clear();
  lcd.backlight();
  scrambleString();
  displayWorkingString();

}

void loop(){

  
}

void scrambleString() {
  lcd.clear();
  lcd.print("NUMBER FLIP-FLOP");
  
  for (int i=0; i<10; i++){
    rnd=random(9);
    swap(i,rnd);
  }
  delay(2000);
  lcd.clear();
   
}

void swap(int x, int y){
  byte hold=workingString[x];
  workingString[x]=workingString[y];
  workingString[y]=hold;
}
  

void displayWorkingString(){
  lcd.setCursor(3,0);
  lcd.print(workingString);
  //cursorLocation=4;
  lcd.noCursor();
  //if(workingString==winner) YouWin();
}






Wednesday, February 6, 2013

TMI, Digistump!


Today I hooked up my LCD panel to Sparky and got it working. I learned a lot along the way. We sailors have a saying: 'If everything works out perfectly, you haven't learned a thing!'

Checking into the Digistump Forum showed me that I was not alone. However, once you get all your ducks in a row it works quite well.

The problem is that Digistump has given us Too Much Information. When you unzip their download you install dozens of folders and examples that have nothing to do with your Digispark. Most of them are written for the Arduino and the Arduinio sketches are not going to work on your board. If you grab the wrong one you will probably see something that looks like the image on the right. 


The good news is that the folders you want to use are well labeled. Make sure you are opening files from those that say: Digispark. There are a lot of other similar and interesting choices, but these are the ones you need to use.

After sorting that out, the next thing is setting up the hardware. LCD panels come in two flavors. They really are the same thing, but the ones we need usually have another board riding piggy back on the device. You want a panel that is Hitachi HD44780 compatible. The regular versions will hook up to the Arduino quite well, but they require a minimum of six I/O pins. Many of the sketches you will find in collection you downloaded are meant for these screens. Unfortunately we only have SIX pins on the Digispark, so that leaves nothing left for any other purpose. Make sure you have one that is set up for I2C. This only requires two pins! Digistump offers an LCD Shield Kit that includes everything you need to build up your own. You provide the solder and iron.


I found that I already had everything I needed in my spare parts cupboard, so I thought I would do my own. I looked for a schematic of the kit and couldn't find one. Most of the information was clear on the tutorial. I wasn't sure how the two 4.7K Ohm resistors fit into the scheme. I fired off a quick query to support@digistump.com and Erik got back to me right away. Of course they are swamped trying to get product shipped to everyone which means they haven't had a chance to get all the schematics on line. He told me that the resistors were 'pull up resistors' that go between the two I2C lines and +5V. That was all I needed to know.


I2C is a clever way to connect multiple devices together on a single two line bus. Each device is given a unique ID number and can tap in anywhere along the lines. You only need one pull up resistor for each line. Click here for a good I2C tutorial.


One line, SDA, is the data line. The other, SCL, is the clock. One of the devices in an I2C network is know as the 'master'. It controls all the others, which are referred to as 'slaves'. The master can send commands to any of the slaves and can ask any slave to send data back to it. There are numerous I2C sensors available that measure, temperature, pressure, tilt, compass heading, etc. etc. Many of these have ways to manipulate the lowest three bits of the ID so that you can have more than one of the same type in a circuit with unique ID numbers.


Let's hook it up. The back of the LCD panel has 4 pins labeled:
  • GND
  • VCC
  • SDA
  • SCL
I had a bunch of jumper wires with female connectors on each end that fit fine on these pins. I matched the colors with those in the kit. I use Black for GND, Red for VCC (+5V), White for SDA and Yellow for SCL. I then wrapped them together with tape to make a cable and keep them in the right order as I plug and unplug my project. It is real important to make sure you always connect the Black lead to GND. You really don't want to hook it up wrong.


I plugged the two resistors into the bread board with one leg connected to the 5V bus. I then used male jumpers to hook the other two ends to pins 0 and 2 on Sparky. I had to add male jumpers to the other end of my I2C cable. Hook the White, SDA, lead to Sparky's P0 and the Yellow, SCL, to P2. (In my photo, you will see a green one, I was too hurried to hunt for a yellow one.) The Red and Black leads go to +5V and ground. That's pretty much it.

I loaded up a sketch called: 'BasicUsage' and it worked first time. If you turn the LCD board over, you will find a trim pot on the back, that you can turn with a small Philips screw driver. This adjusts the contrast on the board. In the photo on the right, you will also see a black jumper sticking out of the left hand side of the daughter board. If you pull that off, you turn off the LED back lighting on the LCD. I haven't figured out why I would want to do that.


Now that we have the hardware working, it will be fun to start writing a game. C U Next time!







Tuesday, February 5, 2013

Sparky and His Brothers Arrive

I was very excited to see my packet arrive from the guys down at digiStump.com Inside I found the three DigiSpark micro-controllers that I ordered from the Kickstarter page. My first purchase from a Kickstarter project and I'm pleased!

The tiny boards came in antistatic bags, but I show them removed in the photo on the left. All of the parts were loose in the envelope so things went flying a bit when I tore into it. One of the headers turned up missing, but my wife found it on the floor later.



The directions on the web site suggest that we solder headers on the board and then use the pins to plug it into a breadboard. It seems like a good idea, but I have two issues with it. First, if you do this, the board plugs in upside down which makes it impossible to see the status of the two LEDs. 
Poster's update: My new breadboards have now arrived and I can clearly see that I was not correct about the alignment on the board. It was simply a matter of flipping the board around. On one side the + rail is on the outside and on the other it is on the inside. 
It is clever though, that they spaced everything so that the GPIO pins fan out along the side of the main breadboard workspace and the 5V and GND pins fit right into the power rails along side the board, IF you have two rails on the side of the board. My breadboard has only one rail on each side. So this won't work at all. I do have a small breadboard that would work just fine, but it is currently occupied with a ham radio Arduino project that I am developing. I wasn't willing to vacate that board for Sparky. As luck would have it, I had ordered a few new boards with double rails a week ago.

As I plan to use one of the boards just for development and imbed the others onto a protoboard later, I decided to solder a section of six pins right to the bottom of the board and install the three pin header to the top as they recommended. This allows me to connect two jumper wires between the board and the power rails.

DigiStump has a wiki set up to walk you through the steps for getting started. I tried installing the IDE on both my XP and Win7 machines. I had difficulty with each one and it took some fooling around to get it working. Part of that may have to do with the fact that I already have the Arduino IDE software installed on my computers and Sparky needs a different version. I did get it running, though. I thought I should be able to select a port in the 'tools' menu as you do with the Arduino, but the option was gray!. So went looing for it in the 'Control Panel.'  I expected to find the board in the 'Ports' section of device manager, but not so. That prompted me to try installing again and trying it on another computer. Finally by plugging and unplugging the board while I was in device manager It appears as a new item, higher in the list, under 'libusb-win32 Usb Devices.' It shows up on the IDE as COM5.

The DigiSpark is designed so that the tab on the board will fit into a USB jack. Unfortunately this is not as clean and solid as a regular USB plug would be. For one, you can plug it in upside down. Now that is something I've never been able to do before so I didn't give it much thought. It looks like there is no way to do any harm by plugging it in upside down, but I can attest to the fact that it doesn't work!

Sparky comes already programmed with the 'blink' sketch, so if you plug it in, it should start working right out of the envelope. The power LED comes on first. Then there is about a 5 second delay and the second LED will start blinking. Both of these are green. The delay is a cool part of the design. This little window of time allows Sparky to figure out if your are teaching him a new trick (ie, programming) or expecting him to perform. It's real clever the way they do this. You need to make sure that board is unplugged when you click the 'Upload' button in the IDE. You will see a message appear when it wants you to plug it in.

This 'plug in when prompted' scheme created a problem for me that took a while to figure out. The first few times I tried it, it did not work. I restarted my computer. I reinstalled the drivers. It would not work. The LEDs didn't even come on. What I learned was, that I needed to wiggle the board a little in the USB jack and make sure I was getting good contact. The board is loose enough that it has to be aligned just so. Once I got that sorted out, it worked fine.

I have experienced some issues with my Kaspersky Security Software while trying to upload sketches to my Arduino. With longer programs, that process can take several minutes unless I disable Kaspersky when I upload. I expect to see the same problem with Sparky. I keep the security window open and only disable it for the few seconds it takes to upload the code.

Pay attention to the precautions you find on the DigiSpark Wiki:

Precautions:

The Digispark, due to its small size and low cost is not as robust as a full blown Arduino.
When testing a new circuit we recommend that you test it with an external power supply first. Connecting a shorted circuit to the Digispark and connecting it to your computer could damage your computer and/or its USB ports. We take no responsibility for damage to your machine as a result of the use of a Digispark.
We strongly recommend connecting your Digispark through a USB hub which will often limit the damage caused by a short circuit to the usb hub. For the record, we've found many computers have usb fuses built in, and when we blew them on our 27” Mac monitor, thankfully they reset and everything worked after a power down.
The Digispark does not have short circuit or reverse polarity protection. Connecting power to the Digispark power pins backwards will almost certainly destroy it.
The Digispark is small enough to present a choking hazard and small enough to be inserted into some sockets. We take no responsibility for miss-use of the product. Please treat electricity and electronics with respect and common sense.
I find it easy to pull Sparky off of the breadboard when I upload so that nothing else is hooked up to it. Currently I am using an Arduino plugged into my laptop as a power supply doing nothing but piping 5V and GND to the project.

My first project will be a game that uses an LCD display. It will also give me a chance to work with I2C which is all new to me. It is a repeat of an Arduino project that I have done before. 

I soon learned that I needed to run a real simple sketch the first time, just to confirm that I was actually teaching Sparky a new trick. So I looked at some of the examples that installed with the IDE. That can be confusing, because most to them are Arduino sketches that use I/O pins that aren't even on the DigiSpark. You want to be sure you drill into the DigiSpark folder when looking for something to try. Before I realized that I was having a connection issue with my USB I resorted to simply reloading the 'blink' program, changed the first delay to 3000 so that I could confirm that it loaded by watching the blink rate. If you want to do the same thing, the sketch is called 'start'.