OLED | Arduino |
---|---|
GND | GND |
VCC | 3,3V bzw. 5V |
SCL | A5 |
SDA | A4 |
Zum Betrieb des OLED-Moduls (mittels I²C-Protokoll) wurden zwei vorgefertigte Software-Libraries verwendet, Adafruit_SSD1306 und Adafruit-GFX-Library. Damit kann das OLED sehr einfach angesteuert und einige Test durchgeführt werden.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
void setup()
{
Wire.begin();
/**
* initialize with the I2C address:
* 0x3C -> 128x32 resolution
* 0x3D -> 128x64 resolution
*/
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
/**
* Show image buffer on the display hardware.
* Since the buffer is intialized with an Adafruit splashscreen
* internally, this will display the splashscreen.
*/
display.display();
delay(2000);
display.clearDisplay();
display.drawPixel(10, 10, WHITE);
display.display();
delay(2000);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(5,0);
display.print("Hello World!");
display.display();
delay(2000);
}
void loop()
{
}
Conway´s Game Of Life hatte ich schon in "Zelluläre Automaten" implementiert und
habe den Algorithmus hierfür übernommen aber noch die Feldgröße etwas erweitert. Zusätzlich wurde die
Schaltung noch mit einem Reset-Knopf ausgestattet, damit man das Feld wieder mit zufälligen Zellen
initialisieren kann. Außerdem gibt es noch ein Potentiometer, mit dem man die Geschwindigkeit der
Generationen regeln kann.
Auf dem OLED werden natürlich die Zellen pro Generation angezeigt, aber auch die Generation ("Iter"), die Anzahl
an gleichzeitig gezeigten Zellen ("Alive") und die aktuelle Verzögerungszeit/Geschwindigkeit ("Delay") der
Simulation.
#define FIELD_WIDTH 20
#define FIELD_HEIGHT 20
#define PIN_BUTTON 2
#define PIN_POTENTIOMETER A2
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
byte field[FIELD_WIDTH][FIELD_HEIGHT];
byte fieldLast[FIELD_WIDTH][FIELD_HEIGHT];
int iteration = 0, cellsAlive = 0;
bool isReset = false;
int gameDelay = 150;
void setup()
{
pinMode(PIN_BUTTON, INPUT);
pinMode(PIN_POTENTIOMETER, INPUT);
attachInterrupt(digitalPinToInterrupt(PIN_BUTTON), isrReset, RISING);
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
randomizeField();
}
void loop()
{
if (isReset == true) {
isReset = false;
randomizeField();
}
updateOled();
saveFieldState();
generateNextGeneration();
gameDelay = round(analogRead(PIN_POTENTIOMETER) / 10) * 10;
delay(gameDelay);
iteration++;
}
void isrReset()
{
isReset = true;
}
void randomizeField()
{
iteration = 0;
cellsAlive = 0;
byte rnd = 0;
randomSeed(analogRead(0));
for(byte y=0; y<FIELD_HEIGHT; y++) {
for(byte x=0; x<FIELD_WIDTH; x++) {
field[y][x] = random(2);
if (field[y][x] == 1) {
cellsAlive++;
}
}
}
}
void saveFieldState()
{
for(byte y=0; y<FIELD_HEIGHT; y++) {
for(byte x=0; x<FIELD_WIDTH; x++) {
fieldLast[y][x] = field[y][x];
}
}
}
void generateNextGeneration()
{
byte neighborSum = 0;
for(byte y=0; y<FIELD_HEIGHT; y++) {
for(byte x=0; x<FIELD_WIDTH; x++) {
neighborSum = getNeightborSum(x, y);
if (fieldLast[y][x] == 0) {
if (neighborSum == 3) {
// populate if 3 neighours around it
field[y][x] = 1;
cellsAlive++;
}
} else {
if (neighborSum < 2 || neighborSum > 3) {
// die if only one neighbour or 4 or more neighours
field[y][x] = 0;
cellsAlive--;
}
}
}
}
}
byte getNeightborSum(byte x, byte y)
{
byte sum = 0;
for(int j = -1; j<=1; j++) {
for(int i = -1; i<=1; i++) {
if (j==0 && i==0) {
continue;
}
if (x+i<0 || x+i>FIELD_WIDTH-1) {
continue;
}
if (y+j<0 || y+j>FIELD_HEIGHT-1) {
continue;
}
sum += fieldLast[y+j][x+i];
}
}
return sum;
}
void updateOled()
{
display.fillRect(FIELD_WIDTH + 3, 0, display.width(), display.height(), BLACK);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(FIELD_WIDTH + 10, 0);
display.print("Iter:");
display.setCursor(FIELD_WIDTH + 50, 0);
display.print(String(iteration));
display.setCursor(FIELD_WIDTH + 10, 10);
display.print("Alive:");
display.setCursor(FIELD_WIDTH + 50, 10);
display.print(String(cellsAlive));
display.setCursor(FIELD_WIDTH + 10, 20);
display.print("Delay:");
display.setCursor(FIELD_WIDTH + 50, 20);
display.print(String(gameDelay));
for(byte y=0; y<FIELD_HEIGHT; y++) {
for(byte x=0; x<FIELD_WIDTH; x++) {
if (field[y][x] == 1) {
display.drawPixel(x, y, WHITE);
} else {
display.drawPixel(x, y, BLACK);
}
}
}
display.display();
}
zurück