Sunday, 30 August 2015

Converting .ino file into .cpp

I found myself wanting to have a program folder made up solely of C++ files and the existence of the .ino file irked me for some reason (slightly OCD?)

After a bit of googling it was apparent that the .ino file only differed from regular C++ files in that a preprocessor would run on it before compilation to insert a header include.

So lo and behold a file that looks like this:
myApp.ino
-------
void setup()
{
   //do some setup
}
void loop()
{
   //do cool stuff here
}
-------
can be converted into:
main.cpp
-------
#include "application.h"
void setup()
{
   //do some setup
}
void loop()
{
   //do cool stuff here
}
-------

by simply renaming the file and adding the application.h include.

It is a little strange not to have a main method in this file but I assume the set up is similar to arduino where the main method is hidden away and you are only given the hooks into it by implementing setup() and loop()

Using the particle CLI on Ubuntu 14.04

I spent a bit of time playing with the cloud IDE and flashing some simple programs to the photon. I can't believe how easy it is to get up and running. The fact that you can flash your program onto the photon through the IDE without installing a million drivers and fighting with obscure errors is fantastic.

However, I'm not sure if it was my internet being lame or their servers being a bit laggy, but I sometimes found it would take over 10 seconds to compile my programs and would also time out when trying to flash my photon. I found this behaviour a little frustrating so invested a little time in getting the command line interface working so I could compile and flash programs without needing the cloud IDE. I believe the commands do connect to the particle servers so you still need internet for them to work.

So here we go:

1. Install the CLI


I followed the instructions here but found the spark-cli was deprecated and so at the end I installed the particle-cli instead.

swap

> sudo npm -g install spark-cli
for

> sudo npm -g install particle-cli


2. Compile your program


There are several ways you can compile your program into a binary file that can be flashed onto the photon. I chose the method of putting all the required files in a directory and running the following:

> cd <dir-with-program-files>
> particle compile p .

Note: the 'p' indicates you are compiling the program to run on a photon.

As an example, this was what my folder looked like:

- photon-app/
  |
  - myApp.ino
  - lib1.h
  - lib1.cpp

If your compilation was successful then a binary file will get created inside your directory. (It is named something like 'photon_firmware_1440934375581.bin'.

3. Put the photon in DFU mode

The photon needs to be put in Device Firmware Upgrade mode in order to accept a new program.
Perform the following steps:

  1. Ensure the photon is powered and the LED is pulsing cyan to indicate normal operation
  2. Press and hold the 'setup' and 'reset' buttons simultaneously on the photon 
  3. The LED should now be switched off
  4. Release just the 'reset' button and continue to hold the 'setup' button
  5. The LED will start flashing magenta and quickly change to yellow
  6. Once the LED is flashing yellow, release the 'setup' button
The photon is now in DFU mode and we are ready to flash our program onto it.


4. Flash your binary onto the photon


The command to flash a binary onto the photon is

> sudo particle flash --usb <binary-file>

e.g.
> sudo particle flash --usb photon_firmware_1440933735205.bin


Note: this needs to be done with sudo otherwise you get an error that looks like

> Error writing firmware...dfu-util: Cannot open DFU device 2b04:d006

If the flash was successful, the LED on the photon will return to its normal pulsing cyan colour.

I had to install a few bits and pieces to get this stage to work on my Ubuntu 14.04 laptop.

When I first ran the flash command it complained that dfu-util wasn't installed. After installing it with the standard 'sudo apt-get install dfu-util' I got an error along the lines of:

> 'invalid dfuse address: 0x08005000:leave'.

This led me to a helpful forum post which indicated I needed to install a later version of dfu-util as the official ubuntu repo only had version 0.5 and we need 0.7+.

So I downloaded version 0.8 from here (dfu-util_0.8.orig.tar.gz) and followed the instructions on the forum post to build it. In order to successfully run ./autogen.sh I needed to install 'autoconf'. And then in order to successfully run ./configure.sh I needed to install 'libusb-1.0.0-dev'.

After finishing up the dfu-util instructions I was able to successfully flash my program onto the photon. The only slightly annoying thing is that I get an error out of dfu-util despite the successful flash. From what I can tell from other people on the internet this is not unexpected. 

Here is an example output:

jenny@jenny-940X3G:~/code/sht71-photon$ sudo particle flash --usb photon_firmware_1440934375581.bin [sudo] password for jenny: Found DFU device 2b04:d006checking file  photon_firmware_1440934375581.binspawning dfu-util -d 2b04:d006 -a 0 -i 0 -s 0x080A0000:leave -D photon_firmware_1440934375581.bindfu-util 0.8
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.Copyright 2010-2014 Tormod Volden and Stefan SchmidtThis program is Free Software and has ABSOLUTELY NO WARRANTYPlease report bugs to dfu-util@lists.gnumonks.org
dfu-util: Invalid DFU suffix signaturedfu-util: A valid DFU suffix will be required in a future dfu-util release!!!Opening DFU capable USB device...ID 2b04:d006Run-time device DFU version 011aClaiming USB DFU Interface...Setting Alternate Setting #0 ...Determining device status: state = dfuIDLE, status = 0dfuIDLE, continuingDFU mode device DFU version 011aDevice returned transfer size 4096DfuSe interface name: "Internal Flash   "Downloading to address = 0x080a0000, size = 7756Download [=========================] 100%         7756 bytesDownload done.File downloaded successfullydfu-util: Error during download get_status
Error writing firmware...dfu-util: Invalid DFU suffix signaturedfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
dfu-util: Error during download get_status


Tuesday, 25 August 2015

Phat Photon Pins

So the pins on the photon are slightly too fat to fit in either of my standard sized breadboards. You can jam it in and the pins will stick but it will bounce out soon after if you touch it. I also found that it did not create a solid connection with the breadboard connectors so the components were not getting powered unless you wiggled the photon.

While developing the software and working out the circuits I really want to have the photon on a breadboard so I thought about how to modify the pin size. I have just had great success using shield extender headers. The photon with its chunky legs fit inside the header strips and they have slightly thinner legs which fit snugly in the breadboard and seems to provide a solid reliable connection.


You need a header strip with 12 pins. Unfortunately I couldn't find any at short notice so have improvised with smaller ones. You can pick them up on ebay for a couple of pounds.

Sunday, 23 August 2015

Particle photon battery pack

In order to allow my photon to be stand-alone and not require a power cable I bought the accompanying power shield. This is a lithium battery you can connect to your photon to give it it's own power source.

Here's a little guide to using  it:


In the pack you get a shield to attach your photon to, a battery and 2 header strips.


Plug the battery into the shield. It will only fit one way round.


Plug a powered USB cable into the shield. The red LED shows it is receiving power. The LED next to the battery connector will be blue if the battery is currently charging and will change to red when fully charged.


The photon is then placed over the power shield with the USB connector on the opposite end to the battery connector

 

If you plug the photon directly into the power shield then the photon board does not sit evenly and could potentially damage the components below. This is why we have the header strips.


Plug the header strips into the photon pins and then plug it into the power shield. You can now see the boards are cleanly separated.


However I found that the holes in the power shield are too large to provide connections with the header pins unless you push the photon to one side to make the legs slant into the holes. This means no power is provided to the photon. For this reason I will leave out the header strips while developing my project and solder the header strips to the power shield once I am happy with everything.

Move over Arduino Uno, Particle Photon is here!

I recently found myself wanting to create something to measure the temperature, humidity and light levels around a rather needy orchid I was growing to help me not kill it so quickly. This immediately made me think of my arduino uno. However it requires a separate shield to use wifi and is pretty large for what I wanted to do so I looked for alternatives. It was then I found the Particle photon.


This tiny component is usb powered, has an onboard wifi chip and a really cool ecosystem of software to help you interact with it (cloud IDE, mobile app, cloud storage etc.).

Any look how tiny!



Here is a guide on how to initialise your photon, connect it to your wifi network and make an LED flash using the mobile phone app.




First plug a powered USB cable into the power socket of the photon. Then open the particle app on your phone.

    

You won't have any devices listed yet so press the '+' to start setting up the photon. It may take a while for your device to appear in the list. Your board should be flashing blue to indicate it is in setup mode. If it is not then hold the 'setup' button for 3 seconds which should switch it to setup mode.

Once your photon has been discovered it will pop up in the list with a random name.

  

Click the photon and follow the wizard to connect it to your wifi network of choice. If all goes well you will end on the the setup complete screen.


Your photon will now be listed under your devices. If you click on the menu icon you can rename it to something more sensible. The first time you pair your photon with your account it may take a while for the status of your device to change to 'online' with a green circle. When I did mine the LED on the photon was flashing and changing colours for a few minutes before it settled down on a solid cyan light indicating it was finished initialising. I assume it was downloading updates. Any subsequent time you open the app (assuming your photon is powered and connected to the wifi) the status should appear as online almost immediately.

You can now enter 'Tinker' mode on the app where you are presented with the pin layout below. You can click on the pins to set a hi/low value to the output.  There is an LED on the board attached to pin D7, so set D7 to hi and you should see the LED light up on your board. Pretty cool!




Thursday, 3 May 2012

Persisting Hi Scores


When you switch off the battery pack on the GamePack or unplug it from your computer, the AVR chip loses power and you lose all your data stored in standard memory. This means we need to write the hi scores to an area of memory that will persist even when power is lost in order to recover them again when the game restarts. The ATMega2560 comes with 4kb EEPROM. Data stored here will remain even when power is lost.

The WinAVR development tools contains a library to read and write from EEPROM and it is pretty simple to use. See this blog post for some details about using it. The save/load functionality is encapsulated in the HiScores class in Tetris.

Here are some code snippets from this class:

You need to include the library:

 #include <avr/eeprom.h>  

Detecting if valid data has been saved:

 uint8_t data_flag = eeprom_read_byte((uint8_t*)DATA_FLAG_ADDRESS);  
   
 if(data_flag == VALID_DATA_FLAG){  
   return true;  
 }else{  
   return false;  
 }  

It is dangerous to assume that the data you want is present in the address you are looking in without some kind of check to confirm the data exists. For example if you run the game for the very first time, no high score data will exist. Who knows what data is written to the addresses you expect to read from. This can be solved by setting a single byte address to a value that indicates that valid data exists. If you read this address and the value is correct, you can assume the other addresses also contain valid data. If not, then you should not assume valid data in the other addresses. This mechanism makes resetting the hi score very easy as you don't actually have to erase the data, just set the flag to not be valid so the existing data will be ignored and overwritten (you can see this in HighScore.cpp).

Save a name and score to EEPROM:

 //indicate there is valid data to be read  
 eeprom_write_byte((uint8_t*)DATA_FLAG_ADDRESS, VALID_DATA_FLAG);  
   
 //save the player name  
 for(int i=0 ; i<player_name_length_ ; i++){  
   eeprom_write_byte((uint8_t*)(DATA_NAME_ADDRESS+i), player_name[i]);  
 }  
 //terminate the name array  
 eeprom_write_byte((uint8_t*)(DATA_NAME_ADDRESS+player_name_length_), '\0');  
   
 //save the player score  
 eeprom_write_word((uint16_t*)(DATA_SCORE_ADDRESS), score);  

An example set of data saved in Tetris is as follows:

   Address:  1    2    3   4   5   6   7
   Data:        9   B   O   B  \0   123

Where address 1 contains the valid check flag (where a value of 9 means valid data exists). This gives us a name of BOB (terminated by the null character) and a hi score of 123. The score is a stored as a 2 byte word.


Load the name and score back from EEPROM:

 //extra character to include the terminating character  
 char* player_name = new char[player_name_length_+1];  
   
 for(int i=0 ; i<player_name_length_+1 ; i++){  
   player_name[i] = eeprom_read_byte((uint8_t*)(DATA_NAME_ADDRESS+i));  
 }  
   
 int score = eeprom_read_word((uint16_t*)(DATA_SCORE_ADDRESS));  

Note: It is important to terminate the player name with a null character so no garbage gets appended on the end when you are displaying it on the screen. The graphics function text(char*, int, int) that will take the player name will stop looking for characters when it encounters the null character so without it you may get all sorts of stuff appended to the name.

The LandingScreen loads the hi score data and displays it to the player. The NameEntryScreen saves the hi score data back. Simples.

You can download version 2 of the Tetris Eclipse project here.

Check out a video of the hi score persistence in action. You can also see the game transition screens implemented from the last post:


Watch the video on youtube if you want to see the annotations. They seem to have been chopped off in this tiny format and I don't see a way to make it any bigger.

Note: There is a super secret button combo to reset the high score. On the landing screen where it says press A to continue, if you hold down the B button then press A, the screen will say 'HI SCORE RESET' and then continue. 

Game state transitions


I thought I'd tackle the top item on the Tetris to-do list; adding persistent hi scores. It's a little sad to have played a game and have no evidence of your achievements. It also encourages replay through a little competition. As I started implementing this feature I realised that the current code structure was getting a little unwieldy and could do with some refactoring first.

The current game path is controlled by the main method in Tetris.cpp. It is essentially a procedural style list of things to do in a list that loops forever:

e.g.

while(true){
   gameLoop();
   gameOver();
}

But then what happens when you want to add new states the to path? For example a landing page or name entry screen if you get a hi score. It would probably look something like this:

while(true){
   showLandingPage();
   gameLoop(); 
   gameOver();

   if(gotHiScore()){
      saveHiScore();
   }
}

This structure can get messy quite quickly if you want to add more states, especially ones are only moved to on a particular condition. To solve this I have introduced a Screen base class into Tetris with an implementation for each game state. The Screen then encapsulates the state transition logic within it.

 class Screen {  
   
   virtual void activate();  
   virtual Screen* getNextScreen();  
 }  

example Screen implementation:

 class PlayScreen : public Screen {  
   
   void activate(){  
    //code to play a game of tetris  
   }  
   
   Screen* getNextScreen(){  
    return new GameOverScreen();  
   }  
   
 }  

This reduces the main loop to:

Screen screen = new LandingScreen();

while(true){
   screen.activate();
   screen = screen.getNextScreen();
}

and it never needs to change, even when new screens are added. It also encapsulates all the code required for that state in a single class. 

Tetris screen state transitions

You can download version 2 of the Tetris Eclipse project here. This new version includes the state transitions and hi score saving/loading (as described here)