Overview Part 1: Simple Version of Restaurant Finder

CMPUT 274 — Tangible Computing
Assignment 2 - Restaurant Finder
Fall 2013
Version 1.2 – 2013-09-30
Overview
You will be implementing a restaurant finder for the Edmonton area on your Arduino. The program will
load an Edmonton map and show a dot for the current location on the map. Using a joystick, you will
be able to move the dot around the map and press down the joystick to select the current location. Then,
the restaurants in the order closest to that location are displayed on the LCD. Pushing the button again
returns you to the map.
We will discuss in class the code for loading the map, drawing the dot, handling joystick input and LCD
printing and scrolling. You will write the code for
1. Loading the restaurants.
2. Sorting the restaurants based on the closest restaurants to the current point.
3. Displaying the nearest restaurants (in order) on the LCD screen.
The assignment is structured into two parts. The first part is worth 60% and the second part is worth 40%
of the total value of the assignment.
Part 1 is due on Monday Nov 4 at 11:55pm
Part 2 is due on Monday Nov 11 at 11:55pm
You can work with a partner on this assignment using the full collaboration model. You must cite
all of your sources that substantially contributed to your assignment.
Part 1: Simple Version of Restaurant Finder
In the first part, you will develop a simple version of the restaurant finder. You will use a small map of
Edmonton, which fits on the LCD screen, and you will display as many of the nearest restaurants that fit
in the 20 lines of the LCD screen.
Operation of your Program
Your program will have two modes. Mode 0 displays the map and lets you move the cursor around.
Mode 1 is entered when you push the button on the joystick. In Mode 1 you display the restaurants
nearest to the cursor in ascending order of distance. When you push the button again you enter Mode 0
and redisplay the map.
Loading the restaurants
You have to load in the restaurant structs from the SD card into memory. Recall that each block is 512
bytes and each restaurant is 64 bytes.
typedef struct {
1
int32_t latitude_scaled;
int32_t longitude_scaled;
int8_t rating;
char name[55];
} restaurant;
// scaled by 100,000
// average rating, scale from 0-10
// always null terminated
Due to how slow it can be loading from the SD card, you will discover that it is important to load data
efficiently. This will be further discussed in worksheets and in class.
Sorting the restaurants
Sorting the restaurants will involve computing which restaurants are closest to the current position. We
could use a straight-line distance to the restaurant; but to be more realistic, we will instead use Manhattan
distance:
d((x1 , y1 ), (x2 , y2 )) = |x1 − x2 | + |y1 − y2 |
This is the distance if we strictly have to travel on a grid, rather than on diagonals. Though still not
realistic for crossing rivers (or other impassable areas), it is slightly more realistic than straight-line
distance.
In the actual implementation, we will want to load all the restaurants into memory for sorting, as
read/write access on the SD card is too slow for sorting. However, with 64 byte structs for restaurants, we would need 64 bytes ×875 ≈ 55KB. So, the restaurants cannot be stored in the Arduino’s 8K
of memory. Instead we will use a simplified, smaller restaurant struct so that the 875 restaurants can all
fit in the 8K of memory. Since we are sorting them on (x, y) position, we will use the following struct:
typedef struct {
uint16_t index;
// index of restaurant from 0 to last restaurat
uint16_t dist;
// manhatten distance to curspo position
} RestDist;
RestDist rest_dist[NUM_RESTAURANTS];
where NUM_RESTAURANTS = 1066. Using this smaller struct now gives us 4 bytes per restaurant;
since 4 bytes ×1066 < 4.5K, we can now sort in memory. When loading in restaurant info, each
restaurant needs to be converted into this form for sorting. If more information is needed after sorting
(such as name or rating), it can be fetched later from the SD card with the index field i.
Part 2: Full Version of Restaurant Finder
The full version of the restaurant finder adds three extensions:
1. Scrollable map: Use the big Edmonton map and enable scrolling around the map at greater detail.
2. Scrollable restaurant list: Use the joystick to scroll through more than the restaurants than can be
displayed on one screen.
3. Rating selector: Filter out only those restaurants that have a rating above the value set by the
potentiometer.
2
Rating selector
The rating selector will involve adding a potentiometer to select the minimum rating of restaurants displayed. We will assume a 0 to 5 star rating system. Since the rating is stored on the scale 0-10, you can
assume the natural conversion to a 5 point scale for x ∈ {0, 1, 2, . . . , 10} :
x+1
s=
2
To display what minimum rating is currently selected, you will also connect five LEDs to display the
current rating. For example, at the beginning, the minimum rating could be zero. As the potentiometer
is turned, the rating will reach the first threshold and increase to 1. At this point, the first light should
turn on. Correspondingly, pretend you have turned the potentiometer up to a 4 star rating. When you
start turning down the potentiometer, it should reach a threshold where it drops to a 3 star rating and the
4th light should be turned off, with now only 3 lights on. You will have to determine these thresholds to
reasonably discretize the analog output from the potentiometer. You should refer to an earlier lab where
we used potentiometers to help with this part of the assignment.
Using the rating input from the potentiometer, you will remove restaurants from the list that are below the
minimum rating. For example, if you turn the potentiometer up to a 5 star rating, then only restaurants
with a 5 star rating are displayed on the LCD, ordered still by proximity.
Further Information
Wiring Conventions
The TA’s will be testing your submissions on hardware, so it is
important that you all use the same wiring conventions:
// Display pins:
// standard U of A library settings, assuming Atmel Mega SPI pins
#define SD_CS
5 // Chip select line for SD card
#define TFT_CS
6 // Chip select line for TFT display
#define TFT_DC
7 // Data/command line for TFT
#define TFT_RST
8 // Reset line for TFT (or connect to +5V)
// Joystick pins:
#define JOYSTICK_HORIZ 0
#define JOYSTICK_VERT 1
#define JOYSTICK_BUTTON 9
// Analog input A0 - horizontal
// Analog input A1 - vertical
// Digitial input pin 9 for the button
// Potentiometer and ratings leds
#define RATING_DIAL 2
// Analog input A2 - restaurant dial selector
#define RATING_LED_0 2
// rating leds 0-4
#define RATING_LED_1 3
#define RATING_LED_2 4
#define RATING_LED_3 10
3
#define RATING_LED_4 11
Maps
The 2048x2048 tile of Edmonton (zoom level 13)
yeg-big.lcd.zip - in 16 bit format for the lcd screen
yeg-big.png
- in png format to see the image
The one-screen single tile 128x128 map of Edmonton
yeg-sm.lcd
- 16 bit format for lcd screen
yeg-sm.png
- in png format to see the image
Parrot.zip
parrot.bmp
board.jpg
- the parrot display example from class
- the parrot
- image of what the board with display should look like
Converting Units
// These constants are for the 2048 by 2048 map.
const int16_t map_width = 2048;
const int16_t map_height = 2048;
const int32_t map_north = 5361858;
const int32_t map_west = -11368652;
const int32_t map_south = 5340953;
const int32_t map_east = -11333496;
// These constants are for the 128 by 128 map.
const int16_t map_width = 128;
const int16_t map_height = 128;
const int32_t map_north = 5359942;
const int32_t map_west = -11365028;
const int32_t map_south = 5345428;
const int32_t map_east = -11340367;
// These functions convert between x/y map position and lat/lon
// (and vice versa.)
int32_t x_to_lon(int16_t x) {
return map(x, 0, map_width, map_west, map_east);
}
int32_t y_to_lat(int16_t y) {
return map(y, 0, map_height, map_north, map_south);
}
int16_t lon_to_x(int32_t lon) {
4
return map(lon, map_west, map_east, 0, map_width);
}
int16_t lat_to_y(int32_t lat) {
return map(lat, map_north, map_south, 0, map_height);
}
Display Text on the Display
typedef struct {
uint16_t index;
uint16_t dist;
} RestDist;
Here’s a code snippet that displays the names of the first 20 restaurants
as stored in the rest_dist array, which is a RestDist struct. Note that we
have to read the name for the restaurant off the SD card because it’s not
stored in the RestDist struct. Note that you will be writing the function
get_restaurant.
tft.fillScreen(0);
tft.setCursor(0, 0);
tft.setTextColor(0xFFFF);
tft.setTextWrap(false);
for (int i=0; i < 20; i++) {
Restaurant r;
get_restaurant(rest_dist[i].index, &r);
tft.print(r.name);
tft.print("\n");
}
tft.print("\n");
5