We use the
ST7735 library from adafruit, as well as the
SPI Arduino library to communicate with the SPI devices (screen and SD card) and the Arduino
SD library as well. This code listens to the x and y values coming from the accelerometer. The critical code is here:
String img2 = "fs_";
img2 += String(x_index);
img2 += String(y_index);
img2 += ".bmp";
char img2c[10] ;
for(int ii = 0; ii < 9; ii++){
img2c[ii] = img2.charAt(ii);
}
img2c[9] = 0;
open_file(img2c,file_pos);
We take the normalized x and y values from the accelerometer and use them to choose an image from a set of bitmaps stored on the SD card. The images have names like "fs_XY.bmp" where X is a number between 0 and 6 and y is a number between o and 4. Each of these numbers corrseponds to different points of view of the face along the horizontal and vertical axes.
/* LucidTronix 3D Accelerometer Picture Frame
* For instructions, details and schematic, See:
* http://www.lucidtronix.com/tutorials/31
* Uses the adafruit st7735 library
* calibrates the accelerometer readings
*/
#include <ST7735.h>
#include <SD.h>
#include <SPI.h>
// If we are using the hardware SPI interface, these are the pins (for future ref)
#define sclk 13
#define mosi 11
// You can also just connect the reset pin to +5V (we do a software reset)
#define rst 8
// these pins are required
#define cs 10
#define dc 9
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// For Arduino Uno/Duemilanove, etc
// connect the SD card with MOSI going to pin 11, MISO going to pin 12 and SCK going to pin 13 (standard)
// Then pin 4 goes to CS (or whatever you have set up)
#define SD_CS 4 // Set the chip select line to whatever you use (4 doesnt conflict with the library)
// to draw images from the SD card, we will share the hardware SPI interface
ST7735 tft = ST7735(cs, dc, rst);
// the file itself
File bmpFile1;
// information we extract about the bitmap file
int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;
int btn1 = 1;
int btn0 = 0;
int cur_h = 1;
int cur_v = 1;
int sensor_maxx = 0;
int sensor_minx = 1024;
int sensor_maxy = 0;
int sensor_miny = 1024;
int old_x = 0;
int old_y = 0;
boolean change_img = false;
void setup(void) {
//Serial.begin(9600);
pinMode(cs, OUTPUT);
digitalWrite(cs, HIGH);
// initialize a ST7735R TFT
tft.initR(); // change this to initB() for ST7735B TFT's
// Just do a simple test
tft.writecommand(ST7735_DISPON);
tft.fillScreen(WHITE);
delay(200);
tft.drawString(10,20,"Gyro setup..." , GREEN);
tft.drawString(12,22, "Try SD" ,BLUE);
if (!SD.begin(SD_CS)) {
tft.drawString(12,42, "SD Failed" ,RED);
return;
}
tft.drawString(12,42, "SD Good" ,BLUE);
delay(500);
pinMode(btn0,INPUT);
pinMode(btn1,INPUT);
tft.fillScreen(BLACK);
bmp_load_and_draw_image("frame.bmp",0,0);
bmp_load_and_draw_image("fs_00.bmp",40,50);
delay (1000);
change_img = true;
}
void loop() {
bmpdraw(40,50);
}
void open_file(char * filename, unsigned int file_pos){
bmpFile1.close();
delay(20);
bmpFile1 = SD.open(filename);
delay(20);
bmpFile1.seek(0);
bmpFile1.seek(file_pos);
if (!bmpFile1) {
tft.drawString(12,62, "Coodn't open image" ,RED);
return;
}
}
void bmp_load_and_draw_image(char* filename, int ax, int ay) {
bmpFile1 = SD.open(filename);
if (!bmpFile1) {
tft.drawString(12,62, "Coodn't find image" ,RED);
return;
}
if (!bmpReadHeader(bmpFile1)) {
tft.drawString(12,82, "Bad image" ,RED);
return;
}
tft.drawString(12,102, "Try 2 draw image" ,GREEN);
bmpdraw( ax, ay);
//bmpFile1.close();
}
/*********************************************/
// This procedure reads a bitmap and draws it to the screen
// its sped up by reading many pixels worth of data at a time
// instead of just one pixel at a time. increading the buffer takes
// more RAM but makes the drawing a little faster. 20 pixels' worth
// is probably a good place
#define BUFFPIXEL 20
void bmpdraw(int x, int y) {
bmpFile1.seek(bmpImageoffset);
unsigned int file_pos = bmpImageoffset;
uint32_t time = millis();
uint16_t p;
uint8_t g, b;
int i, j;
uint8_t sdbuffer[3 * BUFFPIXEL]; // 3 * pixels to buffer
uint8_t buffidx = 3*BUFFPIXEL;
if ( change_img ) check_acc_data(file_pos);
for (i=0; i< bmpHeight; i++) {
// bitmaps are stored with the BOTTOM line first so we have to move 'up'
for (j=0; j<bmpWidth; j++) {
// read more pixels
if (buffidx >= 3*BUFFPIXEL) {
bmpFile1.read(sdbuffer, 3*BUFFPIXEL);
buffidx = 0;
}
// convert pixel from 888 to 565
b = sdbuffer[buffidx++]; // blue
g = sdbuffer[buffidx++]; // green
p = sdbuffer[buffidx++]; // red
file_pos += 3;
p >>= 3;
p <<= 6;
g >>= 2;
p |= g;
p <<= 5;
b >>= 3;
p |= b;
tft.drawPixel(x+j, y+i, p);
}
}
}
boolean bmpReadHeader(File f) {
// read header
uint32_t tmp;
f.seek(0);
if (read16(f) != 0x4D42) {
// magic bytes missing
return false;
}
// read file size
tmp = read32(f);
//Serial.print("size 0x"); Serial.println(tmp, HEX);
// read and ignore creator bytes
read32(f);
bmpImageoffset = read32(f);
//Serial.print("offset "); Serial.println(bmpImageoffset, DEC);
// read DIB header
tmp = read32(f);
//Serial.print("header size "); Serial.println(tmp, DEC);
bmpWidth = read32(f);
bmpHeight = read32(f);
if (read16(f) != 1)
return false;
bmpDepth = read16(f);
//Serial.print("bitdepth "); Serial.println(bmpDepth, DEC);
if (read32(f) != 0) {
// compression not supported!
return false;
}
//Serial.print("compression "); Serial.println(tmp, DEC);
return true;
}
/*********************************************/
// These read data from the SD card file and convert them to big endian
// (the data is stored in little endian format!)
// LITTLE ENDIAN!
uint16_t read16(File f) {
uint16_t d;
uint8_t b;
b = f.read();
d = f.read();
d <<= 8;
d |= b;
return d;
}
// LITTLE ENDIAN!
uint32_t read32(File f) {
uint32_t d;
uint16_t b;
b = read16(f);
d = read16(f);
d <<= 16;
d |= b;
return d;
}
void check_acc_data(unsigned int file_pos){
int ax = analogRead(1);
int ay = analogRead(0);
if ( ay > sensor_maxy) sensor_maxy = ay;
if ( ay < sensor_miny ) sensor_miny = ay;
if ( ax > sensor_maxx) sensor_maxx = ax;
if ( ax < sensor_minx ) sensor_minx = ax;
float y_adjust = ay - sensor_miny;
float ratioy = y_adjust / (float)(1+sensor_maxy-sensor_miny);
float x_adjust = ax - sensor_minx;
float ratiox = x_adjust / (float)(1+sensor_maxx-sensor_minx);
int x_index = (int)(ratiox*6.0);
int y_index = (int)(ratioy*4.0);
boolean changed = false;
if ( x_index != old_x || y_index != old_y ){
String img2 = "fs_";
img2 += String(x_index);
img2 += String(y_index);
img2 += ".bmp";
char img2c[10] ;
for(int ii = 0; ii < 9; ii++){
img2c[ii] = img2.charAt(ii);
}
img2c[9] = 0;
open_file(img2c,file_pos);
old_y = y_index;
old_x = x_index;
}
}
Comments: