Odkaz je tady: https://www.michaluvbrloh.cz/2026/09/23 ... a-arduino/
OLED displej 128x32 0,91" SSD1306 I²C a Arduino
Pravidla fóra
Vkládejte prosím jen HOTOVÉ projekty, které chcete představit ostatním.
Vkládejte prosím jen HOTOVÉ projekty, které chcete představit ostatním.
OLED displej 128x32 0,91" SSD1306 I²C a Arduino
Dnes jsem se podíval na malý OLED displej 128x32 0,91" s řadičem SSD1306 a I²C sběrnicí a jak ho připojit k Arduinu. Mám pár základních prográmků a pár fotek a videí, prostě jako vždy
Odkaz je tady: https://www.michaluvbrloh.cz/2026/09/23 ... a-arduino/
Odkaz je tady: https://www.michaluvbrloh.cz/2026/09/23 ... a-arduino/
https://www.michaluvbrloh.cz - Můj web
https://hackaday.io/projects/hacker/1326779 - Moje některé probíhající i dokončené projekty
https://hackaday.io/projects/hacker/1326779 - Moje některé probíhající i dokončené projekty
Re: OLED displej 128x32 0,91" SSD1306 I²C a Arduino
Tu máš tetris, ať to máš ještě zajímavější ten článek.
Kód: Vybrat vše
#include <U8glib.h>
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);
/*********************************************************/
#define bW 4
#define bH 4
#define ROW 23
#define COL 10
#define bOffX 1
#define bOffY 33
#define nextX 4
#define nextY 4
#define bP 3
#define DOWN_SCORE 1+1*lvl
int board[ROW][COL];
boolean isStarted = 0;
unsigned long int gameTime = 0;
unsigned long int score = 0;
unsigned int lines = 0;
int lvl = 0;
int gameSpeed = 1000;
boolean gameOver = 1;
unsigned int IBlock[4] = {0x4444,0x0F00,0x4444,0x0F00};
unsigned int JBlock[4] = {0x2260,0x4700,0x3220,0x0710};
unsigned int LBlock[4] = {0x4460,0x0E80,0xC440,0x2E00};
unsigned int OBlock[4] = {0x6600,0x6600,0x6600,0x6600};
unsigned int SBlock[4] = {0x6C00,0x4620,0x06C0,0x8C40};
unsigned int TBlock[4] = {0x0270,0x4640,0x7200,0x1310};
unsigned int ZBlock[4] = {0xC600,0x2640,0x0C60,0x4C80};
unsigned int nextBlock;
unsigned int activeBlock[4];
int nbR;
int nbID;
int abID;
int abX;
int abY;
int abR;
byte mID;
bool mActive;
/*********************************************************/
/*-------------------------------------------------------*/
class Button {
public:
enum State {
OFF,
ON,
HELD
};
Button(uint8_t pin, unsigned long timeToHeld, unsigned long debounceTime = 20)
: _pin(pin), _timeToHeld(timeToHeld), _debounceTime(debounceTime) {
pinMode(_pin, INPUT_PULLUP); // předpokládám tlačítko proti GND
_lastStableState = HIGH;
_lastReading = HIGH;
_lastDebounceTime = 0;
_state = OFF;
_pressedTime = 0;
}
void update() {
int reading = digitalRead(_pin);
// debounce
if (reading != _lastReading) {
_lastDebounceTime = millis();
}
_lastReading = reading;
if ((millis() - _lastDebounceTime) > _debounceTime) {
if (reading != _lastStableState) {
_lastStableState = reading;
if (_lastStableState == LOW) {
// tlačítko zmáčknuto
_pressedTime = millis();
_state = ON;
} else {
// tlačítko puštěno
_state = OFF;
}
}
// check held
if (_lastStableState == LOW && (millis() - _pressedTime) >= _timeToHeld) {
_state = HELD;
}
}
}
State getState() const {
return _state;
}
private:
uint8_t _pin;
unsigned long _timeToHeld;
unsigned long _debounceTime;
int _lastStableState;
int _lastReading;
unsigned long _lastDebounceTime;
unsigned long _pressedTime;
State _state;
};
/*-------------------------------------------------------*/
Button upBtn(2, 100); // pin 2, HELD po 100 ms
Button leftBtn(3, 100); // pin 3, HELD po 100 ms
Button downBtn(4, 100); // pin 4, HELD po 100 ms
Button rightBtn(5, 100); // pin 5, HELD po 100 ms
Button rotBtn(6, 100); // pin 6, HELD po 100 ms
void setup() {
Serial.begin(115200);
u8g.setRot90();
abX = 0;
abY = 0;
abR = 0;
isStarted = 0;
gameOver = 1;
gameSpeed = 1200;
mID = 0;
mActive = 0;
randomSeed(analogRead(A0));
delay(500);
}
byte up_btnState, up_btnLastState, left_btnState, left_btnLastState, down_btnState, down_btnLastState, right_btnState, right_btnLastState, rot_btnState, rot_btnLastState;
void loop() {
upBtn.update();
leftBtn.update();
downBtn.update();
rightBtn.update();
rotBtn.update();
up_btnState = upBtn.getState();
left_btnState = leftBtn.getState();
down_btnState = downBtn.getState();
right_btnState = rightBtn.getState();
rot_btnState = rotBtn.getState();
//UP
if(up_btnState != up_btnLastState || up_btnState == Button::HELD){
switch (up_btnState) {
case Button::OFF:
break;
case Button::ON:
if(gameOver == 0){
//moveLeft();
} else {
if(!mActive){
if(mID == 0){mID = 2;}else{mID = (mID - 1) % 3;}
} else {
if(lvl > 0 && mID == 1){lvl--;}
}
}
break;
case Button::HELD:
break;
}
}
//LEFT
if(left_btnState != left_btnLastState || left_btnState == Button::HELD){
switch (left_btnState) {
case Button::OFF:
break;
case Button::ON:
if(gameOver == 0){
moveLeft();
} else {
if(!mActive){
if(mID == 0){mID = 2;}else{mID = (mID - 1) % 3;}
} else {
if(lvl > 0 && mID == 1){lvl--;}
}
}
break;
case Button::HELD:
if(gameOver == 0){
moveLeft();
moveLeft();
}
break;
}
}
//DOWN
if(down_btnState != down_btnLastState || down_btnState == Button::HELD){
switch (down_btnState) {
case Button::OFF:
break;
case Button::ON:
if(gameOver == 0){
//moveRight();
} else {
if(!mActive){
mID = (mID + 1) % 3;
} else {
if(lvl < 9 && mID == 1){lvl++;}
}
}
break;
case Button::HELD:
if(gameOver == 0){
moveDown();
score += DOWN_SCORE;
moveDown();
score += DOWN_SCORE;
}
break;
}
}
//RIGHT
if(right_btnState != right_btnLastState || right_btnState == Button::HELD){
switch (right_btnState) {
case Button::OFF:
break;
case Button::ON:
if(gameOver == 0){
moveRight();
} else {
if(!mActive){
mID = (mID + 1) % 3;
} else {
if(lvl < 9 && mID == 1){lvl++;}
}
}
break;
case Button::HELD:
if(gameOver == 0){
moveRight();
moveRight();
}
break;
}
}
//ROT
if(rot_btnState != rot_btnLastState || rot_btnState == Button::HELD){
switch (rot_btnState) {
case Button::OFF:
break;
case Button::ON:
if(gameOver == 0){
moveRotate();
} else {
menuOpen();
//isStarted = 1;
//gameOver = 0;
}
break;
case Button::HELD:
break;
}
}
up_btnLastState = up_btnState;
left_btnLastState = left_btnState;
down_btnLastState = down_btnState;
right_btnLastState = right_btnState;
rot_btnLastState = rot_btnState;
//--------------------------------------
if(!gameOver){
if (millis()-gameTime > (gameSpeed-lvl*100)) {
moveDown();
gameTime = millis();
}
}
if(isStarted && gameOver == 0){
//gameOver = 0;
score = 0;
lines = 0;
isStarted = 0;
prepareNext();
createBlock();
}
//--------------------------------------
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
}//end loop
//--------------------------------------
void menuOpen(){
if(mID == 0){
isStarted = 1;
gameOver = 0;
}else{
mActive = !mActive;
}
}
void drawMenu(){
if(!mActive || mID == 1){
u8g.setFont(u8g_font_5x7);
u8g.setPrintPos(4, 42);
u8g.print(F("Start"));
u8g.setPrintPos(4, 52);
u8g.print(F("Level"));
u8g.setPrintPos(4, 62);
u8g.print(F("Score"));
u8g.drawLine(2,42+mID*10,28,42+mID*10);
if(mActive){
u8g.drawLine(2,42-8+mID*10,28,42-8+mID*10);
u8g.drawLine(2,42-7+mID*10,2,42+mID*10);
u8g.drawLine(28,42-7+mID*10,28,42+mID*10);
}
}
}
void drawGUI(void){
u8g.drawFrame(2, 2, 16, 16);
u8g.drawFrame(0, 32, COL*bP+2, ROW*bP+2);
u8g.setFont(u8g_font_7x14);//lvl
u8g.setPrintPos(22, 15);
u8g.print(lvl);
drawScore();
}
void drawScore(){
u8g.setFont(u8g_font_5x7);//score
u8g.setPrintPos(1, 28);
u8g.print(score);
}
void drawBlock(int x, int y){
u8g.drawFrame(x ,y , bP, bP);
}
void drawNextBlock(void){
int b = 15;
for(int s=0;s < bW; s++){
for(int r=0;r < bH; r++){
if(!bitRead(nextBlock, b)){ b--;continue;}
drawBlock(r*bP+nextX, s*bP+nextY);
b--;
}
}
}
void drawBoard(){
for(int y=0;y < ROW; y++){
for(int x=0;x < COL; x++){
if(!board[y][x]){continue;}
drawBlock(x*bP+bOffX, y*bP+bOffY);
}
}
}
void drawActiveBlock(){
int b = 15;
for(int s=0;s < bW; s++){
for(int r=0;r < bH; r++){
if(!bitRead(activeBlock[abR], b)){ b--;continue;}
drawBlock(r*bP+bOffX+abX*bP, s*bP+bOffY+abY*bP);
b--;
}
}
}
void prepareNext(){
nbID = random(6);
nbR = random(3);
switch(nbID){
case 0:
nextBlock = IBlock[nbR];
break;
case 1:
nextBlock = JBlock[nbR];
break;
case 2:
nextBlock = LBlock[nbR];
break;
case 3:
nextBlock = OBlock[nbR];
break;
case 4:
nextBlock = SBlock[nbR];
break;
case 5:
nextBlock = TBlock[nbR];
break;
case 6:
nextBlock = ZBlock[nbR];
break;
}
}
void createBlock(){
abX = 3;
abY = 0;
abR = nbR;
abID = nbID;
switch(abID){
case 0:
for(int i=0; i < 4;i++){activeBlock[i] = IBlock[i];}
break;
case 1:
for(int i=0; i < 4;i++){activeBlock[i] = JBlock[i];}
break;
case 2:
for(int i=0; i < 4;i++){activeBlock[i] = LBlock[i];}
break;
case 3:
for(int i=0; i < 4;i++){activeBlock[i] = OBlock[i];}
break;
case 4:
for(int i=0; i < 4;i++){activeBlock[i] = SBlock[i];}
break;
case 5:
for(int i=0; i < 4;i++){activeBlock[i] = TBlock[i];}
break;
case 6:
for(int i=0; i < 4;i++){activeBlock[i] = ZBlock[i];}
break;
}
prepareNext();
}
void moveRight(){
if(notColision(abX+1,abY,abR)){
abX++;
}
}
void moveLeft(){
if(notColision(abX-1,abY,abR)){
abX--;
}
}
void moveDown(){
if(notColision(abX,abY+1,abR)){
abY++;
}else{
lockBlock();
}
}
void moveRotate(){
byte kOff = 1;
if(notColision(abX,abY,(abR + 1) % 4)){
abR = (abR + 1) % 4;
}else{
if(abX <= 0){
if(notColision(abX+1,abY,(abR + 1) % 4)){
abX++;
abR = (abR + 1) % 4;
}
}
if(abX >= 7){
if(abID == 0 && abX == 8){kOff = 2;}
if(notColision(abX-kOff,abY,(abR + 1) % 4)){
abX -= kOff;
abR = (abR + 1) % 4;
}
}
}
}
void lockBlock(){
int b = 15;
int fullRowCounter = 0;
for(int s=0;s < bW; s++){
for(int r=0;r < bH; r++){
if(!bitRead(activeBlock[abR], b)){ b--;continue;}
board[abY+s][abX+r] = 1;
b--;
if(abY == 0){
gameOver = 1;
}
}
}
if(!gameOver){
for(int y=0;y < ROW; y++){
boolean isRowFull = true;
for(int x=0;x < COL; x++){
isRowFull = isRowFull && board[y][x];
}
if(isRowFull){
for(int r = y;r > 1; r--){
for(int s = 0; s < COL; s++){
board[r][s] = board[r-1][s];
}
}
score += 10 + (10*fullRowCounter);
fullRowCounter++;
}
}
createBlock();
} else {
eraseGame();
}
}
boolean notColision(int newX, int newY, int newR){
boolean nocolide = true;
int b = 15;
for(int s=0;s < bW; s++){
for(int r=0;r < bH; r++){
if(!bitRead(activeBlock[newR], b)){b--; continue;}
if((newX+r >= COL)||(newX+r < 0)){nocolide=false;}
if(newY+s >= ROW){nocolide=false;}
if(board[newY+s][newX+r]){nocolide=false;}
b--;
}
}
return nocolide;
}
void eraseGame(){
for(int y=0;y < ROW; y++){
for(int x=0;x < COL; x++){
board[y][x] = 0;
}
}
gameOver = 1;
isStarted = 0;
}
void draw(void) {
drawGUI();
drawScore();
if(gameOver) {
drawMenu();
}else{
drawActiveBlock();
drawNextBlock();
drawBoard();
}
}
Kdo je online
Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host