LTE project gets a status bar!

In my continuing effort to learn about programming, cellular service, and Arduino, I’ve made a couple of great developments on my LTE project. Essentially, I’m turning these parts into a texting/gps device. I want to say a phone, but since it uses LTE only, it can’t actually make a phone call. So it is a “smart device” rather than a “smart phone”.

Of course, any useful device needs to have a status bar. And that is what I have done so far. The Nokia 5110 display, at the current font, supports 5 lines of text. So, I decided the top line will always be the status bar. Just like your smart phone, this device uses a status bar to tell you the “status” of everything you really, really need to know in one glance.

The first digits displayed are the battery percentage. If you don’t know how much time you have left on the device before it dies, it can be a little hard to use. Here you can see the magic behind the curtain:

// Get the battery percentage:
uint16_t vbat;
if (! fona.getBattPercent(&vbat)) {
Serial.println(F(“Failed to read Batt”));
lcd.print(“**% “);
} else {
Serial.print(F(“VPct = “)); Serial.print(vbat); Serial.println(F(“%”));
lcd.print(vbat); lcd.print(“% “);
}

Next up is the GPS indicator. Note that this doesn’t tell you if you have a lock, but does tell you if the battery draining GPS is turned on or off (GPS for on, — for off). Fortunately, the fona library includes a GPS status checking function, so we just call it, like so:

// Get the GPS status:
int statGPS = fona.GPSstatus(); Serial.print(F(“GPS status = “)); Serial.println(statGPS);
if (statGPS == 1) {lcd.print(“GPS “);} else {lcd.print(“— “);}

After that, we have the network status indicator. I’ll delve into that a bit more. It looks like the traditional multi-bar display, but unlike traditional ones on your smart phone, this actually is just full bars, or not. As you can see, you can get different letters for different status, or just the home made bar indicator glyph for roaming or home connections.

// Get the network status:
uint8_t n = fona.getNetworkStatus();
Serial.print(F(“Network status “));
Serial.print(n);
Serial.print(F(“: “));
if (n == 0) {Serial.println(F(“Not registered”)); lcd.print(“X”);}
if (n == 1) {Serial.println(F(“Registered (home)”)); lcd.write(0);}
if (n == 2) {Serial.println(F(“Not registered (searching)”)); lcd.print(“S”);}
if (n == 3) {Serial.println(F(“Denied”)); lcd.print(“D”);}
if (n == 4) {Serial.println(F(“Unknown”)); lcd.print(“?”);}
if (n == 5) {Serial.println(F(“Registered roaming”)); lcd.write(0);}
lcd.print(” “);

Finally, there is a number that tells you how many text messages you currently have.

// Get the number of SMS messages:
int8_t smsnum = fona.getNumSMS();
if (smsnum < 0) {
Serial.println(F(“Could not read # SMS”));
lcd.print(“-0- “);
} else {
Serial.print(smsnum); Serial.println(F(” SMS’s on SIM card!”));
lcd.print(smsnum);
}

You are welcome to check out the whole commit, but this is the gist of how the status bar works. Currently, the sketch takes up 78% of the Arduino’s memory. I think the direction I am going with this is trying to make a beginning to end, build at home smart device that allows you to at lease navigate by GPS, and send/receive text messages.

If wishes were fishes, and moose’s excuses, I guess we would all have full freezers. With that said, if I am able, I wish I could work in a couple other simple tasks as well, such as a way to play a simple game, perhaps check an email, or maybe a very rudimentary e-link style web browser. But I think that might be a whole lot more than I can realistically accomplish with so little memory on the device. We’ll see though!

Linux – keep it simple.

Advertisements

Arduino LTE Botletics shield and a Nokia 5110 display!

image2

Today was a lot of fun, and I mean a lot! I was able to connect not only the Botletics LTE shield, but also the Nokia 5110 screen to the Arduino, AT THE SAME TIME! I know, for the rest of the Arduino enthusiasts out there, this may seem like child’s play, but it was a big deal for me.

First, I was using the Botletics modified fona library, and with the soldered board pins, it can only connect to the Arduino one way. The problem was that I was also using the PCD8544 library to control the Nokia 5110 display, but some of the pins needed were the same ones for both devices. That certainly wouldn’t do. So, I edited the PCD8544.h file as follows:

PCD8544(uint8_t sclk = 3, // clock (display pin 2)
uint8_t sdin = 4, // data-in (display pin 3)
uint8_t dc = 5, // data select (display pin 4)
uint8_t reset = 12, // reset (display pin 8)
uint8_t sce = 13); // enable (display pin 5)

Changing these pin outs allowed me to control it with the remaining pins on the board. Now I can have both the display and the LTE shield at the same time! Essentially, the old PCD8544 library had used pins 3,4,5,6, and 7, for simplicity. I however couldn’t use 6 and 7, as those were taken by the LTE shield. So, I swapped them in the header file to point to pins 12 and 13, since they were not being used.

The only problem I ran into, though, was space. It takes a lot of space for the fona library to run the LTE shield. Originally, I was going to use the U8 library, but using those two together actually took 109% of the storage space on the Arduino Uno. I tried to trim down the portions of code for the fona side, but couldn’t get everything small enough. Fortunately, the PCD8544 library was much, much smaller, and I found that it even has a simpler interface for text only, which is mostly what I want to use the screen for.

With those two libraries pared up, I added some lines to my LTE demo sketch to allow me to display the battery information on the Nokia 5110 screen. All told the sketch uses 26470 bytes (82%) of the program storage space, the maximum is 32256 bytes. It worked great, looked good, and still leaves room for more programming.

You can check out the full commit, of course, but here is the portion about the screen:

case ‘b’: {
// read the battery voltage and percentage
uint16_t vbat;
if (! fona.getBattVoltage(&vbat)) {
Serial.println(F(“Failed to read Batt”));
} else {
lcd.setCursor(0, 0);
lcd.print(“Battery Status”);
Serial.print(F(“VBat = “)); Serial.print(vbat); Serial.println(F(” mV”));
lcd.setCursor(0, 1); lcd.print(“VBat = “); lcd.print(vbat); lcd.print(” mV”);
}

if (! fona.getBattPercent(&vbat)) {
Serial.println(F(“Failed to read Batt”));
} else {
Serial.print(F(“VPct = “)); Serial.print(vbat); Serial.println(F(“%”));
lcd.setCursor(0, 2); lcd.print(“VPct = “); lcd.print(vbat); lcd.print(“%”);
}

break;
}

Really simple commands to set up the cursor, and then just lcd.print to display information. I really like this simple screen library for text. It doesn’t handle graphics too well, though, which is what the U8 library excelled at.

So I guess now I need to work out some sort of menu system, as well as some sort of buttons if I want to turn this thing into a portable texting/gps/data interface device.

Linux – keep it simple.

Testing other SIM cards with the Arduino LTE shield from Botletics

IMG_20190423_084454

In the continuing process of testing out various aspects of using the Botletics LTE Arduino shield, I’ve decided to do a quick test with a few other SIM cards that I have available. I tested two other options, my Straight Talk SIM card, and a Freedom Pop SIM card. I was particularly interested in the Freedom Pop card, since that would allow me to have a free option for my board.

The first thing I did was add the following lines to my sketch, to handle the APN’s:

//fona.setNetworkSettings(F(“your APN”), F(“your username”), F(“your password”));
//fona.setNetworkSettings(F(“m2m.com.attz”)); // For AT&T IoT SIM card
//fona.setNetworkSettings(F(“telstra.internet”)); // For Telstra (Australia) SIM card – CAT-M1 (Band 28)
fona.setNetworkSettings(F(“hologram”)); // For Hologram SIM card
// WJH fona.setNetworkSettings(F(“fp.com.attz”)); // For Freedom Pop SIM card – Sort of works. Connects, but you need their app to text/call/sms/web/etc.
// WJH fona.setNetworkSettings(F(“tfdata”)); // For Straight Talk SIM card – sort of works. Connects and sends/receives SMS, but no web data.

That way, I just un-comment whichever option I need, and flash that to the board. Note that there are other options that I think you can pass for APN controls, but these three options (APN, user name, password) are the only ones this sketch accepts.

Here was the results of my test. Starting with Freedom Pop:

FONA> C
—> AT+CCID
<— ***************
SIM CCID = ***************
FONA> 1
—> AT+CPSI?
<— +CPSI: LTE CAT-M1,Online,310-410,0×9308,125708560,61,EUTRAN-BAND12,5110,3,3,-16,-98,-65,10
—> AT+COPS?
<— +COPS: 0,0,”AT&T”,7

OK FONA>
n
—> AT+CGREG?
<— +CGREG: 0,1
Network status 1: Registered (home)
FONA> i
—> AT+CSQ
<— +CSQ: 24,99
RSSI = 24: -66 dBm
FONA> R
—> AT+CMGF=1
<— OK
—> AT+CPMS?
<— +CPMS: “SM”,0,10,”SM”,0,10,”SM”,0,10
FONA> s
Send to #***************
Type out one-line message (140 char): test FP
—> AT+CMGF=1
<— OK
—> AT+CMGS=”19073714586″
<— >
> test FP
^Z
Sent!
FONA> R
—> AT+CMGF=1
<— OK
—> AT+CPMS?
<— +CPMS: “SM”,0,10,”SM”,0,10,”SM”,0,10
FONA> w
URL to read (e.g. dweet.io/get/latest/dweet/for/sim7500test123):
http://www.google.com
****
—> AT+HTTPTERM
<— OK
—> AT+HTTPINIT
<— OK
—> AT+HTTPPARA=”CID”
<— OK
—> AT+HTTPPARA=”UA”
<— OK
—> AT+HTTPPARA=”URL”
<— OK
—> AT+HTTPACTION=0
<— OK
Status: 601
Len: 0
—> AT+HTTPREAD
<— OK
Failed!
FONA>

And Straight Talk:

FONA> n
—> AT+CGREG?
<— +CGREG: 0,1
Network status 1: Registered (home)
FONA> 1
—> AT+CPSI?
<— +CPSI: LTE CAT-M1,Online,310-410,0×9308,125708560,61,EUTRAN-BAND12,5110,3,3,-18,-98,-64,8
—> AT+COPS?
<— +COPS: 0,0,”HOME”,7

OK FONA>
w
URL to read (e.g. dweet.io/get/latest/dweet/for/sim7500test123):
http://www.google.com
****
—> AT+HTTPTERM
<— ERROR
—> AT+HTTPINIT
<— OK
—> AT+HTTPPARA=”CID”
<— OK
—> AT+HTTPPARA=”UA”
<— OK
—> AT+HTTPPARA=”URL”
<— OK
—> AT+HTTPACTION=0
<— OK
Status: 601
Len: 0
—> AT+HTTPREAD
<— OK
Failed!
FONA> s
Send to #***************
Type out one-line message (140 char): test 2 st
—> AT+CMGF=1
<— OK
—> AT+CMGS=”***************”
<— >
> test 2 st
^Z
Sent!
FONA>
+CMTI: “SM”,1
R
—> AT+CMGF=1
<— OK
—> AT+CPMS?
<— +CPMS: “SM”,2,30,”SM”,2,30,”SM”,2,30

Reading SMS #1
—> AT+CMGF=1
<— OK
—> AT+CSDH=1
<— OK
AT+CMGR=1
+CMGR: “REC UNREAD”,”+***************”,,”19/04/29,10:42:01-32″,145,4,0,0,”+12085978931″,145,13
test 2 st
***** SMS #1 (13) bytes *****
test 2 st
*****

Reading SMS #2
—> AT+CMGF=1
<— OK
—> AT+CSDH=1
<— OK
AT+CMGR=2
OK
Failed!
FONA>

What is more important is what all that garble means. Essentially, it boils down to this:

  • Freedom Pop connects instantly to the AT&T network. However, you can’t read data, and you can’t send or receive text messages.
  • Straight Talk connects instantly to the AT&T network. It does send and receive text messages, but it cannot use data. So, there is no way to support web interface or tunneling.

So, without further breaking it down, and just using the sketches as is, you can connect with both FP and ST, but only ST can send/receive text messages, and no data, so neither option seems to really work out of the box. If you’ve tried other options, be sure to let me know the results.

Linux – keep it simple.

Texting trouble with the LTE shield!

sim7000a

Next on my bucket list for things to test out with the Botletics LTE Shield was text messaging, or SMS. According to the demo, it was supposed to be really easy and straight forward, but it wasn’t.

First, I used the Hologram Dashboard to send an SMS message to the device. It “showed up” but I couldn’t read it:

FONA> R
—> AT+CMGF=1
<— OK
—> AT+CPMS?
<— +CPMS: “SM”,1,10,”SM”,1,10,”SM”,1,10

Reading SMS #1
—> AT+CMGF=1
<— OK
—> AT+CSDH=1
<— OK
AT+CMGR=1
OK
Failed!
FONA>

Then I tried sending one from the device:

FONA> s
Send to #<MYPHONENUMBER>
Type out one-line message (140 char): testing
—> AT+CMGF=1
<— OK
—> AT+CMGS=”<MYPHONENUMBER>”
<— >
> testing
^Z

Failed!
FONA>

And it wouldn’t send one either. I tried several variations of this for about an hour, and just wound up frustrated. Later, I took a look through prior issues, and I found another user who had the same problem. Turns out, in their situation, they originally connected to Verizon, and then couldn’t send or receive. Then they connected to AT&T, and they could send and receive. So, I took a look, and sure enough, I was connected to a Verizon network. I reset my board, and tried connecting again. This time (by no work of my own) it connected to an AT&T network, and I too could send and receive SMS messages! Check it out:

  • Sending – I received it on my phone in seconds!

FONA> s
Send to #<MYPHONENUMBER>
Type out one-line message (140 char): testing
—> AT+CMGF=1
<— OK
—> AT+CMGS=<MYPHONENUMBER>
<— >
> testing
^Z
Sent!
FONA>

  • Receiving – I sent the reply of “Cool!” from my phone.

FONA> r
Read #1
Reading SMS #1
—> AT+CMGF=1
<— OK
—> AT+CSDH=1
<— OK
AT+CMGR=1
+CMGR: “REC READ”,”+<MYPHONENUMBER>”,,”19/04/25,21:39:28+00″,145,4,0,3,”+19703769316″,145,5
FROM: +<MYPHONENUMBER>
—> AT+CMGF=1
<— OK
—> AT+CSDH=1
<— OK
AT+CMGR=1
+CMGR: “REC READ”,”+<MYPHONENUMBER>”,,”19/04/25,21:39:28+00″,145,4,0,3,”+19703769316″,145,5
Cool!
***** SMS #1 (5) bytes *****
Cool!
*****
FONA>

So, if you too are trying to follow the tutorial for the LTE demo using the Botletics SIM7000A shield, be sure you are hooked up to AT&T. Also, if you were hooked up to Verizon, be sure you unplug the Arduino, and the power supply/battery of the board. Otherwise, the modem might still be on!

Linux – keep it simple.

LTE shield for Arduino: Web Page Download!

IMG_20190423_084454

First up on my list of learning about this Botletics LTE shield was how to pull data. Fortunately for me, the LTE demo sketch included a method for downloading something from the internet. It works like this:

// The code below was written by Adafruit and only works on some modules
case ‘w’: {
// read website URL
uint16_t statuscode;
int16_t length;
char url[80];
flushSerial();
Serial.println(F(“URL to read (e.g. dweet.io/get/latest/dweet/for/sim7500test123):”));
Serial.print(F(“http://&#8221;)); readline(url, 79);
Serial.println(url);
Serial.println(F(“****”));
if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) {
Serial.println(“Failed!”);
break;
}
while (length > 0) {
while (fona.available()) {
char c = fona.read();

// Serial.write is too slow, we’ll write directly to Serial register!
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
#else
Serial.write(c);
#endif
length–;
if (! length) break;
}
}
Serial.println(F(“\n****”));
fona.HTTP_GET_end();
break;
}

As the code states, it was originally written by Adafruit, and some portions of this code (the Adafruit Fona library) were updated by Timothy Woo of Botletics) and it allows you to look up a URL and download it. So, I tested Google. It downloaded it like so:

googleWebsite

And I copied/pasted it into a text file, and saved it as html, which opened in a browser, like this:

googletest

So, that works. Granted, using this method was extremely slow. I am using a serial monitor connection over USB at a 9600 baud rate, which really took a while to catch all of the data. You could literally watch the characters being written on the screen. However, I think the modem is much faster, just my interface to it is not as quick. I’ll have to play with it some more, but it was nice to be able to download a web page at least!

Linux – keep it simple.

Trial run of SIM 7000A LTE and GPS shield for Arduino

I wanted to start playing around with cellular devices and using them with the Arduino. So, I bought a Botletics SIM7000 LTE CAT-M1 NB-IoT Cellular + GPS + Antenna Shield Kit for Arduino (SIM7000A)  that works in my locale. There are different modules, SIM7000 A,C,E, etc. that work in different places, so I picked up this one which works with AT&T as well as Verizon LTE bands in my area.

So far, I’m just getting started, and I haven’t done much yet. You can head over to the wiki to see the available open source software and examples are available. I love Open Source Hardware (OSHW)! It is really nice buying a piece of equipment and seeing all of the available diagrams, schematics, software, etc., all laid out for you to use.

In any event, I’m just getting started with this, and so far all I’ve done is register my new Hologram.io sim card, and set it up with an LTE demo sketch. Essentially, the demo sketch allows you to connect over USB with the Arduino serial monitor and use a text based menu interface to play around with the modem, without having to know all of the AT commands.

Here’s a screenshot of my Hologram dashboard:

dashboard

Of course there is more information on the upper parts of the page, but I felt it was probably wise not to include my IEMI and other information on this shot. The dashboard is really intuitive. As for Hologram.io itself, so far so good. When I signed up they sent me a free card in the mail, as well as gave me 1 MB of free data a month to play with. Sending text messages to the device is free, but sending a text from the device costs 19 cents each. Overall, the monthly charge is $1.50/month to keep the card active. I think it is 40 cents for each additional MB of data I use.

The price seems a bit much for each SMS sent, but it is nice to allow me to play with this without having to get a $30+/month sim card for another carrier. I was going to try some of my other sims in it from my other phones, but you do need a phone sim that specifically does CAT-M1, which supposedly not all do.

One item of note is that the modem will not work without a battery while plugged into the Arduino. It turns out that the Arduino can’t supply enough juice during some operations that cause it to pull a little extra juice. These spikes are sporadic, and while the battery is plugged in, the battery is charged by the board, so my battery level keeps going up while plugged in.

The interesting thing about the battery is that I couldn’t get any place to ship me a battery in the mail to Alaska. Fortunately, I have several dead Android phones laying around and I pulled a 3.7v, 1400mAH battery out of one and was able to solder the wires to the terminals and hook it up that way. Check out the pictures if you want to see my handy work.

I’ll let you know as I try out a few of the features what I can come up with. I’m hoping to build some sort of rudimentary texting/web phone, and grow in some lower level cellular/gps knowledge. As always, you can follow along with my sketches on my GitLab!

Linux – keep it simple.

Arduino Asteroids Game: Randomly!

game3

I wanted to post a video, but sadly the free version of WordPress doesn’t allow this. So, you can click here to watch the video of me playing “Asteroids Game!” on my Uno with the LCD Keypad Shield. Sorry for the low quality of the video, but I’m sure you’ll enjoy it all the same.

The game is complete, and you are welcome to head over to my GitLab and download the ino file and compile it yourself. Remember, you will need the LCD Keypad Shield library as well. Some stats about the game and program:

Sketch uses 7510 bytes (23%) of program storage space. Maximum is 32256 bytes.
Global variables use 473 bytes (23%) of dynamic memory, leaving 1575 bytes for local variables. Maximum is 2048 bytes.

Also, the entire game is programmed in less than 600 lines (would be significantly less without all the explanation blocks I put in there), and the ino file is less than 20 kb!

One of the biggest parts of the game is making sure that the asteroids show up in a random fashion. With only 4 asteroids, it is important that the pattern is not discernible by the player, or they will easily be able to win over and over again. Here is how I called it:

gameAsteroidOne = get_random(4);

I am calling the “get_random” function with an integer (in this case) of 4. That will make more sense once I show you the function:

int get_random (int addOn) {
srand(millis()+addOn); // Use time since turned on and add on number as seed for random number.
int r = rand() % 10; // Returns a random integer between 0 and 10.
r += 10; // Add 10 to keep it off of the display screen.
return r;
}

You see, computers can’t actually make random numbers, so you have to “seed” it with something to grow a number from. As a “seed” I input the time in milliseconds that the game has been running. From this it makes a “random” number from 1 to 10. It then adds 10 to that number to place the asteroid off of the screen, giving the appearance that it existed before and slowly came into view.

The problem is that sometimes the game loop runs fast enough where two asteroids are asking for a new random number at the exact same time. If they do, they will both receive the exact same “random” number. This will cause them to “overlap” or be in the same physical spot, which means that they will both go off screen at the same time, and request a new random number at the same time, receiving the same “random” number again. It’s a loop.

To solve this, I added the integer “addOn” to the milliseconds to make a new number. This “addOn” number is passed with each asteroid, and each one has a different number, creating a new instance of “seed” for the random number generator. That way no two should return the exact same “random” number. Although it can still happen.

Just like rolling two dice can sometimes give you the same number, the random function can still randomly return the same number. The smaller the number pool, a six sided dice would have a pool of 6, our game has a pool of 10, the more likely a repeat of a random number happens.

Another case scenario is when asteroid one, for say, goes off screen, while asteroid two is 2 steps behind. Asteroid one gets a random number of, let’s say 6, which added to 10 makes 16. Now the asteroids move. One is 15, two is 1. Then one is 14, and two is 0. Then one is 13, and two falls off screen, getting a new number, which randomly could be 3, which, when added to 10, makes 13, and the two asteroids now occupy the same space.

A programmer could add a check for this, and if the asteroids are in the same space, cause a new random number to be chosen, or add or subtract a number to it, but in this simple game, it happens so rarely that it isn’t really a problem. The player just gets a bonus when those two asteroids pass next time.

Either way, I hope that you have enjoyed the game itself, and more so the creation of it. The game is open source and feel free to put it to good use!

Linux – keep it simple.

Arduino Asteroids Game: Play mode and pause state!

Today was the big push! It took a while to figure out how to implement what I wanted to do, but now it’s done! The game play mode and pause state are completed! You can, of course, check out the full commits on my GitLab, but I plan to go over some of the most important parts here.

if (gameState == 3) { // Play state.
// The player has entered play mode.

gameTime++;
if (gameTime > 1){
gameTime = 0;
gamePaused = false;
}

This portion allows the game to pause. An odd occurrence is that you cannot press the pause button and release it fast enough. It will essentially get pressed and check that it is pressed about 1000 times per second, so I needed to add an “unpause” delay, and this is how I did it. If the buttons were software buttons, I could have done this differently, but they are physical buttons, so I needed this to make it work every time.

gameShoot = true; // you have not shot yet this round.
gameAsteroidOne–; // First asteroid starting space.
gameAsteroidTwo–; // Second asteroid starting space.
gameAsteroidThree–; // Third asteroid starting space.
gameAsteroidFour–; // Fourth Asteroid starting space.

Here, we increment (or move) each asteroid by one space.

if (gameAsteroidOne == -1) {
if (gamePosition == 0) {
// Game over, you lose.
gameState = 6;
gameLineNum = 0;
} else {
gameScore++; // get a point!
gameSpeed = set_gameSpeed(gameScore);
gameAsteroidOne = get_random(4);
}
} // end gameAsteroidOne.

In this block, I am figuring out everything for asteroid number one. So, if it’s position (which we moved just the block before this) is now -1, then it is at the position on the screen where the player’s ship is. It now checks if it is on the same row as the ship (gamePosition is the position of the ship, 0 for upper, 1 for lower). If they both are on the same row, then a collision has occurred. So, you switch to the lose screen.

If they are not on the same row, then the player gets a point for passing the asteroid. Then the game speed is increased (there are some other factors that change it as well), and the asteroid is moved to a random new location.

if (gameAsteroidTwo == -1) {
if (gamePosition == 0) {
// Game over, you lose.
gameState = 6;
gameLineNum = 0;
} else {
gameScore++; // get a point!
gameSpeed = set_gameSpeed(gameScore);
gameAsteroidTwo = get_random(2);
}
} // end gameAsteroidTwo.

if (gameAsteroidThree == -1) {
if (gamePosition == 1) {
// Game over, you lose.
gameState = 6;
gameLineNum = 0;
} else {
gameScore++; // get a point!
gameSpeed = set_gameSpeed(gameScore);
gameAsteroidThree = get_random(3);
}
} // end gameAsteroidThree.

if (gameAsteroidFour == -1) {
if (gamePosition == 1) {
// Game over, you lose.
gameState = 6;
gameLineNum = 0;
} else {
gameScore++; // get a point!
gameSpeed = set_gameSpeed(gameScore);
gameAsteroidFour = get_random(1);
}
} // end gameAsteroidFour.

if (gameScore > 99){
// You win! Great job!
gameState = 5;
gameLineNum = 0;
}

These are the portions for asteroids two through four, which work identically to asteroid one. Note that there are two asteroids on row 0, and two asteroids on row 1. Four asteroids total. It seems rather limited, but it is appropriate for such a small screen.

// Set up our display.
// The space ship
String shipUpper = ” “;
String shipLower = ” “;
if (gamePosition == 0){
shipUpper = “>”;
shipLower = ” “;
} else {
shipUpper = ” “;
shipLower = “>”;
}

Here we check the location of the player’s space ship and set the upper and lower icons appropriate for the display.

// Upper blocks.
lcd.setCursor(0,0);
lcd.print(“00”);
lcd.setCursor(2,0);
lcd.print(gameBullets);
lcd.setCursor(3,0);
lcd.print(“|”);
lcd.setCursor(4,0);
lcd.print(shipUpper);

for (int a = 5; a < 17; a++){
lcd.setCursor(a,0);
if (a == gameAsteroidOne+5){
lcd.print(“*”);
} else if (a == gameAsteroidTwo+5){
lcd.print(“*”);
} else {
lcd.print(” “);
}
}

Now we draw the upper blocks. As you can see, I just set the LCD cursor to the correct spot and print the text to display what I want displayed. The “for” loop cycles through the remaining display area, or “asteroid field” and checks for asteroids. If there is one, it displays an asterisk, if not, then a blank space.

// Lower blocks.
lcd.setCursor(0,1);
lcd.print(gameScore);
if (gameScore < 10) {
lcd.setCursor(1,1);
lcd.print(” “);
} else if (gameScore < 100) {
lcd.setCursor(2,1);
lcd.print(” “);
}

lcd.setCursor(3,1);
lcd.print(“|”);
lcd.setCursor(4,1);
lcd.print(shipLower);

for (int a = 5; a < 17; a++){
lcd.setCursor(a,1);
if (a == gameAsteroidThree+5){
lcd.print(“*”);
} else if (a == gameAsteroidFour+5){
lcd.print(“*”);
} else {
lcd.print(” “);
}
}

Here we draw the lower line of the screen. It works basically the same as the upper line, but with the score instead of the number of bullets.

gameDelay = 0;
while (gameDelay < 1000){
// Add a delay in the loop.
delay(1);
gameDelay+=gameSpeed;
lcd_key = read_LCD_buttons(); // read the buttons

switch (lcd_key){

case btnRIGHT:{
// Shoot command
if (gameBullets > 0 && gameShoot) {
if (gamePosition == 0){
lcd.setCursor(5,0);
lcd.print(“————“);
gameBullets–;
gameShoot = false; // You already shot.
gameAsteroidOne = get_random(4);
gameAsteroidTwo = get_random(2);
} else {
lcd.setCursor(5,1);
lcd.print(“————“);
gameBullets–;
gameShoot = false; // You already shot.
gameAsteroidThree = get_random(3);
gameAsteroidFour = get_random(1);
}
}
break;
}
case btnLEFT:{
if (!gamePaused) {
gameState = 4;
gameLineNum = 0;
gamePaused = true;
}
break;
}
case btnUP:{
gamePosition = 0;
break;
}
case btnDOWN:{
gamePosition = 1;
break;
}
case btnSELECT:{
gameState = 0;
gameLineNum = 0;
break;
}
}
}
} // End gameState 3, play state.

The remainder is the delayed “while” loop, which checks the status of the buttons every millisecond and increments towards ending this “round” of display. Because it is using a counter that is based on game speed, the game will speed up as the game increases. At first, an entire game loop takes about 1 second, then .5 seconds, then .33 seconds, and finally, .25 seconds towards the end of the game.

The pause mode is much simpler:

if (gameState == 4) { // Pause state.
// The player paused the game.
lcd_key = read_LCD_buttons(); // read the buttons

switch (lcd_key){

case btnLEFT:{
gameState = 3;
gameLineNum = 0;
break;
}
case btnSELECT:{
gameState = 0;
gameLineNum = 0;
break;
}
}
} // End gameState 4, pause state.

The pause mode doesn’t actually draw anything, which is good, because then the screen displays what it was displaying last. Hence the game still visually appears, but no calculations are made to move anything.

Next post I’ll discuss the random number generator and some background information, as well as try to post a video of the game being played. If you have an LCD Keypad Shield and Arduino Uno, feel free to download my GitLab repository and play the game! You will need the LCD Keypad Shield library as well. Be sure to let me know if you tried it out!

Linux – keep it simple.

Arduino Asteroids Game: Win some, Lose some!

It isn’t really a game if you can’t win or lose. You need some driving force to make the game worth playing. With that, I also needed a way to inform the user that they either won or lost the game. Hence enter these win and lose game states. Almost identical to the credits or information screens, these win/lose screens just display that the winner won or the loser lost.

Feel free to check out the latest commit on this, but there isn’t much to see that is different from the info/credits commits.

Linux – keep it simple.

Arduino Asteroids Game: Info and Credit Screens!

While not very exciting from the gamer standpoint, the information and credits screens are really important for several reasons. The main one being that it tells you how to play the game. It also lets you know how to contact the developer and who made the game. In the event you want to find more great material to play with!

Essentially, I have set up a scrolling screen that scrolls information over and over again. Pretty boring. However, I found a useful gem that I’d like to share with you here.

You see, as the information scrolls by, you might decide to click a button to do something, e.g., go back to the main menu, start the game, or what not. Well, the original method I was using was:

  • Loop through displayed data.
  • Check if they clicked a button.
  • Add 1.5 second delay.

This is a problem because you may have to hold the button for 1.5 seconds before it is picked up by the program. So, how do we include a delay, but constantly check for button presses? Well, with a “while” loop of course! Check it out:

gameDelay = 0;
      while (gameDelay < 2000){
       // Add a delay in the loop.
       delay(1);
       gameDelay++;
     lcd_key = read_LCD_buttons();   // read the buttons
  
       switch (lcd_key){ // depending on which button was pushed, we perform an action
    
           case btnSELECT:{
                 gameState = 0;
                 gameLineNum = 0;
                 break;
           }
       }
       }

So, instead of 2 seconds of delay all at once, I have a while loop that delays 1 ms, checks for button pushes, and then repeats for 2000 times, or roughly 2 seconds. This allows the player to press the button at any time, and only delays by 1 ms before reading it. Not only is this more functional, but it looks cooler in code too!

You can check out the full commit for the credits screen and info screens on my GitLab if you want more information.

Linux – keep it simple.