Ein großes Stück weiter

Nach einiger Arbeit an diesem Wochenende habe ich die Einzelteile meines Projektes zusammengebaut (ein paar Kleinigkeiten fehlen noch) und kann mich nun auf die restliche Programmierung stürzen :D

Das Aussehen des Tresors wird natürlich noch ausgebaut. :)

Hier ein paar Bilder: (etwas chaotisch, wird aber noch kaschiert)

Safe Front

Safe Tür innen


Mein Projekt: „SafeDuino“ :D

Ahoi :D

Also nachdem ich eine längere Zeit keine Artikel erstellt habe, wollte ich gebündelt einmal ein paar Aspekte meines Projektes zeigen.

Ich habe mich, nach vielem Ausprobieren und Herumbasteln, dafür entschieden einen Tresor zu bauen, der mit Hilfe des Arduinos gesteuert wird.

Hier einmal ein paar Aspekte zum Projekt (was soll es können und Ähnliches) :

  • Der Tresor wird aus Holz gebaut (es soll eher modellhaft, als diebstahlsicher sein :D )

skizze_maße

  • Der Safe kann sich selbst verschließen und entriegeln (Durch die Konstruktion ist der Riegel besonders standhaft)
  • Auch ohne die Verbindung mit einem Computer kann er betrieben werden ( mit Hilfe einer 9V Batterie und einem zum Arduino passenden Stecker)
  • Damit das Projekt nicht fortwährend Strom verbraucht baue ich einen Kippschalter ein, mit welchem der Tresor an- und ausgeschaltet werden kann
  • Damit gespeicherte Passwörter o.Ä. nicht mit dem Ausschalten gelöscht werden, nutze ich den im Arduino eingebauten Flash Speicher (EEPROM), welcher bis zu 512 Einträge mit Zahlenwerten von 0 bis 255 verwalten kann
  • Ich habe ein Tastenfeld gebaut, welches 12 Tasten besitzt und dank „register shifting“ nur vier Input Pins benötigt.

Keypad(3x4)

  • Als grafische Benutzeroberfläche verwende ich ein TFT Display, welches ich in einem anderen Artikel vorgestellt habe.

TFT Front

  • Das Display besitzt ein SD Shield, welches ich für die Kommunikation von Arduino und Computer nutzen möchte, was mehrere Vorteile im Gegensatz zu einer seriellen Kommunikation mit sich bringt. Dadurch dass sowohl Tresor als auch Computer Daten auf eine SD Karte schreiben und diese auslesen können, baue ich folgende Funktionen ein:
  • –> TAN Generator, Versand der TAN’s per Email
  • –> Wenn der Code mehrfach falsch eingegeben wird, soll sich der Tresor sperren und nur mit Hilfe eines Keys (MD5 -Algorithmus) entsperren lassen.
  • Der Tresor wird von Innen Beleuchtet, wenn er geöffnet wird
  • Ein aus einem alten PC ausgebauter 8Ohm Lautsprecher sorgt für eine Tonausgabe
  • Neben Keypad und Display befindet sich auf der Vorderseite des Safes auch ein „LED Bargraph“ welcher das Display visuell unterstützt :D
  • Die ganze Elektronik ist oben in einem Zwischenraum deponiert
  • Natürlich wird der Tresor zum Schluss auch optisch gestaltet :)

Hier dann noch ein Paar Bilder :)

safeduino

safe

Riegel v.3

2013-02-01 17.27.46

Shift Register

Stecker Stromversorgung

Kippschalter

Bargraph (10LED's)

Shift Register

SD


TFT Display – Bilder Über SD Karte anzeigen

Auf dem TFT Display, welches ich im letzten Post vorgestellt habe, kann man ebenfalls Bilder anzeigen lassen.

Hier mal ein Beispiel:

spongii <3

Wichtig ist, dass:

  • Die Bilder im *.bmp – Format vorliegen
  • Das Format sollte 128 x 160 Pixel betragen
  • Die Bilder müssen im /root Verzeichnis der SD Karte sein
  • Die SD Karte sollte FAT32 formatiert sein
  • Die Bilder sollten im 24BIT Farbformat vorliegen

Hier die Schaltung:

Leonardo Display
10 CS
9 DC
8 RES
SDA SDA
SCL SCL
5V VCC
GND GND
4 SD-CS
ICSP-1 MISO
ICSP-3 SCLK
ICSP-4 MOSI

Programmcode:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>
#define SD_CS    4  // Chip select line for SD card
#define TFT_CS  10  // Chip select line for TFT display
#define TFT_DC   9  // Data/command line for TFT
#define TFT_RST  8  // Reset line for TFT (or connect to +5V)

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, SDA, SCL, TFT_RST);

void setup(void) {
Serial.begin(9600);
tft.initR(INITR_REDTAB);
Serial.print(„Initializing SD card…“);
if (!SD.begin(SD_CS)) {
Serial.println(„failed!“);
return;
}
Serial.println(„OK!“);
}

void loop() {

bmpDraw(„1.bmp“, 0, 0);
delay(4000);
bmpDraw(„2.bmp“, 0, 0);
delay(4000);
bmpDraw(„3.bmp“, 0, 0);
delay(4000);
bmpDraw(„4.bmp“, 0, 0);
delay(4000);
}

#define BUFFPIXEL 20

void bmpDraw(char *filename, uint8_t x, uint8_t y) {

File     bmpFile;
int      bmpWidth, bmpHeight;   // W+H in pixels
uint8_t  bmpDepth;              // Bit depth (currently must be 24)
uint32_t bmpImageoffset;        // Start of image data in file
uint32_t rowSize;               // Not always = bmpWidth; may have padding
uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean  goodBmp = false;       // Set to true on valid header parse
boolean  flip    = true;        // BMP is stored bottom-to-top
int      w, h, row, col;
uint8_t  r, g, b;
uint32_t pos = 0, startTime = millis();

if((x >= tft.width()) || (y >= tft.height())) return;

Serial.println();
Serial.print(„Loading image ‚“);
Serial.print(filename);
Serial.println(‚\“);

// Open requested file on SD card
if ((bmpFile = SD.open(filename)) == NULL) {
Serial.print(„File not found“);
return;
}

// Parse BMP header
if(read16(bmpFile) == 0x4D42) { // BMP signature
Serial.print(„File size: „);
Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.print(„Image Offset: „);
Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(„Header size: „);
Serial.println(read32(bmpFile));
bmpWidth  = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1) { // # planes — must be ‚1‘
bmpDepth = read16(bmpFile); // bits per pixel
Serial.print(„Bit Depth: „);
Serial.println(bmpDepth);
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

goodBmp = true; // Supported BMP format — proceed!
Serial.print(„Image size: „);
Serial.print(bmpWidth);
Serial.print(‚x‘);
Serial.println(bmpHeight);

// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;

// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip      = false;
}

// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width())  w = tft.width()  – x;
if((y+h-1) >= tft.height()) h = tft.height() – y;

// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x+w-1, y+h-1);

for (row=0; row<h; row++) { // For each scanline…

// Seek to start of scan line.  It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding.  Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight – 1 – row) * rowSize;
else     // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if(bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}

for (col=0; col<w; col++) { // For each pixel…
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}

// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
tft.pushColor(tft.Color565(r,g,b));
} // end pixel
} // end scanline
Serial.print(„Loaded in „);
Serial.print(millis() – startTime);
Serial.println(“ ms“);
} // end goodBmp
}
}

bmpFile.close();
if(!goodBmp) Serial.println(„BMP format not recognized.“);
}

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}

uint32_t read32(File f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}

 


1.8″ TFT Display (128×160 Pixel)

Ich habe mir vor knapp zwei Wochen nach langem hin und her einmal ein TFT Display angeschafft. Ich habe es auf Ebay relativ günstig gekauft : ) ..Das Display ist von Sainsmart und es besitzt einen eingebauten MicroSD Slot.

sainsmart_frontsainsmart_back

 

 

 

 

 

 

 

 

 

Die Libary kann über die Produktseite von Adafruit heruntergeladen werden.Da die aktuelle Bibliothek nicht auf dem neusten Stand des Arduinos ist (< 1.0.1), muss man ein paar Stellen in der Programmierung abändern, kann dann jedoch alle Funktionen des Displays nutzen.

Hier einmal ein paar Ergebnisse:

Foto 04.12.12 16 17 53

tft_test'_text

Foto 04.12.12 16 17 50

Hier noch die Schaltung des Displays an das Arduino (Leonardo):

Leonardo Display
10 CS
9 DC
8 RES
SDA SDA
SCL SCL
5V VCC
GND GND

TFT_wire

Und zum Schluss noch den Programmcode: (Beispielcode mit leichten Änderungen)

#define sclk SCL
#define mosi SDA
#define cs   10
#define dc   9
#define rst  8
//……………..
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);

float p = 3.1415926;

void setup(void) {
tft.initR(INITR_REDTAB);
uint16_t time = millis();
tft.fillScreen(ST7735_BLACK);
time = millis() – time;
delay(500);

// large block of text
tft.fillScreen(ST7735_BLACK);
testdrawtext(„Lorem ip….  „, ST7735_WHITE);
delay(1000);

// tft print function!
tftPrintTest();
delay(4000);

// a single pixel
tft.drawPixel(tft.width()/2, tft.height()/2, ST7735_GREEN);
delay(500);

// line draw test
testlines(ST7735_YELLOW);
delay(500);

// optimized lines
testfastlines(ST7735_RED, ST7735_BLUE);
delay(500);

testdrawrects(ST7735_GREEN);
delay(500);

testfillrects(ST7735_YELLOW, ST7735_MAGENTA);
delay(500);

tft.fillScreen(ST7735_BLACK);
testfillcircles(10, ST7735_BLUE);
testdrawcircles(10, ST7735_WHITE);
delay(500);

testroundrects();
delay(500);

testtriangles();
delay(500);

mediabuttons();
delay(500);

Serial.println(„done“);
delay(1000);
}

void loop() {
tft.invertDisplay(true);
delay(500);
tft.invertDisplay(false);
delay(500);
}

void testlines(uint16_t color) {
tft.fillScreen(ST7735_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(0, 0, x, tft.height()-1, color);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(0, 0, tft.width()-1, y, color);
}

tft.fillScreen(ST7735_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(tft.width()-1, 0, 0, y, color);
}

tft.fillScreen(ST7735_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(0, tft.height()-1, x, 0, color);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
}

tft.fillScreen(ST7735_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
}
}

void testdrawtext(char *text, uint16_t color) {
tft.setCursor(0, 0);
tft.setTextColor(color);
tft.setTextWrap(true);
tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
tft.fillScreen(ST7735_BLACK);
for (int16_t y=0; y < tft.height(); y+=5) {
tft.drawFastHLine(0, y, tft.width(), color1);
}
for (int16_t x=0; x < tft.width(); x+=5) {
tft.drawFastVLine(x, 0, tft.height(), color2);
}
}

void testdrawrects(uint16_t color) {
tft.fillScreen(ST7735_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
}
}

void testfillrects(uint16_t color1, uint16_t color2) {
tft.fillScreen(ST7735_BLACK);
for (int16_t x=tft.width()-1; x > 6; x-=6) {
tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
}
}

void testfillcircles(uint8_t radius, uint16_t color) {
for (int16_t x=radius; x < tft.width(); x+=radius*2) {
for (int16_t y=radius; y < tft.height(); y+=radius*2) {
tft.fillCircle(x, y, radius, color);
}
}
}

void testdrawcircles(uint8_t radius, uint16_t color) {
for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
tft.drawCircle(x, y, radius, color);
}
}
}

void testtriangles() {
tft.fillScreen(ST7735_BLACK);
int color = 0xF800;
int t;
int w = 63;
int x = 159;
int y = 0;
int z = 127;
for(t = 0 ; t <= 15; t+=1) {
tft.drawTriangle(w, y, y, x, z, x, color);
x-=4;
y+=4;
z-=4;
color+=100;
}
}

void testroundrects() {
tft.fillScreen(ST7735_BLACK);
int color = 100;
int i;
int t;
for(t = 0 ; t <= 4; t+=1) {
int x = 0;
int y = 0;
int w = 127;
int h = 159;
for(i = 0 ; i <= 24; i+=1) {
tft.drawRoundRect(x, y, w, h, 5, color);
x+=2;
y+=3;
w-=4;
h-=6;
color+=1100;
}
color+=100;
}
}

void tftPrintTest() {
tft.setTextWrap(false);
tft.fillScreen(ST7735_BLACK);
tft.setCursor(0, 30);
tft.setTextColor(ST7735_RED);
tft.setTextSize(1);
tft.println(„Hello World!“);
tft.setTextColor(ST7735_YELLOW);
tft.setTextSize(2);
tft.println(„Hello World!“);
tft.setTextColor(ST7735_GREEN);
tft.setTextSize(3);
tft.println(„Hello World!“);
tft.setTextColor(ST7735_BLUE);
tft.setTextSize(4);
tft.print(1234.567);
delay(1500);
tft.setCursor(0, 0);
tft.fillScreen(ST7735_BLACK);
tft.setTextColor(ST7735_WHITE);
tft.setTextSize(0);
tft.println(„Hello World!“);
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN);
tft.print(p, 6);
tft.println(“ Want pi?“);
tft.println(“ „);
tft.print(8675309, HEX); // print 8,675,309 out in HEX!
tft.println(“ Print HEX!“);
tft.println(“ „);
tft.setTextColor(ST7735_WHITE);
tft.println(„Sketch has been“);
tft.println(„running for: „);
tft.setTextColor(ST7735_MAGENTA);
tft.print(millis() / 1000);
tft.setTextColor(ST7735_WHITE);
tft.print(“ seconds.“);
}

void mediabuttons() {
// play
tft.fillScreen(ST7735_BLACK);
tft.fillRoundRect(25, 10, 78, 60, 8, ST7735_WHITE);
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_RED);
delay(500);
// pause
tft.fillRoundRect(25, 90, 78, 60, 8, ST7735_WHITE);
tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_GREEN);
tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_GREEN);
delay(500);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_BLUE);
delay(50);
// pause color
tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_RED);
tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_RED);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_GREEN);
}


Arduino Kommunikation mit einem SNES Controller

Nachdem im Buch von der Steuerung des Arduino Boards mit Hilfe eines WII Nunchuk die Rede war, habe ich mal ein wenig die Foren nach anderen Arduino-kompatiblen Controllern durchsucht.
Sehr erfreut war ich, dass der gute, alte SNES Controller sogar eine Arduino Libary besaß. :D
Die Libary und auch eine kurze Anleitung zur Schaltung kann auf der Seite des Programmierers eingesehen werden.
Leider ist die Libary nicht mehr auf dem neusten Stand der Arduino IDE (1.0.1), weswegen sie leicht abgeändert werden muss. Danach funktioniert sie jedoch super :D

Hier mal der angeschlossene Controller: (eine Schaltungsskizze folgt noch)

 

Nachdem man die SNESpad installiert hat (Anleitung siehe hier) kann man in der Arduino IDE Beispiele unter „SNES“ öffnen.

Hier mal ein Programmbeispiel:

#include <SNESpad.h>
//——————————-
SNESpad nintendo = SNESpad(10,9,8);
//——————————-
int state = 0;
//——————————-
void setup()
{Serial.begin(57600);}
void loop() {
state = nintendo.buttons();
Serial.println(~state, BIN);
delay(500); //Reaktion der Knöpfe
}

Dieses Programm gibt im Serial Monitor auf dem Controller gedrückte Tasten in Form von Nullen und Einsen wieder. Mit der Einstellung des delay() lässt sich die Reaktionsgeschwindigkeit des Boards einstellen.
Echt eine coole Sache :D Hab schon ein paar Ideen, was man so machen könnte :)

 


LCD – Eigene Zeichen / charachters erstellen

Eine echt Tolle Libary stellt  arduino.cc zur Verfügung, mit der man eine Menge mit dem LC Display anstellen kann.

Ich habe mich zunächst einmal mit der createChar() Methode befasst, welche ganz interessant klang.

Mit dieser Methode ist es möglich eigene Zeichen zu erstellen und diese auf dem Display auszugeben.

Hier schon einmal vorweg das Ergebnis:

So wird es gemacht:

Zunächst einmal die Vorarbeit, die geleistet werden muss

  • Zeichen entwerfen (5×8 Pixel)

  • Nun kann man den Code schreiben:

die Zeichen werden in einem Array mit 8 Elementen in Form von Byte’s gespeichert.

Hier das Beispiel gezeigt am Zeichen des Sterns:

Eine Eins seht dafür, dass das Pixel an dieser Stelle schwarz wird.

———-byte star———-

byte star[8] = {
B00000,
B00100,
B00100,
B11111,
B01110,
B01010,
B10001,
B00000
};

——————————

Ein kleines Rubyscript für das Erstellen der Zeichen hier <—–

——————————

Hier der komplette Code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
char a = 0;
char b = 1;
char c = 2;
char d = 3;
byte smiley[8] = {
B00000,
B01010,
B01010,
B00000,
B11111,
B10001,
B01110,
B00000
};
byte star[8] = {
B00000,
B00100,
B00100,
B11111,
B01110,
B01010,
B10001,
B00000
};
byte heart[8] = {
B00000,
B01010,
B11111,
B01110,
B00100,
B00000,
B00000,
B00000

};
byte cross[8] = {
B00100,
B00100,
B11111,
B00100,
B00100,
B00100,
B00100,
B00100
};
void setup() {
lcd.createChar(a, smiley);
lcd.createChar(b, star);
lcd.createChar(c, heart);
lcd.createChar(d, cross);
lcd.setCursor(0, 0);
lcd.write(a);
lcd.print(“  „);
lcd.write(b);
lcd.print(“  „);
lcd.write(c);
lcd.print(“  „);
lcd.write(d);
}
void loop() {}

——————————

Die Schaltung des Displays ist gleich geblieben. (Siehe hier)


Liquid Crystal Display

Heute ist endlich das Paket von Reichelt angekommen :) Juhu
Nadine und ich haben uns vor einiger Zeit LCDisplays zugelegt, die jedoch einen Potentiometer* benötigen, welches wir leider nicht mit bestellt haben :P Nachdem wir nun unsere Bauteile haben kann es endlich weitergehen :D

Noch vielen Dank für das Verlöten des Displays an Max! :D

 

CODE:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
    lcd.begin(16, 2);
    lcd.print(„arduinokevin.“);
}

void loop() {
    lcd.setCursor(0, 1);
    lcd.print(„wordpress.com“);
}

Hier die Schaltung:

Die Anleitung für das Ansteuern des LC Displays kann man hier finden.

*Das Potentiometer wird für die Einstellung des Kontrasts des Displays benötigt.


Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.